AndroidStudioでNDKデバッグをできるようにする

2019年4月10日

Gradle のアップデートができたので、公式のリファレンス「Experimental Plugin User Guide」に沿って NDK のデバッグ環境を構築してみます。

スポンサーリンク

環境

  • Android Studio 1.3 RC3
  • Android SDK 22
  • Android NDK r10e
  • Gradle 2.5

公式のリファレンスを読んでみる

NDK デバッグをできるようにするために既存のプロジェクトに対して更新が必要だそう。

対象は以下の3つと書かれています。

  • Project 直下の build.gradle
  • app 直下の build.gradle
  • gradle/wrapper/ 直下の gradle-wrapper.properties

まずは、Gradle 2.5 の書式に合わせます

Project の build.gradle の “classpath" を変更する

classpath 'com.android.tools.build:gradle:1.2.3’

classpath 'com.android.tools.build:gradle-experimental:0.1.0’

app の build.gradle をいろいろ変更する

・プラグイン名
apply plugin: 'com.android.application’

apply plugin: 'com.android.model.application’

※Android aar library なるものを作る場合には、上記の “application" を “library" にするらしい

・model スコープの追加
Gradle 2.4 までは、以下のように書いていましたが、

android {
    compileSdkVersion 22
    buildToolsVersion "22.0.1"

    defaultConfig {
        applicationId "com.example.user.myapplication"
        minSdkVersion 15
        targetSdkVersion 22
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    sourceSets {
        main {
            jni.srcDirs = []
            jniLibs.srcDirs = ["src/main/libs", "src/main/jniLibs"]
        }
    }
}

これを、以下のように変更します。

android {
    compileSdkVersion 22
    buildToolsVersion "22.0.1"
    
    defaultConfig {
        applicationId "com.example.user.myapplication"
        minSdkVersion 15
        targetSdkVersion 22
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    sourceSets {
        main {
            jni.srcDirs = []
            jniLibs.srcDirs = ["src/main/libs", "src/main/jniLibs"]
        }
    }
} 

NDK 用の設定を追加していきます

android.ndk を追加します

model 内に anrdoid.ndk を追加します。

model {
    android.ndk {
        moduleName = "module-name"
    }
}

ということで、公式リファレンスはここまでしか書いてないです。

そして残念なことに、私のプロジェクトはこれだけでは動作しませんでした。

そこで、以下の対応を行いました。

LOCAL_C_INCLUDE の代わりは?

Android.mk での LOCAL_C_INCLUDE の代わりが宣言できていないため、各種ヘッダファイルの include でエラーがでました。

android.ndk に、以下のように記述すると該当ディレクトリを参照できるようになるみたいです。

CFlags += "-I${file("src/main/jni/headers")}".toString()
cppFlags += "-I${file("src/main/jni/headers")}".toString()\

注意:

参照の先頭に “/" を付けて、"/src/main/jni/" としているとフォルダへの参照パスが通りません。

私は Android.mk に “/src/main/jni/" と書いていたので、なぜかヘッダの include が通らずにしばらく悩みました。

LOCAL_LDLIBS で行っていた外部ライブラリの読み込み

Android.mk での LOCAL_LDLIBS の代わりは、以下のように記述すると参照できるようになりました。

ldFlags += "src/main/jni/lib/x86/libxml.so"

アーキテクチャを指定するマクロがあるのかわからなかったので、とりあえず決め打ちです。

あと、この手順ではディレクトリは指定できないみたいでした。

他のやり方があるかもしれません。

私のプロジェクトの問題

Gradle では、基本的に jni フォルダ以下にある .c および .cpp ファイルをすべて読み込むようになっています。

これまでは自前の Android.mk を使っていたため、読み込まないファイルを LOCAL_SRC_FILES に書かないことで避けていました。

Gradle の場合は、android.source のところで exclude 設定を行うと回避できるようにはなっているようですが、現時点ではバグがあり、exclude を設定しても動作しないことが報告されていました。
https://code.google.com/p/android/issues/detail?id=180715

ということで、仕方がないので使っていないファイルをすべて退避しました。

exclude の不具合が直ったら戻します。

ここまでの対応で、Gradle で NDK ビルドしたアプリケーションが Android で起動できるようになりました。

おしまい。

スポンサーリンク

Android,NDKandroid,NDK

Posted by peliphilo