设为首页 加入收藏

TOP

系统应用集成过程中的一些坑(一)
2019-09-01 23:27:04 】 浏览:90
Tags:系统 应用 集成 过程 一些

本篇文章已授权微信公众号 dasu_Android(大苏)独家发布

这次想来讲讲系统应用集成过程中遇到的一些坑,尤其是 so 文件相关的坑。

背景

埋这些坑的最初来源是由于测试人员在集成新终端设备时提了个 bug: app 在这个设备上无法启动。

随后抛来了一份日志,过滤了下,最重要的其实就一条,crash 日志:

java.lang.UnsatisfiedLinkError: No implementation found for long com.facebook.imagepipeline.memory.NativeMemoryChunk.nativeAllocate(int) (tried Java_com_facebook_imagepipeline_memory_NativeMemoryChunk_nativeAllocate and Java_com_facebook_imagepipeline_memory_NativeMemoryChunk_nativeAllocate__I)

app 使用了 fresco 图片库,最初猜想是不是因为 so 文件没有 push,因为我们的 app 是系统应用,集成的时候是直接将 apk push 到 system/app 下的,因为没有 install 过程,所以 so 文件得自己 push 到 system/lib 下。

但把机子拿过来一看,so 文件有在啊,尝试将其删掉,再运行,又报出了如下异常:

java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file "/system/app/xxxx.apk"],nativeLibraryDirectories=[/system/lib64/xxxx, /vendor/lib64, /system/lib64]]] couldn't find "libimagepipeline.so"

看了下日志,它是说,在 system/lib64 目录下没有找到 so 文件,奇怪,以前都是只集成到 system/lib 下就可以了啊,怎么这次多出了个 system/lib64,难道这个机子支持的 CPUABI 不一样?试着运行了下 getprop | get cpu

cpu.png

果然,这个机子支持的 CPUABI 多了个 arm64-v8a。

那这个机子既支持 arm64-v8a,又支持 armeabi-v7a,我怎么知道,我的 app 该将 so 文件集成在哪里,什么场景该放 system/lib 下,什么时候该集成到 system/lib64 中?还是说,两个地方都放?

应该不至于两个目录都得集成,因为三方应用安装时,从 apk 包中也只会解压一份 so 文件而已,并不会将 lib 下所有 abi 架构的 so 文件都解压。

后来,试着查找相关资料,发现可以在 data/system/packages.xml 文件中找到自己 app 的相关配置信息,这里有明确指出该去哪里加载 so 文件,以及 app 所运行的 CPU 架构,所以我们可以运行如下命令:

cat /data/system/packages.xml | grep {你自己app的包名}

packages.png

后来有些疑惑,这里的 primaryCpuAbi 属性值,系统是如何确定的,因为遇到过,明明这次的值是 armeabi-v7a,但当重启之后,有时候居然变成 arm64-v8a 了,所以就又去查找了相关资料,发现,这个值确定的流程蛮复杂的,影响因素也很多。

那么,就没有办法根据某些条件确定某个场景来确定 so 文件是该放 system/lib,还是 system/lib64 了,只能两个都集成了。于是乎,尝试着直接将 system/lib 下的 so 文件拷贝了一份到 system/lib64,结果发现运行报了如下异常:

java.lang.UnsatisfiedLinkError: dlopen failed: "libimagepipeline.so" is 32-bit instead of 64-bit

哎,想当然了,不同 CPU 架构的 so 文件肯定不一样,哪里可以直接将 armeabi-v7a 的 so 文件放到 system/lib64 里。因此,重新编译、打包了一份 arm64-v8a 架构的 so 文件,集成到 system/lib64 下,再运行,搞定。

但你以为事情到这里就结束了吗?年轻人,too yang.

由于以前 app 合作的机子,都只有 armabi-v7a 的,所以集成方式就一种,只需要集成到 system/lib 下就可以了,但由于新合作的机子有 arm64-v8a 的了,那么此时就需要修改以前的集成方式,分别将对应的 so 文件集成到对应的 system/lib 和 system/lib64 目录下。

但运维人员表示说,他不懂这些,他怎么判断说,什么时候该用旧的集成方式,什么时候用新的集成方式。我跟他说,你需要先执行 getprop | grep cpu 命令,查看当前机子支持的 CPUABI,然后再来决定你如何集成。但运维又说,这好复杂,能否有方法就统一一种集成方式,不必分场景考虑。

emmm,你们都是老大,你们说了算。只能又去瞎搞了,这次去开源库的 issue 里尝试寻找了下,结果发现,哈哈哈,原来这么多人碰到过这个问题:

issus.png

要相信,你绝对不是第一个遇到问题的人。是吧,这么多人都来这里提问了,开源库的负责人肯定给出解决方案了,所以接下去继续在这些 issues 里过滤一下,找出那些跟你一样的问题就可以了。如下面这篇:

java.lang.UnsatisfiedLinkError #1552

issue.png

官方人员已经说了,可以尝试使用 Relinker 或 SoLoader 来解决。

最后,我选择了 ReLinker,发现它的源码并不多,直接将所有源码拷贝到项目中,修改了源码中某个流程的逻辑,用于解决我自己这种场景下的 so 文件加载问题,搞定,具体在下面的埋坑一节讲述。

这整个过程中,遇到了一个又一个问题,一个又一个坑,解决这个异常,出现另一个异常,但整个过程梳理过来,也掌握了很多干货知识点,下面就用自己的理解,将这些相关的知识点梳理一下:

知识点

看完本篇,你能了解到哪些知识点呢,如下:

P1:了解系统应用集成方式,大概清楚 apk 的 install 过程都做了些什么。

P2:知道如何判断系统应用是否安装成功,懂得查看 data/system/packages.xml 文件来得知应用的基础信息,如 so 库地址,primaryCpuAbi 等。

P3:掌握 System.load() 和 System.loadlibrary() 的区别。

P4:清楚系统寻找 so 文件的大体流程,知道系统什么时候会去 system/lib 下加载 so 文件,什么时候去 system/lib64。

P5:了解 ReLinker 和 SoLoder 库的用途和大体原理。

正文

ps: 由于接触尚浅,还看不懂源码,正文部分大多数是直接从各大神博客中梳理出的结论,再用以自己的理解表达出来,因为并没有结合源码来分析,因此给出的结论观点不保证百分百正确,如有错误,欢迎指点一下。

ps: 以下知识点梳理基于的设备系统 Android 5.1.1,api 22,不同系统的设备,也许过程会有些许差别。

1. install 过程

要了解 apk 的 install 过程都干了哪些事,

首页 上一页 1 2 3 4 下一页 尾页 1/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇学习安卓开发[4] - 使用隐式Inten.. 下一篇安卓开发学习笔记(六):如何实..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目