2016-02-01 17 views
12

Poszukuję sposobu na spakowanie natywnej biblioteki do pakietu AAR, aby można było jej użyć poprzez deklarację zależności w gradle script.Pakiet AAR Android dla biblioteki natywnej

Przez bibliotekę natywną mam na myśli zestaw plików .cpp lub skompilowaną bibliotekę statyczną i zestaw plików nagłówkowych. Mam na myśli to, że sama aplikacja wywoła bibliotekę z natywnego kodu, a nie z Javy. Innymi słowy, biblioteka potrzebna do skompilowania natywnego kodu aplikacji. Aby możliwe było łatwe zarządzanie zależnościami natywnego kodu.

Czy to możliwe?

Do tej pory mogłem tylko znaleźć wiele pytań/przykładów jak utworzyć bibliotekę macierzystą JNI z plikiem .so i jego interfejsem Java, więc lib jest tylko biblioteką Java z natywną implementacją, ale to nie jest czego potrzebuję.

+0

Okazało się, że tutaj https://github.com/googlesamples/android-ndk/tree/master/hello-libs może być jakiś ciekawy info, ale nadal nie wiem, jak spakować to wszystko do AAR – igagis

+0

Możesz zajrzeć na https://github.com/realm/realm-java - to dość złożony system kompilacji. Możesz dołączyć Realm za pomocą wtyczki Gradle. – geisshirt

+0

https://github.com/googlesamples/android-ndk/issues/261 – igagis

Odpowiedz

1

Znaleziono następujące hacky rozwiązanie problemu:

Użyj Android Experimental Gradle Wersja wtyczki 0.9.1 . Chodzi o to, aby umieścić nagłówki biblioteki i biblioteki statyczne w .aar. Nagłówki są przesyłane do ndkLibs/include i statycznych bibliotek do ndkLibs/<arch> dla każdej architektury. Następnie, w aplikacji lub innej bibliotece zależnej od tej upakowanej biblioteki, po prostu wyodrębniamy katalog ndkLibs z AAR do katalogu build w projekcie. Zobacz przykładowy plik gradle poniżej.

Plik build.gradle dla biblioteki z komentarzem:

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') 
0

Z tego Link, nie wygląda na to, że jest to możliwe. Ja wklejania zawartości poniżej:

Anatomia pliku AAR

Rozszerzenie pliku dla pliku AAR jest .aar oraz Maven typu artefakt powinien być AAR również. Sam plik jest plikiem zip zawierający następujące obowiązkowe pozycje:

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

Dodatkowo , plik AAR może zawierać jeden lub więcej z następujących opcjonalnych wpisów:

  • /obrotowe/
  • /libs/name.jar
  • /jni/abi_name/name.so (gdzie abi_name jest do androidki obsługiwane ABI)
  • /proguard.txt
  • /lint.jar

Jak wspomniano powyżej, obowiązkowy wpis zawiera słoik. Możesz jednak spróbować, ręcznie usuwając plik jar, ponownie rozpakowując kod aar i zip. Nie jestem pewien, czy to zadziała.

+0

Jest całkiem jasne, że nie ma oficjalnego sposobu na zrobienie tego, mam bezpośrednią odpowiedź od programistów tutaj https://github.com/googlesamples/android-ndk/issues/261, zamiarem pytania jest znalezienie możliwych dobrych obejść – igagis

0

chociaż ja osobiście nie próbował, znalazłem kilka kroków here:

Prawdopodobnie pośrednio [próbowała ze wspólną lib raz jakiś czas temu], a ja osobiście nie sądzę, że warto:

  • zbudować lib najpierw wygenerować statyczny lib, a jeden AAR [model.library nie przywiązują * .a do katalogu libs chociaż]
  • rozpakować URS, i umieścić * .a do folderu libs
  • znajdź miejsce dla pliku nagłówków
  • rozpakuj go z powrotem do aplikacji wewnątrz, spraw, aby był on twoją zależną biblioteką, więc zostanie wyodrębniony do folderu rozbitego; wtedy pojawia się kolorowy obraz.
  • dodać pośredni rozbity katalog aar do ścieżki włączania Myślę, że jest zbyt odlotowy i może nie być dobrym pomysłem, aby nałożyć je na swoich klientów.

Tradycyjny sposób dystrybucji plików lib i nagłówków bezpośrednio jest jeszcze lepszy, w porównaniu do powyższego hakowania. Dla bibliotekami budowlanych, CUpewnij sposób jest o wiele lepsza, kasowe hello-libs master-CUpewnij oddziału nadzieję, że to pomaga

+1

tak, ten problem z Github został zgłoszony przeze mnie, szukam tylko lepszego obejścia, które nie wymagałoby użytkownika aby ręcznie wprowadzić ścieżki włączania – igagis

Powiązane problemy