Пакет Android AAR для собственной библиотеки

Я ищу способ упаковки собственной библиотеки в пакет AAR, поэтому можно было бы использовать ее через объявление зависимостей в gradle script.

По собственной библиотеке я имею в виду набор .cpp файлов или скомпилированную статическую библиотеку и набор файлов заголовков. Итак, я имею в виду, что само приложение вызовет библиотеку из собственного кода, а не из Java. Другими словами, библиотека должна была скомпилировать собственный код приложения. Таким образом, можно будет легко управлять зависимостями собственного кода.

Возможно ли это?

До сих пор я мог найти только много вопросов/примеров того, как создать AAR из JNI-родной библиотеки с .so файлом и его интерфейсом Java, поэтому lib просто Java lib с собственной реализацией, но это не то, что Мне нужно.

Ответ 1

Нашел следующее хакерское решение проблемы:

Используйте Android Experimental Gradle версия плагина 0.9.1. Идея состоит в том, чтобы помещать заголовки библиотек и статические библиотеки в .aar. Заголовки помещаются в ndkLibs/include и static libs на ndkLibs/<arch> для каждой архитектуры. Затем в приложении или другой библиотеке, которая зависит от этой упакованной библиотеки, мы просто извлекаем каталог 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')

Ответ 2

Из Ссылка, похоже, что это невозможно. Я вставляю ниже содержимого:

Анатомия файла 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
  • /lint.jar

Как указано выше, обязательная запись включает банку. Тем не менее, вы можете попробовать, вручную удалив файл jar, разархивируя aar и zip обратно. Я не уверен, будет ли это работать.

Ответ 3

Хотя я лично не пытался, я нашел несколько шагов здесь:

Вероятно, косвенно [попытался с общим lib один раз назад], и я лично не думаю, что это стоит:

  • сначала создайте свою библиотеку, чтобы создать статический lib, и один aar [model.library не вставляет *.a в каталог libs, хотя]
  • разархивируйте свой аар и поместите *.a в папку libs
  • найдите место для файлов заголовков.
  • запишите его обратно в aar внутри вашего приложения, сделайте aar зависимым от lib, поэтому он будет извлечен в папку с взорванными aar; затем появляется цветное изображение.
  • добавить промежуточную вложенную директорию aar в путь включения Я думаю, что это слишком хаки и, возможно, не очень хорошая идея навязать их своим клиентам.

традиционный способ распространения файлов lib и заголовков напрямую по-прежнему лучше, по сравнению с вышеупомянутым взломом. Для создания libs путь cmake намного лучше, checklo hello-libs в ветке master-cmake, надеюсь, что это поможет