系列文章目录
提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加
例如:第一章 Python 机器学习入门之pandas的使用
文章目录
- 系列文章目录
- 前言
- 一、AdLoader$Builder广告构建ANR
- 二、AdView布局动态创建案例
- 总结
前言
一、AdLoader$Builder广告构建ANR
trace.txt日志如下:
"main" tid=1 Native
#00 pc 0x000000000009aff8 /apex/com.android.runtime/lib/bionic/libc.so (__ioctl+8)
#01 pc 0x0000000000068f6b /apex/com.android.runtime/lib/bionic/libc.so (ioctl+26)
#02 pc 0x0000000000039bdb /system/lib/libbinder.so (android::IPCThreadState::talkWithDriver(bool)+238)
#03 pc 0x000000000003a815 /system/lib/libbinder.so (android::IPCThreadState::waitForResponse(android::Parcel*, int*)+32)
#04 pc 0x000000000003a5eb /system/lib/libbinder.so (android::IPCThreadState::transact(int, unsigned int, android::Parcel const&, android::Parcel*, unsigned int)+126)
#05 pc 0x00000000000352e7 /system/lib/libbinder.so (android::BpBinder::transact(unsigned int, android::Parcel const&, android::Parcel*, unsigned int)+98)
#06 pc 0x00000000000c964f /system/lib/libandroid_runtime.so (android_os_BinderProxy_transact(_JNIEnv*, _jobject*, int, _jobject*, _jobject*, int)+82)
at android.os.BinderProxy.transactNative (BinderProxy.java)
at android.os.BinderProxy.transact (BinderProxy.java:545)
at android.database.BulkCursorProxy.getWindow (BulkCursorProxy.java:165)
at android.database.BulkCursorToCursorAdaptor.onMove (BulkCursorToCursorAdaptor.java:82)
at android.database.AbstractCursor.moveToPosition (AbstractCursor.java:248)
at android.database.AbstractCursor.moveToFirst (AbstractCursor.java:270)
at android.database.CursorWrapper.moveToFirst (CursorWrapper.java:75)
at com.google.android.gms.dynamite.DynamiteModule.zzb (com.google.android.gms:play-services-basement@@18.1.0:11)
at com.google.android.gms.dynamite.DynamiteModule.zza (com.google.android.gms:play-services-basement@@18.1.0:47)
at com.google.android.gms.dynamite.DynamiteModule.getRemoteVersion (com.google.android.gms:play-services-basement@@18.1.0:1)
at com.google.android.gms.ads.internal.client.zzav.zzd (com.google.android.gms:play-services-ads-lite@@21.3.0:5)
at com.google.android.gms.ads.internal.client.zzau.zzc (com.google.android.gms:play-services-ads-lite@@21.3.0:2)
at com.google.android.gms.ads.AdLoader$Builder.<init> (com.google.android.gms:play-services-ads-lite@@21.3.0:3)
at com.xxx.xx.adc.request.platform.go.GoNativeAd.load (GoNativeAd.java:67)
at com.xxx.xx.adc.process.displaying.AdDisplayingProcess.loadAd (AdDisplayingProcess.java:223)
结合日志查看GoNativeAd代码,逻辑如下:
public void load{
...
mAdLoader = new AdLoader.Builder(context, id)
.forNativeAd(nativeAd -> {
mNativeAd = nativeAd;
...
})
.withAdListener().build();
...
}
可知最终阻塞点为AdLoader.Builder,由于Google广告源码混淆了,通过调用堆栈追踪,其内部执行了数据耗时操作:
查看Google广告官方Demo相关issue问题:
https://groups.google.com/g/google-admob-ads-sdk/c/fXW1yZnGt6g/m/H_YTBDVhAQAJ
由issue也可以验证,AdLoader$Builder的创建为耗时方法,应该放到后台子线程进行。
故修改方案为将AdLoader$Builder放到子线程中创建,创建完成后再回到主线程使用。
二、AdView布局动态创建案例
trace.txt日志如下:
"main" tid=1 Native
#00 pc 0x000000000009bad4 /apex/com.android.runtime/lib64/bionic/libc.so (__ioctl+4)
#01 pc 0x00000000000581b8 /apex/com.android.runtime/lib64/bionic/libc.so (ioctl+160)
#02 pc 0x0000000000051e04 /system/lib64/libbinder.so (android::IPCThreadState::talkWithDriver(bool)+300)
#03 pc 0x0000000000053504 /system/lib64/libbinder.so (android::IPCThreadState::waitForResponse(android::Parcel*, int*)+60)
#04 pc 0x000000000005326c /system/lib64/libbinder.so (android::IPCThreadState::transact(int, unsigned int, android::Parcel const&, android::Parcel*, unsigned int)+188)
#05 pc 0x000000000004b0a8 /system/lib64/libbinder.so (android::BpBinder::transact(unsigned int, android::Parcel const&, android::Parcel*, unsigned int)+152)
#06 pc 0x0000000000126868 /system/lib64/libandroid_runtime.so (android_os_BinderProxy_transact(_JNIEnv*, _jobject*, int, _jobject*, _jobject*, int)+152)
at android.os.BinderProxy.transactNative (Native method)
at android.os.BinderProxy.transact (BinderProxy.java:559)
at android.content.ContentProviderProxy.query (ContentProviderNative.java:470)
at android.content.ContentResolver.query (ContentResolver.java:1198)
at android.content.ContentResolver.query (ContentResolver.java:1130)
at android.content.ContentResolver.query (ContentResolver.java:1086)
at com.google.android.gms.dynamite.DynamiteModule.zzb (com.google.android.gms:play-services-basement@@18.1.0:10)
at com.google.android.gms.dynamite.DynamiteModule.zza (com.google.android.gms:play-services-basement@@18.1.0:47)
at com.google.android.gms.dynamite.DynamiteModule.getRemoteVersion (com.google.android.gms:play-services-basement@@18.1.0:1)
at com.google.android.gms.ads.internal.client.zzav.zzd (com.google.android.gms:play-services-ads-lite@@21.3.0:5)
at com.google.android.gms.ads.internal.client.zzau.zzg (com.google.android.gms:play-services-ads-lite@@21.3.0:2)
at com.google.android.gms.ads.nativead.NativeAdView.zze (com.google.android.gms:play-services-ads-lite@@21.3.0:3)
at com.google.android.gms.ads.nativead.NativeAdView.<init> (com.google.android.gms:play-services-ads-lite@@21.3.0:6)
at java.lang.reflect.Constructor.newInstance0 (Native method)
at java.lang.reflect.Constructor.newInstance (Constructor.java:343)
at android.view.LayoutInflater.createView (LayoutInflater.java:852)
at android.view.LayoutInflater.createViewFromTag (LayoutInflater.java:1008)
at android.view.LayoutInflater.createViewFromTag (LayoutInflater.java:959)
at android.view.LayoutInflater.inflate (LayoutInflater.java:657)
at android.view.LayoutInflater.inflate (LayoutInflater.java:532)
at android.view.LayoutInflater.inflate (LayoutInflater.java:479)
at com.xxx.xx.adc.request.platform.go.GoAnchorAd.render (GoAnchorAd.java:125)
at com.xxx.kit.widget.BottomView.PlayCtrlBarFragment.dealAnchorAdResponse (XxCtrlBarFragment.java:994)
at com.xxx.kit.widget.BottomView.XxCtrlBarFragment.lambda$mXms0X-1vlklJGMtkt1L4HFOTFs (XxCtrlBarFragment.java)
at com.xxx.kit.widget.BottomView.-$$Lambda$XxCtrlBarFragment$mXms0X-1vlklJGMtkt1L4HFOTFs.onChanged (lambda)
at com.jeremyliao.liveeventbus.LiveEventBus$ObserverWrapper.onChanged (LiveEventBus.java:444)
at androidx.lifecycle.LiveData.considerNotify (LiveData.java:133)
at androidx.lifecycle.LiveData.dispatchingValue (LiveData.java:151)
at androidx.lifecycle.LiveData.setValue (LiveData.java:309)
at androidx.lifecycle.MutableLiveData.setValue (MutableLiveData.java:50)
at com.jeremyliao.liveeventbus.LiveEventBus$LiveEvent.postInternal (LiveEventBus.java:341)
at com.jeremyliao.liveeventbus.LiveEventBus$LiveEvent.post (LiveEventBus.java:230)
at com.xxx.xx.adc.util.AdAnchorUtils$2.onSuccess (AdAnchorUtils.java:310)
at com.xxx.xx.adc.process.displaying.AdDisplayingProcess.lambda$notifySuccess$2 (AdDisplayingProcess.java:260)
at com.xxx.xx.adc.process.displaying.AdDisplayingProcess.lambda$notifySuccess$2$AdDisplayingProcess (AdDisplayingProcess.java)
at com.xxx.xx.adc.process.displaying.-$$Lambda$AdDisplayingProcess$VHdTj9zhPkL1etq57Obw9tn3cZM.run (lambda)
at android.os.Handler.handleCallback (Handler.java:938)
at android.os.Handler.dispatchMessage (Handler.java:99)
at android.os.Looper.loop (Looper.java:268)
at android.app.ActivityThread.main (ActivityThread.java:8017)
at java.lang.reflect.Method.invoke (Native method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:627)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:997)
日志分析可知最终阻塞点为LayoutInflater,结合业务分析,GoAnchorAd调用比较频繁:
public class GoAnchorAd extends GoAd {
public void render(Activity activity, String adSpaceName) {
...
AdView mAdView = (AdView) LayoutInflater.from(activity).inflate(R.layout.ad_content_container, null);
mAdView.setAdType(AdConfig.AD_SOURCE_GOOGLE);
mAdView.setSpaceName(adSpaceName);
NativeAdView nativeAdView = (NativeAdView) LayoutInflater.from(activity)
.inflate(AdConfig.getLayoutResId(adSpaceName, AdConfig.AD_SOURCE_GOOGLE), null);
nativeAdView.setHeadlineView(nativeAdView.findViewById(R.id.native_title));
...
}
广告数据请求回来,回调这里,由于调用比较频繁,每次inflater低端机上Binder资源不足,容易阻塞住,可以换一种思路,改为Java直接new出来AdView。修改后:
public class GoAnchorAd extends GoAd {
public void render(Activity activity, String adSpaceName) {
...
AdView mAdView = new AdView(activity);
mAdView.setAdType(AdConfig.AD_SOURCE_GOOGLE);
mAdView.setSpaceName(adSpaceName);
NativeAdView nativeAdView = (NativeAdView) LayoutInflater.from(activity)
.inflate(AdConfig.getLayoutResId(adSpaceName, AdConfig.AD_SOURCE_GOOGLE), null);
nativeAdView.setHeadlineView(nativeAdView.findViewById(R.id.native_title));
...
}
该inflater问题得以解决。