网站登记备案,权重高的博客网站,魔法自助建站,wordpress一百万文章转自#xff1a;【欧阳鹏】http://blog.csdn.net/ouyang_peng Android 设备的CPU类型(通常称为”ABIs”) armeabiv-v7a: 第7代及以上的 ARM 处理器。2011年15月以后的生产的大部分Android设备都使用它.arm64-v8a: 第8代、64位ARM处理器#xff0c;很少设备#xff0c;三星 G…转自【欧阳鹏】http://blog.csdn.net/ouyang_peng Android 设备的CPU类型(通常称为”ABIs”) armeabiv-v7a: 第7代及以上的 ARM 处理器。2011年15月以后的生产的大部分Android设备都使用它.arm64-v8a: 第8代、64位ARM处理器很少设备三星 Galaxy S6是其中之一。armeabi: 第5代、第6代的ARM处理器早期的手机用的比较多。x86: 平板、模拟器用得比较多。x86_64: 64位的平板。问题描述 今天测试人员测试集成版本时除了一个bug关于华为 Mate 8手机Android 6.0系统运行刚刚提测的版本时出现闪退的bug而小米 4 手机Android 6.0系统却没有出现任何bug运行良好。后来查看本人相关模块的代码发现本人集成版本相关模块的代码和分支版本相关模块的代码是一模一样的那就是说本人把分支代码合并到主干代码是没有问题的所以去查看主干代码的问题。 经过一番查看提交日志发现有位同事再我合并代码之前提交了一个关于友盟推送的so文件的记录原来他加入了一个arm64-v8a文件夹里面有友盟推送的arm64-v8a的so库文件。而其他的so库文本却没有arm64-v8a对应的版本。 通过百度查到知乎有一段关于arm64-v8a的解释 arm64-v8a是可以向下兼容的但前提是你的项目里面没有arm64-v8a的文件夹如果你有两个文件夹armeabi和arm64-v8a两个文件夹armeabi里面有a.so 和 b.so,arm64-v8a里面只有a.so那么arm64-v8a的手机在用到b的时候发现有arm64-v8a的文件夹发现里面没有b.so就报错了所以这个时候删掉arm64-v8a文件夹这个时候手机发现没有适配arm64-v8a就会直接去找armeabi的so库所以要么你别加arm64-v8a,要么armeabi里面有的so库arm64-v8a里面也必须有 作者green jim 链接http://www.zhihu.com/question/36893314/answer/78467097 来源知乎 著作权归作者所有。商业转载请联系作者获得授权非商业转载请注明出处。 发现原来华为 Mate 8手机是64位的操作系统而小米 4 手机是32位的操作系统所以小米 4 手机手机运行APP没bug,而华为 Mate 8手机运行APP出现闪退bug。 解决方法 1、解决之前的截图 从截图可以看出来第一个项目中有 arm64-v8a而没有x86目录第二个项目中没有 arm64-v8a而有x86目录。第一个项目是作为项目引用导入到第二个项目中的。 2、解决后的截图 从截图可以看出来第一个项目中和第二个项目中没有的libs目录下都是armeabi-v7a、armeabi、x86三个目录保持一致。第一个项目是作为项目引用导入到第二个项目中的。 3、解决方法 解决方法是从友盟官方中去下载x86的相关so文件放在x86目录下把arm64-v8a目录删除。将所有关于so文件的都要保持一致即如果你要添加一个armeabi-v8a目录下面放第三方的armeabi-v8a相关的so文件那么你其他的so文件都要有相应想armeabi-v8a版本不然就会报错。 4、建议 来自于博客《与 .so 有关的一个长年大坑 》给的建议是 为了减小 apk 体积只保留 armeabi 和 armeabi-v7a 两个文件夹并保证这两个文件夹中 .so 数量一致对只提供 armeabi 版本的第三方 .so原样复制一份到 armeabi-v7a 文件夹 下面文章转载于asce1885简书作者关于Android的.so文件你所需要知道的 原文链接http://www.jianshu.com/p/cb05698a1968 著作权归作者所有转载请联系作者获得授权并标注“简书作者”。 早期的Android系统几乎只支持ARMv5的CPU架构你知道现在它支持多少种吗7种 Android系统目前支持以下七种不同的CPU架构ARMv5ARMv7 (从2010年起)x86 (从2011年起)MIPS (从2012年起)ARMv8MIPS64和x86_64 (从2014年起)每一种都关联着一个相应的ABI。 应用程序二进制接口Application Binary Interface定义了二进制文件尤其是.so文件如何运行在相应的系统平台上从使用的指令集内存对齐到可用的系统函数库。在Android系统上每一个CPU架构对应一个ABIarmeabiarmeabi-v7ax86mipsarm64-v8amips64x86_64。 为什么你需要重点关注.so文件 如果项目中使用到了NDK它将会生成.so文件因此显然你已经在关注它了。如果只是使用Java语言进行编码你可能在想不需要关注.so文件了吧因为Java是跨平台的。但事实上即使你在项目中只是使用Java语言很多情况下你可能并没有意识到项目中依赖的函数库或者引擎库里面已经嵌入了.so文件并依赖于不同的ABI。 例如项目中使用RenderScript支持库OpenCVUnityandroid-gif-drawableSQLCipher等你都已经在生成的APK文件中包含.so文件了而你需要关注.so文件。 Android应用支持的ABI取决于APK中位于lib/ABI目录中的.so文件其中ABI可能是上面说过的七种ABI中的一种。 Native Libs Monitor这个应用可以帮助我们理解手机上安装的APK用到了哪些.so文件以及.so文件来源于哪些函数库或者框架。 当然我们也可以自己对app反编译来获取这些信息不过相对麻烦一些。 很多设备都支持多于一种的ABI。例如ARM64和x86设备也可以同时运行armeabi-v7a和armeabi的二进制包。但最好是针对特定平台提供相应平台的二进制包这种情况下运行时就少了一个模拟层例如x86设备上模拟arm的虚拟层从而得到更好的性能归功于最近的架构更新例如硬件fpu更多的寄存器更好的向量化等。 我们可以通过Build.SUPPORTED_ABIS得到根据偏好排序的设备支持的ABI列表。但你不应该从你的应用程序中读取它因为Android包管理器安装APK时会自动选择APK包中为对应系统ABI预编译好的.so文件如果在对应的libABI目录中存在.so文件的话。 App中可能出错的地方 处理.so文件时有一条简单却并不知名的重要法则。 你应该尽可能的提供专为每个ABI优化过的.so文件但要么全部支持要么都不支持你不应该混合着使用。你应该为每个ABI目录提供对应的.so文件。 当一个应用安装在设备上只有该设备支持的CPU架构对应的.so文件会被安装。在x86设备上libs/x86目录中如果存在.so文件的话会被安装如果不存在则会选择armeabi-v7a中的.so文件如果也不存在则选择armeabi目录中的.so文件因为x86设备也支持armeabi-v7a和armeabi。 其他地方也可能出错 当你引入一个.so文件时不止影响到CPU架构。我从其他开发者那里可以看到一系列常见的错误其中最多的是”UnsatisfiedLinkError””dlopen: failed”以及其他类型的crash或者低下的性能 使用android-21平台版本编译的.so文件运行在android-15的设备上 使用NDK时你可能会倾向于使用最新的编译平台但事实上这是错误的因为NDK平台不是后向兼容的而是前向兼容的。推荐使用app的minSdkVersion对应的编译平台。 这也意味着当你引入一个预编译好的.so文件时你需要检查它被编译所用的平台版本。 混合使用不同C运行时编译的.so文件 .so文件可以依赖于不同的C运行时静态编译或者动态加载。混合使用不同版本的C运行时可能导致很多奇怪的crash是应该避免的。作为一个经验法则当只有一个.so文件时静态编译C运行时是没问题的否则当存在多个.so文件时应该让所有的.so文件都动态链接相同的C运行时。 这意味着当引入一个新的预编译.so文件而且项目中还存在其他的.so文件时我们需要首先确认新引入的.so文件使用的C运行时是否和已经存在的.so文件一致。 没有为每个支持的CPU架构提供对应的.so文件 这一点在前文已经说到了但你应该真的特别注意它因为它可能发生在根本没有意识到的情况下。 例如你的app支持armeabi-v7a和x86架构然后使用Android Studio新增了一个函数库依赖这个函数库包含.so文件并支持更多的CPU架构例如新增android-gif-drawable函数库 compile ‘pl.droidsonroids.gif:android-gif-drawable:1.1.’ 11发布我们的app后会发现它在某些设备上会发生Crash例如Galaxy S6最终可以发现只有64位目录下的.so文件被安装进手机。 解决方案重新编译我们的.so文件使其支持缺失的ABIs或者设置 ndk.abiFilters 11显示指定支持的ABIs。 最后一点如果你是一个SDK提供者但提供的函数库不支持所有的ABIs那你将会搞砸你的用户因为他们能支持的ABIs必将只能少于你提供的。 将.so文件放在错误的地方 我们往往很容易对.so文件应该放在或者生成到哪里感到困惑下面是一个总结 Android Studio工程放在jniLibs/ABI目录中当然也可以通过在build.gradle文件中的设置jniLibs.srcDir属性自己指定Eclipse工程放在libs/ABI目录中这也是ndk-build命令默认生成.so文件的目录AAR压缩包中位于jni/ABI目录中.so文件会自动包含到引用AAR压缩包的APK中最终APK文件中的lib/ABI目录中通过PackageManager安装后在小于Android 5.0的系统中.so文件位于app的nativeLibraryPath目录中在大于等于Android 5.0的系统中.so文件位于app的nativeLibraryRootDir/CPU_ARCH目录中。只提供armeabi架构的.so文件而忽略其他ABIs的 所有的x86/x86_64/armeabi-v7a/arm64-v8a设备都支持armeabi架构的.so文件因此似乎移除其他ABIs的.so文件是一个减少APK大小的好技巧。但事实上并不是这不只影响到函数库的性能和兼容性。 x86设备能够很好的运行ARM类型函数库但并不保证100%不发生crash特别是对旧设备。64位设备arm64-v8a, x86_64, mips64能够运行32位的函数库但是以32位模式运行在64位平台上运行32位版本的ART和Android组件将丢失专为64位优化过的性能ARTwebviewmedia等等。 以减少APK包大小为由是一个错误的借口因为你也可以选择在应用市场上传指定ABI版本的APK生成不同ABI版本的APK可以在build.gradle中如下配置 android {... splits {abi {enable truereset()include x86, x86_64, armeabi-v7a, arm64-v8a //select ABIs to build APKs for universalApk true //generate an additional APK that contains all the ABIs } } // map for the version code project.ext.versionCodes [armeabi: 1, armeabi-v7a: 2, arm64-v8a: 3, mips: 5, mips64: 6, x86: 8, x86_64: 9] android.applicationVariants.all { variant - // assign different version code for each output variant.outputs.each { output - output.versionCodeOverride project.ext.versionCodes.get(output.getFilter(com.android.build.OutputFile.ABI), 0) * 1000000 android.defaultConfig.versionCode } } } 更多参考 安卓so库你应该注意的事 http://www.voidcn.com/blog/u013278099/article/p-4944290.html Android开发不可不知的so文件知识大全 http://alphayang.community/2015/11/27/so-files-guide/ 与 .so 有关的一个长年大坑 https://zhuanlan.zhihu.com/p/21359984 Android jniLibs下目录详解.so文件http://www.jianshu.com/p/b758e36ae9b5