System.loadLibrary(...) не смог найти родную библиотеку в моем случае
Я хочу использовать существующую собственную библиотеку из проекта другого Android, поэтому я просто скопировал библиотеку NDK (libcalculate.so) в свой новый проект Android. В моем новом проекте Android я создал папку libs/armeabi/
и разместил там libcalculate.so. Существует папка нет jni/. Мое тестовое устройство имеет архитектуру ARM.
В моем java-коде я загружаю библиотеку:
static{
System.loadLibrary("calculate");
}
Когда я запускаю свой новый проект для Android, я получил ошибку:
java.lang.UnsatisfiedLinkError: ...
nativeLibraryDirectories=[/vendor/lib, /system/lib]]] couldn't find "libcalculate.so"
Итак, как говорит ошибка, скопированная собственная библиотека не находится в /verdor/lib или/system/lib, как решить эту проблему в моем случае?
(Я распаковал пакет apk, в lib/есть libcalculate.so)
==== ===== ОБНОВЛЕНИЕ
Я также попытался создать jni/папку под корнем проекта и добавить файл Android.mk в jni/. Содержимое Android.mk:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libcalculate
LOCAL_SRC_FILES := libcalculate.so
include $(PREBUILT_SHARED_LIBRARY)
Затем, в корне проекта, я выполнил ndk-build. После этого каталоги armeabi/и armeabi-v7a/генерируются ndk-build (с libcalculate.so внутри папки).
Затем я запустил проект maven для создания проекта. В последнем пакете apk есть:
lib/armeabi/libcalculate.so
lib/armeabi-v7a/libcalculate.so
Но когда я запускаю свое приложение, тот же самый код ошибки:
java.lang.UnsatisfiedLinkError: ...
nativeLibraryDirectories=[/vendor/lib, /system/lib]]] couldn't find "libcalculate.so"
Ответы
Ответ 1
Чтобы вызвать причину (и, возможно, решить вашу проблему в одно и то же время), вот что вы можете сделать:
-
Удалите папку jni и все файлы .mk. Вам не нужны эти или NDK, если вы ничего не компилируете.
-
Скопируйте файл libcalculate.so
внутри <project>/libs/(armeabi|armeabi-v7a|x86|...)
. При использовании Android Studio он <project>/app/src/main/jniLibs/(armeabi|armeabi-v7a|x86|...)
, но я вижу, что вы используете eclipse.
-
Создайте APK и откройте его как zip файл, чтобы проверить, что ваш файл libcalculate.so
находится внутри lib/(armeabi | armeabi-v7a | x86 |...).
-
Удалите и установите приложение
-
Запуск пакетов пакетов dumpsys | grep yourpackagename, чтобы получить nativeLibraryPath или legacyNativeLibraryDir вашего приложения.
-
Запустите ls на nativeLibraryPath, который у вас был или на legacyNativeLibraryDir/armeabi, чтобы проверить, действительно ли ваш libcalculate.so.
-
Если он там, проверьте, не изменился ли он из исходного файла libcalculate.so: он скомпилирован против правильной архитектуры, содержит ли он ожидаемые символы, есть ли какие-либо недостатки. Вы можете проанализировать libcalculate.so, используя readelf.
Чтобы проверить шаг 5-7, вы можете использовать мое приложение вместо командной строки и readelf: Native Libs Monitor
PS: Легко запутать, где .so файлы должны быть помещены или сгенерированы по умолчанию, вот резюме:
-
libs/CPU_ABI внутри проекта eclipse
-
jniLibs/CPU_ABI в проекте Android Studio
-
jni/CPU_ABI внутри AAR
-
lib/CPU_ABI внутри окончательного APK
-
внутри приложения nativeLibraryPath на устройстве < 5.0 и внутри приложения legacyNativeLibraryDir/CPU_ARCH на устройстве >= 5.0.
Где CPU_ABI есть любой из: armeabi, armeabi-v7a, arm64-v8a, x86, x86_64, mips, mips64. В зависимости от того, какие архитектуры вы нацеливаете, и ваши библиотеки были скомпилированы.
Обратите также внимание на то, что libs не смешиваются между каталогами CPU_ABI: вам нужен полный набор того, что вы используете, lib, находящийся внутри папки armeabi, не будет установлен на устройстве armeabi-v7a, если есть какие-либо libs внутри папки armeabi-v7a из APK.
Ответ 2
В gradle, после копирования всех папок файлов на libs/
jniLibs.srcDirs = ['libs']
Добавление вышеприведенной строки в sourceSets
в файле build.gradle
. Ничего больше не работало.
Ответ 3
Используете ли вы gradle? Если это так, поместите файл .so
в <project>/src/main/jniLibs/armeabi/
Надеюсь, это поможет.
Ответ 4
В моем случае я должен исключить компиляцию источников с помощью gradle и установить путь libs
android {
...
sourceSets {
...
main.jni.srcDirs = []
main.jniLibs.srcDirs = ['libs']
}
....
Ответ 5
Попробуйте вызвать вашу библиотеку после раздела 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:
Если вы будете использовать эту библиотеку в Java, вам необходимо скомпилировать ее как общую библиотеку
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libcalculate
LOCAL_SRC_FILES := <PATH>/libcalculate.so
include $(BUILD_SHARED_LIBRARY)
И вам нужно развернуть библиотеку в каталоге /vendor/lib
.
Ответ 6
Для справки у меня появилось это сообщение об ошибке, и решение заключалось в том, что когда вы указываете библиотеку, вы пропускаете "lib" спереди и ".so" с конца.
Итак, если у вас есть файл libmyfablib.so, вам нужно позвонить:
System.loadLibrary("myfablib"); // this loads the file 'libmyfablib.so'
Посмотрев в apk, установил/удалил и попробовал всевозможные сложные решения, я не мог видеть простой проблемы, которая была прямо перед моим лицом!
Ответ 7
добавьте все suport
приложение/build.gradle
ndk {
moduleName "serial_port"
ldLibs "log", "z", "m"
abiFilters "arm64-v8a","armeabi", "armeabi-v7a", "x86","x86_64","mips","mips64"
}
Приложение\SRC\JNI\Application.mk
APP_ABI := arm64-v8a armeabi armeabi-v7a x86 x86_64 mips mips64
Ответ 8
Это обновление для Android 8.
В более ранней версии Android, для собственных библиотек LoadLibrary (для доступа через JNI, например), я подключил свой собственный код к итерации через ряд потенциальных путей к папке lib, основанный на различных установках 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
Этот подход является hokey и не будет работать для Android 8; от https://developer.android.com/about/versions/oreo/android-8.0-changes.html
вы увидите, что в рамках их изменений "Безопасность" вам теперь нужно использовать sourceDir:
"Вы больше не можете предполагать, что APK находятся в каталогах, имена которых заканчиваются на -1 или 2. Приложения должны использовать sourceDir для получения каталога и не полагаться непосредственно на формат каталога.
Исправление, sourceDir - это не способ найти ваши родные общие библиотеки; используйте что-то вроде. Протестировано для Android 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;
}
Ответ 9
По моему опыту, в мобильном устройстве armeabi-v7a, когда в apk присутствуют как армеаби, так и armeabi-v7a, файлы .so в каталоге armeabi не будут связаны, хотя файлы .so в armeabi будут связанный в том же мобильном, что и armeabi-v7a, если armeabi-v7a нет.
Ответ 10
на самом деле, вы не можете просто поместить файл .so в /libs/armeabi/
и загрузить его с помощью System.loadLibrary
. Вам нужно создать файл Android.mk и объявить предварительно построенный модуль, в котором вы укажете свой .so файл в качестве источника.
Чтобы сделать это, поместите ваш .so файл и файл Android.mk в папку jni
.
Ваш Android.mk должен выглядеть примерно так:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libcalculate
LOCAL_SRC_FILES := libcalculate.so
include $(PREBUILT_SHARED_LIBRARY)
Источник: Документация Android NDK о готовых