- 公開日:2017年11月18日
記事概要
kotlinとJavaの混じったアプリを2.3.x系でビルドすると、制約がひどく、ビルドも遅いのでAndroid Studio 3.0に移行しました.
結構色々なエラーと修正が発生したので、今後移行する人の役に立つように作業メモを記載して残しておきます。
環境
- Android Studio 2.3.1 → Android Studio 3.0
Android Studio 3.0に対応
ダイアログで表示されるgradleのversionにアップデートします。ダイアログでOKを押下します。
自動的にbuild.gradleと/gradle/wrapper/gradle-wrapper.propertiesが上書きされます。
dependencies { - classpath 'com.android.tools.build:gradle:2.3.3' + classpath 'com.android.tools.build:gradle:3.0.0' classpath 'com.google.gms:google-services:3.0.0' }
-#Fri Jul 28 22:16:36 JST 2017 +#Sat Nov 18 19:40:49 JST 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip
jackOptionsを無効化
gradleの変更だけだと、おそらくビルドに失敗します。jackOptionsが有効だと以下のエラーが出力されます。
Warning:The Jack toolchain is deprecated and will not run. To enable support for Java 8 language features built into the plugin, remove 'jackOptions { ... }' from your build.gradle file, and add android.compileOptions.sourceCompatibility 1.8 android.compileOptions.targetCompatibility 1.8 Future versions of the plugin will not support usage of 'jackOptions' in build.gradle. To learn more, go to https://d.android.com/r/tools/java-8-support-message.html
エラーの内容は、jackOptionsはもうすぐサポート終わるから使わないでってことです。
なので、以下のように変更します。
defaultConfig { // something... vectorDrawables.useSupportLibrary = true - jackOptions { - enabled true - } multiDexEnabled true // something... }
jackOptionsを削除するだけです。sourceCompatibilityとtargetCompatibilityは残しておきます。
flavor dimensionsの設定
Android Studio 3.0からは、単一のflavor dimensionを使用する場合でも、すべてのflavorが名前付きflavor dimensionに属している必要があります。でないと、以下のようなエラーが発生します。
All flavors must now belong to a named flavor dimension. Learn more at https://d.android.com/r/tools/flavorDimensions-missing-error-message.html
つまり、dimensionを定義してね。ってことです。正直、ダメな仕様だと思います。大規模なプロジェクトには便利な機能ですが、必須である理由がわかりません。大抵のアプリは小さいアプリなはずです。いずれ元に戻ると思いたいですね。
ビルド周りは大きく変わっているので、面倒でもサンプルプロジェクトを作成して仕様を確認することをお勧めします。ドキュメントを読むだけだと、ピンと来ないと思います。
私の環境は分ける必要がないので、以下のように名前を一つ追加しただけです。
+ flavorDimensions 'normal' productFlavors { dev { + dimension 'normal' } prod { + dimension 'normal' } }
kotlinのバージョンアップ
jackOptionsが不要になったので、kotlinのバージョン縛りがなくなりました。なので、このままだと以下のエラーが発生します。
Unable to find method 'com.android.build.gradle.internal.variant.BaseVariantData.getOutputs()Ljava/util/List;'. Possible causes for this unexpected error include: Gradle's dependency cache may be corrupt (this sometimes occurs after a network connection timeout.) Re-download dependencies and sync project (requires network) The state of a Gradle build process (daemon) may be corrupt. Stopping all Gradle daemons may solve this problem. Stop Gradle build processes (requires restart) Your project may be using a third-party plugin which is not compatible with the other plugins in the project or the version of Gradle requested by the project. In the case of corrupt Gradle processes, you can also try closing the IDE and then killing all Java processes.
エラーにkotlinの文字が出ないのは良くないですね。いずれは改善して欲しいですね。
kotlinのアップデートはgradleの記載を変更するだけです。
buildscript { ext { - kotlin_version = '1.1.1' + kotlin_version = '1.1.51' }
buildToolのバージョンアップ
buildToolも更新が必要です。buildToolのバージョンが古いと以下の警告メッセージが表示されます。
Error:The specified Android SDK Build Tools version (26.0.1) is ignored, as it is below the minimum supported version (26.0.2) for Android Gradle Plugin 3.0.0. Android SDK Build Tools 26.0.2 will be used. To suppress this warning, remove "buildToolsVersion '26.0.1'" from your build.gradle file, as each version of the Android Gradle Plugin now has a default version of the build tools.
gradleを更新します。
android { - compileSdkVersion 26 + compileSdkVersion 27 buildToolsVersion rootProject.buildToolsVersion
allprojects { repositories { + google() mavenCentral() - maven { url 'https://maven.google.com' } } } ext { - buildToolsVersion = "26.0.1" - supportLibVersion = "26.1.0" + buildToolsVersion = "27.0.1" + supportLibVersion = "27.0.1" multidexVersion = "1.0.0" - constraintLayoutVersion = "1.0.2" + constraintLayoutVersion = "1.1.0-beta3" rxandroidVersion = "2.0.1" rxjavaVersion = "2.1.3"
maven { url 'https://maven.google.com' } を google() に書き換えできるようになりました。
また、Android Studio 3.0だと、constraintLayoutが安定してIDEで表示されるようになりました。ConstraintLayoutを使うとviewの入れ子を少なくできて、描写が高速になるので、積極的に利用していきましょう。beta版が嫌な人は1.0.2でも良いと思います。サポートライブラリとArchitecture Componentsの更新も忘れずに。
コード修正
最後にkotlinのアップデートとsdk27のアップデートのコード対応を行います。
私の環境で発生したエラーと修正方法を記載しておきます。
Error: style attribute '@android:attr/windowEnterAnimation' not found.
@が不要になりました。
<style name="Animations.GrowFromBottom"> - <item name="@android:windowEnterAnimation">@anim/grow_from_bottom</item> - <item name="@android:windowExitAnimation">@anim/shrink_from_top</item> + <item name="android:windowEnterAnimation">@anim/grow_from_bottom</item> + <item name="android:windowExitAnimation">@anim/shrink_from_top</item> </style> <style name="Animations.GrowFromTop"> - <item name="@android:windowEnterAnimation">@anim/grow_from_top</item> - <item name="@android:windowExitAnimation">@anim/shrink_from_bottom</item> + <item name="android:windowEnterAnimation">@anim/grow_from_top</item> + <item name="android:windowExitAnimation">@anim/shrink_from_bottom</item> </style> <style name="Animations.PopDownMenu"> - <item name="@android:windowEnterAnimation">@anim/grow_from_topleft_to_bottomright</item> - <item name="@android:windowExitAnimation">@anim/shrink_from_bottomright_to_topleft</item> + <item name="android:windowEnterAnimation">@anim/grow_from_topleft_to_bottomright</item> + <item name="android:windowExitAnimation">@anim/shrink_from_bottomright_to_topleft</item> </style>
Android3.0からは、デフォルトでAAPT2が有効になったことの影響です。
Error: Smart cast to 'Bundle' is impossible, because 'arguments' is a mutable property that could have been changed by this time
getArguments()のSmart castができなくなりました。コードを見ると、sdk27(サポートライブラリ)では以下のように実装されています。
/** * Return the arguments supplied when the fragment was instantiated, * if any. */ @Nullable final public Bundle getArguments() { return mArguments; }
sdk26(26.1.0)では以下のような実装でした。
/** * Return the arguments supplied when the fragment was instantiated, * if any. */ final public Bundle getArguments() { return mArguments; }
@Nullableが追加されています。ブロックの引数を指定する必要があります。
- arguments?.let { + arguments?.let { it ->
というかこれは既存コードに潜在的なバグが含まれていたっぽいです。。。letのブロック内の変数はなるべくitに置き換えるか、名称を変更するべきですね。
Error: Class 'XYZPagerAdapter' is not abstract and does not implement abstract base class member public abstract fun isViewFromObject(@NonNull p0: View, @NonNull p1: Any): Boolean defined in android.support.v4.view.PagerAdapter
PagerAdapterにも変更が入ったようです。コードを見ると、sdk27(サポートライブラリ)では以下のように実装されています。
public abstract boolean isViewFromObject(@NonNull View view, @NonNull Object object);
sdk26(26.1.0)では以下のような実装でした。
public abstract boolean isViewFromObject(View view, Object object);
これも同じように@Nullableが追加されています。?を削除します。
- override fun isViewFromObject(view: View?, `object`: Any?): Boolean { + override fun isViewFromObject(view: View, obj: Any): Boolean {
isViewFromObjectの引数って@NonNullだったんですね。チェックしてコード書いてた時期があったような。
Error: Fragment
Fragmentも変更されてますね。これもsdk27で@Nullableのアノテーションが追加されたのではないでしょうか。
@Nullable public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { return null; }
sdk26(26.1.0)では以下のような実装でした。
@Nullable public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { return null; }
LayoutInflaterが@NonNullになっています。これは良い修正ですね。以下のように修正します。
- override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, - val view = inflater!!.inflate(R.layout.fragment_floating_action, container, false) + val view = inflater.inflate(R.layout.fragment_floating_action, container, false)
Error: Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type FragmentActivity?
FragmentActivityも変更されてますね。これも@Nullableのアノテーションが追加されたのではないでしょうか。
final public FragmentActivity getActivity() { return mHost == null ? null : (FragmentActivity) mHost.getActivity(); } public Context getContext() { return mHost == null ? null : mHost.getContext(); }
sdk26(26.1.0)では以下のような実装でした。
@Nullable final public FragmentActivity getActivity() { return mHost == null ? null : (FragmentActivity) mHost.getActivity(); } /** * Return the {@link Context} this fragment is currently associated with. */ @Nullable public Context getContext() { return mHost == null ? null : mHost.getContext(); }
Safe-call演算子を使って書き換えます。
- activity.supportFragmentManager.popBackStack() + activity?.supportFragmentManager?.popBackStack() - Toast.makeText(context, context.getString(R.string.sample), Toast.LENGTH_SHORT).show() + Toast.makeText(context, context?.getString(R.string.sample), Toast.LENGTH_SHORT).show()
gradle修正
gradleを変更します。
compileをimplementationに変更します。
implementationにするとビルドが早くなります。
なぜなら、implementationは、コンパイルする必要がある依存ライブラリだけをコンパイルします。
- compile 'com.android.support:multidex:' + rootProject.multidexVersion - compile 'com.android.support:appcompat-v7:' + rootProject.supportLibVersion - compile 'com.android.support:design:' + rootProject.supportLibVersion - compile 'com.android.support:support-v4:' + rootProject.supportLibVersion - compile 'com.android.support.constraint:constraint-layout:' + rootProject.constraintLayoutVersion - compile 'com.android.support:recyclerview-v7:' + rootProject.supportLibVersion - compile 'com.android.support:cardview-v7:' + rootProject.supportLibVersion + implementation 'com.android.support:multidex:' + rootProject.multidexVersion + implementation 'com.android.support:appcompat-v7:' + rootProject.supportLibVersion + implementation 'com.android.support:design:' + rootProject.supportLibVersion + implementation 'com.android.support:support-v4:' + rootProject.supportLibVersion + implementation 'com.android.support.constraint:constraint-layout:' + rootProject.constraintLayoutVersion + implementation 'com.android.support:recyclerview-v7:' + rootProject.supportLibVersion + implementation 'com.android.support:cardview-v7:' + rootProject.supportLibVersion
以上で終了です。お疲れさまでした。
コンパイルが随分と高速化されました。
結論
kotlinのNull Safety機能は強力ですね。小さいアプリだとAndroid Architecture Componentsは不要ですね。導入すると無駄にコードも増えますし。
kotlinの導入とconstraintLayoutの導入は本当にお勧めです。8.1のリリースも近いので、そろそろ既存アプリのandroid studio3.0の対応は終了させておきたいですね。
0 件のコメント:
コメントを投稿