如何为 Android 不同平台打包原生预建库
Posted
技术标签:
【中文标题】如何为 Android 不同平台打包原生预建库【英文标题】:How to package native prebuilts libraries for Android different platforms 【发布时间】:2021-05-09 16:18:45 【问题描述】:为了编译原生预建库,我们使用 NDK 工具链和这两个选项 -Dandroid_ABI
和 -DANDROID_PLATFORM
,所以如果我们支持 android-28
、android-29
平台和 armeabi-v7a
、arm64-v8a
、x86
, x86_6
ABIs 我们将要生成的库集:
.
├── android-28
│ ├── arm64-v8a
│ │ └── libMy.so
│ ├── armeabi-v7a
│ │ └── libMy.so
│ ├── x86
│ │ └── libMy.so
│ └── x86_64
│ └── libMy.so
└── android-29
├── arm64-v8a
│ └── libMy.so
├── armeabi-v7a
│ └── libMy.so
├── x86
│ └── libMy.so
└── x86_64
└── libMy.so
我们可以很容易地在Android cmake中使用这些获得的预编译,因为它支持$ANDROID_PLATFORM
和$ANDROID_ABI
变量,例如CMakeLists.txt
:
...
list(APPEND CMAKE_FIND_ROOT_PATH $THIRDPARTY_PREBUILT_DIR/$ANDROID_PLATFORM/$ANDROID_ABI/mylib)
...
但是我似乎不清楚将这些预构建的内容打包到 APK 中,因为 app/src/main/jniLibs
不支持平台层次结构,只支持 ABI:
.
└── jniLibs
├── arm64-v8a
│ └── libMy.so
├── armeabi-v7a
│ └── libMy.so
├── x86
│ └── libMy.so
└── x86_64
└── libMy.so
在输出 app-debug.apk/lib
中也是相同的结构。
所以问题:为什么我们在工具链和Android cmake 选项中有不同平台的选项,但原生库(jni 库)的打包却忽略了它们?
我使用Android Studio 3.6.3
和Gradle 5.6.4
。
【问题讨论】:
您是否需要为这两个平台级别提供单独的库,或者您可以将它们组合成一个库?如果它们确实需要单独的库,那么您可能需要为不同的最低 API 级别构建单独的应用程序包/APK(参见例如developer.android.com/studio/build/…)。 @Michel:感谢您的评论。我需要构建一些第三方库,然后像 Android 应用程序项目中的预建库一样使用它们,但是为了编译它们,NDK 工具链需要我指定-DANDROID_PLATFORM
参数,但这些库不依赖于特定的 Android API(28 或 29 或其他)只有应用程序需要支持 28 和 29。所以我会像 @Dan Albert 回答的那样做 - 将应用最旧的版本来编译第三方库。
【参考方案1】:
您可以选择平台作为构建的一部分,因为这决定了您的代码将与哪些设备兼容。如果您的目标是 21,则不能保证您的代码可以在比 Lollipop 更早的任何设备上运行。
不过,应用程序是向前兼容的,因此如果您构建 21 版,您将在 Lollipop 和之后的所有内容上运行(极少数例外,只要您坚持公共 API 的定义行为,就非常罕见)。这就是为什么您不需要为每个平台打包库,只需要为您支持的最旧的平台打包。
【讨论】:
以上是关于如何为 Android 不同平台打包原生预建库的主要内容,如果未能解决你的问题,请参考以下文章
跨平台:如何在 UWP 中设置不同的递增内部版本号并保持版本名称,如 iOS/Android