Androidndk开发打包时我们应该如何注意平台的兼容(x86,arm,arm-v7a)

Androidndk开发打包时我们应该如何注意平台的兼容(x86,arm,arm-v7a),第1张

很多朋友在开发 Android JNI的的时候,会遇到findlibrary returned null的错误,因为某种原因,so没有打包到apk中。下面浅析下引起该错误的原因以及平台兼容性问题。
一、没有将so打包到apk中的原因。

当你发现到findlibrary returned null的错误时,其实最直接的解决办法就是解压apk,看看apk中的x86、armeabi、armeabi-v7a文件夹中是否有对应的so,此时你可能在对应的文件夹下发现少了so,然后再去查原因即可。

一般有两方面的原因:
1apk中有对应平台的文件夹,但是文件夹里却没有对应的so。

举个例子,apk中lib下面一旦出现x86文件夹,程序运行的时候就会去加载x86对应的库,但是如果此时x86文件夹没有将so放进来,则会遇到报错。

2第三方对平台的兼容策略与自己不一致。

可能第三方选择了只支持armeabi(假设某支付sdk),但是我们的游戏在Applicationmk中配置了APP_ABI := all,如此,我们的游戏打包出 了所有平台的so,但是第三方却只有armeabi文件夹对应的so,造成程序运行异常,这种情况在开发期间最常见,一些小公司由于测试人员不足或者测试设备不足,上线后才发现这个问题也不奇怪。

二、对于平台的支持,我们应该如何选择。

armeabi-v7a确实是可以兼容armeabi的,而v7a的CPU支持硬件浮点运算,目前绝大对数设备已经是v7a了,所以为了性能上的更优,就不要为了兼容放到armeabi。 x86是可以兼容armeabi平台运行的,无论是armeabi-v7a还是armeabi,同时带来的也是性能上的损耗,另外需要指出的是,打包出的x86的so,总会比armeabi平台的体积更小,对于性能有洁癖的童鞋们,还是建议在打包so的时候支持x86。具体会有怎样的性能损耗,作者还不能说的非常清楚,可以访问下intel官方在csdn的博客。 总结一下在项目中的表现就是:

随着不断的开发迭代,apk的大小不断的增大,在用户体验上变得不太友好,因此apk的瘦身显得很有必要。

首先要apk的大小需要分析,我们才知道那部分可以瘦身

在Android Studio工具栏里,打开build–>Analyze APK, 选择要分析的APK包
或者直接从project目录下面寻找build outputs下的apk包然后双击。

从上方的apk分析图中,我们可以看出apk中什么资源占据了较多内存,然后进行瘦身优化。

在gradle使用minifyEnabled进行Proguard混淆的配置,可大大减小APP大小:

混淆时候注意配置混淆
具体配置参考 混淆模版

这里的去除并不是物理上的删除,而是编译器自动帮我们找出没有使用到的资源并在build的时候将这些资源保存为1x1的位图,因此大大缩小了打包后这些重复资源占据的空间。实测大概只有几十b大小。

只保留中文,其余几十种语言都不需要。

在程序中我们会用到很多资源,png格式或者jpg的,这些少则十多k,多着几兆。
资源多了就会影响最后apk的大小。
其实在安卓50之后,谷歌就支持了svg矢量图,我们可以直接从美工小哥哥那里拿svg图然后使用。
或者使用自带的svg资源。
使用方法:
新建Vector资源:

在这里可以选择使用系统自带的资源或者,从本地选取。

其实,我们平常用的默认的ic_launcherxml就是矢量图,点击去看看,你就会发现其中有Vector的节点。

除了矢量图可以节约本身的大小,那么我们还可以使用Tinit着色器,减少一些重复的使用。
当然这里的重复也并不是说同样的,其实在平常的开发中,我们会用到很多资源只是颜色不同而已,为了做出点击效果或者按压效果等。
其实这些不同颜色效果的都可以用同一张实现,那就是Tinit着色器。

除了直接写死,当然也可以尝试下selectorxml哦,做出按压效果。

我们平常会使用到很多JnILibs下面的so库来进行一些功能的集成,但是在接手项目或者使用别人的库的时候,看到JnILibs下面有很多不同名字包下都有同样的so文件。

这些都必须吗?都能用得着吗?
那不一定哈,具体看你使用在什么设备上面,一般来说使用一个armeabi-v7a就行了

如果程序需要上架到GooglePlay上面的,从2019年8月1日起,就必须支持64位的啦!
这点还是需要注意下哈 GooglePlay上架强制支持64位
顺便说一下这个动态库的 含义 :
简单来说就是:
Android 设备的CPU类型(通常称为”ABIs”)
armeabi-v7a: 第7代及以上的 ARM 处理器。2011年15月以后的生产的大部分Android设备都使用它
arm64-v8a: 第8代、64位ARM处理器,很少设备,三星 Galaxy S6是其中之一。
armeabi: 第5代、第6代的ARM处理器,早期的手机用的比较多。
x86: 平板、模拟器用得比较多。
x86_64: 64位的平板。

刚刚说过,我们可以使用svg矢量图来代替png等减小大小。那么如果非要使用png等又怎么办呢?
答案谷歌也给我们提供好了,那就是使用自带的webp有损压缩。
测试了大概1mb的最后就会变成100kb,压缩效果很明显,也不会出现失真太多。
使用方法:找到,然后右键,直接找到最下面的convert to WebP

最后效果

感觉还可以吧。

res资源文件混淆 我还没尝试过,希望大家可以在评论区互相启发一下怎么给apk瘦身,还有什么方法?

在安装google play service时,一定要注意,除了版本外,还要注意版本后面的编号,编号其中有3个数字,可能放在前面,也可能放在后面。这三个数字就是针对使用某种机型的。具体如下表:
App Notes:
To figure out the right version of Google Play services for your Android device, download Play Services info or go to Settings -> Apps -> Google Play services, and look at the 3-digit sequence (let's use XYZ) in the parentheses:
X defines Android version:
0 for Android <50
2 for Android 50 and 51 starting with Play Services v8
4 for Android 50 and 51 before Play Services v8, Android >= 60 after
5 for Android Wear
7 for Android 50
8 for Android TV
Y defines CPU architecture:
1 for armeabi
3 for armeabi-v7a
4 for arm64-v8a
5 for mips
7 for x86
8 for x86_64
Z defines DPI:
0 for universal
2 for 160
4 for 240
6 for 320
8 for 480
Notes:
It seems that 7YZ builds became 4YZ with Google Play services v65 If you were on 7YZ before, you should now install 4YZ
It seems that 4YZ builds got split into 2YZ for Lollipop and 4YZ for Marshmallow with Google Play services v8 If you were on 4YZ before, you should now install 2YZ in Lollipop and 4YZ in Marshmallow
Examples:
014 for Android <50 armeabi CPU 240 DPI device
438 for Android 60+ armeabi-v7a CPU 480 DPI device
876 for Android TV x86 CPU 320 DPI device

最近,我们公司的APP,要做包体积的优化,其中一个方面就是so包的优化。
对于so包的知识点,不是很清楚,特地来整理下。

这三种方案都是可以的,现在的大厂APP适配中,这三种都有,大部分是前两种。

具体选择哪一种,就看我们的考量了,要性能就是arm64-v8a,要兼容就是armeabi,要性能和兼容的平衡就是armeabi-v7a。

1armeabiv-v7a: 第7代及以上的 ARM 处理器
2arm64-v8a: 第8代、64位ARM处理器,现在很多手机使用X86的手机红米11三星 Galaxy S6是其中之一。
3armeabi: 第5代、第6代的ARM处理器,早期的手机用的比较多。
4x86: 平板、模拟器用得比较多。

使用命令:adb shell getprop roproductcpuabi

查看Android设备的CPU架构信息,可以使用命令来完成:
1、adb shell
2、cat /proc/cpuinfo

解析说明:
processor: 0/1 表示第几个核。
BogoMIPS:伪MIPS,用于测量CPU速度
Features:表示当前CPU所支持的特性,比如neon,vfp等。
CPU architecture:7表示arm-v7,8表示arm-v8

如何为安卓应用提供64位原生的支持?
必须承认,64位构建会让APK的体积变的更大,多了so库嘛
64位通常会使应用运行的更加的快,因为64位的指令集支持更高的代码运行效率,举个例子:能够使用两倍数量的寄存器,支持双精度的浮点的运算,这使得编译器可以做更加复杂的矢量化优化
使用App Bundle发布格式在GooglePlay,Apk包的体积也不会受到太大影响,GooglePlay会按照用户设备的架构仅推送所需的文件,即使提供了32位和64位的文件,根据用户设备的架构类型,只需下载最使用的一套文件
在GooglePaly上可以构架一个包含X86和X86-64的文件Bundle,而不用担心对目标ARM设备应用体积的影响
从 2019 年 8 月 1 日开始,您在 Google Play 上发布的应用必须支持 64 位架构。后续不知道国内的应用市场是否也要强制
64 位 CPU 能够为您的用户提供更快、更丰富的体验。添加 64 位的应用版本不仅可以提升性能、为未来创新创造条件,还能针对仅支持 64 位架构的设备做好准备。
1、使用以 Java 编程语言或 Kotlin 编写的代码(包括任何库或 SDK),那么就表示该应用已经支持 64 位设备
2、应用使用了任何原生代码,或者不确定自己的应用是否使用了这类代码,那么需要评估应用并相应采取措施。
是否使用了原生代码?
使用了任何 C/C++(原生)代码。
与任何第三方原生库关联。
通过使用原生库的第三方应用构建程序构建而成。
应用是否包含 64 位库?
要确定应用是否包含 64 位库,最简单的方法就是检查 APK 文件的结构,在编译时,APK 会与应用所需的所有原生库打包在一起。应用无需支持所有 64 位架构,但对于支持的每种原生 32 位架构,则应用都必须包含相应的 64 位架构。,说通俗一点就是成对的出现应当支持的架构
对于 ARM 架构,32 位库位于 armeabi-v7a 中。对应的 64 位库位于 arm64-v8a 中
对于 x86 架构, x86(32 位)和 x86_64(64 位)
分析APK,只有32的架构
imagepng
分析APK,32位和64位的架构
imagepng
如果使用 Android Studio 或Gradle 进行编译,如何为安卓应用提供64位原生的支持呢?
大多数 Android Studio 项目都使用 Gradle 作为底层编译系统,因此本部分适用于使用这两种工具进行编译的情况。针对原生代码进行编译很简单,只需将 arm64-v8a和/或 x86_64(取决于您要支持的架构)添加到应用的“buildgradle”文件中的 ndkabiFilters 设置
在 buildgradle 加入ndkabiFilters 'armeabi-v7a','arm64-v8a','x86','x86_64'
imagepng
如果使用 CMake 进行编译?
可以通过将 arm64-v8a 传递到“-DANDROID_ABI”参数来编译 64 位 ABI
:: Command Line
> cmake -DANDROID_ABI=arm64-v8a … or
> cmake -DANDROID_ABI=x86_64 …

使用 ndk-build 进行编译?JNI
可以通过 APP_ABI 变量修改“appmk”文件,从而编译 64 位 ABI:
APP_ABI := armeabi-v7a arm64-v8a x86 x86_64


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/13409958.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-07-30
下一篇 2023-07-30

发表评论

登录后才能评论

评论列表(0条)

保存