Android AdMob provoca fugas de memoria?

He integrado AdMob v4.1.0 en mi aplicación y parece haber causado una fuga de memoria enorme (bastante seguro de que ya sucedió en 4.0.4).

Para aislar el problema, creé un nuevo proyecto con un diseño lineal en blanco y le agregé el AdView (esto es en realidad una copia y pega del código de ejemplo proporcionado por AdMob). Vea mi main.xml, MainActivity.java y contenido de manifiesto:

Main.xml:

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" android:id="@+id/linearLayout"> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" /> </LinearLayout> 

MainActivity.java:

 package AdsTry.main; import com.google.ads.AdRequest; import com.google.ads.AdSize; import com.google.ads.AdView; import android.app.Activity; import android.os.Bundle; import android.widget.LinearLayout; public class MainActivity extends Activity { private final int AD_VIEW_ID = 1000000; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // Lookup R.layout.main LinearLayout layout = (LinearLayout)findViewById(R.id.linearLayout); // Create the adView // Please replace MY_BANNER_UNIT_ID with your AdMob Publisher ID AdView adView = new AdView(this, AdSize.BANNER, "MY_BANNER_UNIT_ID"); adView.setId(AD_VIEW_ID); // Add the adView to it layout.addView(adView); // Initiate a generic request to load it with an ad AdRequest request = new AdRequest(); adView.loadAd(request); } @Override protected void onPause() { Log.i("AdsTry", "onPause"); getAdView().stopLoading(); super.onPause(); } @Override protected void onDestroy() { Log.i("AdsTry", "onDestroy"); getAdView().destroy(); super.onDestroy(); } private AdView getAdView() { return (AdView) findViewById(AD_VIEW_ID); } } 

manifiesto:

 <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".MainActivity" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <!-- AdMobActivity definition --> <activity android:name="com.google.ads.AdActivity" android:configChanges="orientation|keyboard|keyboardHidden" /> </application> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> 

Y ese es todo el código que tengo.

Ahora, al ejecutar esta aplicación, puedo ver que tanto onPause como onDestory son llamados y la Actividad se termina, PERO el problema es que nunca estará disponible para el GC ya que hace que el InputMethodManager contenga una referencia a la Actividad Imagen tomada de salida HPROF después de la actividad fue destruida): MainActivity Combina el camino más corto con GC Roots

Una vez que quite el código relacionado con AdView (y otra vez, éste es el ÚNICO código de esta aplicación) el problema desaparece: La misma salida HPROF sin usar AdView

EDIT: También intentado quitar TODO el código de onCreate y actualizado el main.xml para contener lo siguiente (todavía obtener el mismo resultado):

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:ads="http://schemas.android.com/apk/lib/com.google.ads" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/linearLayout"> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" /> <com.google.ads.AdView android:id="@+id/Ad" android:layout_width="match_parent" android:layout_height="wrap_content" ads:adUnitId="MY_ID" ads:adSize="BANNER" ads:loadAdOnCreate="true"/> </LinearLayout> 

Algunas ideas ????

Aquí está mi trabajo alrededor para este lío:

He limitado la fuga de memoria, utilizando la misma instancia de actividad vacía:

 public final class AdMobActivity extends Activity { public static AdMobActivity AdMobMemoryLeakWorkAroundActivity; public AdMobActivity() { super(); if (AdMobMemoryLeakWorkAroundActivity != null) throw new IllegalStateException("This activity should be created only once during the entire application life"); AdMobMemoryLeakWorkAroundActivity = this; } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); finish(); } public static final void startAdMobActivity(Activity activity) { Intent i = new Intent(); i.setComponent(new ComponentName(activity.getApplicationContext(), AdMobActivity.class)); activity.startActivity(i); } } 

Se crearía otro anuncio con AdMobActivity.AdMobMemoryLeakWorkAroundActivity .

También es necesario agregar la actividad al manifiesto por supuesto:

 <activity android:launchMode="singleInstance" android:name="com.nu.art.software.android.modules.admob.AdMobActivity" /> 

Esta implementación va en contra de mis creencias con respecto a las referencias estáticas, que no son constantes, pero esta implementación evita la filtración ya que sólo se usa una instancia de actividad para crear todos los anuncios y, por lo tanto, no más fugas de actividad además del hecho de que la actividad está completamente vacía .

NOTA: Debe llamar al método startAdMobActivity del método onCreate de la actividad principal de la aplicación.

Adán.

ACTUALIZAR

Esta solución sólo funciona si crea el anuncio dinámicamente y lo agrega al diseño con código … y no olvide destruirlo en Activity.onDestroy ().

Estoy utilizando "play-services-ads: 7.5.0" y no era necesario crear AdMobActivity. Trabajó por:

Crear adView dinámicamente

 mAdView = new AdView(getApplicationContext(), AdSize.BANNER, banner_ad_unit_id); mAdsContainer.addView(mAdView); 

Eliminar todas las vistas de linearLayout en destruir y destruir adView

 mAdView.setAdListener(null); mAdsContainer.removeAllViews(); mAdView.destroy(); 

Desafortunadamente Interstitial todavía filtra

Una forma de solucionar este problema es crear una única instancia de adview utilizando la actividad base de la aplicación. Agregue este anuncio a cualquier actividad que desee, pero recuerde eliminarla en el método de actividades en destruir.

De esta manera, el anuncio sólo se pierde la actividad base, que casi nunca debe tener más de una instancia de.

Ejemplo:

 @Override public void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.setContentView(R.layout.venue); mainLayout = (LinearLayout) findViewById(R.id.venueLayout); adview = StaticStateClass.getAdview(); AdRequest request = new AdRequest(); request.addKeyword(name); mainLayout.addView(adview); adview.loadAd(request); } @Override public void onDestroy() { mainLayout.removeView(adview); super.onDestroy(); } 

Estoy enfrentando el mismo problema. La única cosa que me ayudó – su System.exit (0). No me gusta, pero es la única manera que he encontrado.
AdMob sólo permanece en RAM 4ever y no dejes que mi aplicación termine correctamente. Cuando reinicio mi sistema operativo sólo aumenta la aplicación de no-muertos y pronto causa la excepción de memoria.
Mi tema del foro de soporte de AdMob : no hay soporte hasta ahora. Parece que no1 cuida.

Descubrí que llamar a: –

 mAdView.destroy(); 

Antes de salir de la actividad resuelve la fuga para mí.

Aquí es cómo declaro los anuncios de la bandera en xml: –

  <com.google.android.gms.ads.AdView android:id="@+id/adView2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal|bottom" ads:adSize="BANNER" ads:adUnitId="@string/banner_ad_unit_id_2" /> 

Obtener una referencia a admob banner en onCreate (): –

 mAdView = (AdView) findViewById(R.id.adView2); AdRequest banneradRequest = new AdRequest.Builder().build(); mAdView.loadAd(banneradRequest); 

Y destruirlo en undestroy () de la actividad: –

 @Override protected void onDestroy() { super.onDestroy(); mAdView.destroy(); } 

Otra respuesta que aborda esta cuestión, aunque es un dolor para hacerlo, es seguir los siguientes pasos.

  • Unpersist todos los datos que se necesitan de sharedPreferences o cualquier otro tipo de en la persistencia de almacenamiento,
    Almacenar esos valores en variables / objetos locales

  • LIMPIE TODOS SUS DATOS APP

  • Vuelve a persistir todo

Puede iniciar un servicio a medida que se cierre la aplicación. Esto evitaría que los datos se hicieran realmente grandes debido a la pérdida de memoria. Desagradable manera de abordar, pero lo he probado y funciona.

Donot fusionar su interfaz de usuario con Admob, puede ejecutar otro hilo para obtener el anuncio de Admob. También puede actualizar el anuncio en un intervalo de tiempo particular. Eso será más fácil para usted para depurar donde el problema de memoria puede ser.

Gracias Deepak

Básicamente, esto no es realmente un problema. Lo que ocurre es que su actividad está recibiendo onDestroy, haciendo su limpieza, y luego esperando por un GC. Cuando ocurre el GC, ve este viejo contexto y repara todo el gunk subyacente, pero no parece borrar la Activity en ese pase, por eso tu actividad "filtrada" tiene una huella tan pequeña: es Básicamente una cáscara. En el próximo GC paso, se limpiarán.

Usted puede ver esto usted mismo disparando su actividad, retrocediendo (para activar OnDestroy), volviendo al proceso, disparando un GC y un volcado hprof, esperando un poco, luego disparando otro GC y hprof volcado. En el primer vertedero – en mis pruebas al menos – vi resultados similares a los suyos: una actividad extra con una huella de memoria muy pequeña. En el segundo tugurio, vi sólo la actividad actualmente en ejecución.

  • Memoria interna llena de imágenes, probablemente causada por Bitmap.compress (formato, int, flujo)
  • No se puede asignar suficiente memoria en JNI
  • Android ViewPager con imágenes: pérdida de memoria / fallos de la aplicación
  • Android cómo implementar eficientemente el caché de datos y los eventos de cambio de configuración en fragmentos?
  • Reciclaje de bitmaps
  • Android - recuperarse de una condición de memoria baja
  • ¿Por qué Android no limpia la memoria después de terminar la actividad?
  • Fuera de los errores de memoria se producen con un tamaño de montón alto pero tamaño asignado bajo. ¿Por qué?
  • ¿Cómo puedo encontrar fugas de memoria en una aplicación javascript de una sola página?
  • ¿Cuándo es exactamente seguro usar clases anónimas internas?
  • LeakCanary informa actividad filtrada Instancia por implementación anónima de localización
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.