如何减少 Android 需要 openCv lib 的应用程序的 apk 大小(仅用于图像处理)
How to reduce the apk size of Android app which need openCv lib( only for Image processing)
我正在使用 min SDK 15
构建一个 Android 应用程序,它使用 OpenCV library.The 问题是当我构建它的 apk 大小超过 60
MB不是很大。
我检查了应用程序文件,我可以看到由于 libopencv_java3.so
文件在所有体系结构中太大,例如 amr64
、armeabi
、mips
, x86
等等
我只对图像使用 opneCv processing.This 库有很多其他功能,如视频处理、3d 图像、对象检测等等,我的应用程序不需要这些功能,比如
如果我删除所有这些文件并构建 APK,那么大小将减少 50 MB,但要使此应用正常运行,我需要安装 OpenCVManager
到 运行 我的应用。
有什么方法可以减小我的 apk 大小吗?
或者是否可以仅从 OpenCV
中提取我感兴趣的特征并为这些特征创建 .so
?
您不能删除库 libopencv_java3.so
,它是必需的。
Is there any way by which I can reduce my apk size?
无需修改库 libopencv_java3.so
,您可以为不同的架构构建多个 apk,而不是打包一个平面 APK。只有 libopencv_java3.so
的一个拱门将被打包到您的拆分 APK 中。例如,您可以使用下面的配置只为 x86
、armeabi-v7a
和 mips
架构构建 build.gradle
splits {
abi {
enable true
reset()
include "x86", "armeabi-v7a", "mips"
universalApk false
}
}
有关通过拆分减小 apk 大小的更多信息,请参阅 here。
Or is it possible just to extract only the feature from OpenCV which I am interested in and create .so for those features?
当然可以。 opencv
的构建过程是完全自定义的。如果您已经知道如何为 Android 构建 opencv,请直接转到 步骤 2。
步骤 1
- 获取 opencv
的来源
- 创建目录
opencv_build
- 更改为您刚刚克隆的
opencv
的根目录
- 调用构建脚本
platforms/android/build_sdk.py --ndk_path $ANDROID_NDK_ROOT --sdk_path $ANDROID_SDK_ROOT ../opencv_build .
备注
构建过程需要android
命令来构建apk,所以AndroidSDK工具版本必须小于25.3.0
,来自25.3.0
,android
命令已被删除。
第 2 步
假设 运行 上面的 步骤 1 正确。这里我以armeabi-v7a
为例。
- 转到目录
opencv_build/o4a/lib/armeabi-v7a
- 你会发现许多*.a 用于不同的 opencv 模块,库
libopencv_java3.so
也在这个目录中
从您需要的模块创建一个小型版本共享库,例如
$ arm-linux-androideabi-gcc -shared -o libopencv_tiny.so --sysroot=$ANDROID_NDK_ROOT/platforms/android-9/arch-arm -Wl,--whole-archive libopencv_core.a libopencv_imgcodecs.a libopencv_imgproc.a -Wl,--no-whole-archive
$ du -h libopencv_tiny.so
5.2M libopencv_tiny.so
$ arm-linux-androideabi-strip --strip-unneeded libopencv_tiny.so
$ du -h libopencv_tiny.so
4.1M libopencv_tiny.so
$ du -h libopencv_java3.so
9.8M libopencv_java3.so
包含 core
、image codecs
和 image proc
的微型版本在剥离后的大小为 4.1M
,但完整版本 libopencv_java3.so
的大小为9.8M
.
我使用libopencv_tiny.so
作为名称只是为了方便,您必须在您的项目中使用相同的名称libopencv_java3.so
。否则Java中System.loadLibrary
找不到原生库
对于您需要的其余架构,例如 arm64-v8a
,执行相同的操作。
对我来说, 第二个答案是最好的解决方案,但我陷入了这个过程。所以,我通过apk split解决了这个问题。您需要上传与平台相关的 apk,并且通用 apk.It 将是理想的,因为 OpenCV 不提供在模块级别添加依赖项。
如果平台不匹配,将下载通用apk。Here 写得很好关于apk 发布多个apk 的博客。您需要维护相同的应用程序 ID、密钥库、相同的应用程序版本但不同的代码版本
步骤 1。为 spk 拆分添加 gradle 代码。包括您要为其创建单独的 apk 的体系结构。
android{
//......
splits {
abi {
enable true
reset()
include "armeabi","armeabi-v7a",'arm64-v8a',"mips","x86","x86_64",'arm64-v8a'
universalApk true
}
}
}
步骤 2。为不同平台的不同代码版本添加以下代码。
android{
//......
}
ext.versionCodes = ['armeabi': 3, 'armeabi-v7a': 4, 'arm64-v8a': 5,
mips: 6, 'x86': 7, 'x86_64': 8]
import com.android.build.OutputFile
// For each APK output variant, override versionCode with a combination
// of ABI APK value * 1000 + defaultConfig.versionCode
android.applicationVariants.all { variant ->
// assign different version code for each output
variant.outputs.each { output ->
def abiFilter = output.getFilter(OutputFile.ABI)
def abiMultiplier = 0
if (abiFilter != null) {
abiMultiplier = project.ext.versionCodes.get(abiFilter)
}
output.versionCodeOverride =
abiMultiplier * 1000 + android.defaultConfig.versionCode
}
}
例如,如果初始版本代码为 1,则生成的代码将为:
armeabi -> 3001
armeabi-v7a -> 4001
arm64-v8a -> 5001
mips -> 6001
x86 -> 7001
x86_64 -> 8001
你的 Gradle 代码看起来像这样。
android{
//......
splits {
abi {
enable true
reset()
include "armeabi","armeabi-v7a",'arm64-
v8a',"mips","x86","x86_64",'arm64-v8a'
universalApk true
}
}
ext.versionCodes = ['armeabi': 3, 'armeabi-v7a': 4, 'arm64-v8a': 5,
mips: 6, 'x86': 7, 'x86_64': 8]
import com.android.build.OutputFile
android.applicationVariants.all { variant ->
variant.outputs.each { output ->
def abiFilter = output.getFilter(OutputFile.ABI)
def abiMultiplier = 0
if (abiFilter != null) {
abiMultiplier = project.ext.versionCodes.get(abiFilter)
}
output.versionCodeOverride =
abiMultiplier * 1000 + android.defaultConfig.versionCode
}
}
现在您需要将所有apk 一个一个地发布到playstore 上。
注意:发布时请确保保留所有平台和通用 apk。
我正在使用 min SDK 15
构建一个 Android 应用程序,它使用 OpenCV library.The 问题是当我构建它的 apk 大小超过 60
MB不是很大。
我检查了应用程序文件,我可以看到由于 libopencv_java3.so
文件在所有体系结构中太大,例如 amr64
、armeabi
、mips
, x86
等等
我只对图像使用 opneCv processing.This 库有很多其他功能,如视频处理、3d 图像、对象检测等等,我的应用程序不需要这些功能,比如
如果我删除所有这些文件并构建 APK,那么大小将减少 50 MB,但要使此应用正常运行,我需要安装 OpenCVManager
到 运行 我的应用。
有什么方法可以减小我的 apk 大小吗?
或者是否可以仅从 OpenCV
中提取我感兴趣的特征并为这些特征创建 .so
?
您不能删除库 libopencv_java3.so
,它是必需的。
Is there any way by which I can reduce my apk size?
无需修改库 libopencv_java3.so
,您可以为不同的架构构建多个 apk,而不是打包一个平面 APK。只有 libopencv_java3.so
的一个拱门将被打包到您的拆分 APK 中。例如,您可以使用下面的配置只为 x86
、armeabi-v7a
和 mips
架构构建 build.gradle
splits {
abi {
enable true
reset()
include "x86", "armeabi-v7a", "mips"
universalApk false
}
}
有关通过拆分减小 apk 大小的更多信息,请参阅 here。
Or is it possible just to extract only the feature from OpenCV which I am interested in and create .so for those features?
当然可以。 opencv
的构建过程是完全自定义的。如果您已经知道如何为 Android 构建 opencv,请直接转到 步骤 2。
步骤 1
- 获取 opencv 的来源
- 创建目录
opencv_build
- 更改为您刚刚克隆的
opencv
的根目录 - 调用构建脚本
platforms/android/build_sdk.py --ndk_path $ANDROID_NDK_ROOT --sdk_path $ANDROID_SDK_ROOT ../opencv_build .
备注
构建过程需要android
命令来构建apk,所以AndroidSDK工具版本必须小于25.3.0
,来自25.3.0
,android
命令已被删除。
第 2 步
假设 运行 上面的 步骤 1 正确。这里我以armeabi-v7a
为例。
- 转到目录
opencv_build/o4a/lib/armeabi-v7a
- 你会发现许多*.a 用于不同的 opencv 模块,库
libopencv_java3.so
也在这个目录中 从您需要的模块创建一个小型版本共享库,例如
$ arm-linux-androideabi-gcc -shared -o libopencv_tiny.so --sysroot=$ANDROID_NDK_ROOT/platforms/android-9/arch-arm -Wl,--whole-archive libopencv_core.a libopencv_imgcodecs.a libopencv_imgproc.a -Wl,--no-whole-archive $ du -h libopencv_tiny.so 5.2M libopencv_tiny.so $ arm-linux-androideabi-strip --strip-unneeded libopencv_tiny.so $ du -h libopencv_tiny.so 4.1M libopencv_tiny.so $ du -h libopencv_java3.so 9.8M libopencv_java3.so
包含 core
、image codecs
和 image proc
的微型版本在剥离后的大小为 4.1M
,但完整版本 libopencv_java3.so
的大小为9.8M
.
我使用libopencv_tiny.so
作为名称只是为了方便,您必须在您的项目中使用相同的名称libopencv_java3.so
。否则Java中System.loadLibrary
找不到原生库
对于您需要的其余架构,例如 arm64-v8a
,执行相同的操作。
对我来说,
如果平台不匹配,将下载通用apk。Here 写得很好关于apk 发布多个apk 的博客。您需要维护相同的应用程序 ID、密钥库、相同的应用程序版本但不同的代码版本
步骤 1。为 spk 拆分添加 gradle 代码。包括您要为其创建单独的 apk 的体系结构。
android{
//......
splits {
abi {
enable true
reset()
include "armeabi","armeabi-v7a",'arm64-v8a',"mips","x86","x86_64",'arm64-v8a'
universalApk true
}
}
}
步骤 2。为不同平台的不同代码版本添加以下代码。
android{
//......
}
ext.versionCodes = ['armeabi': 3, 'armeabi-v7a': 4, 'arm64-v8a': 5,
mips: 6, 'x86': 7, 'x86_64': 8]
import com.android.build.OutputFile
// For each APK output variant, override versionCode with a combination
// of ABI APK value * 1000 + defaultConfig.versionCode
android.applicationVariants.all { variant ->
// assign different version code for each output
variant.outputs.each { output ->
def abiFilter = output.getFilter(OutputFile.ABI)
def abiMultiplier = 0
if (abiFilter != null) {
abiMultiplier = project.ext.versionCodes.get(abiFilter)
}
output.versionCodeOverride =
abiMultiplier * 1000 + android.defaultConfig.versionCode
}
}
例如,如果初始版本代码为 1,则生成的代码将为:
armeabi -> 3001
armeabi-v7a -> 4001
arm64-v8a -> 5001
mips -> 6001
x86 -> 7001
x86_64 -> 8001
你的 Gradle 代码看起来像这样。
android{
//......
splits {
abi {
enable true
reset()
include "armeabi","armeabi-v7a",'arm64-
v8a',"mips","x86","x86_64",'arm64-v8a'
universalApk true
}
}
ext.versionCodes = ['armeabi': 3, 'armeabi-v7a': 4, 'arm64-v8a': 5,
mips: 6, 'x86': 7, 'x86_64': 8]
import com.android.build.OutputFile
android.applicationVariants.all { variant ->
variant.outputs.each { output ->
def abiFilter = output.getFilter(OutputFile.ABI)
def abiMultiplier = 0
if (abiFilter != null) {
abiMultiplier = project.ext.versionCodes.get(abiFilter)
}
output.versionCodeOverride =
abiMultiplier * 1000 + android.defaultConfig.versionCode
}
}
现在您需要将所有apk 一个一个地发布到playstore 上。
注意:发布时请确保保留所有平台和通用 apk。