System.loadLibrary (...) nie mogłem znaleźć natywnej biblioteki w moim przypadku

Chcę użyć istniejącej biblioteki natywnej z innego projektu Androida, więc skopiowałem bibliotekę zbudowaną przez NDK ( libcalculate.so ) do mojego nowego projektu Android. W moim nowym projekcie Android utworzyłem folder libs/armeabi/ i umieściłem libcalculate.so tam. Nie ma JNI/ folder. Moje urządzenie testujące ma architekturę ARM.

W moim kodzie Javy Ładuję bibliotekę przez:

  static{
    System.loadLibrary("calculate");
  }

Kiedy uruchamiam mój nowy projekt z Androidem, mam błąd:

java.lang.UnsatisfiedLinkError:  ...
nativeLibraryDirectories=[/vendor/lib, /system/lib]]] couldn't find "libcalculate.so"

Tak więc, jak mówi błąd, skopiowana natywna biblioteka nie jest w /verdor / lib lub / system / lib , jak rozwiązać ten problem w moim przypadku?

(rozpakowałem pakiet apk, pod lib / jest libcalculate.so)

====Aktualizacja=====

Próbowałem również utworzyć JNI / folder pod project root i dodać Android.mk plik pod jni/. Zawartość Android.mk jest:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE    := libcalculate
LOCAL_SRC_FILES := libcalculate.so
include $(PREBUILT_SHARED_LIBRARY)

Następnie, w ramach projektu root, wykonałem ndk-build . Po tym, armeabi/ i katalogi armeabi-v7a / są generowane przez NDK-build (z libcalculate.so wewnątrz folderu).

Następnie uruchomić mój Maven zbudować projekt pomyślnie. W końcowym pakiecie apk znajdują się:

lib/armeabi/libcalculate.so
lib/armeabi-v7a/libcalculate.so

Ale kiedy uruchamiam aplikację, ten sam błąd rzuca:

java.lang.UnsatisfiedLinkError:  ...
nativeLibraryDirectories=[/vendor/lib, /system/lib]]] couldn't find "libcalculate.so"
Author: user842225, 2014-12-11

13 answers

Do przyczyny źródłowej (i być może rozwiązać swój problem w tym samym czasie), oto co możesz zrobić:

  1. Usuń folder jni i wszystkie pliki . mk. Nie potrzebujesz tych ani NDK, jeśli nic nie kompilujesz.

  2. Skopiuj plik {[0] } do <project>/libs/(armeabi|armeabi-v7a|x86|...). Podczas korzystania z Android Studio, to <project>/app/src/main/jniLibs/(armeabi|armeabi-v7a|x86|...), ale widzę, że używasz eclipse.

  3. Zbuduj swój APK i otwórz go jako plik zip , aby sprawdzić, czy Twój plik libcalculate.so znajduje się w środku lib / (armeabi / armeabi-v7a / x86/...).

  4. Usuń i zainstaluj aplikację

  5. Uruchom dumpsys packages packages | grep yourpackagename, aby uzyskać nativeLibraryPathlub legacyNativeLibraryDir Twojej aplikacji.

  6. Run ls on the nativeLibraryPath you had or on legacyNativeLibraryDir / armeabi , to check if your libcalculate.so w rzeczy samej.

  7. Jeśli to tam sprawdź, czy nie został zmieniony w stosunku do oryginału libcalculate.so Plik: czy jest skompilowany zgodnie z właściwą architekturą, czy zawiera oczekiwane symbole, czy są jakieś brakujące zależności. Możesz analizować libcalculate.so korzystanie z readelf.

Aby sprawdzić krok 5-7, możesz użyć mojej aplikacji zamiast linii poleceń i przeczytać: Native Libs Monitor

PS: łatwo się pomylić gdzie .więc pliki powinny być umieszczane lub generowane przez domyślnie, tutaj jest podsumowanie:

  • Libs / CPU_ABI wewnątrz projektu eclipse

  • JniLibs / CPU_ABI wewnątrz projektu Android Studio

  • Jni / CPU_ABI wewnątrz AAR

  • Lib / CPU_ABI wewnątrz końcowego APK

  • Wewnątrz aplikacji nativeLibraryPath na urządzeniu legacyNativeLibraryDir / CPU_ARCH na a >=5.0 urządzenie.

Gdzie CPU_ABI jest dowolne z: armeabi, armeabi-v7a, arm64-v8a, x86, x86_64, mips, mips64 . W zależności od architektur, które są kierowane i libs zostały skompilowane dla.

Zauważ również, że libs nie są mieszane pomiędzy katalogami CPU_ABI: potrzebujesz pełnego zestawu tego, czego używasz, lib, który znajduje się w folderze armeabi nie będzie zainstalowany na urządzeniu armeabi-v7a armeabi-v7a folder z APK.

 181
Author: ph0b,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-15 09:24:11

W gradle, po skopiowaniu wszystkich folderów plików do libs/

jniLibs.srcDirs = ['libs']

Dodanie powyższej linii do sourceSets w pliku build.gradle zadziałało. Nic innego nie działało.

 22
Author: Mukund Muralikrishnan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-12 08:41:02

W moim przypadku muszę wykluczyć kompilowanie źródeł przez gradle i ustawić ścieżkę libs

android {

    ...
    sourceSets {
        ...
        main.jni.srcDirs = []
        main.jniLibs.srcDirs = ['libs']
    }
....
 14
Author: Dawid Drozd,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-27 13:06:59

Używasz gradle ' a? Jeśli tak, umieść plik {[0] } w <project>/src/main/jniLibs/armeabi/

Mam nadzieję, że to pomoże.
 12
Author: Assaf Gamliel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-15 15:32:34

Powodem tego błędu jest niedopasowanie ABI między aplikacją a biblioteką macierzystą, z którą się łączyłeś. Innymi słowy, twoja aplikacja i twoja .so celują w różne ABI.

Jeśli tworzysz swoją aplikację przy użyciu najnowszych szablonów Android Studio, prawdopodobnie jest ona kierowana do arm64-v8a, ale twoja .so może być kierowana do armeabi-v7a na przykład.

Jest 2 sposób na rozwiązanie tego problemu:

  1. twórz natywne biblioteki dla każdej aplikacji ABI wsparcie.
  2. Zmień swoją aplikację na kierowaną do starszych ABI, z którymi Twoja .so została zbudowana.

Wybór 2 jest brudny, ale chyba bardziej cię to interesuje:

Zmień swoją aplikację build.gradle

android {
    defaultConfig {
        ...
        ndk {
            abiFilters 'armeabi-v7a'
        }
   }
}
 8
Author: wdanxna,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-08 08:40:34

To jest aktualizacja Androida 8.

We wcześniejszej wersji Androida, aby załadować natywne biblioteki współdzielone Library (na przykład dla dostępu przez JNI), podłączyłem mój kod natywny do iteracji przez szereg potencjalnych ścieżek katalogów dla folderu lib, w oparciu o różne algorytmy instalacji/aktualizacji apk:

/data/data/<PackageName>/lib
/data/app-lib/<PackageName>-1/lib
/data/app-lib/<PackageName>-2/lib
/data/app/<PackageName>-1/lib
/data/app/<PackageName>-2/lib

To podejście jest hokey i nie będzie działać dla Androida 8; od https://developer.android.com/about/versions/oreo/android-8.0-changes.html zobaczysz to jako część zmian "zabezpieczeń" musisz teraz użyć sourceDir:

" nie można już zakładać, że APK znajdują się w katalogach, których nazwy kończą się na -1 lub -2. Aplikacje powinny używać sourceDir, aby uzyskać Katalog, a nie polegać bezpośrednio na formacie katalogu."

Poprawka, sourceDir nie jest sposobem na znalezienie natywnych bibliotek współdzielonych; użyj czegoś takiego. Testowane dla Androida 4.4.4 -- > 8.0

// Return Full path to the directory where native JNI libraries are stored.
private static String getNativeLibraryDir(Context context) {
    ApplicationInfo appInfo = context.getApplicationInfo();
    return appInfo.nativeLibraryDir;
}
 7
Author: AlgebraWinter,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-30 12:52:31

Dla odniesienia, miałem ten Komunikat o błędzie i rozwiązaniem było to, że po określeniu biblioteki brakuje 'lib' z przodu i'. so ' od końca.

Więc jeśli Masz plik libmyfablib.so, musisz zadzwonić:

   System.loadLibrary("myfablib"); // this loads the file 'libmyfablib.so' 

Po spojrzeniu w apk, zainstalowaniu/odinstalowaniu i wypróbowaniu wszelkiego rodzaju złożonych rozwiązań nie mogłem zobaczyć prostego problemu, który był tuż przed moją twarzą!

 6
Author: Andy Krouwel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-20 11:10:23

Spróbuj wywołać bibliotekę po sekcji include PREBUILT_SHARED_LIBRARY:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE    := libcalculate
LOCAL_SRC_FILES := <PATH>/libcalculate.so
include $(PREBUILT_SHARED_LIBRARY)

#...

LOCAL_SHARED_LIBRARIES += libcalculate

Update:

Jeśli używasz tej biblioteki w Javie, musisz skompilować ją jako bibliotekę współdzieloną

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE    := libcalculate
LOCAL_SRC_FILES := <PATH>/libcalculate.so
include $(BUILD_SHARED_LIBRARY)

I musisz wdrożyć bibliotekę w katalogu /vendor/lib.

 4
Author: Alex,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-18 12:19:24

Możesz po prostu zmienić ABI, aby używać starszych buildów:

defaultConfig {
    ...

    ndk {
        abiFilters 'armeabi-v7a'
    }
    ...
}

Należy również użyć przestarzałego NDK, dodając tę linię do gradle.properties:

android.useDeprecatedNdk=true
 1
Author: rezam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-10-23 06:15:17

Nie można po prostu umieścić pliku. so w /libs/armeabi/ i załadować go System.loadLibrary. Musisz stworzyć Android.mk file and declare a prebuilt module where you specify your. so file as a source.

Aby to zrobić, umieść plik .so I Android.mk plik w folderze jni. Twój Android.mk powinno tak wyglądać:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE    := libcalculate
LOCAL_SRC_FILES := libcalculate.so
include $(PREBUILT_SHARED_LIBRARY)

Źródło: dokumentacja Android NDK o prebuilt

 0
Author: Yannshu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-23 17:38:08

Proszę dodać wszystkie suport

App / build.gradle

ndk {
        moduleName "serial_port"
        ldLibs "log", "z", "m"
        abiFilters "arm64-v8a","armeabi", "armeabi-v7a", "x86","x86_64","mips","mips64"
}

App\src\jni\Application.mk

APP_ABI := arm64-v8a armeabi armeabi-v7a x86 x86_64 mips mips64
 0
Author: Lion耿,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-20 08:36:28
defaultConfig {
ndk {
            abiFilters "armeabi-v7a", "x86", "armeabi", "mips"
    }
}

Wystarczy dodać te linie w build.poziom aplikacji gradle

 0
Author: Savan Patel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-12-18 11:15:09

Z mojego doświadczenia, w armeabi-v7a mobile, gdy oba katalogi armeabi i armeabi-v7a są obecne w apk, pliki. so w katalogu armeabi nie będą połączone, chociaż pliki. so w armeabi będą połączone w tym samym armeabi-v7a mobile, jeśli armeabi-v7a nie jest obecny.

 -1
Author: loopscn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-17 04:01:49