即使父活动暂停,admob AdView使用的WebViewCoreThread也使用高CPU

时间:2012-10-14 16:57:49

标签: android android-webview admob adview

我正在使用Google Admob SDK v6.1.0(https://developers.google.com/mobile-ads-sdk/download),并以编程方式(不是以XML格式)实例化com.google.ads.AdView ,并在我的Activity中动态地将它添加到LinearLayout中。

我的一位用户报告说,当他们在我的Activity中点击Home按钮时(为了让它背景),他们开始看到来自我的应用程序的高CPU使用率。我能够在Jellybean平台上重现这一点,并注意到高CPU使用率的来源是WebViewCoreThread。

My Activity根本不使用任何WebView,但我能够逐步完成Activity的初始化,并注意到当我实例化AdMob AdView对象时,此WebViewCoreThread会启动。作为AdMob引用中的状态,我在Activity的onDestroy()方法中调用此AdView上的destroy()。我改变了我的代码,在我的onPause()方法中调用了AdView.onDestroy()。但似乎没有任何因素导致WebViewCoreThread停止。我猜,如果那个线程坚持下去,我没关系。但是,如果我反复多次启动我的Activity,这个线程开始使用我的CPU的8到25%之间的任何地方,即使我的活动不在前台。

我注意到其他一些用户说你必须调用WebView.onPause()作为纠正措施。 (http://stackoverflow.com/questions/2040963/webview-threads-never-stop-webviewcorethread-cookiesyncmanager-http0-3)但这对我来说不是直接可行的,因为我的网页视图是由AdMob的AdView创建的。我还改变了我的代码,调用.removeAllViews()为mt Admob AdView的容器LinearLayout对象,然后调用System.gc()强制垃圾收集,但似乎没有什么东西可以杀死我的WebViewCoreThread并最终开始吃掉CPU,直到我强行 - 杀死我的应用程序。

为什么AdMob会这样做的任何线索,以及我如何强制杀死此线程?

我附加了一个我创建的类来封装AdView的创建和销毁。我在我的活动的初始化中调用了这个类的getNewAd()方法。我在Activity的onPause()和onDestroy()方法中调用了这个类的removeAd():

package com.shiprack.client;

import com.google.ads.AdRequest;
import com.google.ads.AdSize;
import com.google.ads.AdView;
import com.mobclix.android.sdk.Mobclix;
import com.mobclix.android.sdk.MobclixMMABannerXLAdView;

import android.app.Activity;
import android.view.Gravity;
import android.view.ViewGroup.LayoutParams;
import android.widget.LinearLayout;

public class AdManager {
    public AdManager(EventLog logger, LinearLayout container, Activity activity) {
        _container = container;
        _activity = activity;
        _eventLogger = logger;
    }

    public void setNetwork(int network) {
        _network = network;
    }

    public void getNewAd() {
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT);
        params.gravity = Gravity.CENTER;
        switch (_network) {
            case TrackDatabase.AD_NETWORK_ADMOB: {
                _admobBanner = new AdView(_activity, AdSize.BANNER, "a14dc419375634c");
                _container.addView(_admobBanner, params);
                _admobBanner.loadAd(new AdRequest());
                break;
            }
            case TrackDatabase.AD_NETWORK_MOBCLIX: {
                Mobclix.onCreate(_activity);
                _mobclixBanner = new MobclixMMABannerXLAdView(_activity);
                _container.addView(_mobclixBanner, params);
                _mobclixBanner.getAd();
                break;
            }
        }
    }

    public void removeAd() {
        switch (_network) {
            case TrackDatabase.AD_NETWORK_ADMOB: {
                _admobBanner.destroy();
                break;
            }
            case TrackDatabase.AD_NETWORK_MOBCLIX: {
                _mobclixBanner.cancelAd();
                break;
            }
        }
        _container.removeAllViews();
    }

    private EventLog _eventLogger;
    private LinearLayout _container;
    private Activity _activity;
    private AdView _admobBanner;
    private MobclixMMABannerXLAdView _mobclixBanner;
    private int _network;
}

3 个答案:

答案 0 :(得分:10)

不确定是否还有人需要此信息,但我一直在寻找解决方案。显然AdMob仍然存在缺陷。

唯一的问题是,这将阻止所有WebView在后台运行。如果您的应用依赖于此操作,则只会出现问题。

添加到onPause()

new WebView(this).pauseTimers();

onResume()

new WebView(this).resumeTimers();

这是来自Google员工,声称他们正在调查: https://groups.google.com/d/msg/google-admob-ads-sdk/Qu4G19NFAuI/wcNkoV0AeDUJ

答案 1 :(得分:3)

在admob AdView对象上调用destroy()之后,我现在将引用设置为null,这将删除对AdView的所有引用,可能导致它被垃圾收集,从而避免任何WebViewCoreThreads无限期地运行。总的来说,我不喜欢这种方法 - 这种清理工作应该在AdMob销毁中处理。或者实际上,我甚至不必调用destroy() - 它会减慢我在onPause上的活动。

但是很大的缺点是:在我的应用程序中按下后面或主页按钮时,我的很多用户抱怨速度很慢。显然,这是因为在调用admob destroy()时花在onPause()方法上的时间。长期解决方案是使用Fragments和ActionBar,而不必创建Admob横幅的多个副本(每个活动中有一个)

答案 2 :(得分:3)

PZolee在他的博客中发表了关于这个主题和建议的解决方案:https://pzoleeblogen.wordpress.com/2014/07/08/android-how-to-solve-adview-cpu-consuming/

我进一步调查了这一点(在博客文章的评论中记录了我的挣扎)并得出以下结论:

  1. 的确,只调用adView.pause();即使应用处于后台并且广告不可见,也不会阻止Google广告组件消耗CPU。
  2. 在我们的adView中查找所有WebView并在其上调用onPause()和onResume()WevView方法并不能解决不必要的CPU消耗问题。
  3. 作为上述帖子的作者,只有对WebView pauseTimers()和resumeTimers()方法的调用才能阻止不必要的CPU消耗。
  4. 递归查找所有WebView并在所有这些WebView上调用pauseTimers()和resumeTimers()是不必要的,因为一个这样的调用“暂停(或恢复 - )所有WebView的所有布局,解析和JavaScript计时器。 (在一个过程中 - g。)“ - 请参阅WebView组件文档。
  5. 如果您在应用中的任何其他位置使用WebView - 可能在其他活动中,您必须为其恢复Timers(),否则它将无法正常工作。另外,请注意,WevView可能会暂时构建,并由您在项目中使用的某些库函数使用,而无需您明确了解它。它可以是例如提示登录某个网站,社交网络等。如果在您的进程中调用了pauseTimers()并且您没有恢复它们,那么这样的WebView可能无法正常工作。尽可能小心并尽力测试。
  6. 令人遗憾的是,谷歌和AdMob用他们的广告组件处理了我们这样一个令人讨厌的惊喜(即使你背景应用程序,隐藏他们的组件,甚至用他们自己的API调用暂停()它,CPU也会持续消耗......