Система.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 56

11 ответов:

до первопричины (и, возможно, решить вашу проблему, в то же время), вот что вы можете сделать:

  1. удалите папку jni и все файлы .mk. Вам не нужны ни эти, ни NDK, если вы ничего не компилируете.

  2. скопировать внутри <project>/libs/(armeabi|armeabi-v7a|x86|...) . При использовании Android Studio, это <project>/app/src/main/jniLibs/(armeabi|armeabi-v7a|x86|...), но я вижу, что вы используете Eclipse.

  3. создайте свой APK и откройте его как zip файл, чтобы проверить, что ваш внутри lib|(armeabi|armeabi-v7a|x86/...).

  4. удалить и установить приложение

  5. выполнить dumpsys package packages / grep yourpackagename для получения nativeLibraryPath или legacyNativeLibraryDir приложения.

  6. выполнить ls на nativeLibraryPath вы должны были или на legacyNativeLibraryDir / armeabi, чтобы проверить, если ваш libcalculate.so действительно есть.

  7. если он есть, проверьте, не был ли он изменен с вашего оригинала 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 способа решить эту проблему:

  1. построить свои собственные библиотеки для каждый ABI поддерживает ваше приложение.
  2. измените свое приложение, чтобы оно было нацелено на более старый 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