最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • Android解耦式so库加载方案

    正文概述 掘金(好未来技术团队)   2021-01-16   390

    背景说明

    在业务开发过程中经常会进入一些三方sdk,这些三方的sdk引入so库,有些so库文件还比较大,这时候我们就需要考虑so库从网络获取异步加载,减少发布包的体积

    Android解耦式so库加载方案

    传统方案

    关于so异步加载方案,网上的资料随便搜下大把,核心思想
    so库文件放到网络->下载到本地沙盒->通过System.load载入
    看起来挺简单的 然而挺多资料没提到的是

    so库存在依赖关系

    比如当你把libunity.so下载下来通过
    System.load("/data/data/com.example.soload/files/libunity.so")
    加载的时候会得到如下异常

    原因分析

    Android解耦式so库加载方案

    解决方案

    载入libunity.so之前需要先载入libmain.so

    扩展思考

    我们写代码的时候怎么控制加载顺序呢
    github.com/facebook/S.…
    github.com/KeepSafe/R.…
    以上2个开源库 都有处理相关逻辑
    核心思想就是解析so库ELF格式,分析依赖并递归,直到依赖库都加载完成再载入自身
    这里不扩展开来 有兴趣的伙伴可以看源码研究下

    text relocations问题

    当你把liblbs.so下载下来通过

    原因分析:

    blog.csdn.net/chjqxxx...

    扩展思考:

    我们可以通过命令进行自查

    Android解耦式so库加载方案

    有源码的可以重新编译,没有源码的只能通过降低targetSdkVersion处理(然而也是治标不治本)

    进阶方案

    除了System.load方案 还有没有其他方案呢
    答案当然是肯定的
    github.com/Tencent/ti.…
    核心思路:通过反射把自定义的native库path插入nativeLibraryDirect ories最前面,即使安装包libs目录里面有同名的so,也优先加载指定路径的外部so
    这里截取tinker部分代码
    com.tencent.tinker.lib.library.TinkerLoadLibrary.java

    Android解耦式so库加载方案

    Android解耦式so库加载方案

    这个方案是不是看起来更简单了,由于这个方案是非常规手段,存在兼容风险, 我们需要验证该方案的兼容性,写个helloword的so,通过该方案加载,提前找个版本线上带上去,进行埋点统计
    截至目前最新版上线2天 统计到数据如下

    Android解耦式so库加载方案

    其中失败的1例是上线前自测故意让校验失败产生的
    也就是说截至目前可以认为改方案是靠谱的
    当然了如果后续有新的Android系统版本更新
    我们还需要关注新版本的兼容情况

    项目应用

    上面铺垫了那么多,现在进入正题
    技术方案是一回事,落实到实际项目是另一回事
    现在开始我们思考下如下几个问题

    1. 项目中引用的so库都是那些功能再用何时载入
    2. 三方jar(aar)引入的so库加载时机不受我们代码逻辑控制
    3. 使用的so库那些适合做异步加载
    4. so库文件没有下载完成之前 用户用相关功能如何处理
    5. 版本迭代so文件升级如何处理
    6. 打包阶段如何把so文件进行剔除
    解决问题1、2、3

    我们可以通过切面编程的思路解决,这里用到了开源库github.com/HujiangTec.…
    由于so库的加载都是通过调用系统函数System.loadLibrary进行,
    那么我们全局拦截该函数的调用并打印调用链,
    运行app,配合日志,就能分析so库的具体使用情况

    Android解耦式so库加载方案
    Android解耦式so库加载方案

    这里我们需要根据自己业务场景分析,比如app进入到首页依赖的库不建议进行异步加载,需要异步加载的库最好是完成一个功能(我们需要按照经验进行逻辑分组 参考文章开头的图)

    解决问题4、5

    Android是依据Activity作为活动单位,启动Activity是通过startActivity函数调用进行的,那么我们就可以拦截织入自己的逻辑
    大致思路如下
    Android解耦式so库加载方案

    对应实现部分代码截图
    Android解耦式so库加载方案

    Android解耦式so库加载方案

    Android解耦式so库加载方案
    Android解耦式so库加载方案

    通过规则配置化+字节码拦截的逻辑 对原有业务无侵入即可实现动态加载
    研发关注正常的业务逻辑 不需要针对性编写代码
    后续引入新的so库,修改配置文件即可
    在实现的过程中有些细节是需要考虑的
    比如校验下载文件的完整性,下载要不要支持断点续传,so文件需要更新如何处理等

    解决问题6

    通过上面的介绍,我们实现了so文件的异步加载
    但是打包的时候 我们如何剔除so 减少最终发布包的大小
    可以在build.gradle进行配置
    Android解耦式so库加载方案

    但是上面提到了我们是通过json配置的规则
    这样再重复配置一遍
    而且还有可能2处配置不一致
    而且我们的大原则是解耦
    那么我们就继续hook打包流程
    Android解耦式so库加载方案

    Android解耦式so库加载方案

    汇总小结

    通过上面的介绍大致说明了原理

    有兴趣的伙伴可以评论区留言,提出自己的想法

    目前还在灰度验证阶段,等线上验证稳定后在评论区放出相关代码

    so异步加载方案大同小异,该方案跟其他方案相比

    个人感觉特色就是侵入性低

    接入只需要3个步骤
    Android解耦式so库加载方案
    Android解耦式so库加载方案
    Android解耦式so库加载方案

    未完待续

    目前该方案还存在几个点有待优化

    ====================

    问题1

    目前用的是进阶方案实现的so库加载 比较理想的方式是传统方案和进阶方案都应该支持 一开始其实我想用传统方案去实现 但是该方案在unity那块有问题(unity相关so的加载逻辑有点特殊 存在通过jni直接加载so的情况 由于没有源码 内部逻辑不太清楚 ) 后续还需要研究完善 毕竟官方System.load是官方提供的api 更可靠

    问题2

    进度加载的dialog是依附于调用startActivity的窗口
    如果startActivuty之后里面 立马调用finish会导致dialog泄露
    这个是需要注意的一个点 也就意味着对原有逻辑存在一定依赖
    这个可以通过启动一个FLAG_ACTIVITY_NEW_TASK类型的activity
    代理解决 但是感觉这样有点重 目前还有点纠结

    问题3

    目前文件只是放到了阿里云,用户的网络环境复杂多变,需要考虑支持腾讯云,七牛云等更多的服务商。

    问题4

    上传到oss的动作目前是动手完成的,需要做成脚本。

    前端


    起源地下载网 » Android解耦式so库加载方案

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元