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で指定しないとうまくいかないことがあるだろう。