FLYING

/* TODO: 気の利いた説明を書く */

Android Studioで外部ライブラリを使うアプリを実行する

Googleから新しいAndroidアプリ開発用IDEであるAndroid Studioが発表されましたね!UIもカッコイイし,モッサリ動くEclipse環境から移行したら幸せになれるんじゃないか?という予感がひしひしとします。そこで,サンプルレベルのアプリを試しにAndroid Studioで作って動かしてみました。

……しかしながら,まだEarly Access Preview版とのことなんで,少し込み入ったアプリを作ろうとするとうまくいきません。Android Studioの導入後,数時間ほどStack Overflowを読みながら格闘した結果,なんとか外部ライブラリ(.jarや.soなどのファイルを必要とするもの)を使うアプリをコンパイル・実行することに成功したので,途中でハマったポイントを紹介します。なお,ここで対象にしているバージョンはVersion 0.1のMac版なので,他のプラットフォームだと同じ手順を踏んでもうまくいかないかもしれません。

Androidプロジェクトの作成

テキトーに「Test」みたいな名前で作成すればいいと思います。こちらのエントリなどが参考になります。

Javaライブラリ(.jarファイル)の導入

Eclipse環境と同様に,libsディレクトリに必要なjarをどんどん突っ込んでいく前提で解説します。

例えば「Test」と言う名前のプロジェクトを作成すると,上図のようなファイルツリーが生成されます。Test/Test以下にlibsというディレクトリがあるので,ここに必要なjarファイルをコピーしてください。

続いてメニューバーの「File」→「Project Structure」を開き,左側のカラムで「Libraries」を選択します。ウィンドウ上部の+ボタンを押してJavaを選択すると,ファイルツリーが表示されるので,先ほどのlibsディレクトリを選択してOKします。Moduleとして追加する対象のプロジェクトを選べと言われるので,「Test-Test」を選択してOKします。なお,元々あったLibraryは(libsディレクトリ全体をLibraryとして追加したので)消してしまって構いません。


LibrariesとModulesの項目が上図のようになっていればOKです。OKを押してProject Structureの画面を閉じましょう。

これだけだとビルド時にエラーが出るので,ビルド構成ファイルであるbuild.gradleを直接編集します。ファイルツリーにbuild.gradleが2つあると思いますが,Test/Test以下にある方のbuild.gradleを次のように編集してください。

buildscript {
    repositories {
        maven { url 'http://repo1.maven.org/maven2' }
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:0.4'
    }
}
apply plugin: 'android'

dependencies {
    compile fileTree(dir: 'libs', include: '*.jar')
}

android {
    compileSdkVersion 17
    buildToolsVersion "17.0.0"

    defaultConfig {
        minSdkVersion 7
        targetSdkVersion 16
    }
}

デフォルトから変更したのはdependenciesの項目で,libsディレクトリ以下のjarファイルをすべて依存ファイルに含めるようにしています。

ネイティブライブラリ(.soファイル)の導入

上図のように,libsディレクトリ以下に各アーキテクチャ用のディレクトリを作り,soファイルを突っ込みます。Eclipse環境だとこれだけでOKですが,Android Studioではちょっとしたハックが必要です。先ほど編集したbuild.gradleを再度開き,次の記述を追加します。

// https://gist.github.com/khernyo/4226923
task copyNativeLibs(type: Copy) {
    from('libs') { include '**/*.so' }
    into new File(buildDir, 'native-libs')
}
tasks.withType(Compile) { compileTask -> compileTask.dependsOn copyNativeLibs }
tasks.withType(com.android.build.gradle.tasks.PackageApplication) {
    pkgTask -> pkgTask.jniDir(new File(buildDir, 'native-libs'))
}
clean.dependsOn 'cleanCopyNativeLibs'

Gradle Android configuration with .so hackで紹介されているハックほぼそのままです(変更されているクラス名の部分のみ編集しました)。まだあまり理解していないためにふわっとした解説しかできないのですが,libsディレクトリ以下の.soファイルを専用のディレクトリにコピーし,コピー先のディレクトリをjniのバイナリがあるディレクトリとして指定しているようですね。

cleanする(大事)

以上で設定は完了ですが,このまま実行しても手元の環境では実行時のNoClassDefFoundErrorが解消しませんでした。これを解消するには,コマンドラインからcleanを実行する必要があります。ターミナルを開き,次のようにしてcleanを実行してください。

$ cd ~/AndroidStudioProjects/Test
$ ./gradlew clean
Picked up _JAVA_OPTIONS: -Dfile.encoding=UTF-8
The TaskContainer.add() method has been deprecated and is scheduled to be removed in Gradle 2.0. Please use the create() method instead.
:Test:cleanCopyNativeLibs UP-TO-DATE
:Test:clean

BUILD SUCCESSFUL

Total time: 10.427 secs

ここまで済んだら,Android Studioから「Run」を選んで実機で実行してみてください。無事アプリが動作すれば完了です。