[转+补]Android打包so后魅族5中安装运行崩溃问题的解决方法
上周在做噪音检测so集成中,遇到不同的so库打包到 APK 时,安装在某些机器上,出现 java.lang.UnsatisfiedLinkError
加载失败。
为此,深究了一下原理,和给出了解决方案。
原理
Android 系统本质是一个经过改造的 Linux 系统。最早,Android 系统只支持 ARMv5 的 CPU 构架,随着 Android 系统的发展,又加入了 ARMv7 (2010), x86 (2011), MIPS (2012), ARMv8, MIPS64 和 x86_64 (2014)。
每一种 CPU 构架,都定义了一种 ABI(Application Binary Interface),ABI 决定了二进制文件如何与系统进行交互。
当你的 APP 中用到了些包含 SO 库第三方库,或者自己使用 NDK 来实现了某些功能,你就需要认真阅读接下来的教程。
NDK SO 支持不同的 CPU 构架
在使用 NDK 开发包含 c/c++ 代码的 SO 库的时候,你可以选择输出支持如下 ABI CPU 构架:
armeabi
armeabiv7a
arm64v8a
x86
x86_64
mips
mips64
NDK 库支持如上所有的 CPU 构架:
但不是所有人的开发者提供的 NDK 库都支持所有的 CPU 构架:
上面的这个开发者提供的库,就只支持 armeabi。
其实一般情况下,是没有问题的,x86 的设备,也会兼容 armeabi 的 so 库。
合并打包到 APK 中
如果不做任何设置,Android 的构建系统会把这些来自不同开发者的 SO 库都合并在一起,打进 APK 压缩包中。
【假设你的so是手动添加的,只提供了 armeabi 和 armeabi-v7a ,则构建时也会默认创建mips、mips64、x86等文件夹,而这些文件夹中其实是没有so文件,
当将apk安装到x86的系统中,应用程序会去x86文件夹查找so,如果没有找到则会出现异常 】
├── AndroidManifest.xml
├── classes.dex
├── lib
│ ├── arm64-v8a
│ │ └── libBugtags.so
│ ├── armeabi
│ │ ├── libhyphenate.so
│ │ └── libBugtags.so
│ ├── armeabi-v7a
│ │ └── libBugtags.so
│ ├── mips
│ │ └── libBugtags.so
│ ├── mips64
│ │ └── libBugtags.so
│ ├── x86
│ │ └── libBugtags.so
│ └── x86_64
│ └── libBugtags.so
├── res
系统安装 APK
根据官方 ndk-abi 文档, Android 系统在安装一个 APK 的时候,会考虑当前的设备的 CPU 构架和配置(称为所谓的 primary-abi 和 secondary-abi),去该 APK 文件的对应文件夹去寻找 SO 库。
假设当前设备是 x86 机器,会优先去 lib/x86 文件夹下寻找 SO 库:
lib/<primary-abi>/lib<name>.so
如果找不到,同时定义了 secondary-abi,则去如下文件夹寻找:
lib/<secondary-abi>/lib<name>.so
如果找到了,就将文件拷贝到 APK 的安装目录的如下文件夹中:
/lib/lib<name>.so
找不到对应的 SO,安装正常,但是当这个 SO 在运行时被使用时,会崩溃。
问题来了
可能你已经发现问题了,当一个 APK 是这种情况:
├── AndroidManifest.xml
├── classes.dex
├── lib
│ ├── arm64-v8a
│ │ └── libBugtags.so
│ ├── armeabi
│ │ ├── libhyphenate.so
│ │ └── libBugtags.so
│ ├── armeabi-v7a
│ │ └── libBugtags.so
│ ├── mips
│ │ └── libBugtags.so
│ ├── mips64
│ │ └── libBugtags.so
│ ├── x86
│ │ └── libBugtags.so
│ └── x86_64
│ └── libBugtags.so
├── res
同时 APK 被安装到一个 x86 的设备上的时候,以上的寻找过程,将会失败,运行时,将出现如下报错:
D/xxx (10674): java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/xxx-2/base.apk"],nativeLibraryDirectories=[/data/app/xxx-2/lib/x86, /vendor/lib, /system/lib]]] couldn't find "libirdna_sdk.so"
D/xxx (10674): at java.lang.Runtime.loadLibrary(Runtime.java:366)
此处,笔者有点费解,既然在 x86 文件夹中找不到,应该去 armeabi 文件夹中自动寻找啊,此处原因不明,可能要去确认是否是某些机器的原因。
解决方案
准则
NDK SO 开发者应该遵循一个准则:支持所有的平台,否则将会搞砸你的用户。
NDK SO 使用者应该遵循一个准则:要么支持所有平台,要么都不支持。
然而,事与愿违,因为种种原因(遗留 SO、芯片市场占有率、APK 包大小等),并不是所有人都遵循这样的原则。
折中方案
Android Studio
- Android Gradle 插件中,可以使用如下方式对 abi 进行过滤:
android {
... defaultConfig {
...
ndk {
// 设置支持的 SO 库构架,注意这里要根据你的实际情况来设置
abiFilters 'armeabi'// 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64', 'mips', 'mips64'
}
} }
关键行:
abiFilters 'armeabi'// 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64', 'mips', 'mips64'
根据你的 APP 中使用的 SO 库所支持的构架具体情况,你可以进行具体设置。最终输出的 apk 中,将会包含你所选择的 abi。
像前面举出的例子,就应该只允许 armeabi。
- 如果在添加 “abiFilter” 之后 Android Studio 出现以下提示:
NDK integration is deprecated in the current plugin. Consider trying the new experimental plugin
则在项目根目录的 gradle.properties 文件中添加:
android.useDeprecatedNdk=true
[转+补]Android打包so后魅族5中安装运行崩溃问题的解决方法的更多相关文章
- [Android Studio Problems]记录克隆项目中遇到的坑(问题)以及解决方法
①Migrate project to Gradle? 问题描述: This project does not use the Gradle build system. We recommend th ...
- 关于Android app的launcher图标更换后,仍然显示默认的ic_launcher图标的解决方法
<h1>概要</h1>在做手机适配的时候,遇到了一个很奇怪的问题,在1080x720的手机可以正常显示替换的ic_launcher.png图标,但是在1920x1080的手机上 ...
- sql server 还原数据库后,删除用户,提示数据库主体在该数据库中拥有架构,无法删除解决方法
将另一台服务器上的数据库备份文件,在现在用的这台服务器上还原之后,再创建相同的用户名,提示用户已存在 想将之前的用户先删除掉,却提示“数据库主体在该数据库中拥有架构,无法删除解决方法” 在网上找到方法 ...
- WPF:验证登录后关闭登录窗口,显示主窗口的解决方法
http://www.27ba.com/post/145.html WPF:验证登录后关闭登录窗口,显示主窗口的解决方法 最近想做一个基于Socket的通讯工具,想模仿QQ那样,需要先登录,登录成功后 ...
- ECSHOP后台登陆后一段时间不操作就超时的解决方法
ECSHOP后台登陆后一段时间不操作就超时的解决方法 ECSHOP教程/ ecshop教程网(www.ecshop119.com) 2012-05-27 客户生意比较好,因此比较忙,常常不在电脑前 ...
- 【转】chrome 67版本后无法拖拽离线安装CRX格式插件的解决方法
第一种:开启开发者模式即可 (推荐) chrome 的设置 -> 更多工具 -> 扩展程序,开启开发者模式即可! 第二种方法:修改参数 首先打开下面地址:chrome://flags/# ...
- android studio更新后,构建gradle卡在Refreshing Gradle Project 解决办法
Android Studio每次更新版本都会更新Gradle这个插件,但由于墙的问题,导致更新很慢或者最后更新失败,又是停止在Refreshing Gradle Project ,有时新建项目的时候报 ...
- Android eclipse导入项目后出现Unable to resolve target 'android-17'解决方法
eclipse导入项目后出现Unable to resolve target 'android-17'解决方法.在最后附带还有一种编译逻辑不成功情况解决方法. 一.问题情况 二.解决的方法 1.改动项 ...
- vs2010打包系统必备选择.net framework 3.5sp1编译错误的解决方法
利用visual studio 2010进行打包程序,默认安装的是Framework 4.0,如果需要将3.5sp1打包到系统中一起安装(选择了"从与我的应用程序相同的位置下载系统必备组件& ...
随机推荐
- kafka之六:为什么Kafka那么快
转自: http://mp.weixin.qq.com/s?__biz=MzIxMjAzMDA1MQ==&mid=2648945468&idx=1&sn=b622788361 ...
- Win7点击文件夹右键可打开cmd控制台,并获取当前目录
当我们用cmd时,有时要切换到某个文件夹的目录,可以在当前目录下,按住shift单击右键打开控制台,也可以在鼠标右键中添加cmd启动命令: 1.在开始搜索框输入regedit,打开注册表: 2.打开 ...
- hibernate学习二 基本用法
一 映射文件User.hbm.xml 定义了持久化类实例是如何存储和加载的,这个文件定义了持久化类和表的映射. 根据映射文件,Hibernate可以生成足够的信息以产生所有的SQL语句,也就是类的实 ...
- ubuntu下安装显卡驱动
前言 以下内容是个人学习之后的感悟,转载请注明出处~ 作者的显卡是GT 730,现以NVIDIA-Linux-x86-384.69为例. 1.打开终端,先删除旧的驱动: sudo ...
- AI—家庭组机器人平台环境配置,高级人工智能实验总结
首先说一下我的环境:Ubuntu 12.04 32bit, gcc 4.6.3 一,安装boost 1.48,建议用这个版本的,不然会出现兼容性问题 步骤: 其实在ubuntu下,可以用一下命令直接 ...
- Jacob开发文件转PDF
这三种方法我都有试过word转PDF,第2种.第3种对于图片,表格.中文转换效果都不好,方法1效果最好.但方法1 只支持Windows环境下. 1.开发环境 Windows系统: 2.准备工作: st ...
- Linux locate 文件搜索
在学习 兄弟连 linux教学视频 的时候,我将所学的 linux 命令记录在我的博客中,方便自己查阅. 文件处理命令:locate 基础的命令 命令名称:locate 命令的所在路径:/usr/bi ...
- .NET开发人员如何开始使用ML.NET
随着谷歌,Facebook发布他们的工具机器学习工具Tensorflow 2和PyTorch ,微软的CNTK 2.7之后不再继续更新(https://docs.microsoft.com/zh-cn ...
- 原创|高逼格企业级MySQL数据库备份方案,原来是这样....
很多人,这里说的是运维工程师们,一提到写某某方案,很是头疼.不是上某度一统搜索,就是同样一句话在N个群全部群发一遍:“有没有某某方案,可以共享一下的吗??求助,各位大佬们”,估计十有八九,全部石沉大海 ...
- [Xcode 实际操作]一、博主领进门-(4)设置项目的属性
目录:[Swift]Xcode实际操作 本文将演示如何设置项目的属性. 点击项目名称[DemoApp],打开项目信息面板. [Identity识别]设置区域 [Display Name]:DemoAp ...