ANR实战案例1 - Google广告导致ANR解决

news2024/11/26 5:31:21

系列文章目录

提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加
例如:第一章 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问题得以解决。


总结

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/529537.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux 安装JDK详解

安装步骤 1. 从官网下载安装包保存到 /home/download 下面 2.下载后解压到指定目录&#xff0c;例如&#xff1a;/usr/java/jdk11 3. 解压压缩包 [rootlocalhost linux-x86-64]# cd /usr/java/jdk11 [rootlocalhost jdk11]# [rootlocalhost jdk11]# [rootlocalhost jdk11]…

【换模型更简单】如何用 Serverless 一键部署 Stable Diffusion?

作者&#xff1a;寒斜 本篇章是阿里云函数计算部署 Stable Diffusion 系列的第三篇&#xff0c;如果说第一篇是尝试使用云服务来解决用户本地部署 Stable Diffusion 的问题&#xff08;显卡成本&#xff0c;部署技术复杂&#xff09;&#xff0c;第二篇是面向技术同学解决云服…

Wijmo 2023 v1 Crack

改进了 FlexGrid&#xff0c;支持 React 18 严格模式和可访问性。 5月 15&#xff0c; 2023 - 10&#xff1a;51 新版本 特征 改进了对 React 18 的支持 - 添加了对 React 18 严格模式的支持&#xff0c;可帮助开发人员在开发过程中查找常见错误。辅助功能改进 - 以下是此版本中…

postman工具使用中,遇到的简单疑问

post请求和get请求有什么区别&#xff1f; GET请求和POST请求都是HTTP协议中的两种常见请求方式&#xff0c;主要区别如下&#xff1a; GET请求在请求URL的后面附带参数&#xff0c;而POST请求则将参数包含在请求体中。 GET请求的数据是以查询字符串的形式传递的&#xff0c;而…

JavaEE(系列4) -- 多线程(线程的状态)

目录 观察线程的所有状态 1. new状态 2. TERMINATED 状态 3. RUNNABLE 就绪状态,运行状态 4. TIMED_WAITNG 休眠状态 5. BLOCKED 表示等待锁出现的状态 6. WAITING 使用wait方法出现的状态 观察线程的所有状态 线程的状态是一个枚举类型 public class test2 {public static v…

【AI绘图 丨 Midjourney 系列教程二】— 初识超火的AI绘画神器Midjourney

今天起&#xff0c;由 Midjourney 打头阵&#xff0c;让我们开始共同探索一系列的 AI 领域革命性作品&#xff0c;包括 Midjourney、Stable Diffusion、ChatGPT 等等&#xff0c;学习这些新时代的魔法和它的咒语。 写在前面 官方文档是最好的入门课程。相较于市面上琳琅满目的…

git入门(必看)

git入门 git简介 文章目录 git入门git简介版本控制系统发展可以分为三个阶段&#xff1a; Git 的诞生Git 诞生的背景Linus 两周完成 GitGit 的发展壮大 git安装在 Windows 上安装在 macOS 上安装在 Linux 上安装 Git环境配置配置用户名和邮件地址检查配置Git 颜色配置Git忽略文…

STC15单片机+nRF24L01通讯利用PCA输入捕获触发

STC15单片机+nRF24L01通讯利用PCA输入捕获触发 📍相关篇《STC单片机 NRF24L01通讯实验》📌《STC单片机 NRF24L01通讯带状态反馈》🔖验证对象:STC15L2K60S2📍STC15L2K60S2自制系统板硬件开源地址:https://oshwhub.com/perseverance51/stc15l2k60s2-ji-tong-ban⏱时钟频…

C++ - AVL树

之前的文章中我们学习过二叉搜索树&#xff0c;学习完该部分之后&#xff0c;在进行OJ的练习和思考中会发现如果一颗搜索树由于初始结点选择的不好这棵树就会变成成一颗歪脖子树&#xff0c;这样搜索的效率反而会变的不是很理想。那么在今天的文章中我们就要来介绍一种基于搜索…

【啃书C++Primer5】-c++有些理论基础需要了解,墙裂建议看看原书,有太多细节需要注意了

任何常用的编程语言都具备一组公共的语法特征&#xff0c;不同语言仅在特征的细节上有所区别。要想学习并掌握–种编程语言&#xff0c;理解其语法特征的实现细节是第一步。最基本的特征包括: 整型、字符型等内置类型变量&#xff0c;用来为对象命名 表达式和语句&#xff0c;…

10款最好的Photoshop替代软件

Photoshop作为一种老式的设计软件&#xff0c;在世界上享有很高的声誉&#xff0c;所以很多人说学习设计&#xff0c;第一反应是学习Photoshop&#xff0c;结果打开电脑发现&#xff1a;配置不够&#xff0c;预算不足&#xff0c;课程有点困难&#xff0c;因为这条路不起作用&a…

嵌入式系统入门基础知识分析(一)

目录 ​编辑 一、什么是嵌入式 二、嵌入式系统的组成 三、实时系统

薪资21K,在字节外包工作是一种什么样的体验...

我17年毕业于一个普通二本学校&#xff0c;电子信息工程学院&#xff0c;是一个很不出名的小本科。大学期间专业知识也没有去认真的学习&#xff0c;所以毕业的时候就随便找了一份工作&#xff0c;在一个小公司做功能测试。 记得那时候税前薪资大概是7k左右&#xff0c;因为是…

每日一练 | 华为认证真题练习Day46

1、在存在冗余的二层网络中&#xff0c;可以使用下列哪种协议避免出现环路&#xff1f; A. ARP B. STP C. UDP D. VRRP 2、静态MAC地址表在系统复位、接口板热插拔或接口板复位后&#xff0c;保存的表项不会丢失。 A. 对 B. 错 3、如下图所示&#xff0c;假设SWA的MAC地址…

web开发 处理多媒体文件

文章目录 图片格式gifpngjpgwebp图片格式对比 图片的使用方式图片的其它内容 视频格式转换 音频wavmp3转换 图片 html用img标签在网页上输出图片。 格式 图片的格式有很多种&#xff0c;常见如下 gif、jpg、png、webp。 gif gif 格式&#xff0c;常用于页面中的简单动画&a…

《链》接未来:力扣“复制带随机指针的链表”题解

本篇博客会讲解力扣“138. 复制带随机指针的链表”的解题思路&#xff0c;这是题目链接。 先来审题&#xff1a; 以下是输出示例&#xff1a; 以下是提示&#xff1a; 本题要实现复杂链表的深拷贝。复杂链表&#xff0c;是正常的单链表&#xff0c;每个结点中多存了一个指针…

【Vector VN1630/40 I/O应用】-2-信号发生器

案例背景(共5页精简)&#xff1a;该篇博客将告诉您&#xff1a; 将Vector VN1630A/VN1640A CAN/LIN Interface的I/O接口充当一个简易的“信号发生器”使用&#xff1a;高低电平(如TTL电平)和PWM波。用作信号发生器&#xff0c;唤醒ECU控制器&#xff08;硬件唤醒&#xff0c;如…

C语言参悟-循环控制

C语言参悟-循环控制 一、循环综述1. C语言的循环概念2. 循环条件3. 循环单元4. 循环中断 二、for 循环三、while 循环四、do while 循环 一、循环综述 下面只是我的对于C语言的认识拙见&#xff0c;可以多多提出批评建议&#x1f604; 计算机的诞生很大程度上就是为了来进行重…

即拼七人拼团系统开发模式,上帮下扶机制逻辑规则解析

即拼七人拼团模式是最近非常火爆的商业模式&#xff0c;它主要融合了二二复制和拼团两种模式玩法&#xff0c;在快速裂变团队的同时&#xff0c;还能提高用户活跃度和粘性。这个模式中最大的亮点&#xff0c;就是它的上帮下扶机制&#xff0c;今天就在这里详细说一下。 所谓上帮…

6.文本三剑客--sed

文章目录 文本三剑客sed介绍命令介绍打印内容删除替换插入分组 文本三剑客 sed 介绍 sed编辑器 sed是一种流编辑器&#xff0c;流编辑器会在编辑器处理数据之前基于预先提供的一组规则来 编辑数据流。 sed编辑器可以根据命令来处理数据流中的数据&#xff0c;这些命令要么…