适用于本机库的Android AAR包

我正在寻找一种方法将本机库打包到AAR包中,因此可以通过gradle脚本中的依赖项声明来使用它。

本机库我指的是.cpp文件集或编译的静态库和一组头文件。 所以,我的意思是应用程序本身将从本机代码而不是Java调用库。 换句话说,库需要编译应用程序的本机代码。 这样就可以轻松管理本机代码的依赖关系。

它甚至可能吗?

到目前为止,我只能find很多关于如何使用.so文件及其Java接口创建JNI本机库的AAR的问题/示例,因此lib只是一个带有本机实现的Java库,但这不是我需要的。

find以下hacky解决问题的方法:

使用Android Experimental Gradle插件版本0.9.1。 我们的想法是将库头和静态库放入.aar。 对于每个体系结构,标头都放在ndkLibs/include和静态库到ndkLibs/ 。 然后,在应用程序或依赖于这个打包的lib的另一个lib中,我们只需从AAR ndkLibs目录提取到项目中的build目录。 请参阅下面的示例gradle文件。

带有注释的库的build.gradle文件:

 apply plugin: "com.android.model.library" model { android { compileSdkVersion = 25 buildToolsVersion = '25.0.2' defaultConfig { minSdkVersion.apiLevel = 9 targetSdkVersion.apiLevel = 9 versionCode = 1 versionName = '1.0' } ndk { platformVersion = 21 moduleName = "mylib" toolchain = 'clang' abiFilters.addAll(['armeabi', 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64', 'mips', 'mips64']) //this is default ldLibs.addAll(['android', 'log']) stl = 'c++_static' cppFlags.add("-std=c++11") cppFlags.add("-fexceptions") cppFlags.add("-frtti") //Add include path to be able to find headers from other AAR libraries cppFlags.add("-I" + projectDir.getAbsolutePath() + "/build/ndkLibs/include") } //For each ABI add link-time library search path to be able to link against other AAR libraries abis { create("armeabi") { ldFlags.add("-L" + projectDir.getAbsolutePath() + "/build/ndkLibs/armeabi") } create("armeabi-v7a") { ldFlags.add("-L" + projectDir.getAbsolutePath() + "/build/ndkLibs/armeabi-v7a") } create("arm64-v8a") { ldFlags.add("-L" + projectDir.getAbsolutePath() + "/build/ndkLibs/arm64-v8a") } create("x86") { ldFlags.add("-L" + projectDir.getAbsolutePath() + "/build/ndkLibs/x86") } create("x86_64") { ldFlags.add("-L" + projectDir.getAbsolutePath() + "/build/ndkLibs/x86_64") } create("mips") { ldFlags.add("-L" + projectDir.getAbsolutePath() + "/build/ndkLibs/mips") } create("mips64") { ldFlags.add("-L" + projectDir.getAbsolutePath() + "/build/ndkLibs/mips64") } } } //Configure this library source files android.sources { main { jni { //This does not affect AAR packaging exportedHeaders { srcDir "../../src/" } //This tells which source files to compile source { srcDirs '../../src' } } } } } //Custom Maven repository URLs to download AAR files from repositories { maven { url 'https://dl.bintray.com/igagis/android/' } } //Our custom AAR dependencies, those in turn are also packed to AAR using the same approach dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'io.github.igagis:libutki:+' compile 'io.github.igagis:libsvgdom:+' compile 'org.cairographics:cairo:+' } //=================================== //=== Extract NDK files from AARs === //This is to automatically extract ndkLibs directory from AAR to build directory before compiling any sources task extractNDKLibs { doLast { configurations.compile.each { def file = it.absoluteFile copy { from zipTree(file) into "build/" include "ndkLibs/**/*" } } } } build.dependsOn('extractNDKLibs') tasks.whenTaskAdded { task -> if (task.name.startsWith('compile')) { task.dependsOn('extractNDKLibs') } } //================================= //=== pack library files to aar === //This stuff re-packs the release AAR file adding headers and static libs to there, but removing all shared (.so) libs, as we don't need them. The resulting AAR is put to the project root directory and can be uploaded to Maven along with POM file (you need to write one by hand). def aarName = name task copyNdkLibsToAAR(type: Zip) { baseName = aarName version = "\$(version)" extension = 'aar.in' destinationDir = file('..') //put resulting AAR file to upper level directory from zipTree("build/outputs/aar/" + aarName + "-release.aar") exclude('**/*.so') //do not include shared libraries into final AAR from("../../src") { exclude('makefile') exclude('soname.txt') exclude('**/*.cpp') exclude('**/*.c') into('ndkLibs/include') } from("build/intermediates/binaries/debug/lib"){ include('**/*.a') into('ndkLibs') } } build.finalizedBy('copyNdkLibsToAAR') 

从这个链接 ,它看起来不可能。 我粘贴在内容之下:

AAR文件的剖析

AAR文件的文件扩展名为.aar,Maven工件types也应该是aar。 该文件本身是一个zip文件,包含以下必填项:

  • /AndroidManifest.xml
  • /classes.jar
  • / RES /
  • /R.txt

此外,AAR文件可能包含以下一个或多个可选条目:

  • /资产/
  • /libs/name.jar
  • /jni/abi_name/name.so(其中abi_name是Android支持的ABI之一)
  • /proguard.txt
  • /lint.jar

如上所述,强制性条目包括jar子。 但是,您可以通过解压缩aar并再次拉回来手动删除jar文件来尝试。 我不确定它是否会起作用。

虽然我没有亲自尝试过,但我在这里find了一些步骤:

可能间接[曾经尝试使用共享库],我个人认为这不值得:

  • 首先构建你的lib以生成一个静态库,并且aar [model.library不会将* .a放入libs目录中]
  • 解压缩你的aar,并将* .a放入libs文件夹
  • find头文件的位置
  • 将它拉回你的应用程序内部,将其作为你的依赖库,这样它就会被提取到爆炸的文件夹中; 然后出现了彩色图片。
  • 将中间爆炸的aar目录添加到include路径中我认为它太过于hacky并且可能不是一个好主意将它们强加给你的客户。

与上述黑客相比,传统的直接分发lib和头文件的方式仍然更好。 对于构建库,cmake方式要好得多,在master-cmake分支中检查hello-libs,希望这有助于