Система.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)
затем, в рамках проекта root, я выполнил 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"
11 ответов:
до первопричины (и, возможно, решить вашу проблему, в то же время), вот что вы можете сделать:
удалите папку jni и все файлы .mk. Вам не нужны ни эти, ни NDK, если вы ничего не компилируете.
скопировать внутри
<project>/libs/(armeabi|armeabi-v7a|x86|...)
. При использовании Android Studio, это<project>/app/src/main/jniLibs/(armeabi|armeabi-v7a|x86|...)
, но я вижу, что вы используете Eclipse.создайте свой APK и откройте его как zip файл, чтобы проверить, что ваш внутри lib|(armeabi|armeabi-v7a|x86/...).
удалить и установить приложение
выполнить dumpsys package packages / grep yourpackagename для получения nativeLibraryPath или legacyNativeLibraryDir приложения.
выполнить ls на nativeLibraryPath вы должны были или на legacyNativeLibraryDir / armeabi, чтобы проверить, если ваш libcalculate.so действительно есть.
если он есть, проверьте, не был ли он изменен с вашего оригинала libcalculate.so file: скомпилирован ли он против правильной архитектуры, содержит ли он ожидаемые символы, есть ли какие-либо отсутствующие зависимости. Вы можете анализировать libcalculate.so с помощью readelf.
чтобы проверить шаг 5-7, вы можете использовать мой приложение вместо командной строки и readelf:Родной Монитор Libs
PS: легко запутаться в том, где. so файлы должны быть помещены или сгенерированы по умолчанию, вот резюме:
libs / CPU_ABI внутри проекта eclipse
jniLibs / CPU_ABI внутри проекта Android Studio
jni / CPU_ABI внутри ААР
lib / CPU_ABI внутри финального APK
внутри приложения nativeLibraryPath на устройстве legacyNativeLibraryDir / CPU_ARCH на устройстве a >=5.0.
здесь CPU_ABI это: armeabi, armeabi-v7a, arm64-v8a, x86, x86_64, mips, mips64. В зависимости от того, на какие архитектуры вы ориентируетесь и ваш библиотеки были скомпилированы для.
обратите внимание также, что библиотеки не смешиваются между каталогами CPU_ABI: вам нужен полный набор того, что вы используете, lib, который находится внутри норм папка не будет установлена на armeabi-v7a устройство, если есть какие-то либы внутри armeabi-v7a папка из APK.
в gradle, после копирования всех папок файлов в
libs/
jniLibs.srcDirs = ['libs']
добавляете строку с
sourceSets
на работали. Больше ничего не работало.
вы используете gradle? Если так поставить на
<project>/src/main/jniLibs/armeabi/
Я надеюсь, что это помогает.
в моем случае я должен исключить компиляцию источников по gradle и установить libs path
android { ... sourceSets { ... main.jni.srcDirs = [] main.jniLibs.srcDirs = ['libs'] } ....
попробуйте позвонить в библиотеку после включения :
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
обновление:
если вы будете использовать эту библиотеку в Java, вам нужно скомпилировать ее как общую библиотеку
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := libcalculate LOCAL_SRC_FILES := <PATH>/libcalculate.so include $(BUILD_SHARED_LIBRARY)
и вам нужно развернуть библиотеку в .
для справки, у меня было это сообщение об ошибке, и решение состояло в том, что при указании библиотеки вы пропускаете " lib "спереди и". so " с конца.
Итак, если у вас есть файл libmyfablib.so, вам нужно позвонить:
System.loadLibrary("myfablib"); // this loads the file 'libmyfablib.so'
посмотрев в apk, установил / удалил и попробовал все виды сложных решений, я не мог видеть простую проблему, которая была прямо перед моим лицом!
это обновление для 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
этот подход является Хоки и не будет работать для Android 8; от https://developer.android.com/about/versions/oreo/android-8.0-changes.html вы увидите, что в рамках своих изменений "безопасности" вам теперь нужно использовать sourceDir:
причина этой ошибки заключается в том, что существует несоответствие ABI между вашим приложением и родной библиотекой, с которой вы связаны. Другими словами, ваше приложение и ваш
.so
нацелен на другой ABI.если вы создаете свое приложение с использованием последних шаблонов Android Studio, его, вероятно, нацелены на
arm64-v8a
но ваш.so
может быть таргетированиеarmeabi-v7a
например.есть 2 способа решить эту проблему:
- построить свои собственные библиотеки для каждый ABI поддерживает ваше приложение.
- измените свое приложение, чтобы оно было нацелено на более старый ABI, который ваш
.so
построены.выбор 2 грязный, но я думаю, что вы, вероятно, более заинтересованы в:
изменение вашего приложения
build.gradle
android { defaultConfig { ... ndk { abiFilters 'armeabi-v7a' } } }
пожалуйста, добавьте все suport
приложения/строить.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
по моему опыту, в armeabi-v7a mobile, когда каталоги armeabi и armeabi-v7a присутствуют в apk, файлы .so в каталоге armeabi не будут связаны, хотя файлы .so в armeabi будут связаны в том же armeabi-v7a mobile, если armeabi-v7a нет.
на самом деле, вы не можете просто положить файл .so в
/libs/armeabi/
и загрузить его сSystem.loadLibrary
. Вам необходимо создать Android.mk файл и объявить готовый модуль, где вы указываете ваш. so файл в качестве источника.чтобы сделать это, поместите ваш. so файл и Android.mk файл в . Ваш Android.mk должно выглядеть примерно так:
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := libcalculate LOCAL_SRC_FILES := libcalculate.so include $(PREBUILT_SHARED_LIBRARY)
источник : Android NDK документация о prebuilt