02/15
2017

Android 解决 GMS/Firebase AdView 启动慢的性能问题及 AdView 共用问题

Google Ads(Google 广告) Android 版的性能及其差,com.google.android.gms.ads.AdView 初始化已经赶上 WebView 了。如果 Activity 在 layout 中添加了 AdView 那就等着长时间的黑屏吧,在 Nexus 6P 上都需要好几秒的启动时间。

 

另外 Firebase 文档中建议每个 AdView 用不同的 adUnitId,这样如果希望方便在所有 Activity 中统一添加 AdView 就比较麻烦了,这里分享一种方法解决这个问题,同时能一定程度上缓解 AdViews 性能差带来的启动延时。

 

一. 解决 AdView 性能差带来的启动延时问题

简单实例代码如下,完整代码可见第二部分介绍:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_entrance);
    ……

    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            if (isDestroryed) {
                return;
            }

            try {
                adView = new AdView(getApplicationContext());
                adView.setAdUnitId(adUnitId);
                adView.setAdSize(AdSize.SMART_BANNER);
                AdRequest.Builder adBuilder = new AdRequest.Builder();
                if (BuildConfig.DEBUG) {
                    adBuilder.addTestDevice("CAEC00A596FCCFC2D838832FBBACD8DB");
                }
                adLayout.addView(adView);
                adView.loadAd(adBuilder.build());
                adView.bringToFront();
            } catch (Throwable e) {
                // if exception, not show ad
                adLayout.setVisibility(View.GONE);
            }
        }
    }, 800);
}

不通过布局中添加 AdView 而是在代码中主动创建 AdView,并延时添加到布局中。

 

如果一定要在布局中添加也可以通过开始将 AdView 设置为 gone 或者 viewstub 引用公共广告布局,后期再去主动展示。

 

二. AdView 相关代码复用,同时 AdView 用不同的 adUnitId

1. 定义公共部分——公共广告布局

当然在开始前你是需要添加

compile 'com.google.firebase:firebase-ads:9.6.1'

等依赖以及 gradle plugin 的,具体请参考官方文档。

 

添加布局文件 layout_ad.xml,作为公共广告布局单元,如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/ad_layout"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:layout_centerHorizontal="true"
    android:orientation="vertical">

    <!-- AdView will be added here -->
</LinearLayout>

其实就是一个空的 LinearLayout,后面用来存放 AdView。

 

2. 定义公共部分——Java 公共部分之BaseActivity

在 BaseActivity 中定义 initAdLayout(…) 函数,并绑定 AdView 生命周期。

public class BaseActivity extends Activity {

    private AdView adView;
    private boolean isDestroryed = false;

    protected boolean initAdLayout(final String adUnitId) {
        final ViewGroup adLayout = (ViewGroup) findViewById(R.id.ad_layout);
        if (adLayout == null) {
            return false;
        }

        adLayout.setVisibility(View.VISIBLE);
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                if (isDestroryed) {
                    return;
                }

                try {
                    adView = new AdView(getApplicationContext());
                    adView.setAdUnitId(adUnitId);
                    adView.setAdSize(AdSize.SMART_BANNER);
                    AdRequest.Builder adBuilder = new AdRequest.Builder();
                    if (BuildConfig.DEBUG) {
                        adBuilder.addTestDevice("CAEC00A596FCCFC2D838832FBBACD8DB");
                    }
                    adLayout.addView(adView);
                    adView.loadAd(adBuilder.build());
                    adView.bringToFront();
                } catch (Throwable e) {
                    // if exception, not show ad
                    adLayout.setVisibility(View.GONE);
                }
            }
        }, 800);
        return true;
    }

    @Override
    protected void onResume() {
        super.onResume();

        if (adView != null) {
            adView.resume();
        }
    }

    @Override
    protected void onPause() {
        if (adView != null) {
            adView.pause();
        }

        super.onPause();
    }

    @Override
    protected void onDestroy() {
        if (adView != null) {
            adView.destroy();
        }

        isDestroryed = true;
        super.onDestroy();
    }
}

initAdLayout(…) 函数主要就是新建 AdView 添加到之前的 LinearLayout 中。这个过程是被延时了 800ms 的,为了防止影响初始化速度

 

3. 引用——布局中添加公共广告布局

现在在你需要添加广告的布局中引用公共广告布局

 <include android:id="@+id/ad_layout"
      layout="@layout/layout_ad"/>

 

4. 引用——Java 中初始化广告

需要添加广告的 Activity 继承自 BaseActivity,在 onCreate 方法结束前调用 initAdLayout(String adUnitId) 方法。
而不需要添加广告的 Activity 继承自 BaseActivity 不调用 initAdLayout(…) 函数即可。

您可以使用这些 HTML 标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

One thought on “Android 解决 GMS/Firebase AdView 启动慢的性能问题及 AdView 共用问题