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:
- Android WebView - Fuga de memoria de JavaScript
- Aumento de la memoria de YouWave
- ByteBuffer no libera memoria
- Escaneo y edición de valores de memoria de aplicación de Android mediante programación
- Agregar una ScrollView simple a la Galería provoca una pérdida de memoria
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):
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:
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 ????
- Encontrar el mecanismo de caché de memoria "asesino" para Android
- FragmentStatePagerAdapter OutOfMemoryError
- InputMethodManager contiene referencia al tabhost - Memory Leak - OOM Error
- ¿Los oyentes crean fugas de memoria si no se eliminan de una actividad destruida?
- Pérdida de memoria a pesar de usar weakreference
- Android BitmapRegionDecoder Fuga de memoria
- Fuga de memoria de Android Drawables
- Fuga de memoria durante el uso de anuncios intersticiales de Admob
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.
- Tipo de entrada para EditText en la pantalla de preferencias?
- Cómo comprobar si mi actividad es la actividad actual que se ejecuta en la pantalla