JackでDagger2は使えない(追記:6/16)
最近のAndroidのアプリ開発においてDagger、Dagger2を使ったDIを活用した開発が盛んに行われています。
また、AndroidのNのPreview版が公開も行われ次世代の開発においたアプリ開発も進んできた。
AndroidのNのトピックの一つにJack and Jillという物があります。
Jack(Java Android Compiler Kit)の使い方とDaggerを使った時の問題点を紹介します。
どうやらJackでビルドができるようなりました。 興味がある方はこちらをどうぞ。
Jackの使い方
Androidアプリのパッケージ内を分解するとdexファイルというものがあります。
これはAndroidを実行する際にVirtualMachineで実行するためのバイトコードになります。
今までのdexファイルは下記の手順で実行されてきました。
javac (.java --> .class) --> dx (.class --> .dex)
新しく登場したツールチェインのJackは次のようにdexファイルの生成を実施します。
Jack (.java --> .jack --> .dex)
このようにすることでdexファイルの生成が行われます。
Jackは再パッケージ化、縮小、難読化、Multidex ができるようです。
詳細はこちらを御覧ください。
それではJackを使って見ましょう。
で紹介されているJackの使い方(useJack = true)は今ではDeprecatedになっていますので、今のやり方は次の様になります。
まずAndroid Studio 2.1にアップデートまたはダウンロードします。
そしてSDKバージョンはandroid-N、buildToolsVersionは24以降に設定しましょう。
2016/5/1現在ではrc3が最新になるのでその場合は下記の様になります。
[app/build.gradle]
android { compileSdkVersion 'android-N' buildToolsVersion "24.0.0 rc3" defaultConfig { <省略> jackOptions { enabled true } } <省略> }
ここで注目するのはjackOptionsという部分です。
jackOptionのenabledをtrueするとビルド時にjackを生成してdexを作成する処理が実行されるようになります。
もしbuildToolsVersionが24以降のものを使っていなかった場合ビルド時に下記のエラーでビルドできません。
注意しましょう。
Error:Execution failed for task ':app:jillDebugPackagedLibraries'. > Jack requires Build Tools 24.0.0 or later
これでビルドできるようになりました。
ビルドしてみるとJackでビルドされます。
気になる人はbuildフォルダのintermediates内のpackaged内にあるclasses.zipを解答してみるとclassファイルは生成されずJayceという拡張子のファイルが生成されているのが確認できると思います。
このjayceからdexを生成しています。
ライブラリの利用について
ここからが本題なのですが、Jackのdexの作成のアプローチが今まで全く異なるため下記の用にサポートページに記載されています。
Annotation processing is not supported.
理由としては中間クラスファイルを生成を行わないためそれを活用するannotation processing が全面的に使えなくなります。
そのためDaggerは対象になります。
あえて動かないことを確認してみました。
Dagger2の動くコードを下記に用意しました。(動かすためだけなのでDaggerのコードは適当です。すみません。)
このコードのbuild.gradleの処理にjackOptionsのenabledをtrueにすると下記のようなエラーが表示されます。
Caused by: groovy.lang.MissingPropertyException: Could not find property 'options' on task ':app:compileDebugJavaWithJack'. at org.gradle.api.internal.AbstractDynamicObject.propertyMissingException(AbstractDynamicObject.java:43) at org.gradle.api.internal.AbstractDynamicObject.getProperty(AbstractDynamicObject.java:35) at org.gradle.api.internal.CompositeDynamicObject.getProperty(CompositeDynamicObject.java:97) at com.android.build.gradle.tasks.JackTask_Decorated.getProperty(Unknown Source) at com.neenbedankt.gradle.androidapt.AndroidAptPlugin.configureVariant(AndroidAptPlugin.groovy:72) at com.neenbedankt.gradle.androidapt.AndroidAptPlugin$_apply_closure1_closure3.doCall(AndroidAptPlugin.groovy:39) at org.gradle.api.internal.ClosureBackedAction.execute(ClosureBackedAction.java:67) at org.gradle.api.internal.DefaultDomainObjectCollection.all(DefaultDomainObjectCollection.java:110) at org.gradle.api.internal.DefaultDomainObjectCollection.all(DefaultDomainObjectCollection.java:115) at org.gradle.api.DomainObjectCollection$all.call(Unknown Source) at com.neenbedankt.gradle.androidapt.AndroidAptPlugin$_apply_closure1.doCall(AndroidAptPlugin.groovy:38) at org.gradle.listener.ClosureBackedMethodInvocationDispatch.dispatch(ClosureBackedMethodInvocationDispatch.java:40) at org.gradle.listener.ClosureBackedMethodInvocationDispatch.dispatch(ClosureBackedMethodInvocationDispatch.java:25) at org.gradle.internal.event.AbstractBroadcastDispatch.dispatch(AbstractBroadcastDispatch.java:44) at org.gradle.internal.event.BroadcastDispatch.dispatch(BroadcastDispatch.java:79) at org.gradle.internal.event.BroadcastDispatch.dispatch(BroadcastDispatch.java:30) at org.gradle.messaging.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93) at com.sun.proxy.$Proxy11.afterEvaluate(Unknown Source) at org.gradle.configuration.project.LifecycleProjectEvaluator.notifyAfterEvaluate(LifecycleProjectEvaluator.java:67) ... 54 more 2016-05-01 18:29:45,943 [ 20196] WARN - nal.AbstractExternalSystemTask - Could not find property 'options' on task ':app:compileDebugJavaWithJack'.
このコードをDagger1でも同じように実装してみましたが同じ箇所でエラーになります。
原因はAndroidAptPluginがapp:compileDebugJavaWithJackのタスク実行時に指定のオプションが見つからないために発生していることが読み取れます。
apt(annotation processing tool)を使ったライブラリはAndroidN以降のみでJackを利用するつもりのアプリを開発する際は盛り込まないようにしたほうが良さそうです。