Nuestra aplicación está siendo golpeada por una fuga de memoria. Descubrí que la causa principal es AdMob AdView manteniendo referencias a actividades anteriores. El problema está bastante bien documentado en la pregunta Android AdMob causes memory leak? y los subtítulos en los comentarios/respuestas. Me di cuenta de que el problema no es evidente en ICS, ya que el GC finalmente limpia las WebView con referencias a actividades. Sin embargo, mi pan de jengibre running EVO 3D de HTC nunca recopila las actividades y teniendo en cuenta la cantidad de informes de cierre forzado debido a errores de OOM, el problema está muy extendido en nuestra aplicación.Admob Memory Leak - evitando el uso de la actividad vacía
Me gustaría seguir la solución provista por TacB0sS, https://stackoverflow.com/a/8364820/684893. Él sugirió crear una actividad vacía y usar esa misma actividad para cada AdView de AdMob. La fuga estaría contenida ya que AdView solo mantendrá viva esa actividad vacía. Proporcionó el código para la actividad en sí y cómo hacer referencia a ella, pero no entiendo cómo integrarla en nuestra aplicación. Su código nunca llama nada desde el SDK de AdMob hasta donde yo sé.
Actualmente, estamos utilizando AdView en los diseños XML, por lo que no hacemos ningún esfuerzo dinámico con los anuncios en el código, como por ejemplo, invocar loadAd(). Todos nuestros diseños con anuncios se basan en que el anuncio se encuentra en el XML, ya que están diseñados en relación con él. Mis dos preguntas son, entonces, ¿cómo implemento el código TacB0sS y cómo puedo conservar mis relaciones de diseño XML si tenemos que cambiar a la creación de diseños XML en el código?
actualización 3/6:
Gracias Adam (TacB0sS) para responder! No tengo problemas para pasar a crear el anuncio en el código, pero sigo teniendo dificultades para usar tu actividad ficticia al crear anuncios. Mi código actualmente es:
AdMobActivity adActivity = new AdMobActivity();
adActivity.startAdMobActivity(this);
// Create an ad with the activity reference pointing to dummy activity
AdView adView = new AdView(adActivity.AdMobMemoryLeakWorkAroundActivity, AdSize.IAB_BANNER, "myAdUnitID");
// Create an ad request.
AdRequest adRequest = new AdRequest();
// add the ad to the layout and request it to be filled
RelativeLayout root_main = (RelativeLayout) findViewById(R.id.root_main);
root_main.addView(adView);
adView.loadAd(adRequest);
He colocado este código en el método onCreate de mi actividad inicial. Obtengo una fuerza cercana en la línea donde creo AdView, "AdView adView = new AdView (...)". StackTrace fragmento:
03-06 00:34:28.098 E/AndroidRuntime(16602): java.lang.RuntimeException: Unable to start activity ComponentInfo{org.udroid.wordgame/org.udroid.wordgame.MainMenu}: java.lang.NullPointerException
03-06 00:34:28.098 E/AndroidRuntime(16602): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1830)
(...)
03-06 00:34:28.098 E/AndroidRuntime(16602): Caused by: java.lang.NullPointerException
03-06 00:34:28.098 E/AndroidRuntime(16602): at android.content.ContextWrapper.getApplicationContext(ContextWrapper.java:100)
03-06 00:34:28.098 E/AndroidRuntime(16602): at com.google.ads.AdView.<init>(SourceFile:78)
03-06 00:34:28.098 E/AndroidRuntime(16602): at org.udroid.wordgame.MainMenu.onCreate**(MainMenu.java:71)** <- Line that creates the new AdView
¿Cuál es la forma correcta para inicializar su AdMobActivity y hacer referencia a ella cuando se crea el AdView? ¡Gracias de nuevo!
Actualización 2 3/6:
me di cuenta de mis problemas al crear la actividad. Tengo su solución completamente implementada y la mejor parte es que realmente resuelve mi pérdida de memoria. Después de pasar dos semanas en este problema, estoy tan feliz de que se haya resuelto. Estos son los pasos completos que he utilizado:
crear una nueva actividad llamada AdMobActivity:
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);
Log.i("CHAT", "in onCreate - AdMobActivity");
finish();
}
public static final void startAdMobActivity(Activity activity) {
Log.i("CHAT", "in startAdMobActivity");
Intent i = new Intent();
i.setComponent(new ComponentName(activity.getApplicationContext(), AdMobActivity.class));
activity.startActivity(i);
}
}
Añadir lo siguiente a su AndroidManifest.xml
<activity android:name="org.udroid.wordgame.AdMobActivity"
android:launchMode="singleInstance" />
Es necesario inicializar el AdMobActivity maniquí antes de intentar para cargar cualquier anuncio Esta actividad no contendrá nada. Se mostrará durante una fracción de segundo y luego se cerrará, volviendo a la actividad en la que lo llamó. No puede crearlo en la misma actividad en la que desea cargar anuncios, ya que debe estar completamente inicializado a tiempo antes de usarlo.Me inicializarlo en onCreate de una actividad de la pantalla de bienvenida de carga antes de la actividad principal que contiene un anuncio comienza:
// Start the dummy admob activity. Don't try to start it twice or an exception will be thrown
if (AdMobActivity.AdMobMemoryLeakWorkAroundActivity == null) {
Log.i("CHAT", "starting the AdMobActivity");
AdMobActivity.startAdMobActivity(this);
}
Ahora ya está listo para crear anuncios en el código. Agregue el siguiente LinearLayout a su diseño de actividad XML. Alinee todas las demás vistas necesarias alrededor de este diseño. El AdView que creamos en el código se colocará dentro de esta vista.
<LinearLayout
android:id="@+id/adviewLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true" />
En la actividad que desea cargar un anuncio, crear una variable global para AdView:
AdView adView;
En nuestra aplicación, cargamos diferentes diseños al girar el teléfono. Por lo tanto, llamo al siguiente código en cada giro. Crea adView si es necesario y lo agrega a adviewLayout.
// DYNAMICALLY CREATE AD START
LinearLayout adviewLayout = (LinearLayout) findViewById(R.id.adviewLayout);
// Create an ad.
if (adView == null) {
adView = new AdView(AdMobActivity.AdMobMemoryLeakWorkAroundActivity, AdSize.BANNER, "<ADUNITID>");
// Create an ad request.
AdRequest adRequest = new AdRequest();
// Start loading the ad in the background.
adView.loadAd(adRequest);
// Add the AdView to the view hierarchy. The view will have no size until the ad is loaded.
adviewLayout.addView(adView);
}
else {
((LinearLayout) adView.getParent()).removeAllViews();
adviewLayout.addView(adView);
// Reload Ad if necessary. Loaded ads are lost when the activity is paused.
if (!adView.isReady() || !adView.isRefreshing()) {
AdRequest adRequest = new AdRequest();
// Start loading the ad in the background.
adView.loadAd(adRequest);
}
}
// DYNAMICALLY CREATE AD END
Por último, asegúrese de que usted llama adView.destroy() en las actividades OnDestroy() Método:
@Override
protected void onDestroy() {
adView.destroy();
super.onDestroy();
}
Cualquier otra persona que lee esto, por favor recuerde que esta es la solución de Adam (TacB0sS), no es mio. Solo quería proporcionar los detalles completos de implementación para que otros los implementen más fácilmente. Este error de AdMob es un gran problema para las aplicaciones que ejecutan pre-honeycomb y la solución de Adam es lo mejor que pude encontrar para eludirlo. ¡Y funciona!
funciona como un encanto !! ¡Gracias a los dos @ravishi y @ TacB0sS !! – Regis
Hola, ravishi ... Tengo problemas con esta solución. Podrías ayudarme. Esta es mi pregunta http://stackoverflow.com/questions/15583994/activity-does-not-launch-from-the-recent-activities-android –
¿Hay un enlace al código completo @ravishi? –