Подтвердить что ты не робот

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"
4b9b3361

Ответ 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 о готовых