Ich möchte eine vorhandene native Bibliothek aus einem anderen Android-Projekt verwenden, daher habe ich die von NDK erstellte Bibliothek ( libcalculate.so ) einfach in mein neues Android-Projekt kopiert . In meinem neuen Android-Projekt habe ich einen Ordner erstellt libs/armeabi/
und libcalculate.so dort abgelegt . Es gibt keinen jni / Ordner. Mein Testgerät verfügt über eine ARM-Architektur.
In meinem Java-Code lade ich die Bibliothek durch:
static{
System.loadLibrary("calculate");
}
Beim Ausführen meines neuen Android-Projekts wurde folgende Fehlermeldung angezeigt:
java.lang.UnsatisfiedLinkError: ...
nativeLibraryDirectories=[/vendor/lib, /system/lib]]] couldn't find "libcalculate.so"
Wie der Fehler sagt, befindet sich die kopierte native Bibliothek nicht in / verdor / lib oder / system / lib. Wie kann dieses Problem in meinem Fall behoben werden?
(Ich habe das apk-Paket entpackt, unter lib / gibt es libcalculate.so)
==== UPDATE =====
Ich habe auch versucht, einen jni / -Ordner unter dem Projektstamm zu erstellen und eine Android.mk-Datei unter jni / hinzuzufügen. Der Inhalt von Android.mk ist:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libcalculate
LOCAL_SRC_FILES := libcalculate.so
include $(PREBUILT_SHARED_LIBRARY)
Dann habe ich unter Projektstamm ndk-build ausgeführt. Danach werden die Verzeichnisse armeabi / und armeabi-v7a / von ndk-build generiert (mit libcalculate.so im Ordner).
Dann führe ich meinen Maven aus, um das Projekt erfolgreich zu erstellen. Im endgültigen apk-Paket gibt es:
lib/armeabi/libcalculate.so
lib/armeabi-v7a/libcalculate.so
Aber wenn ich meine App starte, wird der gleiche Fehler ausgelöst:
java.lang.UnsatisfiedLinkError: ...
nativeLibraryDirectories=[/vendor/lib, /system/lib]]] couldn't find "libcalculate.so"
quelle
libs/
? Sie müssen wahrscheinlich ein Unterverzeichnis pro Ziel-ABI erstellen, das Sie unterstützen möchten (armeabi, armeabi-v7a, x86, mips usw.) und die entsprechende .so-Datei in jedem Unterverzeichnis ablegen (dh die für armeabi erstellte .so-Datei wird eingegeben)libs/armeabi/
. etc).unzip -l package.apk
oder benennen Sie die apk in .zip um und öffnen Sie sie mit einer Anwendung. Wenn es nicht vorhanden ist, stimmt etwas beim Packen nicht (hat Ihre IDE bemerkt, dass der Ordner vorhanden ist, müssen Sie das Projekt aktualisieren?).Antworten:
Um die Ursache zu ermitteln (und möglicherweise Ihr Problem gleichzeitig zu lösen), können Sie Folgendes tun:
Entfernen Sie den Ordner jni und alle .mk- Dateien. Sie benötigen diese und das NDK nicht, wenn Sie nichts kompilieren.
Kopieren Sie Ihre
libcalculate.so
Datei hinein<project>/libs/(armeabi|armeabi-v7a|x86|...)
. Wenn Sie Android Studio verwenden, ist dies der Fall<project>/app/src/main/jniLibs/(armeabi|armeabi-v7a|x86|...)
, aber ich sehe, dass Sie Eclipse verwenden.Erstellen Sie Ihre APK und öffnen Sie sie als Zip-Datei , um zu überprüfen, ob Ihre
libcalculate.so
Datei in lib / (armeabi | armeabi-v7a | x86 | ...) befindet .Entfernen und installieren Sie Ihre Anwendung
Führen Sie dumpsys package packages | aus grep yourpackagename , um den nativeLibraryPath oder zu erhalten legacyNativeLibraryDir Ihrer Anwendung abzurufen .
Führen Sie ls auf dem nativeLibraryPath aus, den Sie hatten oder auf dem legacyNativeLibraryDir / armeabi , um zu überprüfen, ob Ihre libcalculate.so tatsächlich vorhanden ist.
Wenn es dort ist, überprüfen Sie, ob es nicht von Ihrem Original geändert wurde libcalculate.so- Datei geändert wurde : Wird es gegen die richtige Architektur kompiliert, enthält es die erwarteten Symbole, fehlen Abhängigkeiten. Sie können libcalculate.so mit readelf analysieren.
Um Schritt 5-7 zu überprüfen, können Sie meine Anwendung anstelle von Befehlszeilen verwenden und sich selbst lesen: Native Libs Monitor
PS: Es ist leicht zu verwechseln, wo .so-Dateien standardmäßig abgelegt oder generiert werden sollen. Hier eine Zusammenfassung:
libs / CPU_ABI in einem Eclipse-Projekt
jniLibs / CPU_ABI in einem Android Studio-Projekt
jni / CPU_ABI in einem AAR
lib / CPU_ABI in der endgültigen APK
innerhalb des nativeLibraryPath der App auf einem <5.0-Gerät und innerhalb der App LegacyNativeLibraryDir / CPU_ARCH auf einem> = 5.0-Gerät.
Wobei CPU_ABI eines der folgenden Elemente ist: armeabi, armeabi-v7a, arm64-v8a, x86, x86_64, mips, mips64 . Abhängig davon, auf welche Architekturen Sie abzielen und für welche Ihre Bibliotheken kompiliert wurden.
Beachten Sie auch, dass Bibliotheken nicht zwischen CPU_ABI-Verzeichnissen gemischt werden: Sie benötigen den vollständigen Satz Ihrer Verwendungszwecke. Eine Bibliothek im Ordner armeabi wird nicht auf einem armeabi-v7a- Gerät installiert , wenn sich Bibliotheken im Armeabi befinden -v7a Ordner aus der APK.
quelle
7
Abschnitt: Meinen Sie, dass die .so-Datei möglicherweise von der APK geändert wird, nachdem sie auf dem Gerät installiert wurde? Wenn ja, besteht die Möglichkeit, dass das System die .so-Datei ruiniert?In gradle nach dem Kopieren aller Dateiordner in
libs/
Das Hinzufügen der obigen Zeile
sourceSets
inbuild.gradle
Datei gearbeitet. Sonst hat nichts funktioniert.quelle
Verwenden Sie Gradle? Wenn ja, setzen Sie die
.so
Datei ein<project>/src/main/jniLibs/armeabi/
Ich hoffe, es hilft.
quelle
In meinem Fall muss ich das Kompilieren von Quellen nach Gradle ausschließen und den libs-Pfad festlegen
quelle
Der Grund für diesen Fehler liegt darin, dass die ABI zwischen Ihrer App und der nativen Bibliothek, mit der Sie verknüpft haben, nicht übereinstimmt. Mit anderen Worten, Ihre App und Ihre
.so
zielen auf unterschiedliche ABI ab.Wenn Sie Ihre App mit den neuesten Android Studio-Vorlagen erstellen, richtet sie sich wahrscheinlich an die,
arm64-v8a
aber.so
möglicherweise an Ihrearmeabi-v7a
.Es gibt zwei Möglichkeiten, um dieses Problem zu lösen:
.so
gegen die Sie gebaut haben.Wahl 2 ist schmutzig, aber ich denke, Sie haben wahrscheinlich mehr Interesse an:
Ändern Sie Ihre App
build.gradle
quelle
Als Referenz hatte ich diese Fehlermeldung und die Lösung war, dass Sie, wenn Sie die Bibliothek angeben, die 'lib' von vorne und die '.so' am Ende vermissen.
Wenn Sie also eine Datei libmyfablib.so haben, müssen Sie Folgendes aufrufen:
Nachdem ich in der apk nachgesehen, installiert / deinstalliert und alle möglichen komplexen Lösungen ausprobiert hatte, konnte ich das einfache Problem nicht erkennen, das direkt vor meinem Gesicht lag!
quelle
System.loadLibrary
im CodeDies ist ein Android 8-Update.
In einer früheren Version von Android habe ich für native LoadLibrary-Shared-Libraries (z. B. für den Zugriff über JNI) meinen nativen Code fest verdrahtet, um eine Reihe potenzieller Verzeichnispfade für den lib-Ordner zu durchlaufen, basierend auf den verschiedenen apk-Installations- / Upgrade-Algorithmen:
Dieser Ansatz ist hokey und funktioniert nicht für Android 8; Unter https://developer.android.com/about/versions/oreo/android-8.0-changes.html sehen Sie, dass Sie im Rahmen der "Sicherheits" -Änderungen jetzt sourceDir verwenden müssen:
"Sie können nicht mehr davon ausgehen, dass sich APKs in Verzeichnissen befinden, deren Namen auf -1 oder -2 enden. Apps sollten sourceDir verwenden, um das Verzeichnis abzurufen, und sich nicht direkt auf das Verzeichnisformat verlassen."
Korrektur, sourceDir ist nicht der Weg, um Ihre nativen gemeinsam genutzten Bibliotheken zu finden. benutze so etwas wie. Getestet für Android 4.4.4 -> 8.0
quelle
Versuchen Sie, Ihre Bibliothek nach dem Include-
PREBUILT_SHARED_LIBRARY
Abschnitt aufzurufen :Aktualisieren:
Wenn Sie diese Bibliothek in Java verwenden möchten, müssen Sie sie als gemeinsam genutzte Bibliothek kompilieren
Und Sie müssen die Bibliothek im
/vendor/lib
Verzeichnis bereitstellen .quelle
Sie können ABI einfach ändern, um ältere Builds zu verwenden:
Sie sollten auch veraltetes NDK verwenden, indem Sie diese Zeile hinzufügen zu
gradle.properties
:quelle
Bitte fügen Sie alle Unterstützung hinzu
app / build.gradle
app \ src \ jni \ Application.mk
quelle
Nach meiner Erfahrung werden in einem armeabi-v7a-Handy, wenn sowohl armeabi- als auch armeabi-v7a-Verzeichnisse in der apk vorhanden sind, die .so-Dateien im armeabi-Verzeichnis nicht verknüpft, obwohl die .so-Dateien in armeabi im dasselbe armeabi-v7a-Handy, wenn armeabi-v7a nicht vorhanden ist.
quelle
Eigentlich kann man nicht einfach eine .so-Datei in die Datei einfügen
/libs/armeabi/
und mit ladenSystem.loadLibrary
. Sie müssen eine Android.mk-Datei erstellen und ein vorgefertigtes Modul deklarieren, in dem Sie Ihre .so-Datei als Quelle angeben.Legen Sie dazu Ihre .so-Datei und die Android.mk-Datei in den
jni
Ordner. Dein Android.mk sollte ungefähr so aussehen:Quelle: Android NDK-Dokumentation zu vorgefertigten
quelle