Android の開発時に、C++などで作られた 静的ライブラリ〜.a や、共有ライブラリ〜.so を利用したい時。
まず、ビルド設定方法は1つではない。CMakeLists.txt を使う方法、Android.mk を使う方法と、やり方が選べる。
また、 so ファイルは、アプリケーションコードからロードできるが、 a ファイルは直接ロードできず、so を経由して読み込むことになる。
選択する言語は、Java・Kotolin どちらでも全く問題ない。
ドキュメントだけでは理解できない部分があったのでまとめた。
公式のドキュメントはこちら。
プロジェクトへの C / C++ コードの追加 | Android Developers
C、C++側の書き方はこちらを参照。
Java Native Interface仕様の目次
Android NDK環境のインストール
Android Studio を起動し、
Android SDK Manager > SDK Toolsタブ と進む。
CMake、LLDB、NDK を選択しインストールする。
プロジェクト作成
ここからは通常通り新規作成をするが、Choose your project で、Native C++ を選択する。
他のサイトでは、Include C++ support のチェックを入れるように書かれているが、その設定はもう無くなっており、必要ない。
プロジェクト内ファイルの説明
cpp フォルダの中に、CMakeLists.txt と、native-lib.cpp ファイルがある。
この2ファイルをいじるだけで、ビルドし、理解する分には十分です。
CMakeLists.txt の書き方
関数の引数は、スペースや改行で区切るイメージ。
共有ライブラリを作成時(C++をそのまま呼び出す場合)
CMakeLists.txt
# ライブラリのルート set( LIB_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../.. ) # ライブラリの出力先 # ANDROID_ABIで、対応するプロセッサごとにフォルダを分ける set( OUTPUT_DIR ${LIB_ROOT}/lib/${ANDROID_ABI} ) # ライブラリのソースファイル # add_library( ライブラリ名 SHARED ソースファイル ) add_library( native-lib SHARED native-lib.cpp ) # 共有ライブラリ 出力先を指定 # set_target_properties( ライブラリ名 PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${OUTPUT_DIR} ) set_target_properties( native-lib PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${OUTPUT_DIR} ) # ライブラリを変数に定義 # 必須ではないが、このような書き方が出来る # find_library( 定義名 ライブラリ名... ) find_library( log-lib log ) # 依存ファイルのリンク # native-lib.cpp の中で、${log-lib} を利用してプログラムをしている場合 # target_link_libraries( ライブラリ名 依存ファイル... ) target_link_libraries( native-lib ${log-lib} )
静的ライブラリを作成する時
CMakeLists.txt
# ライブラリのルート set( LIB_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../.. ) # ライブラリの出力先設定 set( OUTPUT_DIR ${LIB_ROOT}/lib/${ANDROID_ABI} ) # ライブラリのソースファイル # add_library( ライブラリ名 STATIC ソースファイル ) add_library( native-lib STATIC native-lib.cpp ) # 静的ライブラリ 出力先を指定 # set_target_properties( ライブラリ名 PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${OUTPUT_DIR} ) set_target_properties( native-lib PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${OUTPUT_DIR} )
build.gradle
リンクしない STATIC ライブラリはビルドされないため、常にビルドさせる設定
android { defaultConfig { externalNativeBuild { cmake { # targets 'ライブラリ名' targets 'native-lib' } } } }
共有ライブラリを利用する時
読み込めばC++の関数が呼び出せる。
CMakeLists.txt
# ライブラリのルート set( LIB_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../.. ) # ライブラリの出力先設定 set( OUTPUT_DIR ${LIB_ROOT}/lib/${ANDROID_ABI} ) # ライブラリが外部参照である事を指定 add_library( native-lib SHARED IMPORTED ) # ライブラリファイルの位置を指定 set_target_properties( native-lib PROPERTIES IMPORTED_LOCATION ${OUTPUT_DIR}/libanylib.so )
*.java
class Hoge { static { System.loadLibrary("native-lib"); } }
静的ライブラリを利用する時
流れとしては、一度 静的ライブラリを元に、共有ライブラリを作成し、共有ライブラリを読み込むことになる。
なので、上記の方法を全て把握する必要がある。
CMakeLists.txt
# ライブラリのルート set( LIB_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../.. ) # ライブラリの出力先 set( OUTPUT_DIR ${LIB_ROOT}/lib/${ANDROID_ABI} ) # ライブラリが外部参照である事を指定 add_library( anylib STATIC IMPORTED ) # ライブラリファイルの位置を指定 set_target_properties( anylib PROPERTIES IMPORTED_LOCATION ${OUTPUT_DIR}/libanylib.a ) # 共有ライブラリの生成 add_library( native-lib SHARED native-lib.cpp ) # 共有ライブラリ 出力先を指定 set_target_properties( native-lib PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${OUTPUT_DIR} ) # ライブラリのインクルードファイルの参照先 target_include_directories( native-lib PRIVATE ${LIB_ROOT}/include ) # ライブラリを変数に定義 find_library( log-lib log ) # 依存ファイルのリンク # native-lib.cpp の中で、anylibと、${log-lib} を利用してプログラムをしている場合 target_link_libraries( native-lib anylib ${log-lib} )
*.java
class Hoge { static { System.loadLibrary("native-lib"); } }