Androidアプリケーションはプログラムの一部をNativeコードで作ることが出来ます。
Nativeコードとは端末のCPUが直接解釈できるプログラム(マシン語)のことです。
演算負荷の大きい処理を高速化したい場合に有効な手段です。
NativeコードのプログラミングはAndroid NDK(Native Development Kit)を使ってC/C++で行います。
そのためのNative開発環境を、Android Studioは組み込めるようになっています。
今回、Android StudioへNative開発環境を構築してみたので紹介します。
※本記事はAndroid Studio 4.1.1で実施しています。
目次
既存のProjectへ構築
既存のProjectでNativeコードのプログラミングが必要になったとき、後からNative開発環境をProjectへ組み込むことが出来ます。
以下は組み込むための手順です。
mainフォルダ上で 右クリック->New->Directory を指定し、src/main/javaと並列にcppフォルダを作ります。
ここにC/C++のソースとCMakeのシナリオを配置します。
cppフォルダ上で 右クリック->New->File を選択し、CMakeのシナリオ(CMakeLists.txt)を作成します。同様に、cppフォルダ上で 右クリック->New->C/C++ Source File を選択し、C/C++のソースコード(native-lib.cpp)を作成します。
※CMakeLists.txtとnative-lib.cppの詳細は後述
cppフォルダ上で 右クリック->Link C++ Project with Gradle を選択し、cppフォルダをGradleが提供するビルドシーケンスに組み込み(リンク)ます。
この組み込みでCMakeのシナリオの指定が必要です。
この後、組み込みの作業が開始されます。
環境が作られる前にAndroid NDKとCMakeのダウンロードが行われます。このダウンロードに時間がかかります。
気長に待ちましょう。
組み込みが完了するとcppフォルダが青くなります。
構築されたNative開発環境
構築された開発環境は、Native環境の有無を意識することなくアプリの実行やテスト行えるものになっています。
C/C++のプログラミングを行う以外に特別な操作は必要ありません。エミュレータならびにUSB接続されたAndroid端末でアプリを起動したければ、Runを実行するだけです。
以下は、構築された環境の詳細です。
NDKとCMake
Native開発に必要なNDKとCMakeが自動でダウンロードされています。内容はSDK Managerで確認できます。
詳細は「Native開発環境の構築~New Project編~」と同じです。
Native開発のフォルダ
詳細は「Native開発環境の構築~New Project編~」と同じです。
Gradleの設定
build.gradleへNative関連の設定が追記されます。
: android { compileSdkVersion 29 buildToolsVersion "30.0.2" defaultConfig { applicationId "com.example.myapplication" : } externalNativeBuild { cmake { path "src/main/cpp/CMakeLists.txt" } } : } :
確認用のNativeサンプル
開発環境の確認用にNativeのサンプルを作りました。
内容はとても簡単で、TextViewへ「C++より、こんにちは」と表示するサンプルです。
この「C++より、こんにちは」の出力をNativeコードで行っています。
以下はサンプルの詳細です。
CMakeのシナリオ
このシナリオでライブラリをビルドした結果、ファイルlibnative-lib.soが作成されることになります。
詳細は「Native開発環境の構築~New Project編~」と同じです。
cmake_minimum_required(VERSION 3.10.2) project("myapplication") add_library( native-lib SHARED native-lib.cpp ) find_library( log-lib log ) target_link_libraries( native-lib ${log-lib} )
Nativeソースコード
jstring型の文字列”C++より、こんにちは”を返すだけの関数です。
詳細は「Native開発環境の構築~New Project編~」と同じです。
#include <jni.h> #include <string> extern "C" JNIEXPORT jstring JNICALL Java_com_example_myapplication_MainActivity_stringFromJNI( JNIEnv* env, jobject /* this */) { std::string hello = "C++より、こんにちは"; return env->NewStringUTF(hello.c_str()); }
Kotlinから呼出
KotlinはstringFromJNI( )を通してNativeコードを呼び出します。
詳細は「Native開発環境の構築~New Project編~」と同じです。
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) findViewById<TextView>(R.id.sample_text).text = stringFromJNI() } external fun stringFromJNI(): String companion object { init { System.loadLibrary("native-lib") } } }