Blick durch den gradle Plugin-Code zu konfigurieren, fand ich die folgende, die dazu beigetragen benutz ich sowohl NDK und vorkompilierte nativen Bibliotheken:
einfach Links in vorgefertigte native Bibliotheken, nur einen NDK Abschnitt zu Ihrer Aufgabe hinzufügen zum Beispiel, ich habe es in productFlavors unten hinzugefügt der abiFilter ist der Ordner mit dem libs nennen.. sind gespeichert in. abiFilters bedeutet, dass beide Libs aus der kommagetrennten Liste zu deinem endgültigen APK hinzugefügt werden (also könntest du theoretisch "armeabi", "armea" V7A“, "x86" und "mips" alle in einer APK, und die O/S würde die unterstützte Architektur lib wählt bei der Installation):
productFlavors {
arm {
ndk {
abiFilters "armeabi", "armeabi-v7a"
}
}
x86 {
ndk {
abiFilter "x86"
}
}
}
In diesem Beispiel wird der Arm baut eine APK erstellen mit die V5- und V7A-Armbibliotheken darin, und der x86-Build wird ein APK mit nur x86-Bibliotheken darin erstellen. Dies wird nach den nativen Bibliotheken in Ihrem Projekt jniLibs-Verzeichnis suchen. Das Verzeichnis jniLibs sollte wie das alte jni-Verzeichnis strukturiert sein, d. H.:
[project]/[app]/src/main/jniLibs/armeabi/libmyNative.so
[project]/[app]/src/main/jniLibs/armeabi-v7a/libmyNative.so
[project]/[app]/src/main/jniLibs/x86/libmyNative.so
Dann können Sie es in Java wie folgt laden:
Jetzt
static
{
loadLibrary("myNative");
}
, lassen Sie uns hängt von einer anderen eine native Bibliothek sagen. Sie müssen (wenn Ihr min API API 17 oder niedrigere Einstellung) laden die abhängigen Bibliotheken zuerst:
static
{
loadLibrary("myDependency");
loadLibrary("myNative");
}
Sie können auch die NDK platzieren {} Abschnitt in Ihrem DefaultConfig oder eine buildType (wie Debug oder Release oder was auch immer sonst können Sie verwenden). Zum Beispiel:
buildTypes {
debug {
ndk {
abiFilters "armeabi", "armeabi-v7a"
}
}
}
von prebuilt, ich meine 3rd-Party-Libs Sie heruntergeladen oder eine Bibliothek Sie das NDK Werkzeugkette oder Ihr eigenes ARM Toolchain (nicht der NDK-Build-Skript selbst) gebaut werden. In API 18 haben sie ein seit langem bestehendes Architekturproblem behoben, das verhinderte, dass der native lib loader Abhängigkeiten automatisch "lud", weil er das lib-Verzeichnis der Anwendung nicht kannte (Sicherheitsgründe usw.). Wenn in API 18 und höher myNative von myDependency abhängig ist, können Sie einfach loadLibrary ("myNative") aufrufen und das Betriebssystem wird myDependency laden. VERLASSEN Sie sich jedoch nicht darauf, bis die Marktdurchdringung von Geräten mit API 17 und niedriger für Sie akzeptabel ist.
Um explizit NDK Bibliotheken Von Quelle in der aktuellen Version von Android Studio bauen, können Sie folgendes tun:
Stellen Sie den ndk.dir Wert in Ihrem local.properties zu-zu-Punkt NDK home wie zuvor erwähnt. Weiß jemand, ob Sie env vars direkt in local.properties verwenden können? :)
In Ihrer build.gradle Datei, um so etwas zu Ihrer Aufgabe hinzufügen (wieder kann sein DefaultConfig, debuggen, Freigabe, ein productFlavor, usw.):
ndk {
moduleName "myNDKModule"
stl "stlport_shared"
ldLibs "log", "z", "m"
cFlags "-I/some/include/path"
}
Dies ist die grundlegende Struktur mit Derzeit unterstützte Typen (moduleName, stl, ldLibs und cFlags). Ich schaute und fand nicht mehr als das. Es gibt ein Problem, das ich mit ldLibs glaube, weil es automatisch "-l" an die Vorderseite jedes obigen Feldes hinzufügt. Sie können es aber täuschen (ich musste) mit: ldLibs "log -lz -lm -Wl, -whole-archive -l/pfad/zu/someOtherLib -Wl, -no-whole-arch"
In dieser Zeile markieren Sie einfach bis zum Ende des ersten Parameters, um Parameter hinzuzufügen, die nicht mit -l beginnen, damit Sie sich jetzt zurechtfinden. Im obigen Fall binde ich eine ganze statische Bibliothek in mein NDK-Modul zur Verwendung von innerhalb von Java. Ich habe den Google-Entwickler gebeten, zusätzliche Funktionen hinzuzufügen, um diese oder sogar die Möglichkeit zu schaffen, Ihre eigene Android.mk-Datei in den NDK-Build-Prozess zu integrieren, aber da dies alles neu ist, kann es eine Weile dauern.
Derzeit, was auch immer Sie in build.gradle setzen löscht das Temp-Build-Verzeichnis und erstellt es jedes Mal neu, so dass, wenn Sie den Graddle Android-Plugin-Quellcode herunterladen und ändern möchten (es wäre lustig), gibt es einige "machen Es ist nötig, dass deine Sachen in den Build kopiert werden. Das android-Skript, das diese ndk-Unterstützung bereitstellt, generiert im Wesentlichen eine Android.mk-Datei und erstellt das NDK-System in einem temporären Verzeichnis.
Für eine Sekunde abgelenkt.Der Modulname sollte ac oder CPP-Datei in Ihrem Projekt unter dem jni Verzeichnis wie entsprechen:
[project]/[app]/src/main/jni/myNDKModule.cpp
Der stl Wert sollte auf einen Wert von „stlport_shared“ oder „stlport_static“ gesetzt werden, wenn Sie die STLport Bibliotheken verwenden für C++. Sie können stl verlassen, wenn Sie keine erweiterte C++ - Unterstützung benötigen. Denken Sie daran, dass Android standardmäßig nur grundlegende C++ - Unterstützung bietet. Zeigen Sie für andere unterstützte C++ - Bibliotheken Ihre NDK-Dokumentationsrichtlinien in dem NDK an, das Sie downloaden. Beachten Sie, dass die Variable libstlport_shared.so aus dem Verzeichnis sources/cxx-stl/stlport/libs des NDK in die lib-Verzeichnisse Ihres APK kopiert wird, indem Sie sie hier auf stlport_shared setzen. Es behandelt auch den Include-Pfad im Compiler (technisch macht das nicht alles, sondern das Android-NDK-Build-System). Also legen Sie keine eigene Kopie von stlport in Ihr jniLibs-Verzeichnis.
Schließlich denke ich, cFlags ist ziemlich offensichtlich.
Sie können ANDROID_NDK_HOME nicht auf dem Mac OSX (siehe unten) einstellen, aber aus einigen Recherchen, die ich gemacht habe, scheint das vielleicht auch auf anderen Betriebssystemen zu funktionieren. Es wird jedoch entfernt.
Ich wollte kommentieren, aber noch nicht den Ruf haben. Dennis, die Umgebungsvariablen werden komplett ignoriert, nicht nur überschrieben. Tatsächlich erhalten Sie keine Ihrer Umgebungsvariablen. Soweit ich das beurteilen kann, erstellt die Android Studio-IDE eine eigene Umgebung mit nur wenigen spezifischen Umgebungsvariablen (überprüfen Sie System.getenv() und drucken Sie sie aus einem Skript aus).
Ich schrieb dies als Fehler hier, weil env mit Vars baut aus cmd Linie fein:
https://code.google.com/p/android/issues/detail?id=65213
aber wie Sie sehen können, Google beschlossen sie Umgebungsvariablen nicht wollen, von der IDE verwendet wird alle; Ich bin immer noch auf dem Zaun auf dieser Entscheidung. Es macht mir das Leben schwer, local.properties zu aktualisieren, um auf absolute Pfade zu zeigen, die in meine Skripts geladen werden können, die ich bis jetzt noch nicht herausgefunden habe (aber ich habe noch nicht so viel geschaut). Das bedeutet, dass ich meine Teammitglieder entweder dazu zwinge, den gleichen Pfad wie ich zu verwenden, mit Links zu spielen, sie alle bei jedem Abruf des Repos einzutippen oder ein Automatisierungsskript hinzuzufügen. Ich glaube, es ist eine schlechte Entscheidung, die Zeit für alle Entwickler kosten wird, die sich auf env vars verlassen, die auf der Mikroebene klein, auf der Makroebene aber sehr groß sind.
erdschleifen, ich glaube, die IDE wird in Kürze mit der Fähigkeit, den NDK-Ordner Pfad zu Ihrem Projekt hinzuzufügen, und es wird automatisch die local.properties-Datei daraus (zumindest würde es keinen Sinn, wenn sie Daran hatte ich nicht gedacht.
Weitere detaillierte Beispiele von Google, hier sind die neuesten Beispiele (für jni oder NDK suchen): https://docs.google.com/viewer?a=v&pid=sites&srcid=YW5kcm9pZC5jb218dG9vbHN8Z3g6NDYzNTVjMjNmM2YwMjhhNA
plattformübergreifende Fett APKs mit NDK:
Schließlich gibt es ein Nachteil bei der Verwendung von Gradle und nicht in der Lage, Ihre eigene Android.mk-Datei bereitzustellen, so dass Sie nur in nativen Bibliotheken von Drittanbietern von einer einzigen Architektur zu Ihrem NDK verknüpfen können. Hinweis Ich sagte "Link in". Sie können die NDK-Module (moduleName oben) in mehreren Architekturen mit dem Befehl "abiFilters" erstellen, und sie werden in Ihrer App platziert, sodass dieselbe APK auf mehreren Architekturen verwendet werden kann. Wenn Sie in Ihre eigenen 3rd-Party-Bibliotheken einbinden müssen oder je nach Ihrer Architektur unterschiedliche Werte für cFlags haben, gibt es keinen einfachen Weg.
Ich versuchte das Folgende und es schien zuerst zu arbeiten, aber dann fand ich heraus, dass es einfach das NDK baute, indem es alles aus den beiden ndk-Abschnitten anfügte (oder so, es hat irgendwie mehrere Architekturbibliotheken gebaut) :
android {
compileSdkVersion 23
buildToolsVersion '23.0.1'
defaultConfig {
minSdkVersion 14
targetSdkVersion 23
versionCode 28
versionName "3.0"
}
buildTypes {
def commonLibs = " -lfoo -lbar -lwhatever"
def armV7LibsDir = "/whatever/armv7a/libs"
def armX86LibsDir = "/whatever/x86/libs"
def armV7IncDir = "/whatever/armv7a/include"
def x86IncDir = "/whatever/x86/include"
debug {
ndk {
cFlags = "-I" + armV7IncDir
moduleName "myNativeCPPModule"
stl "stlport_shared"
abiFilter "armeabi-v7a"
ldLibs "log -L" + armV7LibsDir + commonLibs
}
ndk {
cFlags = "-I" + armX86IncDir
moduleName "myNativeCPPModule"
stl "stlport_shared"
abiFilter "x86"
ldLibs "log -L" + armX86LibsDir + commonLibs
}
}
}
}
nach viel Schmerz ein fettes binary in einem sauberen Herrenhaus mit gradle und nativer 3rd-Party-libs zu schaffen versucht, ich kam schließlich zu dem Schluss, dass Google Play-integrierte Unterstützung Multi-Architektur für APKs ist wirklich die Die beste Route, um trotzdem zu gehen, also erstelle individuelle APKs für jede Architektur.
Also habe ich mehrere buildTypes, keine Produktaromen erstellt und den folgenden Code hinzugefügt, um den Versionscode für jeden Typ zu generieren.
// This is somewhat nasty, but we need to put a "2" in front of all ARMEABI-V7A builds, a "3" in front of 64-bit ARM, etc.
// Google Play chooses the best APK based on version code, so if a device supports both X86 and
// ARM, it will choose the X86 APK (preferred because Inky ARM running on an X86 with Houdini ARM Emulator crashes in our case)
android.applicationVariants.all { variant ->
if (variant.buildType.name.equals('release')) {
variant.mergedFlavor.versionCode = 2000 + defaultConfig.versionCode
} else if (variant.buildType.name.equals('debug')) {
variant.mergedFlavor.versionCode = 2000 + defaultConfig.versionCode
} else if (variant.buildType.name.equals('debugArmV8a')) {
variant.mergedFlavor.versionCode = 3000 + defaultConfig.versionCode
} else if (variant.buildType.name.equals('releaseArmV8a')) {
variant.mergedFlavor.versionCode = 3000 + defaultConfig.versionCode
} else if (variant.buildType.name.equals('debugMips')) {
variant.mergedFlavor.versionCode = 5000 + defaultConfig.versionCode
} else if (variant.buildType.name.equals('releaseMips')) {
variant.mergedFlavor.versionCode = 5000 + defaultConfig.versionCode
} else if (variant.buildType.name.equals('debugMips64')) {
variant.mergedFlavor.versionCode = 6000 + defaultConfig.versionCode
} else if (variant.buildType.name.equals('releaseMips64')) {
variant.mergedFlavor.versionCode = 6000 + defaultConfig.versionCode
} else if (variant.buildType.name.equals('debugX86')) {
variant.mergedFlavor.versionCode = 8000 + defaultConfig.versionCode
} else if (variant.buildType.name.equals('releaseX86')) {
variant.mergedFlavor.versionCode = 8000 + defaultConfig.versionCode
} else if (variant.buildType.name.equals('debugX86_64')) {
variant.mergedFlavor.versionCode = 9000 + defaultConfig.versionCode
} else if (variant.buildType.name.equals('releaseX86_64')) {
variant.mergedFlavor.versionCode = 9000 + defaultConfig.versionCode
}
}
Alles was Sie jetzt tun müssen, um den Wert für version in Ihrem DefaultConfig Objekt festgelegt ist, wie Sie es normalerweise tun würde, und dies hängt es an das Ende der architekturspezifischen Version Zeichenfolge, basierend auf Buildtyp. Die Versionszeichenfolge bleibt für alle Builds gleich, variiert jedoch den Code, um eine Rangfolge von ARM bis hin zu X86_64 anzugeben. Es ist ein bisschen hackisch oder hart-codiert, aber es macht den Job erledigt. Beachten Sie, dass Sie damit bis zu 999 Versionen erhalten. Wenn Sie also mehr benötigen, multiplizieren Sie die obigen Zahlen mit 10, wobei Sie nicht sicher sind, welchen Maximalwert Sie für den Versionscode eingeben können.
In meinem Fall haben wir ein ziemlich komplexes Build-System. Wir erstellen CPython für 9 Architekturen, von denen 3 Android sind, erstellen dann eine Reihe eigener Bibliotheken und verknüpfen sie für jede Architektur zu einer einzigen Bibliothek. Wir verwenden die Build-Tools ndk, Build und Autake und Python, um alles anstelle von Android.mk-Dateien zu erstellen. Die endgültigen Bibliotheken werden dann in eine einzige JNI-Schnittstellen-CPP-Datei (oben als myNativeCPPModule bezeichnet) verknüpft. Ein Klick auf den Button und alles ist auf einmal erstellt, sehr schönes Android Studio.
NDK Vergessen Sie nicht, Ihre Antwort zu akzeptieren – orip
Ist es eine gute Idee, etwas von Hand in die 'local.properties' Datei zu setzen, da er sagt "Diese Datei wird automatisch von Android Studio erstellt. Ändern Sie diese Datei nicht - IHRE ÄNDERUNGEN WERDEN GELÖSCHT!" ? –