仕事でちょっと困ったので、調査ログを残しておく。
そもそもAndroidXとはなんなのか、Jetifierとはなんなのかを記しておく。
前提知識として、Android開発における最も一般的な外部ライブラリとして Android Support Library / AndroidX
というものが存在する。
もともとAndroidには Android Support Library
というものがあって、これの後述する問題を解消したものが AndroidX
である。
どの程度一般的かというと、Android Studioで新規にプロジェクトを作成するとそもそも標準で入ってくるし、Googleの公開している (Googleのビジネスに依存した) Android向けライブラリでは当然のごとく依存関係に含まれている。
というのも、Support LibraryしかりAndroidXが目指しているのは「Android OSから独立した、Androidのリリース全体に渡る下位互換性の提供」であり、アプリが実行されるOSバージョン自体がどんなバージョンであってもつつがなく動作することを保証するためのライブラリであるからだ。
すなわち特定バージョンのAndroidリリースと同期的に変更されるアプリ、具体的にはOS標準のシステムアプリなどでない限り、アプリはネイティブのAPIを直接叩くのではなく、Support LibraryしかりAndroidXのAPIを利用すべきである。
冒頭の「なぜAndroidXが登場したのか」という部分だが、これは
などのSupport Libraryの問題を解消すべく、
をはじめとする複数の修正を行いイチから再スタートしたのがAndroidX、ということになる。
当然ながら、AndroidXはこれから更新が重ねられていく。すなわち新たな機能を利用したい場合、AndroidXへの移行を余儀なくされる。
しかしながらメンテナンスの停止したライブラリを利用しているだとか、アプリ自身が独立してAndroidXの機能をいち早く利用したいだとかの場合、
などが混在してしまう可能性がある。
これを解決するため、GoogleがJetifierというツールを提供している。これを用いると、Support Library v28を利用していることを前提にそれらのクラス参照たちをAndroidXのものへ繋ぎ変えてくれる。スタンドアロン版を直接利用することも可能だが、ビルドスクリプトでフラグを立てるだけで自動で実行させることができる。
本題。これらの前提のもと、じゃあいつ自分たちの作っているアプリでAndroidXに対応するのか、という話がいつかは出てくる。
実際自分の関わっているいくつかの事業者を見ていると、AndroidXへの本格対応は未だ行っていないケースが散見される。
いくらでも例外はあるものの、筆者としては「早めにやるに越したことはないが、最悪AndroidXの機能が必要になるまではJetifier以上の対応はしなくてよい」という意見を推していきたい。
この「AndroidXの機能が必要になるまで」に外的要因も含まれうるという点で、いくらかの危険性をはらんでいることも無視できないのが難しい部分だ。
下記のようなアプリがあるとする。このアプリはSupport Library v28の機能に依存していて、具体的には古いAndroid OSにおけるbackgroundTint
の実現にAppCompatを利用している。
この機能の実現にはAndroidXでの更新以降の機能は要求しておらず、Support Libraryとして提供されていた期間までの機能で必要十分である。
この時点での依存関係ツリー
./gradlew :app:dependencies --configuration=debugRuntimeClasspath --console=plain # > Task :app:dependencies # # ------------------------------------------------------------ # Project :app # ------------------------------------------------------------ # # debugRuntimeClasspath - Runtime classpath of compilation 'debug' (target (androidJvm)). # +--- org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.50 # | \--- org.jetbrains.kotlin:kotlin-stdlib:1.3.50 # | +--- org.jetbrains.kotlin:kotlin-stdlib-common:1.3.50 # | \--- org.jetbrains:annotations:13.0 # \--- com.android.support:appcompat-v7:28.0.0 # +--- com.android.support:support-annotations:28.0.0 # +--- com.android.support:support-compat:28.0.0 # | +--- com.android.support:support-annotations:28.0.0 # | +--- com.android.support:collections:28.0.0 # | | \--- com.android.support:support-annotations:28.0.0 # | +--- android.arch.lifecycle:runtime:1.1.1 # | | +--- android.arch.lifecycle:common:1.1.1 # | | | \--- com.android.support:support-annotations:26.1.0 -> 28.0.0 # | | +--- android.arch.core:common:1.1.1 # | | | \--- com.android.support:support-annotations:26.1.0 -> 28.0.0 # | | \--- com.android.support:support-annotations:26.1.0 -> 28.0.0 # | \--- com.android.support:versionedparcelable:28.0.0 # | +--- com.android.support:support-annotations:28.0.0 # | \--- com.android.support:collections:28.0.0 (*) # +--- com.android.support:collections:28.0.0 (*) # +--- com.android.support:cursoradapter:28.0.0 # | \--- com.android.support:support-annotations:28.0.0 # +--- com.android.support:support-core-utils:28.0.0 # | +--- com.android.support:support-annotations:28.0.0 # | +--- com.android.support:support-compat:28.0.0 (*) # | +--- com.android.support:documentfile:28.0.0 # | | \--- com.android.support:support-annotations:28.0.0 # | +--- com.android.support:loader:28.0.0 # | | +--- com.android.support:support-annotations:28.0.0 # | | +--- com.android.support:support-compat:28.0.0 (*) # | | +--- android.arch.lifecycle:livedata:1.1.1 # | | | +--- android.arch.core:runtime:1.1.1 # | | | | +--- com.android.support:support-annotations:26.1.0 -> 28.0.0 # | | | | \--- android.arch.core:common:1.1.1 (*) # | | | +--- android.arch.lifecycle:livedata-core:1.1.1 # | | | | +--- android.arch.lifecycle:common:1.1.1 (*) # | | | | +--- android.arch.core:common:1.1.1 (*) # | | | | \--- android.arch.core:runtime:1.1.1 (*) # | | | \--- android.arch.core:common:1.1.1 (*) # | | \--- android.arch.lifecycle:viewmodel:1.1.1 # | | \--- com.android.support:support-annotations:26.1.0 -> 28.0.0 # | +--- com.android.support:localbroadcastmanager:28.0.0 # | | \--- com.android.support:support-annotations:28.0.0 # | \--- com.android.support:print:28.0.0 # | \--- com.android.support:support-annotations:28.0.0 # +--- com.android.support:support-fragment:28.0.0 # | +--- com.android.support:support-compat:28.0.0 (*) # | +--- com.android.support:support-core-ui:28.0.0 # | | +--- com.android.support:support-annotations:28.0.0 # | | +--- com.android.support:support-compat:28.0.0 (*) # | | +--- com.android.support:support-core-utils:28.0.0 (*) # | | +--- com.android.support:customview:28.0.0 # | | | +--- com.android.support:support-annotations:28.0.0 # | | | \--- com.android.support:support-compat:28.0.0 (*) # | | +--- com.android.support:viewpager:28.0.0 # | | | +--- com.android.support:support-annotations:28.0.0 # | | | +--- com.android.support:support-compat:28.0.0 (*) # | | | \--- com.android.support:customview:28.0.0 (*) # | | +--- com.android.support:coordinatorlayout:28.0.0 # | | | +--- com.android.support:support-annotations:28.0.0 # | | | +--- com.android.support:support-compat:28.0.0 (*) # | | | \--- com.android.support:customview:28.0.0 (*) # | | +--- com.android.support:drawerlayout:28.0.0 # | | | +--- com.android.support:support-annotations:28.0.0 # | | | +--- com.android.support:support-compat:28.0.0 (*) # | | | \--- com.android.support:customview:28.0.0 (*) # | | +--- com.android.support:slidingpanelayout:28.0.0 # | | | +--- com.android.support:support-annotations:28.0.0 # | | | +--- com.android.support:support-compat:28.0.0 (*) # | | | \--- com.android.support:customview:28.0.0 (*) # | | +--- com.android.support:interpolator:28.0.0 # | | | \--- com.android.support:support-annotations:28.0.0 # | | +--- com.android.support:swiperefreshlayout:28.0.0 # | | | +--- com.android.support:support-annotations:28.0.0 # | | | +--- com.android.support:support-compat:28.0.0 (*) # | | | \--- com.android.support:interpolator:28.0.0 (*) # | | +--- com.android.support:asynclayoutinflater:28.0.0 # | | | +--- com.android.support:support-annotations:28.0.0 # | | | \--- com.android.support:support-compat:28.0.0 (*) # | | \--- com.android.support:cursoradapter:28.0.0 (*) # | +--- com.android.support:support-core-utils:28.0.0 (*) # | +--- com.android.support:support-annotations:28.0.0 # | +--- com.android.support:loader:28.0.0 (*) # | \--- android.arch.lifecycle:viewmodel:1.1.1 (*) # +--- com.android.support:support-vector-drawable:28.0.0 # | +--- com.android.support:support-annotations:28.0.0 # | \--- com.android.support:support-compat:28.0.0 (*) # \--- com.android.support:animated-vector-drawable:28.0.0 # +--- com.android.support:support-vector-drawable:28.0.0 (*) # \--- com.android.support:support-core-ui:28.0.0 (*) # # (*) - dependencies omitted (listed previously) # # A web-based, searchable dependency report is available by adding the --scan option. # # BUILD SUCCESSFUL in 821ms # 1 actionable task: 1 executed
このアプリでandroid.useAndroidX
をenableにしてみる。
diff --git a/gradle.properties b/gradle.properties index 8964a61..f96c140 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.jvmargs=-Xmx1536m kotlin.code.style=official -android.useAndroidX=false +android.useAndroidX=true android.enableJetifier=false
この時点ではアプリ側のコードを書き換えずビルドが可能である。それもそのはず、依存関係の書き換えは行われないのだ。
このdiffにおける依存関係
./gradlew :app:dependencies --configuration=debugRuntimeClasspath --console=plain # # > Task :app:dependencies # # ------------------------------------------------------------ # Project :app # ------------------------------------------------------------ # # debugRuntimeClasspath - Runtime classpath of compilation 'debug' (target (androidJvm)). # +--- org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.50 # | \--- org.jetbrains.kotlin:kotlin-stdlib:1.3.50 # | +--- org.jetbrains.kotlin:kotlin-stdlib-common:1.3.50 # | \--- org.jetbrains:annotations:13.0 # \--- com.android.support:appcompat-v7:28.0.0 # +--- com.android.support:support-annotations:28.0.0 # +--- com.android.support:support-compat:28.0.0 # | +--- com.android.support:support-annotations:28.0.0 # | +--- com.android.support:collections:28.0.0 # | | \--- com.android.support:support-annotations:28.0.0 # | +--- android.arch.lifecycle:runtime:1.1.1 # | | +--- android.arch.lifecycle:common:1.1.1 # | | | \--- com.android.support:support-annotations:26.1.0 -> 28.0.0 # | | +--- android.arch.core:common:1.1.1 # | | | \--- com.android.support:support-annotations:26.1.0 -> 28.0.0 # | | \--- com.android.support:support-annotations:26.1.0 -> 28.0.0 # | \--- com.android.support:versionedparcelable:28.0.0 # | +--- com.android.support:support-annotations:28.0.0 # | \--- com.android.support:collections:28.0.0 (*) # +--- com.android.support:collections:28.0.0 (*) # +--- com.android.support:cursoradapter:28.0.0 # | \--- com.android.support:support-annotations:28.0.0 # +--- com.android.support:support-core-utils:28.0.0 # | +--- com.android.support:support-annotations:28.0.0 # | +--- com.android.support:support-compat:28.0.0 (*) # | +--- com.android.support:documentfile:28.0.0 # | | \--- com.android.support:support-annotations:28.0.0 # | +--- com.android.support:loader:28.0.0 # | | +--- com.android.support:support-annotations:28.0.0 # | | +--- com.android.support:support-compat:28.0.0 (*) # | | +--- android.arch.lifecycle:livedata:1.1.1 # | | | +--- android.arch.core:runtime:1.1.1 # | | | | +--- com.android.support:support-annotations:26.1.0 -> 28.0.0 # | | | | \--- android.arch.core:common:1.1.1 (*) # | | | +--- android.arch.lifecycle:livedata-core:1.1.1 # | | | | +--- android.arch.lifecycle:common:1.1.1 (*) # | | | | +--- android.arch.core:common:1.1.1 (*) # | | | | \--- android.arch.core:runtime:1.1.1 (*) # | | | \--- android.arch.core:common:1.1.1 (*) # | | \--- android.arch.lifecycle:viewmodel:1.1.1 # | | \--- com.android.support:support-annotations:26.1.0 -> 28.0.0 # | +--- com.android.support:localbroadcastmanager:28.0.0 # | | \--- com.android.support:support-annotations:28.0.0 # | \--- com.android.support:print:28.0.0 # | \--- com.android.support:support-annotations:28.0.0 # +--- com.android.support:support-fragment:28.0.0 # | +--- com.android.support:support-compat:28.0.0 (*) # | +--- com.android.support:support-core-ui:28.0.0 # | | +--- com.android.support:support-annotations:28.0.0 # | | +--- com.android.support:support-compat:28.0.0 (*) # | | +--- com.android.support:support-core-utils:28.0.0 (*) # | | +--- com.android.support:customview:28.0.0 # | | | +--- com.android.support:support-annotations:28.0.0 # | | | \--- com.android.support:support-compat:28.0.0 (*) # | | +--- com.android.support:viewpager:28.0.0 # | | | +--- com.android.support:support-annotations:28.0.0 # | | | +--- com.android.support:support-compat:28.0.0 (*) # | | | \--- com.android.support:customview:28.0.0 (*) # | | +--- com.android.support:coordinatorlayout:28.0.0 # | | | +--- com.android.support:support-annotations:28.0.0 # | | | +--- com.android.support:support-compat:28.0.0 (*) # | | | \--- com.android.support:customview:28.0.0 (*) # | | +--- com.android.support:drawerlayout:28.0.0 # | | | +--- com.android.support:support-annotations:28.0.0 # | | | +--- com.android.support:support-compat:28.0.0 (*) # | | | \--- com.android.support:customview:28.0.0 (*) # | | +--- com.android.support:slidingpanelayout:28.0.0 # | | | +--- com.android.support:support-annotations:28.0.0 # | | | +--- com.android.support:support-compat:28.0.0 (*) # | | | \--- com.android.support:customview:28.0.0 (*) # | | +--- com.android.support:interpolator:28.0.0 # | | | \--- com.android.support:support-annotations:28.0.0 # | | +--- com.android.support:swiperefreshlayout:28.0.0 # | | | +--- com.android.support:support-annotations:28.0.0 # | | | +--- com.android.support:support-compat:28.0.0 (*) # | | | \--- com.android.support:interpolator:28.0.0 (*) # | | +--- com.android.support:asynclayoutinflater:28.0.0 # | | | +--- com.android.support:support-annotations:28.0.0 # | | | \--- com.android.support:support-compat:28.0.0 (*) # | | \--- com.android.support:cursoradapter:28.0.0 (*) # | +--- com.android.support:support-core-utils:28.0.0 (*) # | +--- com.android.support:support-annotations:28.0.0 # | +--- com.android.support:loader:28.0.0 (*) # | \--- android.arch.lifecycle:viewmodel:1.1.1 (*) # +--- com.android.support:support-vector-drawable:28.0.0 # | +--- com.android.support:support-annotations:28.0.0 # | \--- com.android.support:support-compat:28.0.0 (*) # \--- com.android.support:animated-vector-drawable:28.0.0 # +--- com.android.support:support-vector-drawable:28.0.0 (*) # \--- com.android.support:support-core-ui:28.0.0 (*) # # (*) - dependencies omitted (listed previously) # # A web-based, searchable dependency report is available by adding the --scan option. # # BUILD SUCCESSFUL in 1s # 1 actionable task: 1 executed
ではこのフラグはどのような影響を与えるのか?答えはAndroid Developersの記述が全てだ。
android.useAndroidX: true に設定すると、Android プラグインは Support Library ではなく、該当する AndroidX ライブラリを使用します。設定しない場合、このフラグはデフォルトで false です。
Android Pluginが当該ライブラリを利用する箇所としてわかりやすいものには、DataBindingが存在する。たとえば下記のようなDataBindingを用いたアプリの場合。
この時点でのdependencies
./gradlew :app:dependencies --configuration=debugRuntimeClasspath --console=plain # # > Task :app:dependencies # # ------------------------------------------------------------ # Project :app # ------------------------------------------------------------ # # debugRuntimeClasspath - Runtime classpath of compilation 'debug' (target (androidJvm)). # +--- com.android.databinding:baseLibrary:3.5.0 # +--- com.android.databinding:library:3.5.0 # | +--- android.arch.lifecycle:runtime:1.0.3 -> 1.1.1 # | | +--- android.arch.lifecycle:common:1.1.1 # | | | \--- com.android.support:support-annotations:26.1.0 -> 28.0.0 # | | +--- android.arch.core:common:1.1.1 # | | | \--- com.android.support:support-annotations:26.1.0 -> 28.0.0 # | | \--- com.android.support:support-annotations:26.1.0 -> 28.0.0 # | +--- com.android.support:support-core-utils:26.1.0 -> 28.0.0 # | | +--- com.android.support:support-annotations:28.0.0 # | | +--- com.android.support:support-compat:28.0.0 # | | | +--- com.android.support:support-annotations:28.0.0 # | | | +--- com.android.support:collections:28.0.0 # | | | | \--- com.android.support:support-annotations:28.0.0 # | | | +--- android.arch.lifecycle:runtime:1.1.1 (*) # | | | \--- com.android.support:versionedparcelable:28.0.0 # | | | +--- com.android.support:support-annotations:28.0.0 # | | | \--- com.android.support:collections:28.0.0 (*) # | | +--- com.android.support:documentfile:28.0.0 # | | | \--- com.android.support:support-annotations:28.0.0 # | | +--- com.android.support:loader:28.0.0 # | | | +--- com.android.support:support-annotations:28.0.0 # | | | +--- com.android.support:support-compat:28.0.0 (*) # | | | +--- android.arch.lifecycle:livedata:1.1.1 # | | | | +--- android.arch.core:runtime:1.1.1 # | | | | | +--- com.android.support:support-annotations:26.1.0 -> 28.0.0 # | | | | | \--- android.arch.core:common:1.1.1 (*) # | | | | +--- android.arch.lifecycle:livedata-core:1.1.1 # | | | | | +--- android.arch.lifecycle:common:1.1.1 (*) # | | | | | +--- android.arch.core:common:1.1.1 (*) # | | | | | \--- android.arch.core:runtime:1.1.1 (*) # | | | | \--- android.arch.core:common:1.1.1 (*) # | | | \--- android.arch.lifecycle:viewmodel:1.1.1 # | | | \--- com.android.support:support-annotations:26.1.0 -> 28.0.0 # | | +--- com.android.support:localbroadcastmanager:28.0.0 # | | | \--- com.android.support:support-annotations:28.0.0 # | | \--- com.android.support:print:28.0.0 # | | \--- com.android.support:support-annotations:28.0.0 # | \--- com.android.databinding:baseLibrary:3.5.0 # +--- com.android.databinding:adapters:3.5.0 # | +--- com.android.databinding:baseLibrary:3.5.0 # | \--- com.android.databinding:library:3.5.0 (*) # +--- org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.50 # | \--- org.jetbrains.kotlin:kotlin-stdlib:1.3.50 # | +--- org.jetbrains.kotlin:kotlin-stdlib-common:1.3.50 # | \--- org.jetbrains:annotations:13.0 # \--- com.android.support:appcompat-v7:28.0.0 # +--- com.android.support:support-annotations:28.0.0 # +--- com.android.support:support-compat:28.0.0 (*) # +--- com.android.support:collections:28.0.0 (*) # +--- com.android.support:cursoradapter:28.0.0 # | \--- com.android.support:support-annotations:28.0.0 # +--- com.android.support:support-core-utils:28.0.0 (*) # +--- com.android.support:support-fragment:28.0.0 # | +--- com.android.support:support-compat:28.0.0 (*) # | +--- com.android.support:support-core-ui:28.0.0 # | | +--- com.android.support:support-annotations:28.0.0 # | | +--- com.android.support:support-compat:28.0.0 (*) # | | +--- com.android.support:support-core-utils:28.0.0 (*) # | | +--- com.android.support:customview:28.0.0 # | | | +--- com.android.support:support-annotations:28.0.0 # | | | \--- com.android.support:support-compat:28.0.0 (*) # | | +--- com.android.support:viewpager:28.0.0 # | | | +--- com.android.support:support-annotations:28.0.0 # | | | +--- com.android.support:support-compat:28.0.0 (*) # | | | \--- com.android.support:customview:28.0.0 (*) # | | +--- com.android.support:coordinatorlayout:28.0.0 # | | | +--- com.android.support:support-annotations:28.0.0 # | | | +--- com.android.support:support-compat:28.0.0 (*) # | | | \--- com.android.support:customview:28.0.0 (*) # | | +--- com.android.support:drawerlayout:28.0.0 # | | | +--- com.android.support:support-annotations:28.0.0 # | | | +--- com.android.support:support-compat:28.0.0 (*) # | | | \--- com.android.support:customview:28.0.0 (*) # | | +--- com.android.support:slidingpanelayout:28.0.0 # | | | +--- com.android.support:support-annotations:28.0.0 # | | | +--- com.android.support:support-compat:28.0.0 (*) # | | | \--- com.android.support:customview:28.0.0 (*) # | | +--- com.android.support:interpolator:28.0.0 # | | | \--- com.android.support:support-annotations:28.0.0 # | | +--- com.android.support:swiperefreshlayout:28.0.0 # | | | +--- com.android.support:support-annotations:28.0.0 # | | | +--- com.android.support:support-compat:28.0.0 (*) # | | | \--- com.android.support:interpolator:28.0.0 (*) # | | +--- com.android.support:asynclayoutinflater:28.0.0 # | | | +--- com.android.support:support-annotations:28.0.0 # | | | \--- com.android.support:support-compat:28.0.0 (*) # | | \--- com.android.support:cursoradapter:28.0.0 (*) # | +--- com.android.support:support-core-utils:28.0.0 (*) # | +--- com.android.support:support-annotations:28.0.0 # | +--- com.android.support:loader:28.0.0 (*) # | \--- android.arch.lifecycle:viewmodel:1.1.1 (*) # +--- com.android.support:support-vector-drawable:28.0.0 # | +--- com.android.support:support-annotations:28.0.0 # | \--- com.android.support:support-compat:28.0.0 (*) # \--- com.android.support:animated-vector-drawable:28.0.0 # +--- com.android.support:support-vector-drawable:28.0.0 (*) # \--- com.android.support:support-core-ui:28.0.0 (*) # # (*) - dependencies omitted (listed previously) # # A web-based, searchable dependency report is available by adding the --scan option. # # BUILD SUCCESSFUL in 0s # 1 actionable task: 1 executed
useAndroidX
をenabledにしてみる。
diff --git a/gradle.properties b/gradle.properties index 8964a61..f96c140 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.jvmargs=-Xmx1536m kotlin.code.style=official -android.useAndroidX=false +android.useAndroidX=true android.enableJetifier=false
この状態でビルドを試みると失敗することが確認できるだろう。
./gradlew :app:buildDebug --console=plain # > Task :app:preBuild UP-TO-DATE # > Task :app:preDebugBuild UP-TO-DATE # > Task :app:compileDebugRenderscript NO-SOURCE # > Task :app:generateDebugResValues UP-TO-DATE # > Task :app:generateDebugResources UP-TO-DATE # > Task :app:mergeDebugResources UP-TO-DATE # > Task :app:checkDebugManifest UP-TO-DATE # > Task :app:createDebugCompatibleScreenManifests UP-TO-DATE # > Task :app:mainApkListPersistenceDebug UP-TO-DATE # > Task :app:processDebugManifest UP-TO-DATE # > Task :app:bundleDebugResources UP-TO-DATE # > Task :app:mergeDebugShaders UP-TO-DATE # > Task :app:compileDebugShaders UP-TO-DATE # > Task :app:generateDebugAssets UP-TO-DATE # > Task :app:mergeDebugAssets UP-TO-DATE # > Task :app:compileDebugAidl NO-SOURCE # > Task :app:generateDebugBuildConfig UP-TO-DATE # > Task :app:prepareLintJar UP-TO-DATE # > Task :app:prepareLintJarForPublish UP-TO-DATE # > Task :app:generateDebugSources UP-TO-DATE # > Task :app:dataBindingExportBuildInfoDebug UP-TO-DATE # > Task :app:dataBindingMergeDependencyArtifactsDebug UP-TO-DATE # > Task :app:dataBindingMergeGenClassesDebug UP-TO-DATE # > Task :app:dataBindingGenBaseClassesDebug UP-TO-DATE # > Task :app:processDebugResources UP-TO-DATE # # > Task :app:compileDebugKotlin FAILED # e: /Users/s-yoshioka/Documents/android-databinding-support-library-app-example/app/src/main/java/jp/s64/example/android/databindingsupportlibraryapp/MyActivity.kt: (3, 16): Unresolved reference: databinding # e: /Users/s-yoshioka/Documents/android-databinding-support-library-app-example/app/src/main/java/jp/s64/example/android/databindingsupportlibraryapp/MyActivity.kt: (14, 19): Unresolved reference: DataBindingUtil # # FAILURE: Build failed with an exception. # # * What went wrong: # Execution failed for task ':app:compileDebugKotlin'. # > Compilation error. See log for more details # # * Try: # Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights. # # * Get more help at https://help.gradle.org # # BUILD FAILED in 2s # 19 actionable tasks: 1 executed, 18 up-to-date
この時点のdependencies
./gradlew :app:dependencies --configuration=debugRuntimeClasspath --console=plain # # > Task :app:dependencies # # ------------------------------------------------------------ # Project :app # ------------------------------------------------------------ # # debugRuntimeClasspath - Runtime classpath of compilation 'debug' (target (androidJvm)). # +--- androidx.databinding:databinding-common:3.5.0 # +--- androidx.databinding:databinding-runtime:3.5.0 # | +--- androidx.lifecycle:lifecycle-runtime:2.0.0 # | | +--- androidx.lifecycle:lifecycle-common:2.0.0 # | | | \--- androidx.annotation:annotation:1.0.0 # | | +--- androidx.arch.core:core-common:2.0.0 # | | | \--- androidx.annotation:annotation:1.0.0 # | | \--- androidx.annotation:annotation:1.0.0 # | +--- androidx.collection:collection:1.0.0 # | | \--- androidx.annotation:annotation:1.0.0 # | \--- androidx.databinding:databinding-common:3.5.0 # +--- androidx.databinding:databinding-adapters:3.5.0 # | +--- androidx.databinding:databinding-common:3.5.0 # | \--- androidx.databinding:databinding-runtime:3.5.0 (*) # +--- org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.50 # | \--- org.jetbrains.kotlin:kotlin-stdlib:1.3.50 # | +--- org.jetbrains.kotlin:kotlin-stdlib-common:1.3.50 # | \--- org.jetbrains:annotations:13.0 # \--- com.android.support:appcompat-v7:28.0.0 # +--- com.android.support:support-annotations:28.0.0 # +--- com.android.support:support-compat:28.0.0 # | +--- com.android.support:support-annotations:28.0.0 # | +--- com.android.support:collections:28.0.0 # | | \--- com.android.support:support-annotations:28.0.0 # | +--- android.arch.lifecycle:runtime:1.1.1 # | | +--- android.arch.lifecycle:common:1.1.1 # | | | \--- com.android.support:support-annotations:26.1.0 -> 28.0.0 # | | +--- android.arch.core:common:1.1.1 # | | | \--- com.android.support:support-annotations:26.1.0 -> 28.0.0 # | | \--- com.android.support:support-annotations:26.1.0 -> 28.0.0 # | \--- com.android.support:versionedparcelable:28.0.0 # | +--- com.android.support:support-annotations:28.0.0 # | \--- com.android.support:collections:28.0.0 (*) # +--- com.android.support:collections:28.0.0 (*) # +--- com.android.support:cursoradapter:28.0.0 # | \--- com.android.support:support-annotations:28.0.0 # +--- com.android.support:support-core-utils:28.0.0 # | +--- com.android.support:support-annotations:28.0.0 # | +--- com.android.support:support-compat:28.0.0 (*) # | +--- com.android.support:documentfile:28.0.0 # | | \--- com.android.support:support-annotations:28.0.0 # | +--- com.android.support:loader:28.0.0 # | | +--- com.android.support:support-annotations:28.0.0 # | | +--- com.android.support:support-compat:28.0.0 (*) # | | +--- android.arch.lifecycle:livedata:1.1.1 # | | | +--- android.arch.core:runtime:1.1.1 # | | | | +--- com.android.support:support-annotations:26.1.0 -> 28.0.0 # | | | | \--- android.arch.core:common:1.1.1 (*) # | | | +--- android.arch.lifecycle:livedata-core:1.1.1 # | | | | +--- android.arch.lifecycle:common:1.1.1 (*) # | | | | +--- android.arch.core:common:1.1.1 (*) # | | | | \--- android.arch.core:runtime:1.1.1 (*) # | | | \--- android.arch.core:common:1.1.1 (*) # | | \--- android.arch.lifecycle:viewmodel:1.1.1 # | | \--- com.android.support:support-annotations:26.1.0 -> 28.0.0 # | +--- com.android.support:localbroadcastmanager:28.0.0 # | | \--- com.android.support:support-annotations:28.0.0 # | \--- com.android.support:print:28.0.0 # | \--- com.android.support:support-annotations:28.0.0 # +--- com.android.support:support-fragment:28.0.0 # | +--- com.android.support:support-compat:28.0.0 (*) # | +--- com.android.support:support-core-ui:28.0.0 # | | +--- com.android.support:support-annotations:28.0.0 # | | +--- com.android.support:support-compat:28.0.0 (*) # | | +--- com.android.support:support-core-utils:28.0.0 (*) # | | +--- com.android.support:customview:28.0.0 # | | | +--- com.android.support:support-annotations:28.0.0 # | | | \--- com.android.support:support-compat:28.0.0 (*) # | | +--- com.android.support:viewpager:28.0.0 # | | | +--- com.android.support:support-annotations:28.0.0 # | | | +--- com.android.support:support-compat:28.0.0 (*) # | | | \--- com.android.support:customview:28.0.0 (*) # | | +--- com.android.support:coordinatorlayout:28.0.0 # | | | +--- com.android.support:support-annotations:28.0.0 # | | | +--- com.android.support:support-compat:28.0.0 (*) # | | | \--- com.android.support:customview:28.0.0 (*) # | | +--- com.android.support:drawerlayout:28.0.0 # | | | +--- com.android.support:support-annotations:28.0.0 # | | | +--- com.android.support:support-compat:28.0.0 (*) # | | | \--- com.android.support:customview:28.0.0 (*) # | | +--- com.android.support:slidingpanelayout:28.0.0 # | | | +--- com.android.support:support-annotations:28.0.0 # | | | +--- com.android.support:support-compat:28.0.0 (*) # | | | \--- com.android.support:customview:28.0.0 (*) # | | +--- com.android.support:interpolator:28.0.0 # | | | \--- com.android.support:support-annotations:28.0.0 # | | +--- com.android.support:swiperefreshlayout:28.0.0 # | | | +--- com.android.support:support-annotations:28.0.0 # | | | +--- com.android.support:support-compat:28.0.0 (*) # | | | \--- com.android.support:interpolator:28.0.0 (*) # | | +--- com.android.support:asynclayoutinflater:28.0.0 # | | | +--- com.android.support:support-annotations:28.0.0 # | | | \--- com.android.support:support-compat:28.0.0 (*) # | | \--- com.android.support:cursoradapter:28.0.0 (*) # | +--- com.android.support:support-core-utils:28.0.0 (*) # | +--- com.android.support:support-annotations:28.0.0 # | +--- com.android.support:loader:28.0.0 (*) # | \--- android.arch.lifecycle:viewmodel:1.1.1 (*) # +--- com.android.support:support-vector-drawable:28.0.0 # | +--- com.android.support:support-annotations:28.0.0 # | \--- com.android.support:support-compat:28.0.0 (*) # \--- com.android.support:animated-vector-drawable:28.0.0 # +--- com.android.support:support-vector-drawable:28.0.0 (*) # \--- com.android.support:support-core-ui:28.0.0 (*) # # (*) - dependencies omitted (listed previously) # # A web-based, searchable dependency report is available by adding the --scan option. # # BUILD SUCCESSFUL in 1s # 1 actionable task: 1 executed
内部で利用されるライブラリがAndroidXの置き換わるとは、依存関係に下記のような差分が発生することを指しているのである。
10,51c10,23 < +--- com.android.databinding:baseLibrary:3.5.0 < +--- com.android.databinding:library:3.5.0 < | +--- android.arch.lifecycle:runtime:1.0.3 -> 1.1.1 < | | +--- android.arch.lifecycle:common:1.1.1 < | | | \--- com.android.support:support-annotations:26.1.0 -> 28.0.0 < | | +--- android.arch.core:common:1.1.1 < | | | \--- com.android.support:support-annotations:26.1.0 -> 28.0.0 < | | \--- com.android.support:support-annotations:26.1.0 -> 28.0.0 < | +--- com.android.support:support-core-utils:26.1.0 -> 28.0.0 < | | +--- com.android.support:support-annotations:28.0.0 < | | +--- com.android.support:support-compat:28.0.0 < | | | +--- com.android.support:support-annotations:28.0.0 < | | | +--- com.android.support:collections:28.0.0 < | | | | \--- com.android.support:support-annotations:28.0.0 < | | | +--- android.arch.lifecycle:runtime:1.1.1 (*) < | | | \--- com.android.support:versionedparcelable:28.0.0 < | | | +--- com.android.support:support-annotations:28.0.0 < | | | \--- com.android.support:collections:28.0.0 (*) < | | +--- com.android.support:documentfile:28.0.0 < | | | \--- com.android.support:support-annotations:28.0.0 < | | +--- com.android.support:loader:28.0.0 < | | | +--- com.android.support:support-annotations:28.0.0 < | | | +--- com.android.support:support-compat:28.0.0 (*) < | | | +--- android.arch.lifecycle:livedata:1.1.1 < | | | | +--- android.arch.core:runtime:1.1.1 < | | | | | +--- com.android.support:support-annotations:26.1.0 -> 28.0.0 < | | | | | \--- android.arch.core:common:1.1.1 (*) < | | | | +--- android.arch.lifecycle:livedata-core:1.1.1 < | | | | | +--- android.arch.lifecycle:common:1.1.1 (*) < | | | | | +--- android.arch.core:common:1.1.1 (*) < | | | | | \--- android.arch.core:runtime:1.1.1 (*) < | | | | \--- android.arch.core:common:1.1.1 (*) < | | | \--- android.arch.lifecycle:viewmodel:1.1.1 < | | | \--- com.android.support:support-annotations:26.1.0 -> 28.0.0 < | | +--- com.android.support:localbroadcastmanager:28.0.0 < | | | \--- com.android.support:support-annotations:28.0.0 < | | \--- com.android.support:print:28.0.0 < | | \--- com.android.support:support-annotations:28.0.0 < | \--- com.android.databinding:baseLibrary:3.5.0 < +--- com.android.databinding:adapters:3.5.0 < | +--- com.android.databinding:baseLibrary:3.5.0 < | \--- com.android.databinding:library:3.5.0 (*) --- > +--- androidx.databinding:databinding-common:3.5.0 > +--- androidx.databinding:databinding-runtime:3.5.0 > | +--- androidx.lifecycle:lifecycle-runtime:2.0.0 > | | +--- androidx.lifecycle:lifecycle-common:2.0.0 > | | | \--- androidx.annotation:annotation:1.0.0 > | | +--- androidx.arch.core:core-common:2.0.0 > | | | \--- androidx.annotation:annotation:1.0.0 > | | \--- androidx.annotation:annotation:1.0.0 > | +--- androidx.collection:collection:1.0.0 > | | \--- androidx.annotation:annotation:1.0.0 > | \--- androidx.databinding:databinding-common:3.5.0 > +--- androidx.databinding:databinding-adapters:3.5.0 > | +--- androidx.databinding:databinding-common:3.5.0 > | \--- androidx.databinding:databinding-runtime:3.5.0 (*) 58c30,42 < +--- com.android.support:support-compat:28.0.0 (*) --- > +--- com.android.support:support-compat:28.0.0 > | +--- com.android.support:support-annotations:28.0.0 > | +--- com.android.support:collections:28.0.0 > | | \--- com.android.support:support-annotations:28.0.0 > | +--- android.arch.lifecycle:runtime:1.1.1 > | | +--- android.arch.lifecycle:common:1.1.1 > | | | \--- com.android.support:support-annotations:26.1.0 -> 28.0.0 > | | +--- android.arch.core:common:1.1.1 > | | | \--- com.android.support:support-annotations:26.1.0 -> 28.0.0 > | | \--- com.android.support:support-annotations:26.1.0 -> 28.0.0 > | \--- com.android.support:versionedparcelable:28.0.0 > | +--- com.android.support:support-annotations:28.0.0 > | \--- com.android.support:collections:28.0.0 (*) 62c46,68 < +--- com.android.support:support-core-utils:28.0.0 (*) --- > +--- com.android.support:support-core-utils:28.0.0 > | +--- com.android.support:support-annotations:28.0.0 > | +--- com.android.support:support-compat:28.0.0 (*) > | +--- com.android.support:documentfile:28.0.0 > | | \--- com.android.support:support-annotations:28.0.0 > | +--- com.android.support:loader:28.0.0 > | | +--- com.android.support:support-annotations:28.0.0 > | | +--- com.android.support:support-compat:28.0.0 (*) > | | +--- android.arch.lifecycle:livedata:1.1.1 > | | | +--- android.arch.core:runtime:1.1.1 > | | | | +--- com.android.support:support-annotations:26.1.0 -> 28.0.0 > | | | | \--- android.arch.core:common:1.1.1 (*) > | | | +--- android.arch.lifecycle:livedata-core:1.1.1 > | | | | +--- android.arch.lifecycle:common:1.1.1 (*) > | | | | +--- android.arch.core:common:1.1.1 (*) > | | | | \--- android.arch.core:runtime:1.1.1 (*) > | | | \--- android.arch.core:common:1.1.1 (*) > | | \--- android.arch.lifecycle:viewmodel:1.1.1 > | | \--- com.android.support:support-annotations:26.1.0 -> 28.0.0 > | +--- com.android.support:localbroadcastmanager:28.0.0 > | | \--- com.android.support:support-annotations:28.0.0 > | \--- com.android.support:print:28.0.0 > | \--- com.android.support:support-annotations:28.0.0 113c119 < BUILD SUCCESSFUL in 0s --- > BUILD SUCCESSFUL in 1s
android.enableJetifier
による影響はもう少しわかりやすい。たとえば最初に挙げたSupport Libraryによるアプリで有効にしてみる。
diff --git a/gradle.properties b/gradle.properties index 8964a61..b5dd627 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.jvmargs=-Xmx1536m kotlin.code.style=official -android.useAndroidX=false -android.enableJetifier=false +android.useAndroidX=true +android.enableJetifier=true
これにより、依存関係ツリーが書き換わる。
この時点でのdependencies
./gradlew :app:dependencies --configuration=debugRuntimeClasspath --console=plain # # > Task :app:dependencies # # ------------------------------------------------------------ # Project :app # ------------------------------------------------------------ # # debugRuntimeClasspath - Runtime classpath of compilation 'debug' (target (androidJvm)). # +--- org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.50 # | \--- org.jetbrains.kotlin:kotlin-stdlib:1.3.50 # | +--- org.jetbrains.kotlin:kotlin-stdlib-common:1.3.50 # | \--- org.jetbrains:annotations:13.0 # \--- com.android.support:appcompat-v7:28.0.0 -> androidx.appcompat:appcompat:1.0.0 # +--- androidx.annotation:annotation:1.0.0 # +--- androidx.core:core:1.0.0 # | +--- androidx.annotation:annotation:1.0.0 # | +--- androidx.collection:collection:1.0.0 # | | \--- androidx.annotation:annotation:1.0.0 # | +--- androidx.lifecycle:lifecycle-runtime:2.0.0 # | | +--- androidx.lifecycle:lifecycle-common:2.0.0 # | | | \--- androidx.annotation:annotation:1.0.0 # | | +--- androidx.arch.core:core-common:2.0.0 # | | | \--- androidx.annotation:annotation:1.0.0 # | | \--- androidx.annotation:annotation:1.0.0 # | \--- androidx.versionedparcelable:versionedparcelable:1.0.0 # | +--- androidx.annotation:annotation:1.0.0 # | \--- androidx.collection:collection:1.0.0 (*) # +--- androidx.collection:collection:1.0.0 (*) # +--- androidx.cursoradapter:cursoradapter:1.0.0 # | \--- androidx.annotation:annotation:1.0.0 # +--- androidx.legacy:legacy-support-core-utils:1.0.0 # | +--- androidx.annotation:annotation:1.0.0 # | +--- androidx.core:core:1.0.0 (*) # | +--- androidx.documentfile:documentfile:1.0.0 # | | \--- androidx.annotation:annotation:1.0.0 # | +--- androidx.loader:loader:1.0.0 # | | +--- androidx.annotation:annotation:1.0.0 # | | +--- androidx.core:core:1.0.0 (*) # | | +--- androidx.lifecycle:lifecycle-livedata:2.0.0 # | | | +--- androidx.arch.core:core-runtime:2.0.0 # | | | | +--- androidx.annotation:annotation:1.0.0 # | | | | \--- androidx.arch.core:core-common:2.0.0 (*) # | | | +--- androidx.lifecycle:lifecycle-livedata-core:2.0.0 # | | | | +--- androidx.lifecycle:lifecycle-common:2.0.0 (*) # | | | | +--- androidx.arch.core:core-common:2.0.0 (*) # | | | | \--- androidx.arch.core:core-runtime:2.0.0 (*) # | | | \--- androidx.arch.core:core-common:2.0.0 (*) # | | \--- androidx.lifecycle:lifecycle-viewmodel:2.0.0 # | | \--- androidx.annotation:annotation:1.0.0 # | +--- androidx.localbroadcastmanager:localbroadcastmanager:1.0.0 # | | \--- androidx.annotation:annotation:1.0.0 # | \--- androidx.print:print:1.0.0 # | \--- androidx.annotation:annotation:1.0.0 # +--- androidx.fragment:fragment:1.0.0 # | +--- androidx.core:core:1.0.0 (*) # | +--- androidx.legacy:legacy-support-core-ui:1.0.0 # | | +--- androidx.annotation:annotation:1.0.0 # | | +--- androidx.core:core:1.0.0 (*) # | | +--- androidx.legacy:legacy-support-core-utils:1.0.0 (*) # | | +--- androidx.customview:customview:1.0.0 # | | | +--- androidx.annotation:annotation:1.0.0 # | | | \--- androidx.core:core:1.0.0 (*) # | | +--- androidx.viewpager:viewpager:1.0.0 # | | | +--- androidx.annotation:annotation:1.0.0 # | | | +--- androidx.core:core:1.0.0 (*) # | | | \--- androidx.customview:customview:1.0.0 (*) # | | +--- androidx.coordinatorlayout:coordinatorlayout:1.0.0 # | | | +--- androidx.annotation:annotation:1.0.0 # | | | +--- androidx.core:core:1.0.0 (*) # | | | \--- androidx.customview:customview:1.0.0 (*) # | | +--- androidx.drawerlayout:drawerlayout:1.0.0 # | | | +--- androidx.annotation:annotation:1.0.0 # | | | +--- androidx.core:core:1.0.0 (*) # | | | \--- androidx.customview:customview:1.0.0 (*) # | | +--- androidx.slidingpanelayout:slidingpanelayout:1.0.0 # | | | +--- androidx.annotation:annotation:1.0.0 # | | | +--- androidx.core:core:1.0.0 (*) # | | | \--- androidx.customview:customview:1.0.0 (*) # | | +--- androidx.interpolator:interpolator:1.0.0 # | | | \--- androidx.annotation:annotation:1.0.0 # | | +--- androidx.swiperefreshlayout:swiperefreshlayout:1.0.0 # | | | +--- androidx.annotation:annotation:1.0.0 # | | | +--- androidx.core:core:1.0.0 (*) # | | | \--- androidx.interpolator:interpolator:1.0.0 (*) # | | +--- androidx.asynclayoutinflater:asynclayoutinflater:1.0.0 # | | | +--- androidx.annotation:annotation:1.0.0 # | | | \--- androidx.core:core:1.0.0 (*) # | | \--- androidx.cursoradapter:cursoradapter:1.0.0 (*) # | +--- androidx.legacy:legacy-support-core-utils:1.0.0 (*) # | +--- androidx.annotation:annotation:1.0.0 # | +--- androidx.loader:loader:1.0.0 (*) # | \--- androidx.lifecycle:lifecycle-viewmodel:2.0.0 (*) # +--- androidx.vectordrawable:vectordrawable:1.0.0 # | +--- androidx.annotation:annotation:1.0.0 # | \--- androidx.core:core:1.0.0 (*) # \--- androidx.vectordrawable:vectordrawable-animated:1.0.0 # +--- androidx.vectordrawable:vectordrawable:1.0.0 (*) # \--- androidx.legacy:legacy-support-core-ui:1.0.0 (*) # # (*) - dependencies omitted (listed previously) # # A web-based, searchable dependency report is available by adding the --scan option. # # BUILD SUCCESSFUL in 1s # 1 actionable task: 1 executed
\--- com.android.support:appcompat-v7:28.0.0 -> androidx.appcompat:appcompat:1.0.0
ツリー内のこの箇所にあるとおり、アプリ自身で参照していたSupport LibraryがAndroidXのものに置換されるのである。
しかしプロジェクト内のソースコードや出力されるバイトコードそのものには影響が出ないことには注意が必要だ。すなわち、コードの書換えは必要である。
./gradlew :app:buildDebug --console=plain # > Task :app:preBuild UP-TO-DATE # > Task :app:preDebugBuild UP-TO-DATE # > Task :app:generateDebugResValues UP-TO-DATE # > Task :app:checkDebugManifest UP-TO-DATE # > Task :app:createDebugCompatibleScreenManifests UP-TO-DATE # > Task :app:mainApkListPersistenceDebug UP-TO-DATE # > Task :app:compileDebugRenderscript NO-SOURCE # > Task :app:generateDebugResources UP-TO-DATE # > Task :app:mergeDebugResources UP-TO-DATE # > Task :app:processDebugManifest UP-TO-DATE # > Task :app:bundleDebugResources UP-TO-DATE # > Task :app:mergeDebugShaders UP-TO-DATE # > Task :app:compileDebugShaders UP-TO-DATE # > Task :app:generateDebugAssets UP-TO-DATE # > Task :app:mergeDebugAssets UP-TO-DATE # > Task :app:generateDebugBuildConfig UP-TO-DATE # > Task :app:compileDebugAidl NO-SOURCE # > Task :app:processDebugJavaRes NO-SOURCE # > Task :app:processDebugResources UP-TO-DATE # > Task :app:compileDebugKotlin FAILED # e: /Users/s-yoshioka/Documents/android-minimum-support-library-app-example/app/src/main/java/jp/s64/example/android/minimumsupportlibraryapp/MyActivity.kt: (4, 24): Unresolved reference: v7 # e: /Users/s-yoshioka/Documents/android-minimum-support-library-app-example/app/src/main/java/jp/s64/example/android/minimumsupportlibraryapp/MyActivity.kt: (6, 20): Unresolved reference: AppCompatActivity # e: /Users/s-yoshioka/Documents/android-minimum-support-library-app-example/app/src/main/java/jp/s64/example/android/minimumsupportlibraryapp/MyActivity.kt: (8, 5): 'onCreate' overrides nothing # e: /Users/s-yoshioka/Documents/android-minimum-support-library-app-example/app/src/main/java/jp/s64/example/android/minimumsupportlibraryapp/MyActivity.kt: (9, 15): Unresolved reference: onCreate # e: /Users/s-yoshioka/Documents/android-minimum-support-library-app-example/app/src/main/java/jp/s64/example/android/minimumsupportlibraryapp/MyActivity.kt: (10, 9): Unresolved reference: setContentView # FAILURE: Build failed with an exception. # * What went wrong: # Execution failed for task ':app:compileDebugKotlin'. # > Compilation error. See log for more details # * Try: # Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights. # * Get more help at https://help.gradle.org # BUILD FAILED in 1s # 13 actionable tasks: 1 executed, 12 up-to-date
さて、では依存するライブラリではどうだろうか。たとえばSupport Libraryを依存関係に持つライブラリを追加する。Jetifierを有効にしていない場合は下記のような依存関係が出力される。
\--- jp.s64.android.toolbox:supportnotificatonkt:1.3.0 +--- org.jetbrains.kotlin:kotlin-stdlib:1.3.31 -> 1.3.50 (*) \--- com.android.support:support-compat:28.0.0 (*)
この時、この依存するライブラリをデコンパイルすると下記のようなものが確認できるだろう。
// IntelliJ API Decompiler stub source generated from a class file // Implementation of methods is not available package jp.s64.android.toolbox.support.notification @android.support.annotation.RequiresApi public fun android.support.v4.app.NotificationManagerCompat.createNotificationChannel(context: android.content.Context, channel: android.app.NotificationChannel): kotlin.Unit { /* compiled code */ } public fun android.support.v4.app.NotificationManagerCompat.createNotificationChannelOrNothing(context: android.content.Context, channel: android.app.NotificationChannel): kotlin.Boolean { /* compiled code */ } public fun android.support.v4.app.NotificationManagerCompat.getNotificationManager(context: android.content.Context): android.app.NotificationManager { /* compiled code */ } public fun android.support.v4.app.NotificationManagerCompat.isChannelSupported(): kotlin.Boolean { /* compiled code */ }
ではJetifierを有効にしてみる。当然ネストした依存関係も適切に処理され、下記のようになる。
\--- jp.s64.android.toolbox:supportnotificatonkt:1.3.0 +--- org.jetbrains.kotlin:kotlin-stdlib:1.3.31 -> 1.3.50 (*) \--- androidx.core:core:1.0.0 (*)
さきほど検証したとおり、自身のプロジェクトにおけるソースコードは書き換わらない。しかしこの依存ライブラリが持つコードをデコンパイルすると、下記のようなものが確認できる。
// IntelliJ API Decompiler stub source generated from a class file // Implementation of methods is not available package jp.s64.android.toolbox.support.notification @androidx.annotation.RequiresApi public fun androidx.core.app.NotificationManagerCompat.createNotificationChannel(context: android.content.Context, channel: android.app.NotificationChannel): kotlin.Unit { /* compiled code */ } public fun androidx.core.app.NotificationManagerCompat.createNotificationChannelOrNothing(context: android.content.Context, channel: android.app.NotificationChannel): kotlin.Boolean { /* compiled code */ } public fun androidx.core.app.NotificationManagerCompat.getNotificationManager(context: android.content.Context): android.app.NotificationManager { /* compiled code */ } public fun androidx.core.app.NotificationManagerCompat.isChannelSupported(): kotlin.Boolean { /* compiled code */ }
ライブラリ内での参照は自動で書き換わることが確認できた。
これらを踏まえ対応におけるポイントをまとめると、
useAndroidX
, enableJetifier
を有効にするの4点を押さえれば十分ということになる。実に簡単だ。
対応は簡単だが、問題はこの判断を行うタイミングや要因である。
1は完全にプロジェクトのコントローラブルな範囲であるため割愛する。
2に関しては一般的なライブラリにおける破壊的変更が実施された以降とほぼ同じと捉えてよい。
3はほぼ2と同じ事由になることが想像されるが、少し問題があるため後述する。
これらを総合して言えることは、やはり「やれる内に更新をしていないと工数の確保が難しくなる」という点は他のライブラリと変わらないということだ。
もしアプリのロジックやビジネスが特定ライブラリに密に依存していて、それらのアップデートが必要となった際に雪だるま式にやることが増えてしまうかもしれない。
では非アプリ、具体的には複数アプリに導入されうるモジュールの場合にはどうだろうか?対応の判断面は変わらない。要は「機能が必要になった」「依存するライブラリが移行した」場合に対応すればよい、ということだ。
しかし「早めに更新したほうがよいか」というと、そんなことはない。むしろ「できる限り対応を遅めたほうがよい」と筆者は考える。
AndroidXとSupport Libraryの間には名前空間やモジュールの分割といった変更があり、大きな変更のように思わせる。
しかし実際には、アプリ側でJetifierを用いることでSupport Libraryからの移行は容易に行える。
では逆にAndroidXに対応したものをSupport Libraryを前提としたアプリで利用するのが容易かというと、これは難しい。JetifierはSupport Libraryを用いた参照をAndroidXのものに変換する機能こそ利用できるが、その逆は困難だからだ。
AndroidXへの対応は簡単だが、それは十分にそのプロジェクトへアサインされたエンジニアのリソースが存在する場合に限られる。現実問題として、必ずしもプロジェクトにフルタイマーや十分な能力を持ったメンバーがアサインされている保証はない。
複数のアプリで利用されるモジュールがAndroidXの利用を要求するようになった場合、必然的にこのモジュールを利用している全てのアプリは移行の作業を行うこととなる。
「ではAndroidX対応しなくてもいいのか?」と聞かれそうになる。この答えはYesだ。なぜならSupport Libraryさえ使っていれば、実際にどちらを利用するかはアプリ側に判断を委ねることができるからだ。Jetifierを有効にするだけでよい。
長々と書いてきたが、この記事における主張は下記のとおりだ。
筆者は業務でエンドユーザ向けアプリからSDKまで様々な開発に携わっているが、AndroidXに関する対応は事業者によってまちまちである。
しかしながらエンジニアを対象としたプロダクトを作る事業者においては、ユーザであるエンジニアの利便性を損なわない対応を求めたいものだ。
AndroidXからSupport Libraryの利用へ戻すのは困難と記述したが、困難ではあっても可能ではある。
JetifierはAndroid Gradle Pluginと統合されているが、CLIからも利用ができる。そしてこのCLI版には Reverse mode
が存在している。
依存先ライブラリがAndroidXへ移行してしまったが、実態としてAndroidXの機能を利用していない (Support Library時代に提供されていた機能の範囲に留まっている) 場合は、これを利用するのもひとつの手段かもしれない。