Я хочу использовать существующую собственную библиотеку из другого проекта 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"
источник
libs/
? Вероятно, вам нужно создать один подкаталог для каждого целевого ABI, который вы хотите поддерживать (armeabi, armeabi-v7a, x86, mips и т. Д.), И поместить соответствующий файл .so в каждый подкаталог (т. Е. Файл .so, созданный для armeabi, входитlibs/armeabi/
, так далее).unzip -l package.apk
, или переименуйте apk в .zip и откройте его в каком-нибудь приложении. Если его там нет, значит, что-то не так с его упаковкой (заметила ли ваша среда IDE, что папка есть, нужно ли обновить проект?).Ответы:
Чтобы устранить первопричину (и, возможно, решить вашу проблему одновременно), вот что вы можете сделать:
Удалите папку 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 . В зависимости от того, на какие архитектуры вы нацеливаетесь и для которых были скомпилированы ваши библиотеки.
Также обратите внимание, что библиотеки не смешиваются между каталогами CPU_ABI: вам нужен полный набор того, что вы используете, библиотека, которая находится внутри папки armeabi , не будет установлена на устройстве armeabi-v7a, если внутри armeabi есть какие-либо библиотеки Папка -v7a из APK.
источник
7
раздела: вы имеете в виду, что .so может быть изменен из APK после того, как он был установлен на устройстве? Если да, есть ли вероятность, что система испортит файл .so?В gradle после копирования всех папок с файлами в
libs/
jniLibs.srcDirs = ['libs']
Добавление указанной выше строки
sourceSets
вbuild.gradle
файл сработало. Больше ничего не работало.источник
Вы используете Gradle? Если да, поместите
.so
файл в<project>/src/main/jniLibs/armeabi/
Я надеюсь, что это помогает.
источник
В моем случае я должен исключить компиляцию источников с помощью gradle и установить путь к библиотекам
android { ... sourceSets { ... main.jni.srcDirs = [] main.jniLibs.srcDirs = ['libs'] } ....
источник
Причина этой ошибки в том, что существует несоответствие ABI между вашим приложением и собственной библиотекой, с которой вы связались. Другими словами, ваше приложение и ваше
.so
нацелены на разные ABI.если вы создаете свое приложение с использованием последних шаблонов Android Studio, вероятно, оно нацелено на,
arm64-v8a
но ваше.so
может быть нацелено,armeabi-v7a
например.Есть 2 способа решить эту проблему:
.so
построили.Вариант 2 грязный, но я думаю, что вас, вероятно, больше интересуют:
измените свое приложение
build.gradle
android { defaultConfig { ... ndk { abiFilters 'armeabi-v7a' } } }
источник
Для справки, у меня было это сообщение об ошибке, и решение заключалось в том, что когда вы указываете библиотеку, вы пропускаете «lib» спереди и «.so» с конца.
Итак, если у вас есть файл libmyfablib.so, вам нужно вызвать:
System.loadLibrary("myfablib"); // this loads the file 'libmyfablib.so'
Посмотрев в apk, установив / деинсталлировав и попробовав всевозможные сложные решения, я не увидел простую проблему, которая стояла прямо перед моим лицом!
источник
System.loadLibrary
в кодеЭто обновление 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:
«Вы больше не можете предполагать, что 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; }
источник
Попробуйте позвонить в свою библиотеку после
PREBUILT_SHARED_LIBRARY
раздела include :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)
И вам нужно развернуть библиотеку в
/vendor/lib
каталоге.источник
Вы можете просто изменить ABI, чтобы использовать более старые сборки:
defaultConfig { ... ndk { abiFilters 'armeabi-v7a' } ... }
Вы также должны использовать устаревший NDK, добавив эту строку в
gradle.properties
:android.useDeprecatedNdk=true
источник
пожалуйста, добавьте всю поддержку
приложение / 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
источник
По моему опыту, на мобильном устройстве armeabi-v7a, когда каталоги armeabi и armeabi-v7a присутствуют в apk, файлы .so в каталоге armeabi не будут связаны, хотя файлы .so в armeabi БУДУТ связаны в папке тот же armeabi-v7a mobile, если armeabi-v7a нет.
источник
на самом деле вы не можете просто поместить файл .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 о сборке
источник