Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Google Ads interrupt the app. Slow down fps

Tags:

I use AdView mAdView and the last updated libraries.

I placed the AdView into my layout (as shown in the examples):

<com.google.android.gms.ads.AdView
    xmlns:ads="http://schemas.android.com/apk/res-auto"
    android:id="@+id/adView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    ads:adSize="BANNER"
    ads:adUnitId="@string/banner_ad_unit_id">
</com.google.android.gms.ads.AdView>

Then I identify it and try to load a new ad in the onCreate() method:

AdView mAdView = findViewById(R.id.adView);
AdRequest adRequest = new AdRequest.Builder().build();
mAdView.loadAd(adRequest);

But my layout has some animated objects. This animation is freezing (skipping some frames) while new ad is become visible.

We can't catch the same problem with the disabled Internet (it disables ads and not affect lags).

I'm trying to show the problem with my own record (GIF can't show that completely):

https://www.youtube.com/watch?v=adH2Mn79O7w

How can I remove ads' lags and make the user experience better?

like image 889
Egor Avatar asked Feb 07 '20 11:02

Egor


1 Answers

This is a known issue, which has been discussed many times on the net, is enough to search by the words "AdMob fps drop" and the like.

The root of the problem here, most likely, is that running AdMob requires significant resources, which is why the animation starts to stall. As one solution, you can show ads with some delay:

Handler handler = new Handler ();
handler.postDelayed (new Runnable () {
     @Override
     public void run () {
          AdRequest bannerRequest = new AdRequest.Builder (). Build ();
          mAdView.loadAd (bannerRequest);
     }
}, 2000);

You can make the delay not fixed, but bind it to user actions. For example, start downloading ads the moment after the user has stopped scrolling the screen.

Another solution is to disable graphics acceleration for ads by manipulating the LAYER_TYPE_SOFTWARE property.

mAdView.setAdListener(new AdListener(){
    @Override
    public void onAdLoaded(){
        runOnWebView(mAdView, new WebViewAction(){
            @Override
            public void run(WebView view){
                view.setLayerType(View.LAYER_TYPE_HARDWARE, null);
                view.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
            }
        });
    }
});

For such a solution, it is necessary to implement the following interface:

private void runOnWebView (View view, WebViewAction action) {
    if (view instanceof WebView){
        action.run((WebView)view);
        return;
    }

    if (view instanceof ViewGroup) {
        final ViewGroup parent = (ViewGroup)view;

        for (int i = 0; i < parent.getChildCount(); i++) {
            runOnWebView(parent.getChildAt(i), action);
        }
    }
}

private interface WebViewAction{
    void run(WebView view);
}

Similarly, you can turn off the acceleration for some Activity:

<activity 
    android:hardwareAccelerated = "false"
    android:softwareAccelerated = "false" />
like image 161
Egor Avatar answered Sep 30 '22 19:09

Egor