我正在寻找一种将本机库打包成AAR包的方法,因此可以通过gradle脚本中的依赖项声明来使用它。
本机库是指.cpp文件集或编译的静态库和一组头文件。所以,我的意思是应用程序本身将从本机代码调用库,而不是从Java调用。换句话说,库需要编译应用程序的本机代码。这样就可以轻松管理本机代码的依赖关系。
甚至可能吗?
到目前为止,我只能找到很多关于如何使用.so文件及其Java接口创建JNI本机库的AAR的问题/示例,因此lib只是一个带有本机实现的Java库,但这不是什么我需要。
答案 0 :(得分:3)
找到了以下针对此问题的hacky解决方案:
使用Android Experimental Gradle插件版本0.9.1。
我们的想法是将库头和静态库放入.aar。
对于每个体系结构,标头都放到ndkLibs/include
和静态库到ndkLibs/<arch>
。然后,在应用程序或依赖于这个打包的lib的另一个lib中,我们只需将ndkLibs
目录从AAR提取到项目中的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')
答案 1 :(得分:1)
手动修改gradle脚本是可行的,但是很痛苦且容易出错。
我最近发现了一个插件,它在添加依赖项时将标头神奇地捆绑到AAR文件中,并提取它们并设置构建脚本:https://github.com/howardpang/androidNativeBundle
添加导出插件:
apply plugin: 'com.ydq.android.gradle.native-aar.export'
定义头文件的位置:
nativeBundleExport {
headerDir = "${project.projectDir}/src/main/jni/include"
}
添加导入插件:
apply plugin: 'com.ydq.android.gradle.native-aar.import'
将include ${ANDROID_GRADLE_NATIVE_BUNDLE_PLUGIN_MK}
添加到Android.mk
中依赖于它的每个模块中:
include $(CLEAR_VARS)
LOCAL_SRC_FILES := myapp.cpp \
LOCAL_MODULE := myapp
LOCAL_LDLIBS += -llog
include ${ANDROID_GRADLE_NATIVE_BUNDLE_PLUGIN_MK}
include $(BUILD_SHARED_LIBRARY)
答案 2 :(得分:0)
从Link开始,它看起来不可能。我粘贴在内容之下:
AAR文件剖析
AAR文件的文件扩展名为.aar,Maven工件类型也应该是aar。该文件本身是一个zip文件,包含以下必填项:
此外,AAR文件可能包含以下一个或多个可选条目:
如上所述,强制性条目包括一个罐子。但是,您可以通过解压缩aar并再次拉回来手动删除jar文件来尝试。我不确定它是否会起作用。
答案 3 :(得分:0)
虽然我没有亲自尝试过,但我找到了许多步骤here:
可能间接[曾经尝试使用共享库],我个人认为不值得: