15

我正在使用 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。

我的 Activity 根本不使用任何 WebView,但我能够逐步完成 Activity 的初始化,并注意到当我实例化 AdMob AdView 对象时,此 WebViewCoreThread 启动。正如 AdMob 引用中的状态,我在我的 Activity 的 onDestroy() 方法中对这个 AdView 调用了 destroy()。我也更改了我的代码,在我的 onPause() 方法中调用 AdView.onDestroy()。但似乎没有什么会导致 WebViewCoreThread 停止。我想,如果那个线程粘在我身边,我会没事的。但是如果我一遍又一遍地启动我的活动,这个线程开始使用我的 CPU 的 8% 到 25% 之间的任何地方,即使我的活动不在前台。

我注意到其他一些用户说您必须调用 WebView.onPause() 作为纠正措施。(http://stackoverflow.com/questions/2040963/webview-threads-never-stop-webviewcorethread-cookiesyncmanager-http0-3) 但这对我来说是不可能的,因为我的网络视图是由 AdMob 的 AdView 创建的。我还更改了我的代码,为 mt Admob AdView 的容器 LinearLayout 对象调用 .removeAllViews(),然后调用 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;
}
4

3 回答 3

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

于 2014-03-08T06:43:13.723 回答
3

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

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

  1. 事实上,只调用 adView.pause(); 即使应用处于后台且广告不可见,也不会阻止 Google Ads 组件消耗 CPU。
  2. 在我们的 adView 中查找所有 WebView 并对其调用 onPause() 和 onResume() WevView 方法并不能解决不必要的 CPU 消耗问题。
  3. 只有上述帖子的作者提出的对 WebView pauseTimers() 和 resumeTimers() 方法的调用才能停止不必要的 CPU 消耗。
  4. 递归查找所有 WebView 并在所有 WebView 上调用 pauseTimers() 和 resumeTimers() 是不必要的,因为这样的调用“暂停(或恢复 - g.)所有 WebView 的所有布局、解析和 JavaScript 计时器。(在一个进程内 - g.)” - 请参阅 WebView 组件文档。
  5. 如果您在应用程序的其他任何地方使用 WebView - 也许在其他活动中,您必须为它 resumeTimers() ,否则它将无法正常工作。另外,请注意,WevView 可能是临时构建的,并由您在项目中使用的某些库函数使用,而您并不明确知道它。例如,它可能是登录某个网站、社交网络等的提示。如果在您的进程中某处调用了 pauseTimers() 并且您没有恢复它们,则此类 WebView 可能再次无法正常工作。尽可能小心并进行测试。

真可惜,Google 和 AdMob 用他们的广告组件给我们带来了如此令人讨厌的惊喜(即使你在后台运行应用程序、隐藏他们的组件,甚至用他们自己的 API 调用 pause() 它也会持续消耗 CPU...</p>

于 2015-01-29T16:17:31.413 回答
3

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

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

于 2012-10-23T16:35:30.940 回答