web-dev-qa-db-ja.com

私の場合、System.loadLibrary(...)はネイティブライブラリを見つけることができませんでした

another Androidプロジェクトの既存のネイティブライブラリを使用したいので、NDKビルドライブラリ(libcalculate.so)を新しい_にコピーしましたAndroidプロジェクト。新しいAndroidプロジェクトで、フォルダーlibs/armeabi/を作成し、そこにlibcalculate.soを配置しました。 no 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があります)

==== UPDATE ======

また、プロジェクトルートの下にjni /フォルダーを作成し、jni /の下にAndroid.mkファイルを追加しようとしました。 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"
76
user842225

根本的な原因(および問題を同時に解決できる可能性があります)にするには、次のようにします。

  1. Jniフォルダーとすべての。mkファイルを削除します。何もコンパイルしない場合、これらもNDKも必要ありません。

  2. <project>/libs/(armeabi|armeabi-v7a|x86|...)内にlibcalculate.soファイルをコピーします。 Android St​​udioを使用する場合、<project>/app/src/main/jniLibs/(armeabi|armeabi-v7a|x86|...)ですが、Eclipseを使用しているようです。

  3. APKをビルドしてZipファイルとして開きlibcalculate.soファイルが内部にあることを確認しますlib /(armeabi | armeabi-v7a | x86 | ...)

  4. アプリケーションを削除してインストールする

  5. dumpsysパッケージパッケージを実行します| grep yourpackagenameを使用して、アプリケーションのnativeLibraryPathまたはlegacyNativeLibraryDirを取得します。

  6. nativeLibraryPathまたはlegacyNativeLibraryDir/armeabilsを実行して、 libcalculate.soが実際に存在するかどうかを確認してください。

  7. 存在する場合は、元のlibcalculate.soファイルから変更されていないかどうかを確認します:適切なアーキテクチャに対してコンパイルされているか、予想されるシンボルが含まれているか、依存関係がありません。 readelfを使用してlibcalculate.soを分析できます。

ステップ5-7を確認するには、コマンドラインとreadelfの代わりにアプリケーションを使用できます。 Native Libs Monitor

PS:.soファイルをデフォルトで配置または生成する場所について混乱するのは簡単です。以下に要約を示します。

  • libs/CPU_ABI Eclipseプロジェクト内

  • jniLibs/CPU_ABI Android St​​udioプロジェクト内

  • jni/CPU_ABI AAR内

  • lib/CPU_ABI最終APK内

  • <5.0デバイスではアプリのnativeLibraryPath内、> = 5.0デバイスではアプリのlegacyNativeLibraryDir/CPU_Arch内。

CPU_ABIは、armeabi、armeabi-v7a、arm64-v8a、x86、x86_64、mips、mips64のいずれかです。ターゲットとするアーキテクチャとライブラリがコンパイルされているかによって異なります。

また、CPU_ABIディレクトリ間でライブラリが混在しないことに注意してください。使用しているものの完全なセットが必要です。armeabiフォルダー内のライブラリはインストールされません。 armeabi-v7aデバイス(APKのarmeabi-v7aフォルダー内にlibがある場合)。

151
ph0b

Gradleでは、すべてのファイルフォルダをlibs/にコピーした後

jniLibs.srcDirs = ['libs']

上記の行をbuild.gradleファイルのsourceSetsに追加しました。他に何も機能しませんでした。

17

Gradleを使用していますか?その場合は、.soファイルを<project>/src/main/jniLibs/armeabi/に入れます

役に立てば幸いです。

12
Assaf Gamliel

私の場合、私はgradleでコンパイルソースを除外し、libsパスを設定する必要があります

Android {

    ...
    sourceSets {
        ...
        main.jni.srcDirs = []
        main.jniLibs.srcDirs = ['libs']
    }
....
11
Dawid Drozd

このエラーの理由は、アプリとリンク先のネイティブライブラリの間にABIの不一致があるためです。別の言い方をすれば、アプリと.soは異なるABIをターゲットにしています。

最新のAndroid St​​udioテンプレートを使用してアプリを作成する場合、おそらくarm64-v8aをターゲットにしていますが、たとえば.soarmeabi-v7aをターゲットにしている可能性があります。

この問題を解決するには2つの方法があります。

  1. アプリがサポートするABIごとにネイティブライブラリを構築します。
  2. .soが構築された古いABIをターゲットとするようにアプリを変更します。

選択肢2は汚れていますが、おそらくもっと興味があると思います。

アプリのbuild.gradleを変更する

Android {
    defaultConfig {
        ...
        ndk {
            abiFilters 'armeabi-v7a'
        }
   }
}
5
wdanxna

参考までに、このエラーメッセージがありました。解決策は、ライブラリを指定すると、先頭の「lib」と末尾の「.so」が欠落することでした。

したがって、ファイルlibmyfablib.soがある場合は、以下を呼び出す必要があります。

   System.loadLibrary("myfablib"); // this loads the file 'libmyfablib.so' 

Apkを調べ、インストール/アンインストールし、あらゆる種類の複雑なソリューションを試しましたが、私の目の前にある単純な問題は見当たりませんでした!

4
Andy Krouwel

これはAndroid 8アップデートです。

Androidの以前のバージョンでは、LoadLibraryネイティブ共有ライブラリ(たとえばJNIを介したアクセス用)に、さまざまなapkインストール/アップグレードアルゴリズムに基づいて、libフォルダーのさまざまな潜在的なディレクトリパスを反復処理するためにネイティブコードをハードワイヤーしました。

/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では機能しません。 from 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;
}
4
AlgebraWinter

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

更新:

Javaでこのライブラリを使用する場合は、共有ライブラリとしてコンパイルする必要があります

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE    := libcalculate
LOCAL_SRC_FILES := <PATH>/libcalculate.so
include $(BUILD_SHARED_LIBRARY)

そして、/vendor/libディレクトリーにライブラリーをデプロイする必要があります。

4
Alex

すべてのサポートを追加してください

app/build.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
0
Lion耿