Android Studio2.x時代のプロジェクトを3.0環境へ更新
ストアに公開しているアプリは2018年8月までにtargetSdkVersionを26以上にする必要がある。その関係で以前にリリースしたアプリを更新しているのだが、その際に最初のハードルとなるのが古いAndroid Studioで作ったプロジェクトを現在のバージョンに更新する作業である。
最近何回も同じことをやっているので、備忘録的に書いておく。
基本的には全部Migrate to Android Plugin for Gradle 3.0.0に書いてあるので、そのとおりにやるだけである。
書いている途中でAndroid Studio 3.1が正式版になった。が、3.0から3.1への更新はそんなに大きく変更しなくても済むので、基本は3.0へのマイグレーションガイドに書いてあることに対応すればよいはず。
まず始めにGradle(Gradle wrapper)のバージョン更新を行う。Android Studio3.0は最低でもGradle4.1以上が必要。(3.1はGradle4.4以上)
gradle wrapperの更新はgradle-wrapper.properties
ファイルを書き換えてgradle syncを行うだけ。
私は./gradlew wrapper --gradle-version=<Gradleのバージョン>
コマンドで更新している。これで更新したらシェルスクリプトの更新もかかる場合があるので、こっちのほうがいいのかなという雰囲気で選んでいるだけだったりする。
コマンドで更新した場合、distributionUrlで指定されるgradle wrapperが4.x-bin.zip
といった感じでバイナリのみのものになる。Android Studioはallにしとけと変更を促してきて、結局手書きでdistributionUrlを書き換えることになるので、普通にマイグレーションドキュメントにあるようにgradle-wrapper.properties
を書き換えるだけでいいと思う。
ちなみに利用するgradleのバージョンだが、私の場合Twitterで見かけたGradleのリリースツイートを見て覚えてるバージョンを利用している。今だと4.6。
使えるバージョンはhttps://gradle.org/releases/で確認できる。基本的には最新使っとけばいいんじゃないだろうか。
- android gradle pluginのバージョンを更新
- repositoryに`google()`を追加する(先にGradle wrapperのバージョンを上げておく必要がある)
- 利用しているgradle pluginのバージョン更新
プロジェクトで利用しているgradle pluginのバージョンが古い場合、原因がよくわからないエラーが多発する。例えばNo signature of method: com.android.build.gradle.internal.scope.VariantScopeImpl.getGenerateRClassTask() is applicable for argument types: () values: []
とか。こういうのは利用しているgradle pluginを最新のバージョンに更新すると解消されることが多かった。
基本的にAndroid Studioが利用しているプラグインの新しいバージョンがあれば教えてくれるはず(網掛けになって新しいバージョンがあることを示唆してくれる)ので、それに従ってgradle pluginのバージョンを上げてみると解決する場合が多いだろう。
エラーメッセージで検索してもこれといった解決策が見つからないという場合には、利用しているプラグインのバージョンを上げることを試してみよう。
昔はライブラリプロジェクトを利用している場合、publishNonDefault true
を設定して、アプリケーションモジュールをdebugビルドするときは、ライブラリプロジェクトもdebugビルドにするなんて指定をしている人もいただろう。
この設定をしている場合、Android Studio3.xにアップデートするにあたってちょっとした手直しが必要になる。
Android Studio3.0からはライブラリモジュールのビルド設定は、利用するアプリケーションモジュールのものと同じものが利用されるようになった。appモジュールでdebugビルドを選んだら、自動的に依存しているライブラリモジュールもdebugビルドでビルドされる。
そのため以下の手直しが必要。
publishNonDefault true
の記述を削除する。
例えば以下のように記述していたとする。
debugCompile project(path: ":library", configuration: "debug")
releaseCompile project(path: ":library", configuration: "release")
この場合、この2行は不要になるので削除。その後あらためてimplementation project(":library")
とライブラリモジュールへの依存を記述する。
追加でbuildTypeに手を加えている場合(デフォルトのdebug
とrelease
以外に定義している場合)、増やしたbuildTypeの定義にmatchingFallbacks
という行を追加してやる必要がある。
これはそのbuildTypeが使われるときに、それが存在しないライブラリプロジェクトなどがどのbuildTypeを使えばいいかを指定するものだ。
ライブラリモジュールと同様の問題と変更が行われている。publishNonDefault true
が要らなくなって、debugWearApp ...
という記述群がwearApp(":wear")
の1行で済むようになった。
新しくflavorDimensions
を最低1つは定義しないといけなくなった。
productFlavorは何らかの基準で使い分けているはずなので、その基準を定義すれば良い。例えばhttps://github.com/gen0083/FilteredHatebuこのプロジェクトは、ネットワークのレスポンスという観点からmock
とprod
というプロダクトフレーバーを定義している。
ネットワークの観点で切り分けているので、flavorDimensions "network"
という感じで定義してやる。
後はproductFlavorの定義の部分で、どのdimensionに属する定義なのかを指定してやればいい。flavorDimensionsが1つしかないのであれば省略可能である。
私は最初勘違いしていたのだが、これは決して各フレーバーごとに異なるdimensionを割り当てなければならないということではない。このプロジェクトでは最初mock
にtest
、prod
にdefault
というdimensionを割り当てたのだが、そうするとプロダクトフレーバーはmockProdDebug
という形になってしまい、mock
とprod
を切り替えられなくなってしまった。切り替えて使うものについては、同じdimensionを割り当てないといけない。
これは確かmustだったような気がする。(気がするというのは、最近更新したプロジェクトの中にはapt
を使っているものがなかったので)
古いプロジェクトだとgradle pluginを使ってアノテーションによるコード生成ライブラリを使っていたと思うが、その機能は公式に取り込まれているので、gradle pluginの削除とapt
をannotationProcessor
に置き換えてやる。
dependenciesのcompile "com.android.support:appcompat-v7:xxx"
のcompileの部分をimplementation
に置き換える。
これは直さなくてもビルド自体は通るものの、Android Studio3.1からはwarningとして警告されるので、もうさっさと書き換えてしまったほうが良いだろう。
アプリケーションモジュールしかないプロジェクトであれば、全部implementation
にしておけばいいはずである。基本的にimplementation
にしておいて、それではうまくいかない場合にapi
に変更するばよいと思う。api
が必要になってくるのは、ライブラリモジュールを使っている場合だろう。
ライブラリモジュールでのみcompile
で依存性を組み込んでいて、利用側のアプリケーションモジュールではdependenciesに記述していないという状態があるのであればapi
で指定しないとうまくいかないことがあるだろう。