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"
根本的な原因(および問題を同時に解決できる可能性があります)にするには、次のようにします。
Jniフォルダーとすべての。mkファイルを削除します。何もコンパイルしない場合、これらもNDKも必要ありません。
<project>/libs/(armeabi|armeabi-v7a|x86|...)
内にlibcalculate.so
ファイルをコピーします。 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を取得します。
nativeLibraryPathまたはlegacyNativeLibraryDir/armeabiでlsを実行して、 libcalculate.soが実際に存在するかどうかを確認してください。
存在する場合は、元のlibcalculate.soファイルから変更されていないかどうかを確認します:適切なアーキテクチャに対してコンパイルされているか、予想されるシンボルが含まれているか、依存関係がありません。 readelfを使用してlibcalculate.soを分析できます。
ステップ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内
<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がある場合)。
Gradleでは、すべてのファイルフォルダをlibs/
にコピーした後
jniLibs.srcDirs = ['libs']
上記の行をbuild.gradle
ファイルのsourceSets
に追加しました。他に何も機能しませんでした。
Gradleを使用していますか?その場合は、.so
ファイルを<project>/src/main/jniLibs/armeabi/
に入れます
役に立てば幸いです。
私の場合、私はgradleでコンパイルソースを除外し、libsパスを設定する必要があります
Android {
...
sourceSets {
...
main.jni.srcDirs = []
main.jniLibs.srcDirs = ['libs']
}
....
このエラーの理由は、アプリとリンク先のネイティブライブラリの間にABIの不一致があるためです。別の言い方をすれば、アプリと.so
は異なるABIをターゲットにしています。
最新のAndroid Studioテンプレートを使用してアプリを作成する場合、おそらくarm64-v8a
をターゲットにしていますが、たとえば.so
はarmeabi-v7a
をターゲットにしている可能性があります。
この問題を解決するには2つの方法があります。
.so
が構築された古いABIをターゲットとするようにアプリを変更します。選択肢2は汚れていますが、おそらくもっと興味があると思います。
アプリのbuild.gradle
を変更する
Android {
defaultConfig {
...
ndk {
abiFilters 'armeabi-v7a'
}
}
}
参考までに、このエラーメッセージがありました。解決策は、ライブラリを指定すると、先頭の「lib」と末尾の「.so」が欠落することでした。
したがって、ファイルlibmyfablib.soがある場合は、以下を呼び出す必要があります。
System.loadLibrary("myfablib"); // this loads the file 'libmyfablib.so'
Apkを調べ、インストール/アンインストールし、あらゆる種類の複雑なソリューションを試しましたが、私の目の前にある単純な問題は見当たりませんでした!
これは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;
}
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
ディレクトリーにライブラリーをデプロイする必要があります。
すべてのサポートを追加してください
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