随笔:公司App升级第三方SDK踩坑两周小记

0849af677db758764db00cc6f277d53f.jpeg

/   今日科技快讯   /

近日,亚马逊CEO安迪·贾西证实,该公司计划在去年11月宣布和今日媒体曝出的裁员中裁撤略多于1.8万个岗位,将从1月8日起与受裁员影响的员工沟通。贾西表示,有多个团队受到影响,但大部分裁员涉及亚马逊商店与人员、体验和技术(PXT)部门。

/   作者简介   /

明天周六啦,天气越来越冷,大家注意做好防护!

本篇文章转自coder_pig的博客,文章主要分享了他在升级第三方SDK踩坑并解决的过程,相信会对大家有所帮助!

原文地址:

https://juejin.cn/post/7130532039870119973

/   引言   /

如题,最近两周疲于折腾公司第三方SDK升级,掉坑里一直出不来,前天突发奇想,终于定位到问题原因。

1b2bb9b166658e9619e64f6ec38675ea.png

问题很简单,却花费了这么长时间,终究还是我太菜了!

1e2018486b3c802d385d7467b3ca54b0.png

BUG虽然解了,但觉得还是有必要记录复盘下,以便下次遇到类似问题时,能找到更好的切入点,更快地把问题解决。

问题概述

现在哪个房产类APP不上VR全景图啊,所以我司也整了一个,经纪人录盘时,使用全景相机对盘源进行拍摄,在录盘填信息的同时,把全景图也上传到服务器。而他们录盘的过程是这样的:

  • 使用全景相机官方APP,连接相机,对盘源进行拍摄,官方APP拼接生成全景图;

  • 拍完打开公司APP,来到录盘页,填写录盘信息,然后打开手机相册,选择对应的全景图上传;

录一次盘得在两个APP间来回切换,可以是可以,但流程繁琐,效率也低,他们更希望:

直接就在公司APP上就可以完成相机连接、拍摄、拼接和上传。

任务传到客户端这边,所以我们需要:

集成官方SDK,参考官方Demo和文档,根据具体业务进行二次开发。

杰哥徒手封装的Library已经稳定跑了两年:

f2e082105c8e8de81e426d881a07d49e.png

本以为可以一劳永逸,安享晚年,最近却出了幺蛾子:

cb3d79e11ec2f62792976227ee975af1.png

有经纪人买了新款相机,然后用公司APP无法拍照。

3b57dac6e2477790cf8786b5941f3131.png

em...硬件、固件升级,需要更新下SDK,可以理解,那就升吧,正当我以为这次升级,会像当初刚集成时那样丝滑流畅,却是磨人踩坑的开始...

/   第一道坎:SDK自带预览组件黑屏   /

很快新的SDK到位,Library替换上新AAR,API有些变动,跟着Demo改改,算是跑起来了,但问题也来了:

拍摄预览页 → 关闭并跳转新页面 → 再次打开预览页 → 预览组件黑屏

看了下官方Demo有定义这个预览组件,但却没用到,再看一下文档:

7f769a725cd012b62859ad0d8c258f8f.png

难不成是销毁时还要手动去释放什么资源么?上个版本没这个问题啊,尝试寻求技术支持:

a488e43b4b26ddaa63b2b6d9b1ab014c.png

隔天早上,我又试着改了下官方Demo,加上预览组件部分的代码,也会黑屏,再次发问:

bbcdc5a2210f1cf75a1924c2aff3fe75.png

在等待回应的同时,我还对可能有关的方法调用都加上了日志打印,尝试找出问题原因:

3ac466a4b7d08e79dd351a380c4aabdc.png

对面说周一开早会,晚点看问题,结果等到了第二天中午:

b486d83ec0a0ea357396b5ed1134b6c3.png

按照他说的,在页面销毁时主动调用预览组件的releasePreview(),预览的确正常了,问题好像解决了?但这样的操作,却引起了第二个问题...

/   第二道坎:小米机型闪退   /

页面销毁和创建多次会报异常崩溃,有时甚至发生在图片拼接时,再次发问,并提供机型和报错日志:

fdb67a4b37ec085635b6f8a6b5cf4fd9.png

c85c08198d15abe0fa5bbfa37280d42b.png

可能是我表达能力的问题,对面有点懵了:

01bf9a19c52d467308e01ce8bd0ca4d6.png

重新组织了一下语言并附上更详细的奔溃日志,同时把demo中的改动文件发给他们测试:

96555e361538641395c18aac5c5b7dc0.png

2dec604f0d50a51690d0bb327d39f5f6.png

得到的回复:

02cc363e0995a4a18d55df8c35cd0aad.png

em...重复了30多次,看得出对面也很想帮我们解决问题,奈何鞭长莫及。

f39d122a5fa791707eed61c80b662c29.png

我甚至跟领导开玩笑说,要不把测试机寄过去那边给他们排查下吧,哈哈哈!另外,同事说他们这两款机型都是很老的机型了,会不会是CPU架构的问题,于是在build.gradle中指定了架构:

ndk {
    abiFilters 'armeabi-v7a', 'arm64-v8a'
}

运行后发现并没什么卵用,而网上搜了一圈这个异常:

Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x10 in tid 2261

发现一个唯一有用且这边能做的事情,删掉这个文件夹 → /data/local/tmp/perfd,删了可以,但治标不治本,删完下次又得删,麻烦且不说,公司APP也没有访问这个文件夹的权限啊 (root权限)。

fcf2adcaa003f4254f20a2d010808d75.png

唉,无解,关键代码都写在so库里,就一黑盒子,奈何笔者太菜,不会so库逆向调试,只能到这里了...

008f1206c31f0407cdf473af700d75af.png

后面领导说先这样把,目前就一个经纪人用新相机,而且用的华为手机,打包给测试测下,没其它问题就先发包吧~

71e86a752fdf07c462ae4d859861849c.png

/   第三道坎:打Release包无法拍摄   /

隔空艰难对接一周,最后妥协收场,正当我以为此事了解,可以回归摸鱼日常,结果测试一声惊雷平地起:

612104f1585cea256808a549899684ca.png

焯!跟进了一下发现:Debug包可以,Release就不行,旧相机可以,新相机不行,看下日志:

2f77771f17706aa41b5a939b89df5afa.png

果断再次向技术支持请求援助,这次吸取教训, 把问题整理清楚再提问:

a3a5cdd9d86908ab86d80235b878e1a3.png

唉,大概是因为人类的悲欢并不相通吧,并没有得到有效帮助,但也给了我们一个思路,可能是混淆的问题。

6e8ebd07e28ab7460ebd80cbf72ba988.png

但混淆代码没Keep住,调用时不是报ClassNotFound之类的Exception吗?难不成他们用try-catch包住不往外抛?半信半疑,不过眼下好像没有更好排查方向了,死马当活马医吧,这也是钻牛角尖的开始...

混淆排查

说到混淆,这不得打开:《补齐Android技能树 - 从害怕到玩转Android代码混淆》,边看边排查,首先混淆规则是叠加的:

7b0c0ba9eac52d93dcc2b1398ac5e578.png

在他们的AAR里,有看到混淆文件:

89bc631dd5a219e4b41af4db59c47a44.png

理论上来说,这里写了的话,app模块是不要再写一遍的,2333,但是为了保证一定生效,还是再写一遍吧。但重新打包后一样不行,可能这个 keep规则没有完全覆盖?于是写了匹配范围更广的规则:

-keep class com.hozo.** { *;}
-keep class com.hznovi.** { *; }
-keep interface com.hozo.** { *; }
-keep interface com.hznovi.** { *; }

一样不行,不应该啊?难道其他模块的混淆规则影响了?又或者Dex分包?会不会是AAR嵌套的原因?等等。

4c76b9ea823250b3807cf9c6ce06f48c.png

先看下是不是我们项目问题吧,于是尝试写一个Demo来引用这个库,Copy混淆规则,并打Release包,结果发现Demo能正常使用!!!焯,那就是我们项目有问题了,难道因为不知名原因,导致类丢失?于是我用AS打开两个Release的APK(公司APP和Demo)进行比对:

b3112520e663a53dc313abeed9da4fa2.png

方法数啥的完全一样,难道真不是混淆的问题?那还可能是什么原因呢?一时有些找不着方向,同事放弃了,领导甚至在群里提出改方案的建议了(公司App只负责上传图片):

3605af478f6f5acc3fe97fcbd5dac20c.png

配置文件缺失/错误排查

而我还在 坚持,回归现象本身:

  • 连接相机报错HZJsonResponse: Parse json payload failed。

  • 等待很久后回调onNeedInitCamera(),然后跳转相机初始化页面。

  • 点击后打印警告日志:Try to setup processor with invalid version,无法正常初始化。

对方的回复:

c14e0961856fabe7032d1e2e44adc1e2.png

  • 简单点说就是:没连上相机,就调用初始化接口

  • 但明显和我们的代码逻辑相违背:只有连上了,才会进入初始化页面:

9adfca44054c2183f27b7ed0337ffd04.png

fddebe2e2ccdad805fba683fa9c1a034.png

这时,我突发奇想,手机连接相机耗时,会不会是接收相机发过来的某些文件出错导致的?比对下是否有文件缺失不就好了?于是我打开Demo和公司APP的 data/data/包名目录进行比对,发现 shared_prefs 目录下没有这个文件:

eabcc567e4ae0c8f380be87f4fd68ea8.png

copy一下,然后又看了下files目录,看到有个easy_panorama目录,里面明显是相机相关的东西,对比了下公司APP,有部分文件缺失:

8cbf68da291bf5a357cb6ef6457b897b.png

同样copy覆盖一下,然后再次运行公司APP连相机,发现报错:没有文件操作权限,直接修改所有者和用户组为我司APP:

68d71964f4503c758ff7fae0c2692019.png

再次连相机,可以,不用初始化直接进入了拍摄页面,点击拍照,相机开始拍照,卧槽?难道真的是文件损坏或缺失引起的BUG吗?如果是的话可以往这个方面继续排查了,但事实打脸,拼接图片时卡住,然后提示照片下载失败,依旧是这个异常:

HZJsonResponse: Parse json payload failed。

又是空欢喜一场,唉,累了,毁灭了,就这样吧,改方案吧,什么垃圾SDK...

526dd9c481221ccf0850da3ec3192334.png

Xposed Hook调试AAR

度过了慵懒的周末,又到周一。

95f787935e498da4864d8c40bfb35540.png

一到公司,看到桌面的相机就烦,焯!破玩意,浪费我两个星期时间...

7a2e48fd4658e0610c00f83fef6c86dc.png

表面上恨不得立马丢了,实际上又看起了源码,嘴上说着不要,身体却很诚实。

ce1d0ed1ddd57b0e12b735cba3a9fbd7.png

尝试定位到报错位置 (jd-gui反编译class.jar搜字符串常量):

5e1b611e83f608a895197d48c476b9a1.png

报JSONException异常,才会走这里的代码,而这个异常的引发条件:

55cef6d1d65f790d4e75506a233a0d30.png

大概率是Json的问题,比如格式不正确,而这个方法是将byte数组转换成Json字符串:

d798ff49e7162be486543d4d6e89aec3.png

如果可以把入参byte数组搞出来看看就好了,尝试在此下 断点,然后调试附加到 APP进程(手机Root了,并通过Magisk将APP都弄成Debug模式,所以能Debug Release APP)。

0f3db099934d815ca6462d2f54a70105.png

但是,并没有走进来,可能不能这样玩?得想下其他法子把参数打印出来。想到好久没玩的Xposed,立马打开专栏:Xposed从入门到入土「插件开发记录 x 框架源码解析」温故知新。到Github找到前几年写的玩具:CPWechatXposed,clone后Build一下。新建一个Hook类:

c579c1e87905e2e55919bd6d72fb9b21.png

XposedInit.kt加上它:

7e769496f904e7f50fa6de57d09f3afb.png

运行模块后重启设备,然后连相机,日志断断续续打印出来了:

2484a847ab7efb78d25c1488c0eff156.png

连接相机时,会报这个码,错误码么,文档上却没找着,再次发文:

bc2f53e9b1430803eb740c17501b49f7.png

噢,并不是错误码,后续Json数据也陆续打印出来了,复制到Json格式化工具,是正常的Json,这...

1730d6e505e8b7564ca674855c475c8c.png

不过细心的我发现了,我在Xposed里try-catch这个JsonObject实例化的过程,并不会触发JsonException。但是Parse json playload failed. 还是打印出来了,说明是触发 JsonException???

2789253983fa2c9d6d51a84e877d601c.png

好家伙,难不成你们家的 JsonObject 和 JsonException 是金做的还是银做的?

7e9da74476e6c6749db251bed889c796.gif

随手点进 JsonObject 的一定位,直接真相大白:

JsonObject 和 JsonException 指向不同的库!!!

61cff9260e668c9c96a0c6e4d6516084.png

卧槽,这谁埋的雷啊,虽然没定位到具体哪里抛异常,但绝壁是这个库的原因,问了下虾哥能否强制指定,被告知不行:

072b3e72709f0b2564f67c1de21ddbe5.png

后面看了一下引入这个库,只是为了调用下xml转json的方法:

463b2a1abf9c5f0dc9264fcad22f6d1e.png

把 implementation files('jars/java-json.jar') 干掉,引入另一个xml转json的库:implementation 'com.github.smart-fun:XmlToJson:1.4.5',修改调用处相关代码,编译打Release包,安装运行,连接相机,拍照拼接,一气呵成,完美解决。就这样的小BUG磨了我两周,好一个前人挖坑,后人填坑啊...

814eb876e74779792dafa447527222d7.png

/   写在最后   /

事情的大概经过就这样,BUG说解了但又没有完全解,比如没有具体定位到哪里抛JsonException,也有一些让步,比如小米机型还能偶现奔溃问题,但这在我的能力边界外。可惜新相机寄回去了,不然我肯定趁机扩展这方面的姿势~ 

能用就行,在这个过程中也意识到自己的一些不足:

  • 在与人对接描述问题时,并不能简要描述清楚自己的诉求,导致沟通效率并不高;

  • 绝大部分时间都花在打包验证上了,每次一打就十来分钟,一直硬钢,没有想办法去提高编译效率;

  • 容易钻牛角尖,明明自己认知里知道这样做是没问题的,还要去硬怼,而不是尝试换个方向;

  • Native Crash 的排查能力较弱,so库逆向调试也不会,有时间有机会可以了解下~

  • 没有一个可以随时快速验证问题的项目,比如上面写Demo验证,我还得去新建项目,折腾kt版本等;

  • 与之形成鲜明对比的就是我的Xposed插件玩具,改改就能用,当然如果能加上 注解简化调用就更棒了;

综上,还是自己太Vegetable了,得多多磨练和思考啊~

0e8c700e79736a09fb0616ca72efb01a.gif

文中引用到的文章链接如下

补齐Android技能树 - 从害怕到玩转Android代码混淆:

https://juejin.cn/post/6966526844552085512

Xposed从入门到入土插件开发记录 x 框架源码解析:

https://juejin.cn/column/6961682067495059469

推荐阅读:

我的新书,《第一行代码 第3版》已出版!

2022年终总结,我的10年Android之旅

深入探究Kotlin的可见性控制,从internal入手

欢迎关注我的公众号

学习技术或投稿

7c4ff1947f439cf2a6fbabdd8e30027a.png

fa36ef2fc83530a2dd4009d02ca6fe26.jpeg

长按上图,识别图中二维码即可关注

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值