Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/225.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用于本机库的Android AAR包_Android_Android Ndk_Android Gradle Plugin_Aar_Maven Central - Fatal编程技术网

用于本机库的Android AAR包

用于本机库的Android AAR包,android,android-ndk,android-gradle-plugin,aar,maven-central,Android,Android Ndk,Android Gradle Plugin,Aar,Maven Central,我正在寻找一种将本机库打包成AAR包的方法,这样就可以通过gradle脚本中的依赖项声明来使用它 本机库是指一组.cpp文件或编译的静态库和一组头文件。因此,我的意思是,应用程序本身将从本机代码调用库,而不是从Java调用库。换句话说,库需要编译应用程序的本机代码。这样就可以轻松地管理本机代码的依赖关系 有可能吗 到目前为止,我只能找到许多问题/示例,说明如何使用.So文件及其Java接口对JNI本机库进行AAR,因此该库只是一个带有本机实现的Java库,但这不是我所需要的。由此看来,这似乎不可

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

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

有可能吗

到目前为止,我只能找到许多问题/示例,说明如何使用.So文件及其Java接口对JNI本机库进行AAR,因此该库只是一个带有本机实现的Java库,但这不是我所需要的。

由此看来,这似乎不可能。我正在粘贴以下内容:

AAR文件的剖析

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

  • /AndroidManifest.xml
  • /classes.jar
  • /res/
  • /R.txt
此外,AAR文件可包括以下一个或多个可选条目:

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

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

虽然我个人没有尝试过,但我发现了一些步骤:

可能是间接的(不久前曾尝试过共享lib),我个人认为这不值得:

  • 首先构建您的库以生成一个静态库和一个aar [但是model.library不会将*.a塞进libs目录]
  • 解压缩aar,并将*.a放入libs文件夹
  • 为您的头文件找到一个位置
  • 将其压缩回应用程序中的aar,使aar成为您的依赖库,以便将其解压缩到分解的aar文件夹中;然后彩色图片出现了
  • 将中间分解的aar目录添加到include路径中 我认为这太老套了,把这些强加给你的客户可能不是一个好主意
与上述黑客攻击相比,直接分发lib和头文件的传统方式仍然更好。
对于构建LIB,cmake方式要好得多,请在master cmake branch中查看hello LIB,希望这有助于更新2020-06-20=

现在,有一种方法可以很好地解决这个问题。 感谢它的作者和@Paulo Costa的指点

=过时=

找到了该问题的以下黑客解决方案:

使用Android实验Gradle插件版本0.9.1。 其思想是将库头和静态库放入.aar中。 对于每个体系结构,标题被放置到
ndkLibs/include
,静态libs被放置到
ndkLibs/
。然后,在应用程序中或依赖于此压缩库的另一个库中,我们只需将
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')

手动破解gradle脚本是可行的,但是很痛苦而且容易出错

我最近发现了一个插件,它神奇地将头捆绑到AAR文件中,并提取它们,并在添加依赖项时设置构建脚本:

在可重用库上:
  • 添加导出插件:

    apply plugin: 'com.ydq.android.gradle.native-aar.export'
    
    apply plugin: 'com.ydq.android.gradle.native-aar.import'
    
  • 定义头文件的位置:

    nativeBundleExport {
        headerDir = "${project.projectDir}/src/main/jni/include"
    }
    
在使用它的模块上:
  • 添加导入插件:

    apply plugin: 'com.ydq.android.gradle.native-aar.export'
    
    apply plugin: 'com.ydq.android.gradle.native-aar.import'
    
  • 包括${ANDROID\u GRADLE\u NATIVE\u BUNDLE\u PLUGIN\u 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)
    

我发现这里可能有一些有趣的信息,但我仍然不知道如何将这些信息打包到AAR中,您可以看一下——这是一个相当复杂的构建系统。你可以使用Gradle插件包含Realm。试试@AlexCohn上的android-fat-aar-Gradle脚本,这对解决我的问题有什么帮助?我看了一下,这似乎根本不相关。很明显,没有官方的方式来做这件事,我从这里的开发者那里得到了一个直接的答案,这个问题的目的是找到可能的好办法。你是否将可选条目包括在AAR中?更具体地说,
libs
jni
是的,github的问题是由我提交的,我只是在寻找更好的解决方法,不需要用户手动输入包含路径。谷歌已经放弃了实验性的gradle插件,所以这种方法现在有点过时了。但也许标准插件也可以实现类似的功能。我还编写了自己的替代插件:有没有办法在基于CMake的android build中使用它?AndroidNativeBundle支持它,但我还没有测试过。NdkLibraries可能在导出时起作用,但是没有导入代码——PRs Welcome我正在考虑尝试AndroidNativeBundle,只是想问你为什么不喜欢它,以至于你最终编写了自己的插件?它有什么缺点吗?