Admob的内存泄漏 - 避免使用空活动内存、Admob

2023-09-08 15:50:37 作者:女人毁在棒子上。

我们的应用越来越命中pretty的很难受内存泄漏。我发现,根本原因是AdMob的AD浏览报保持引用旧的活动。现在的问题是pretty的有据可查的问题的Andr​​oid AdMob的会导致内存泄漏?并在sublinks的意见/答案。我已经注意到这个问题是不是在ICS明显的GC最终清理WebViews与引用的活动。然而,我的HTC EVO 3D运行的股票姜饼从来没有收集活动,并考虑到因OOM错误强制关闭报告的数量,这个问题是非常wides $ P $垫,我们的应用程序。

Our app is getting hit pretty hard by a memory leak. I've found that the root cause is the AdMob AdView keeping references to old activities. The problem is pretty well documented in question Android AdMob causes memory leak? and the sublinks in the comments/answers. I have noticed that the problem is not apparent in ICS as the GC eventually cleans up the WebViews with references to activities. However, my HTC EVO 3D running stock gingerbread never collects the activities and considering the number of force close reports due to OOM errors, the problem is very widespread for our app.

我想遵循TacB0sS提供的解决方案, http://stackoverflow.com/a/8364820/684893 。他建议创建一个空的活动,并使用相同的活动每个AdMob的AD浏览报。泄漏将被包含,因为AD浏览报只会保持活动,一个空的活动。他提供的code的活动本身以及如何引用它,但我在如何真正整合到我们的应用程序亏损。他的code从不要求AdMob提供的SDK什么,据我可以告诉。

I would like to follow the solution provided by TacB0sS, http://stackoverflow.com/a/8364820/684893. He has suggested to create an empty activity and use that same activity for each AdMob AdView. The leak would be contained since AdView will only keep alive that one empty activity. He provided the code for the activity itself and how to reference it but I'm at a loss of how to actually integrate it into our app. His code never calls anything from AdMob SDK as far as I can tell.

我们正在使用AD浏览报在XML的布局,所以我们不会做动态与code如呼叫loadAd()的广告什么。我们所有的版面与广告依靠广告中的XML是因为他们制定了相对于它。我的两个问题是这样,我该如何实现TacB0sS code,我怎么能留住我的XML布局的关系,如果我们要切换到code创建XML布局?

We are currently using AdView in the XML layouts so we don't dynamically do anything with the ads in code such as call loadAd(). All of our layouts with ads rely on the ad being in the XML since they are laid out relative to it. My two questions are thus, how do I implement TacB0sS code and how can I retain my XML layout relationships if we have to switch to creating the XML layouts in code?

更新3/6:

感谢亚当(TacB0sS)为响应!我没有问题,切换到创造code中的广告,但我仍然有制作广告时,使用虚拟活动的难度。我的code当前是:

Thanks Adam (TacB0sS) for responding! I have no problem switching to creating the Ad in code but I am still having difficulty using your dummy activity when creating Ads. My code currently is:

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);

我已经把这个code在我最初的活动onCreate方法。我得到一个强制关闭在那里我创建AD浏览报,AD浏览报AD浏览报=新的AD浏览报(...)的路线。堆栈跟踪片断:

I have placed this code in the onCreate method of my initial activity. I get a force close on the line where I create the AdView, "AdView adView = new AdView(...)". Stacktrace snippet:

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

什么是正确的方法来初始化AdMobActivity和创建AD浏览报时引用了吗?再次感谢!

What is the proper way to initialize your AdMobActivity and reference it when creating the AdView? Thanks again!

更新2 3/6:

我想通了,我的问题创建活动。我有你的解决方案,全面落实和最好的部分是它的实际上解决了我的内存泄漏。在这个问题上花费了两周之后,我很高兴,它的解决。下面是完整的步骤,我用:

I figured out my problems creating the activity. I have your solution fully implemented and the best part is that it actually solves my memory leak. After spending two weeks on this problem, I am so happy that it's resolved. Here are the full steps I used:

创建一个新的活动称为AdMobActivity:

Create a new activity called 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);
    }
}

以下内容添加到您的Andr​​oidManifest.xml

Add the following to your AndroidManifest.xml

<activity android:name="org.udroid.wordgame.AdMobActivity"
    android:launchMode="singleInstance" />

您需要在尝试加载任何广告之前初始化虚拟AdMobActivity。本次活动将不包含任何东西。这将显示一秒钟,然后关闭,返回回你把它称为活动中要加载广告,因为它必须在时间上完全初始化之前使用相同的活动不能创建它。我在一个闪负荷屏幕活动的onCreate初始化它的主要活动,其中包含一个广告开始之前:

You need to initialize the dummy AdMobActivity before trying to load any ads. This activity won't contain anything. It will be displayed for a split second and then close, returning back to the activity you called it in. You can not create it in the same activity you want to load Ads since it must be fully initialized in time before using. I initialize it in a splash load screen activity's onCreate before the main activity that contains an ad starts:

// 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);
}

现在你已经准备好创建于code广告。添加以下的LinearLayout以你的XML活动的布局。调整围绕此布局所需的其它意见。我们创建AD浏览报于code将被放置在此视图中。

Now you are ready to create ads in code. Add the following LinearLayout to your XML activity layout. Align all other views necessary around this layout. The AdView we create in code will be placed inside this view.

<LinearLayout
android:id="@+id/adviewLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true" />

在要加载的广告活动,为AD浏览报创建一个全局变量:

In the activity you want to load an ad, create a global variable for the AdView:

AdView adView;

在我们的应用程序,我们加载不同的布局的时候,手机旋转。 Therfore,我呼吁每一个旋转以下code。如有必要,它创建了AD浏览报,并把它添加到adviewLayout。

In our app, we load different layouts when the phone rotates. Therfore, I call the following code on every rotate. It creates the adView if necessary and adds it to the 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

最后,确保你在活动中调用adView.destroy()的onDestroy()方法:

Lastly, make sure you call adView.destroy() in the activities onDestroy() method:

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

任何人读这一点,请记住,这是亚当的解决方案(TacB0sS),不是我的。我只是想提供完整的实施细则,使其更容易为他人实施。这AdMob的错误是运行pre-蜂窝和亚当的解决方案是我能找到规避它的最好的东西应用程序的一大问题。 和它的作品!

推荐答案

Ravishi,

您的问题是给点意见,我也没能解决它在我的解决方案。据我可以告诉的解决方案,我发现只能动态地,在那里你可以选择你的活动,同时调用SDK ...

Your question is to the point, and I have failed to address it in my solution. As far as I can tell the solution I've found works only dynamically, where you can choose your activity while calling the sdk...

我的code没有一个用例中的原因,是因为我的解决方案是一个比较复杂一点再一个我presented,涉及整个包装框架,我围绕Android框架,其中,所述AdMob的相对于应用程序是通过中间模块,这使该广告动态使用单个活动实例

The reason my code does not have a use example, is because my solution is a bit more complicated then the one I presented, involving an entire wrapping framework I've build around the Android framework, where the AdMob relation to the application is via an intermediate module, which puts the ad dynamically using the single activity instance.

我真的怀疑你能避免内存泄漏简单地采用了Android XML。

I really doubt you can avoid the memory leak simply using the Android XML.

在任何情况下,如果你是到内存泄漏的生意,你不妨看看你的AsyncTask的使用......它也有它自己的内存泄漏问题......所以这里是我的解决方案

In any case, if you are into the memory leak business, you might as well check out your AsyncTask usage... it also has its own memory leak behavior... so here is my solution

好运...

- 更新 - 14年7月10日

-- UPDATE -- 07/10/14

最近有人upvoted我的答案,其propustorase,这个问题仍然存在,它一直以来我原来的答复近三年来,人们仍然有内存泄漏在他们的应用程序,因为AdMob的的...从谷歌......,使得安卓....

Someone just upvoted my answer, its propustorase that this issue still exists, it has been almost three years since my original answer, and people still have memory leaks in their apps because of AdMob... from Google... that made Android....

反正,我只是想补充一点,你应该设置AdMobActivity透明的主题,将prevent闪烁。

Anyway, I just wanted to add that you should probably set the theme of the AdMobActivity to transparent, it would prevent the flickering.

亚当。