适用于Android的AdMob(SDK 7.0)上的AdActivity泄漏

fra*_*ish 6 android memory-leaks admob

关于带对象的Interstitial广告,我有内存泄漏.每当显示广告时,内存中的对象计数递增1.我在显式调用后检查所有更改.我使用最新版本的一切.AdMobAdActivityAdActivityMATGC

起初,我认为这与我实现UI或项目的方式有关,但创建一个新的空项目会显示相同的泄漏.

此泄漏也存在于之前的Admob SDK(Google Play服务)中,现在它也存在于7.0版本中.

我看到人们试图通过创建一个SingleInstance空活动来解决这类问题,只是为了显示和设置为插页式广告的上下文.我尝试了所有这些并且它们不适合我的情况.有些人提供了帮助,但由于我的应用程序流量,我甚至无法使用它.launchMode在Android中有限制,它对我的​​情况没有帮助.

我已经通知了AdMob团队,但即使他们修复了它,它似乎也不会在短时间内发生,因为他们刚刚发布了7.0版SDK.

我不明白别人怎么不报告这样的泄漏.这对我来说不是一个特例,因为它甚至发生在样本或默认模板上.如果有人以某种方式解决了这个问题(包括丑陋的反思黑客)请分享你的经验.几个月来我一直在努力!真!

AndroidManifest:

<uses-sdk
    android:minSdkVersion="9"
    android:targetSdkVersion="22" />

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

<application
    android:name="MyApplication"
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name" >
    <meta-data
        android:name="com.google.android.gms.version"
        android:value="@integer/google_play_services_version" />

    <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>
    <activity
        android:name="com.google.android.gms.ads.AdActivity"
        android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"
        android:theme="@android:style/Theme.Translucent" />
</application>
Run Code Online (Sandbox Code Playgroud)

主要活动:

package com.example.leaktest1;

import com.google.android.gms.ads.AdListener;
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.InterstitialAd;

import android.app.Activity;
import android.os.Bundle;
public class MainActivity extends Activity {

    private InterstitialAd interstitial=null;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        interstitial= new InterstitialAd(getApplicationContext());
        interstitial.setAdUnitId("YOUR-ADD-ID");

        AdRequest adRequest2 = new AdRequest.Builder()
        // .addTestDevice(AdRequest.DEVICE_ID_EMULATOR)
                .build();

        interstitial.setAdListener(new AdListener() {
            @Override
            public void onAdLoaded() {          
                super.onAdLoaded();

                if(interstitial.isLoaded()){
                    interstitial.show();
                }
            }
        });
        interstitial.loadAd(adRequest2);
    }


    @Override
    protected void onDestroy() {
        if(interstitial!=null){
            interstitial.setAdListener(null);
            interstitial=null;
        }
        super.onDestroy();
    }     
}
Run Code Online (Sandbox Code Playgroud)

布局:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.leaktest1.MainActivity" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" />

</RelativeLayout>
Run Code Online (Sandbox Code Playgroud)
  • 启动应用程序.显示广告时,请使用反压关闭它并再次按回按钮退出应用.
  • 应用程序仍将在内存中,但活动已消失.现在触摸应用图标再次启动活动,它会再次显示广告,像之前一样退出.
  • 导致GC多次并获得堆转储.您将看到有2个AdActivity对象(以及许多其他相关对象).它将根据展示广告的数量继续增长. 在此输入图像描述

以下也不起作用(它仍然泄漏):

/*
interstitial.setAdListener(new AdListener() {
    @Override
    public void onAdLoaded() {          
        super.onAdLoaded();
    }
});*/
interstitial.loadAd(adRequest2);

Runnable r=new Runnable() {
    @Override
    public void run() {
                if(interstitial.isLoaded()){
                    interstitial.show();
                }
}};
new Handler().postDelayed(r,10000);
Run Code Online (Sandbox Code Playgroud)

将代码放在按钮内也不起作用(它仍然泄漏):

Button b = new Button(this);
b.setText("Touch me");
b.setOnClickListener(new OnClickListener() {

    @Override
    public void onClick(View v) {
        if(interstitial.isLoaded()){
            interstitial.show();
        }
    }
});
ViewGroup v = (ViewGroup) this.findViewById(android.R.id.content);
v.addView(b);
Run Code Online (Sandbox Code Playgroud)

泄漏平台和例外: 这种泄漏发生在三星和华硕的各种设备上,各种未修改的(原始固件) Androis系统从2.3到4.4.它也发生在Android模拟器的任何设置上.

(这种泄漏不会出现在有根的Cyanogenmod(Galaxy S3)Android 4.4.4)

UPDATE

如果我使用Activity上下文而不是Application上下文,泄漏不会消失.它也会导致Activity泄漏. 在此输入图像描述

在此输入图像描述

在此输入图像描述