APKに.soファイルを統合します
Android Studioを使用する場合、ネイティブライブラリをアプリケーションに統合する前に、mavenや.aar / .jarパッケージを含むさまざまな複雑なメソッドを使用する必要がありました...幸いなことに、これはもう必要ありません。
サポートされている各ABI(x86、mips、armeabi-v7a、armeabi)ごとに名前が付けられたサブディレクトリのjniLibsディレクトリに.soライブラリを配置するだけです-そしてそれだけです! これで、ビルド中にすべての.soファイルがAPKに統合されます。
jniLibsフォルダー名があなたに合わない場合、 build.gradleで別の場所を指定できます。
android { ... sourceSets.main { jniLibs.srcDir 'src/main/libs' } }
アーキテクチャ上にAPKを1つ作成して成功します!
abiFilterプロパティを使用すると、アーキテクチャごとに1つのAPKを簡単に構築できます。
デフォルトでは、 ndk.abiFilter(s)はallに設定されています 。 このプロパティは、.soファイルの統合とndk-buildの呼び出しに影響します(これについては投稿の最後で説明します)。
build.gradleにいくつかのアーキテクチャ機能(設定)を追加しましょう。
android{ ... productFlavors { x86 { ndk { abiFilter "x86" } } mips { ndk { abiFilter "mips" } } armv7 { ndk { abiFilter "armeabi-v7a" } } arm { ndk { abiFilter "armeabi" } } fat } }
そして、プロジェクトをgradleファイルと同期します:
好みのビルドオプションを選択して、新しい機能をお楽しみください:
これらの各オプションは、選択したアーキテクチャのAPKを提供します。
完全な(リリース|デバッグ)APKには、すべてのライブラリと、この投稿の冒頭で言及した標準パッケージが含まれます。
しかし、この場所で読書をやめないでください! アーキテクチャ依存のAPKは開発に便利ですが、それらのいくつかをGoogle Playストアにアップロードする場合は、それぞれに異なるバージョンコードをインストールする必要があります。 最新のビルドシステムでこれを行うのは非常に簡単です。
ABI依存APKの異なるバージョンコードを自動的に設定する
android.defaultConfig.versionCodeプロパティは、アプリケーションのversionCodeを担当します。 デフォルトでは、-1に設定されています。この値を変更しない場合、 AndroidManifest.xmlファイルで指定されたversionCodeが使用されます。
versionCodeを動的に変更するため 、最初にbuild.gradle内で指定する必要があります。
android { ... defaultConfig{ versionName "1.1.0" versionCode 110 } }
ただし、変更する前に「手動で」取得した場合、この変数をAndroidManifest.xmlに保存することは可能です。
import java.util.regex.Pattern android { ... defaultConfig{ versionCode getVersionCodeFromManifest() } ... } def getVersionCodeFromManifest() { def manifestFile = file(android.sourceSets.main.manifest.srcFile) def pattern = Pattern.compile("versionCode=\"(\\d+)\"") def matcher = pattern.matcher(manifestFile.getText()) matcher.find() return Integer.parseInt(matcher.group(1)) }
これで、さまざまな修飾子でversionCodeを使用できます。
android { ... productFlavors { x86 { versionCode Integer.parseInt("6" + defaultConfig.versionCode) ndk { abiFilter "x86" } } mips { versionCode Integer.parseInt("4" + defaultConfig.versionCode) ndk { abiFilter "mips" } } armv7 { versionCode Integer.parseInt("2" + defaultConfig.versionCode) ndk { abiFilter "armeabi-v7a" } } arm { versionCode Integer.parseInt("1" + defaultConfig.versionCode) ndk { abiFilter "armeabi" } } fat } }
ここでは、x86に6、mipに4、ARMv7に2、ARMv5に1のプレフィックスを付けます。
Android Studioでndkを使用する
プロジェクトソースにjniフォルダーがある場合、ビルドシステムはndk-buildを自動的に呼び出します。
現在の実装では、Android.mkのmakefileは無視されますが、代わりに新しいファイルがすぐに作成されます。 これは小さなプロジェクトには本当に便利です(.mkファイルはもう必要ありません!)。しかし、大きなプロジェクトでは、makefileが提供するすべての機能が必要な場合、迷惑になることがあります。 build.gradleでこのプロパティを無効にすることができます。
android{ ... sourceSets.main.jni.srcDirs = [] //disable automatic ndk-build call }
オンザフライメイクファイルを使用する場合は、 ndk.moduleNameプロパティを次のように設定することで最初に設定できます。
android { ... defaultConfig { ndk { moduleName "hello-jni" } } }
他のndkプロパティを設定することもできます:
- cFlags 、
- ldLibs 、
- stl (すなわち: gnustl_shared 、 stlport_static ...)、
- abiFilters (つまり、 「x86」 、 「armeabi-v7a」 )。
デバッグAPKの生成は、 android.buildTypes.debug.jniDebugBuildプロパティをtrueに設定することにより実現されます。 この場合、 ndk-buildにはNDK_DEBUG = 1が渡されます。
NDKのRenderScriptを使用している場合は、defaultConfig.renderscriptNdkModeプロパティをtrueに設定する必要があります。
自動生成されたメイクファイルを信頼する場合、マルチアーキテクチャAPKをビルドするときに、最終的なアーキテクチャに応じて異なるcFlagsを指定できます。 したがって、gradleを完全に信頼する場合は、前述の構成修飾子を使用して、アーキテクチャ用のさまざまなAPKを生成することをお勧めします。
... productFlavors { x86 { versionCode Integer.parseInt("6" + defaultConfig.versionCode) ndk { cFlags cFlags + " -mtune=atom -mssse3 -mfpmath=sse" abiFilter "x86" } } ...
私のサンプル.gradleファイル
すべてをまとめると、私自身が現在使用しているbuild.gradleファイルをもたらします。 サポートされているさまざまなABIの修飾子はなく、 ndk-buildとの統合を使用しないため、Windows環境で動作し、ソースとライブラリの通常の場所や.mkファイルの内容を変更する必要はありません。
import java.util.regex.Pattern buildscript { repositories { mavenCentral() } dependencies { classpath 'com.android.tools.build:gradle:0.9.0' } } apply plugin: 'android' android { compileSdkVersion 19 buildToolsVersion "19.0.3" defaultConfig{ versionCode getVersionCodeFromManifest() } sourceSets.main { jniLibs.srcDir 'src/main/libs' jni.srcDirs = [] //disable automatic ndk-build call } productFlavors { x86 { versionCode Integer.parseInt("6" + defaultConfig.versionCode) ndk { abiFilter "x86" } } mips { versionCode Integer.parseInt("4" + defaultConfig.versionCode) ndk { abiFilter "mips" } } armv7 { versionCode Integer.parseInt("2" + defaultConfig.versionCode) ndk { abiFilter "armeabi-v7a" } } arm { versionCode Integer.parseInt("1" + defaultConfig.versionCode) ndk { abiFilter "armeabi" } } fat } } def getVersionCodeFromManifest() { def manifestFile = file(android.sourceSets.main.manifest.srcFile) def pattern = Pattern.compile("versionCode=\"(\\d+)\"") def matcher = pattern.matcher(manifestFile.getText()) matcher.find() return Integer.parseInt(matcher.group(1)) }
トラブルシューティング
NDKが構成されていません
エラーが発生した場合:
Execution failed for task ':app:compileX86ReleaseNdk'. > NDK not configured
これは、NDKディレクトリにツールが見つからなかったことを意味します。 2つの方法があります :NDKディレクトリに従ってANDROID_NDK_HOME変数を設定し、 local.propertiesを削除するか、 local.properties内で手動で設定します 。
ndk.dir=C\:\\Android\\ndk
目標を作成するためのルールはありません
エラーが発生した場合:
make.exe: *** No rule to make target ...\src\main\jni
その原因は、コンパイル用のソースファイルが1つしかない場合のNDK for Windowsの既存のエラーかもしれません。 空のファイルをもう1つ追加すると、すべてが機能します。
その他の事項
Googleグループadt-devで質問に対する回答を見つけることができる場合があります。
NDK統合情報の取得
詳細情報を見つけるのに最適な場所は、 公式プロジェクトページです。
変更のリストを見て、全体をスクロールすると、最新のgradle-samples-XXX.zipアーカイブ内にNDK統合に関連するプロジェクトの例があります。
以下のビデオは、Android StudioのNDKソースを使用してプロジェクトをセットアップする方法を示しています。