web-dev-qa-db-ja.com

AndroidネイティブライブラリのAARパッケージ

ネイティブライブラリをAARパッケージにパッケージ化する方法を探しているので、gradleスクリプトの依存関係宣言を介してそれを使用できます。

ネイティブライブラリとは、.cppファイルのセットまたはコンパイルされた静的ライブラリとヘッダーファイルのセットを意味します。つまり、アプリ自体がライブラリをJavaではなくネイティブコードから呼び出すということです。つまり、アプリのネイティブコードをコンパイルするために必要なライブラリです。そのため、ネイティブコードの依存関係を簡単に管理できるようになります。

可能ですか?

これまでのところ、.soファイルとそのJavaインターフェースを使用してJNIネイティブライブラリのAARを作成する方法の多くの質問/例を見つけることができたので、libはJava libですが、これは私が必要とするものではありません。

22
igagis

問題に対する次のハックな解決策が見つかりました:

Android実験的Gradleプラグインバージョン0.9.1。を使用します。アイデアは、ライブラリヘッダーと静的ライブラリを.aarに配置することです。ヘッダーは、アーキテクチャごとにndkLibs/includeに静的ライブラリをndkLibs/<Arch>に配置します。次に、アプリ、またはこのパックされたライブラリに依存する別のライブラリで、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')
5
igagis

個人的には試していませんが、いくつかの手順を見つけました here

おそらく間接的です[しばらく前に共有ライブラリを試してみました]と私は個人的には価値があるとは思いません:

  • 最初にlibをビルドして静的libを生成し、1つのaar [model.libraryは* .aをlibsディレクトリに入れません]
  • aarを解凍し、*。aをlibsフォルダーに入れます。
  • ヘッダーファイルの場所を見つける
  • それをアプリ内のaarに圧縮し、aarを依存ライブラリにして、exploded-aarフォルダーに抽出されるようにします。次に、カラフルな画像が表示されます。
  • 中間の展開されたaarディレクトリをインクルードパスに追加します。これはあまりにもハッキーであり、それらを顧客に課すことはお勧めできないと思います。

libとヘッダーファイルを直接配布する従来の方法は、上記のハッキングと比較してさらに優れています。ライブラリの構築については、cmakeの方法がはるかに優れています。master-cmakeブランチでhello-libsをチェックアウトしてください。これが役立つことを願っています

0
Abdul Wasae

この Link からは、可能ではないようです。私は内容の下に貼り付けています:

AARファイルの構造

AARファイルのファイル拡張子は.aarであり、Mavenアーティファクトタイプもaarである必要があります。ファイル自体は、次の必須エントリを含むZipファイルです。

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

さらに、AARファイルには、次のオプションのエントリが1つ以上含まれている場合があります。

  • / assets /
  • /libs/name.jar
  • /jni/abi_name/name.so(ここでabi_nameはAndroidサポートされているABIの1つです)
  • /proguard.txt
  • /lint.jar

上記のように、必須エントリにはjarが含まれます。ただし、aarとZipを再度解凍してjarファイルを手動で削除することにより、もう一度試すことができます。それがうまくいくかどうかはわかりません。

0
manishg

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)
    
0
Paulo Costa