从15年11月份起,我和qd君开始构思并开发一个运动健身类的app,并且给它起了个又去的名字,叫做QRun。

BDMap 还是 AMap

跑步类的app,免不了和地图打交道。

一开始我们用了百度,但是发现,百度并不能完全符合我们的要求,频繁的onPause onResume时出现了内存泄露的问题。我们的需求比较奇怪,需要不断地改变地图View的位置,所以也不能怪百度。最终,选用的高德地图。

换地图的时候,我们发现一件有趣的事。百度地图的Api,和高德地图的Api,简直一奶同胞的兄弟,几乎一模一样。比方说百度的图叫BDMap,高德就要叫AMap,SDK支持的功能也是毫无二致。只能说不愧是有实力的竞争对手,为了抢用户也是蛮拼的。

CPU架构

高德地图的SDK里,只有一组so库文件,只支持armeabi。
国产CPU的架构那么多,只有一个armeabi怎么兼容呢?
请看知乎@rlei的回答

微信的安装包在只编译了armeabi,没有x86,arm64-v8a是如何运行在各种处理器的手机上的?
下载了几个渠道的微信apk安装包,打开发现里面的lib文件夹只有armeabi一个文件夹,没有x86和armeabi-v7a,以及64位arm处理器的arm64-v8a文件夹,所以感到很疑惑,它是怎么在64位arm处理器上运行的呢?我之前做了一个pdf阅读器的时候,忘记编译arm64-v8a,结果用户反馈在他的64位arm处理器的手机上打开pdf的时候会异常退出。希望知道的知友,不吝赐教,谢谢。


  • 跑x86/x86_64的手机一般自带Intel开发和授权的binary translator,会自行把ARM native code即时翻译成x86指令
  • armeabi-v7a向下兼容armeabi
  • Android 5.0+同时支持32位与64位ABI的.so,有arm64-v8a就用,没有就fallback到armeabi-v7a或armeabi你的应用
  • 异常退出可能有多种原因

可是不管别人怎么说,反正我们的应用还是跪了。尤其是魅族,红米note一类的手机。

于是我陷入了陈思

与其他第三方库兼容 Fresco

机智的qd君解析了apk文件,终于发现了症结所在。
他发现apk中还是有armeabi armeabi-v7 x86 x86_v7 等等好多种架构。只要删除了除armeabi 之外的所有文件夹,apk就可以正常运行了。

那么问题,就呼之欲出了。比方说魅族是x86架构,它加载了x86架构的文件夹,结果却发现里面没有高德地图的.so库,自然就崩了。

所以第一种尝试方法是,在工程中手动创建armeabi-v7这些文件夹,把高德地图的.so文件原模原样的复制进这些文件夹。自然在打包的时候就会在每种架构对应的文件夹中都包含高德地图的.so文件。事实上,我们查到,网上有人把OpenCV和高德同时使用(OpenCV有armeabi和armeabi-v7两个包)就是通过这种方法解决的。

但是,,我们的还是不行。。。

你以前不是这个样子的

在魅族上,报错显示本应该是32位的架构加载了64位的.so库。。。显然,系统没有像我们预想的一样启动Intel的binary translator进行翻译,而是直接加载了那么x86文件夹。

所以,结论就是,在apk中我们不能编入x86文件夹,只保留armeabi文件夹,从而使手机自己兼容。

经过一番查找,我们确认除了armeabi之外的架构文件夹,都是从Fresco中编进来的,我们需要只保留Fresco的armeabi文件夹。

最直接的方法自然就是手动把apk里的这些文件夹删除掉。优点:简单干脆,缺点:这也太无脑了,显然不是我们这种自诩为优秀大学生该干的。

经过在网上查找最终得到了方案:

1
2
3
4
5
6
7
8
9
10
11
12
android {
....

splits {
abi {
enable true
reset()
include "armeabi"
universalApk false
}
}
}

enable 启动abi filter
reset() 默认为适配所有架构,这里reset一下,就是什么架构也不适配
include / exclude 表示增加适配某架构、或者删除适配某架构
universalApk 默认为true 会把所有需要适配的架构文件夹打入一个apk中,false的话则是每种架构打一个apk(到时候再分渠道分发)