web-dev-qa-db-ja.com

Android Studio(cmake)でビルド済みの共有ライブラリを使用する

Androidアプリ内でC++共有ライブラリを使用したい。GoogleのNDKサンプルのhello-libsの例に沿って実行しようとしましたが、どういうわけかうまくいきません。

私のライブラリはAPKにパックされていないようです。私が見つけたすべてのチュートリアルは*.mk-ファイルを使用していますが、cmakeを使用したいと思います。

これは私のCMakeLists.txtです:

# Sets the minimum version of CMake required to build the native library.
cmake_minimum_required(VERSION 3.4.1)

# native lib
add_library(native-lib SHARED
            native-lib.cpp)

set(IMPORT_DIR ${CMAKE_SOURCE_DIR}/../jniLibs)

# shared lib
add_library(shared-lib SHARED IMPORTED)
set_target_properties(shared-lib PROPERTIES IMPORTED_LOCATION
                      ${IMPORT_DIR}/dynamic/lib/${Android_ABI}/libLibrary.so)
target_include_directories(native-lib PRIVATE
                           ${IMPORT_DIR}/dynamic/include)

# linking libs
target_link_libraries(native-lib
                      Android
                      shared-lib
                      log)

shared-libを他のアプリとリンクするとすぐに、アプリの実行時に次のエラーが発生します。

E/art: dlopen("/data/app/my.package.name-1/lib/arm/libnative-lib.so", RTLD_LAZY) failed: dlopen failed: library "C:/projects/HelloLibs/app/src/main/cpp/../jniLibs/dynamic/lib/armeabi-v7a/libLibrary.so" not foun
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
                  Process: my.package.name, PID: 29266
                  Java.lang.UnsatisfiedLinkError: dlopen failed: library "C:/projects/HelloLibs/app/src/main/cpp/../jniLibs/dynamic/lib/armeabi-v7a/libLibrary.so" not found
                      at Java.lang.Runtime.loadLibrary(Runtime.Java:371)
                      at Java.lang.System.loadLibrary(System.Java:988)
                      at my.package.name.MainActivity.<clinit>(MainActivity.Java:11)
                      at Java.lang.reflect.Constructor.newInstance(Native Method)
                      at Java.lang.Class.newInstance(Class.Java:1690)
                      at Android.app.Instrumentation.newActivity(Instrumentation.Java:1078)
                      at Android.app.ActivityThread.performLaunchActivity(ActivityThread.Java:2543)
                      at Android.app.ActivityThread.handleLaunchActivity(ActivityThread.Java:2771)
                      at Android.app.ActivityThread.access$900(ActivityThread.Java:177)
                      at Android.app.ActivityThread$H.handleMessage(ActivityThread.Java:1432)
                      at Android.os.Handler.dispatchMessage(Handler.Java:102)
                      at Android.os.Looper.loop(Looper.Java:135)
                      at Android.app.ActivityThread.main(ActivityThread.Java:5912)
                      at Java.lang.reflect.Method.invoke(Native Method)
                      at Java.lang.reflect.Method.invoke(Method.Java:372)
                      at com.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.Java:1405)
                      at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:1200)

デバイスにライブラリが見つからないようです。そうでなければ、書店の道はまだ私の地元の書店にあるように見えます。

9
Dario

ビルド済みlibLibrary.soにはSONAMEがありません。何らかの理由でこのライブラリを最新のNDKで再構築できない場合は、 patchelf ユーティリティを試してSONAMEを既存のバイナリに追加してください。

4
Alex Cohn

ビルド済みライブラリをAPKにパッケージ化するには、sourceSetsブロックを使用してGradleを手動で構成し、.soファイルへのパスを含める必要があります。 APKをビルドした後、APKアナライザー([ビルド]> [APKの分析...])を使用して、どのライブラリをAPKにGradleパッケージ化するかを確認できます。

Android {
...
sourceSets {
    main {
        jniLibs.srcDirs 'imported-lib/src/', 'more-imported-libs/src/'
    }
}

詳細については、こちらをご覧ください " ビルド済みのネイティブライブラリを含む "

1
Ali Maddi

共有ライブラリ(.soファイル)を使用するためにCMakeを使用する必要はありません。ライブラリをsrc/main/jniLibsディレクトリのそれぞれのディレクトリ内に配置するだけです。次に、ライブラリを直接ロードできます。

Android Studioでは、ネイティブメソッド宣言にエラーが表示される場合がありますが、アプリは正常に動作します。

0
Nabin Bhandari