android memory memory-leaks admob

Android AdMob provoca pérdida de memoria?



memory memory-leaks (8)

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

He limitado la pérdida 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 un anuncio adicional utilizando 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 fuga porque solo se utiliza una instancia de actividad para crear todos los anuncios, por lo que no hay más fugas de actividad, más el hecho de que la actividad está completamente vacía. .

NOTA: debe llamar al método startAdMobActivity desde la actividad principal de la aplicación en el método de creación .

Adán.

ACTUALIZAR

Esta solución solo funciona si crea el anuncio dinámicamente, lo agrega al diseño con código ... y no se olvida de destruirlo en el Activity.onDestroy ().

He integrado AdMob v4.1.0 en mi aplicación y parece haber causado una gran pérdida de memoria (bastante seguro de que ya ocurrió en 4.0.4).

Para aislar el problema, creé un nuevo proyecto con un diseño lineal en blanco y le agregué AdView (esto es en realidad una copia y pegado del código de muestra proporcionado por AdMob). Ver 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, cuando ejecuto esta aplicación, puedo ver que se llama tanto a onPause como a onDestory y se finaliza la actividad, PERO el problema es que nunca estará disponible para el GC ya que hace que el InputMethodManager tenga una referencia a la actividad (ver imagen tomada de la salida de HPROF después de que la actividad fue destruida):

Una vez que elimine el código relacionado con AdView (y nuevamente, este es el ÚNICO código de esta aplicación), el problema desaparece:

EDITAR: También se intentó eliminar TODO el código de onCreate y se actualizó main.xml para que contenga lo siguiente (aún obtenga 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 ????


Básicamente, esto no es realmente un problema. Lo que está sucediendo es que su actividad está recibiendo onDestroy, haciendo su limpieza y luego esperando una ejecución de GC. Cuando sucede el GC, ve este viejo contexto y limpia toda la suciedad subyacente, pero no parece borrar la Actividad en ese pase, es por eso que su Actividad "filtrada" tiene una huella tan pequeña: es básicamente una concha. En la próxima pasada de GC, se limpiará.

Puede ver esto usted mismo activando su actividad, retrocediendo (para desencadenar onDestroy), volviendo al proceso, disparando un GC y un volcado hprof, esperando un poco, luego disparando otro GC y otro volcado hprof. En el primer volcado, al menos en mis pruebas, vi resultados similares a los suyos: una actividad adicional con una huella de memoria muy pequeña. En el segundo volcado, solo vi la actividad actualmente en ejecución.


Descubrí ese llamado:

mAdView.destroy();

Antes de dejar la actividad me resuelve la fuga.

Aquí es cómo declaro los anuncios de banner 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" />

Obtenga una referencia al banner de admob en onCreate (): -

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

y destruirlo en ondestroy () de la actividad: -

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


Estoy enfrentando el mismo problema. Lo único que me ayudó fue su System.exit (0). No me gusta, pero es la única manera que he encontrado.
AdMob solo permanece en la RAM 4 y no permite que mi aplicación termine correctamente. Cuando reinicio mi aplicación, el sistema operativo solo genera esa aplicación de no-muertos y pronto causa la excepción de falta de memoria.
Tema de mi foro de soporte de AdMob - no hay soporte hasta ahora. Parece que no le importa.


Estoy usando "play-services-ads: 7.5.0" y no fue necesario crear AdMobActivity. Funcionó por:

Creando adView dinámicamente

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

Eliminar todas las vistas de linearLayout al destruir y destruir adView

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

Lamentablemente intersticial todavía gotea


No fusione su interfaz de usuario con Admob, puede ejecutar otro hilo para obtener un anuncio de Admob. También puede actualizar el anuncio en un intervalo de tiempo determinado. Será más fácil para usted depurar el problema de la memoria.

Gracias Deepak


Otra respuesta que aborda este problema, aunque es un dolor hacerlo, es seguir los siguientes pasos.

  • no repare todos los datos que se necesitan de sharedPreferences o cualquier otro tipo de persistencia en el almacenamiento,
    almacenar esos valores en variables / objetos locales

  • Limpie todos los datos de su aplicación

  • volver a persistir todo

Podría iniciar un servicio ya que su aplicación se está cerrando para hacer esto. Esto evitaría que los datos se vuelvan realmente grandes debido a la pérdida de memoria. Una forma desagradable de abordarlo, pero lo he probado y funciona.


Una forma de solucionar este problema es crear una sola instancia de adview utilizando su actividad base de su aplicación. Agregue esta vista a cualquier actividad que desee, pero recuerde eliminarla en las actividades del método de destrucción.

De esta manera, la vista previa solo filtra la actividad base, que casi nunca debería 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(); }