Android Studio 3.0でgradleのバージョンを上げたときにつまずいたこと

Android Studio 3.0がリリースされましたね。

個人のアプリがまだGradle3.4だったので、Gradleなどのバージョンを上げましたが、いくつか戸惑った点などありましたので、まとめます。

対象とするプロジェクトは下記のとおりです。
https://github.com/noboru-i/SlideViewer/tree/3f91c7474785d8dd2aa5955683a912a7b76677ac

## Android Studioによるgradleのバージョンアップ

Android Studio 3.0でプロジェクトを開くと、"Android Gradle Plugin Update Recommended"というダイアログが開くので、recommendに従って、"Update"してもらいます。

差分はこちら。

```diff
diff --git a/build.gradle b/build.gradle
index 6763769..138f4ce 100644
--- a/build.gradle
+++ b/build.gradle
@@ -5,7 +5,7 @@ buildscript {
         jcenter()
     }
     dependencies {
-        classpath 'com.android.tools.build:gradle:2.3.2'
+        classpath 'com.android.tools.build:gradle:3.0.0'
         classpath 'com.google.gms:google-services:3.1.0'
         classpath 'me.tatarka:gradle-retrolambda:3.6.1'
         classpath 'com.cookpad.android.licensetools:license-tools-plugin:0.19.1'
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 2297618..e8219c4 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Sun Oct 16 12:42:03 JST 2016
+#Sat Oct 28 12:49:42 JST 2017
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-3.4-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip
```

Gradle自体は3.4 -> 4.1になり、Gradle pluginが3.0.0になりました。

これでGradleのsyncをすると、下記のようなエラーメッセージがでました。

```

The specified Android SDK Build Tools version (25.0.3) 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 '25.0.3'" from your build.gradle file, as each version of the Android Gradle Plugin now has a default version of the build tools. Update Build Tools version and sync project Open File
```

build tools versionを上げる必要がありそうですね。

## build toolsのバージョンアップ

```diff
diff --git a/app/build.gradle b/app/build.gradle
index b8f3813..fb49dff 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -11,7 +11,7 @@ def preDexEnabled = "true".equals(System.getProperty("pre-dex", "true"))
 
 android {
     compileSdkVersion 25
-    buildToolsVersion "25.0.3"
+    buildToolsVersion "26.0.2"
 
     dataBinding {
         enabled = true
```

次は、エラーじゃないですが、retrolambda周りのワーニングが出ました。

```
Warning:One of the plugins you are using supports Java 8 language features. To try the support built into the Android plugin, remove the following from your build.gradle:
    apply plugin: 'me.tatarka.retrolambda'
To learn more, go to https://d.android.com/r/tools/java-8-support-message.html
```

retrolambdaがなくてもlambdaを書けるようになったっぽい？ですね。

## retrolambdaの削除

単純に消していきます。

```diff
diff --git a/app/build.gradle b/app/build.gradle
index fb49dff..cde70cd 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -1,5 +1,4 @@
 apply plugin: 'com.android.application'
-apply plugin: 'me.tatarka.retrolambda'
 apply plugin: 'com.cookpad.android.licensetools'
 apply plugin: 'com.github.ben-manes.versions'
 
diff --git a/build.gradle b/build.gradle
index 138f4ce..3abe1c4 100644
--- a/build.gradle
+++ b/build.gradle
@@ -7,7 +7,6 @@ buildscript {
     dependencies {
         classpath 'com.android.tools.build:gradle:3.0.0'
         classpath 'com.google.gms:google-services:3.1.0'
-        classpath 'me.tatarka:gradle-retrolambda:3.6.1'
         classpath 'com.cookpad.android.licensetools:license-tools-plugin:0.19.1'
         classpath 'com.github.ben-manes:gradle-versions-plugin:0.14.0'
     }
```

これで、一旦gradleのsyncは完了しました。
次に、メニューよりBuild -> Rebuild Projectを選択することで、buildしていきます。

下記のエラーが出ました。

```
Error:Execution failed for task ':app:javaPreCompileDebug'.
> Annotation processors must be explicitly declared now.  The following dependencies on the compile classpath are found to contain annotation processor.  Please add them to the annotationProcessor configuration.
    - lombok-1.16.16.jar (org.projectlombok:lombok:1.16.16)
  Alternatively, set android.defaultConfig.javaCompileOptions.annotationProcessorOptions.includeCompileClasspath = true to continue with previous behavior.  Note that this option is deprecated and will be removed in the future.
  See https://developer.android.com/r/tools/annotation-processor-error-message.html for more details.
```

lombok周りですね。

## lombokのエラーを解消

`annotationProcessor` を追加します。

```diff
diff --git a/app/build.gradle b/app/build.gradle
index cde70cd..858390b 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -87,7 +87,8 @@ dependencies {
     compile "com.google.android.gms:play-services-analytics:${playServicesVersion}"
     compile 'com.j256.ormlite:ormlite-android:5.0'
     compile 'com.github.chrisbanes:PhotoView:2.0.0'
-    provided 'org.projectlombok:lombok:1.16.16'
+    provided 'org.projectlombok:lombok:1.16.18'
+    annotationProcessor 'org.projectlombok:lombok:1.16.18'
     compile "io.reactivex.rxjava2:rxjava:2.1.0"
     compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
     compile 'com.jakewharton.timber:timber:4.5.1'
```

ついでにバージョンも上げておきました。
これで、ビルドが通るようになりました。

## ターミナルでビルドしてみる

`./gradlew assembleDebug` を実行してみます。

```
* What went wrong:
A problem occurred configuring root project 'SlideViewer'.
> Could not resolve all files for configuration ':classpath'.
   > Could not find com.android.tools.build:gradle:3.0.0.
     Searched in the following locations:
         https://jcenter.bintray.com/com/android/tools/build/gradle/3.0.0/gradle-3.0.0.pom
         https://jcenter.bintray.com/com/android/tools/build/gradle/3.0.0/gradle-3.0.0.jar
     Required by:
         project :
   > Could not find com.android.tools.build:gradle:3.0.0.
     Searched in the following locations:
         https://jcenter.bintray.com/com/android/tools/build/gradle/3.0.0/gradle-3.0.0.pom
         https://jcenter.bintray.com/com/android/tools/build/gradle/3.0.0/gradle-3.0.0.jar
     Required by:
         project : > com.cookpad.android.licensetools:license-tools-plugin:0.19.1
```

gradleのpluginが見つからないっぽいですね。
googleのリポジトリが必要っぽいです。

```diff
diff --git a/build.gradle b/build.gradle
index 3c48390..43cd73f 100644
--- a/build.gradle
+++ b/build.gradle
@@ -3,6 +3,7 @@
 buildscript {
     repositories {
         jcenter()
+        google()
     }
     dependencies {
         classpath 'com.android.tools.build:gradle:3.0.0'
@@ -15,6 +16,7 @@ buildscript {
 allprojects {
     repositories {
         jcenter()
+        google()
         mavenCentral()
         maven { url "https://jitpack.io" }
         maven { url "https://maven.google.com" }
```

再度 `./gradlew assembleDebug` を実行すると、エラーが変わりました。

```
* What went wrong:
A problem occurred configuring project ':app'.
> Failed to notify project evaluation listener.
   > Could not initialize class com.android.sdklib.repository.AndroidSdkHandler
```

https://stackoverflow.com/a/37516664 をみると、Java9だとエラーになるっぽいですね。
とりあえず、一時的にJava8を使うようにしてみました。

```
export JAVA_HOME=`/usr/libexec/java_home -v "1.8" -F`
```

再度実行すると、よくわからないエラーも出ましたが、`./gradlew clean assembleDebug` などやると、ビルドが通るようになりました。

Android Studioでのインストールもできるようになりました。

## いろいろバージョンアップ

`./gradlew dependencyUpdates` を実行して、古いライブラリを検出します。
結果は、下記のようになりました。

```
The following dependencies have later milestone versions:
 - com.github.chrisbanes:PhotoView [2.0.0 -> 2.1.3]
 - com.android.databinding:adapters [1.3.1 -> 1.3.3]
 - com.android.support:appcompat-v7 [25.3.1 -> 27.0.0]
 - com.android.databinding:baseLibrary [3.0.0 -> 3.1.0-alpha01]
 - com.android.databinding:compiler [3.0.0 -> 3.1.0-alpha01]
 - com.android.support:design [25.3.1 -> 27.0.0]
 - com.google.firebase:firebase-core [10.2.6 -> 11.4.2]
 - com.google.firebase:firebase-crash [10.2.6 -> 11.4.2]
 - com.github.bumptech.glide:glide [3.7.0 -> 4.2.0]
 - com.google.code.gson:gson [2.8.0 -> 2.8.2]
 - org.jsoup:jsoup [1.10.2 -> 1.10.3]
 - com.squareup.leakcanary:leakcanary-android [1.5.1 -> 1.5.4]
 - com.squareup.leakcanary:leakcanary-android-no-op [1.5.1 -> 1.5.4]
 - com.android.databinding:library [1.3.1 -> 1.3.3]
 - com.squareup.okhttp3:okhttp [3.8.0 -> 3.9.0]
 - org.jacoco:org.jacoco.agent [0.7.4.201502262128 -> 0.7.9]
 - org.jacoco:org.jacoco.ant [0.7.4.201502262128 -> 0.7.9]
 - com.google.android.gms:play-services-ads [10.2.6 -> 11.4.2]
 - com.google.android.gms:play-services-analytics [10.2.6 -> 11.4.2]
 - com.android.support:recyclerview-v7 [25.3.1 -> 27.0.0]
 - io.reactivex.rxjava2:rxjava [2.1.0 -> 2.1.6]
 - com.android.support:support-v4 [25.3.1 -> 27.0.0]
 - com.rmtheis:tess-two [6.2.0 -> 8.0.0]
```

下記のように、バージョンを上げていきました。

```diff
diff --git a/app/build.gradle b/app/build.gradle
index 858390b..0456625 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -9,7 +9,7 @@ def isCi = "true".equals(System.getenv("CI"))
 def preDexEnabled = "true".equals(System.getProperty("pre-dex", "true"))
 
 android {
-    compileSdkVersion 25
+    compileSdkVersion 26
     buildToolsVersion "26.0.2"
 
     dataBinding {
@@ -24,7 +24,7 @@ android {
     defaultConfig {
         applicationId "hm.orz.chaos114.android.slideviewer"
         minSdkVersion 15
-        targetSdkVersion 25
+        targetSdkVersion 26
         versionCode 13
         versionName "3.2.0"
     }
@@ -70,8 +70,8 @@ android {
 }
 
 ext {
-    supportLibVersion = '25.3.1'
-    playServicesVersion = '10.2.6'
+    supportLibVersion = '26.1.0'
+    playServicesVersion = '11.4.2'
 }
 
 dependencies {
@@ -81,26 +81,26 @@ dependencies {
     compile "com.android.support:design:${supportLibVersion}"
     compile "com.android.support:recyclerview-v7:${supportLibVersion}"
     compile "com.google.firebase:firebase-crash:${playServicesVersion}"
-    compile 'com.google.code.gson:gson:2.8.0'
-    compile 'com.github.bumptech.glide:glide:3.7.0'
+    compile 'com.google.code.gson:gson:2.8.2'
+    compile 'com.github.bumptech.glide:glide:4.2.0'
     compile "com.google.android.gms:play-services-ads:${playServicesVersion}"
     compile "com.google.android.gms:play-services-analytics:${playServicesVersion}"
     compile 'com.j256.ormlite:ormlite-android:5.0'
-    compile 'com.github.chrisbanes:PhotoView:2.0.0'
+    compile 'com.github.chrisbanes:PhotoView:2.1.3'
     provided 'org.projectlombok:lombok:1.16.18'
     annotationProcessor 'org.projectlombok:lombok:1.16.18'
-    compile "io.reactivex.rxjava2:rxjava:2.1.0"
+    compile "io.reactivex.rxjava2:rxjava:2.1.6"
     compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
     compile 'com.jakewharton.timber:timber:4.5.1'
-    compile 'com.squareup.okhttp3:okhttp:3.8.0'
-    compile 'org.jsoup:jsoup:1.10.2'
-    compile 'com.rmtheis:tess-two:6.2.0'
+    compile 'com.squareup.okhttp3:okhttp:3.9.0'
+    compile 'org.jsoup:jsoup:1.10.3'
+    compile 'com.rmtheis:tess-two:8.0.0'
     annotationProcessor 'com.rejasupotaro:kvs-schema-compiler:5.0.1'
     compile 'com.rejasupotaro:kvs-schema:5.0.1'
 
-    debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5.1'
-    releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.1'
-    testCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.1'
+    debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5.4'
+    releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.4'
+    testCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.4'
 }
 
 apply plugin: 'com.google.gms.google-services'
diff --git a/app/src/main/java/hm/orz/chaos114/android/slideviewer/ui/SlideActivity.java b/app/src/main/java/hm/orz/chaos114/android/slideviewer/ui/SlideActivity.java
index e1a2622..43a39c3 100644
--- a/app/src/main/java/hm/orz/chaos114/android/slideviewer/ui/SlideActivity.java
+++ b/app/src/main/java/hm/orz/chaos114/android/slideviewer/ui/SlideActivity.java
@@ -7,6 +7,7 @@
 import android.net.Uri;
 import android.os.Bundle;
 import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
 import android.support.v4.view.PagerAdapter;
 import android.support.v4.view.ViewPager;
 import android.support.v7.app.AppCompatActivity;
@@ -23,6 +24,8 @@
 import android.widget.Toast;
 
 import com.bumptech.glide.Glide;
+import com.bumptech.glide.load.DataSource;
+import com.bumptech.glide.load.engine.GlideException;
 import com.bumptech.glide.request.RequestListener;
 import com.bumptech.glide.request.target.Target;
 import com.github.chrisbanes.photoview.PhotoView;
@@ -425,11 +428,11 @@ private void loadImage(Slide slide, View layout, int position) {
             refreshButton.setVisibility(View.GONE);
 
             Glide.with(SlideActivity.this)
-                    .load(slide.getOriginal())
                     .asBitmap()
-                    .listener(new RequestListener<String, Bitmap>() {
+                    .load(slide.getOriginal())
+                    .listener(new RequestListener<Bitmap>() {
                         @Override
-                        public boolean onException(Exception e, String model, Target<Bitmap> target, boolean isFirstResource) {
+                        public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Bitmap> target, boolean isFirstResource) {
                             Timber.d("Glide onException");
                             progressBar.setVisibility(View.GONE);
                             refreshButton.setVisibility(View.VISIBLE);
@@ -437,7 +440,7 @@ public boolean onException(Exception e, String model, Target<Bitmap> target, boo
                         }
 
                         @Override
-                        public boolean onResourceReady(Bitmap resource, String model, Target<Bitmap> target, boolean isFromMemoryCache, boolean isFirstResource) {
+                        public boolean onResourceReady(Bitmap resource, Object model, Target<Bitmap> target, DataSource dataSource, boolean isFirstResource) {
                             Timber.d("Glide onResourceReady: %d", position);
                             if (recognizeTextMap.containsKey(slide.getOriginal())
                                     && position == binding.slideViewPager.getCurrentItem()) {
diff --git a/build.gradle b/build.gradle
index 43cd73f..4e664ff 100644
--- a/build.gradle
+++ b/build.gradle
@@ -9,7 +9,7 @@ buildscript {
         classpath 'com.android.tools.build:gradle:3.0.0'
         classpath 'com.google.gms:google-services:3.1.0'
         classpath 'com.cookpad.android.licensetools:license-tools-plugin:0.19.1'
-        classpath 'com.github.ben-manes:gradle-versions-plugin:0.15.0'
+        classpath 'com.github.ben-manes:gradle-versions-plugin:0.17.0'
     }
 }
```

ほとんどは、破壊的な変更がなく、そのままで動いたのですが、glideだけはメジャーバージョンの変更によってAPIが変わっており、 http://bumptech.github.io/glide/doc/migrating.html を参考に、少し修正しました。

## checkが通らないので修正

https://github.com/monstar-lab/gradle-android-ci-check の1.3.1を利用していたのですが、
`./gradlew :app:check` を実行すると、下記のエラーが発生していました。

```
* What went wrong:
Execution failed for task ':app:checkstyle'.
> Unable to create a Checker: configLocation {/var/folders/7_/6c9mz04n73x21ly6qm85wtk80000gn/T/checkstyle2135433115375948898}, classpath {null}.
```

これだとわからないので、`./gradlew :app:check --stacktrace` で再度実行します。

```
Caused by: com.puppycrawl.tools.checkstyle.api.CheckstyleException: 'RedundantThrows' クラスをインスタンス化することができません、それは としてインスタンス化することもできません com.puppycrawl.tools.checkstyle.checks.annotation.RedundantThrows, com.puppycrawl.tools.checkstyle.checks.blocks.RedundantThrows, com.puppycrawl.tools.checkstyle.checks.coding.RedundantThrows, com.puppycrawl.tools.checkstyle.checks.design.RedundantThrows, com.puppycrawl.tools.checkstyle.checks.header.RedundantThrows, com.puppycrawl.tools.checkstyle.checks.imports.RedundantThrows, com.puppycrawl.tools.checkstyle.checks.indentation.RedundantThrows, com.puppycrawl.tools.checkstyle.checks.javadoc.RedundantThrows, com.puppycrawl.tools.checkstyle.checks.metrics.RedundantThrows, com.puppycrawl.tools.checkstyle.checks.modifier.RedundantThrows, com.puppycrawl.tools.checkstyle.checks.naming.RedundantThrows, com.puppycrawl.tools.checkstyle.checks.regexp.RedundantThrows, com.puppycrawl.tools.checkstyle.checks.sizes.RedundantThrows, com.puppycrawl.tools.checkstyle.checks.whitespace.RedundantThrows, com.puppycrawl.tools.checkstyle.checks.RedundantThrows, com.puppycrawl.tools.checkstyle.filters.RedundantThrows, com.puppycrawl.tools.checkstyle.RedundantThrows, RedundantThrowsCheck, com.puppycrawl.tools.checkstyle.checks.annotation.RedundantThrowsCheck, com.puppycrawl.tools.checkstyle.checks.blocks.RedundantThrowsCheck, com.puppycrawl.tools.checkstyle.checks.coding.RedundantThrowsCheck, com.puppycrawl.tools.checkstyle.checks.design.RedundantThrowsCheck, com.puppycrawl.tools.checkstyle.checks.header.RedundantThrowsCheck, com.puppycrawl.tools.checkstyle.checks.imports.RedundantThrowsCheck, com.puppycrawl.tools.checkstyle.checks.indentation.RedundantThrowsCheck, com.puppycrawl.tools.checkstyle.checks.javadoc.RedundantThrowsCheck, com.puppycrawl.tools.checkstyle.checks.metrics.RedundantThrowsCheck, com.puppycrawl.tools.checkstyle.checks.modifier.RedundantThrowsCheck, com.puppycrawl.tools.checkstyle.checks.naming.RedundantThrowsCheck, com.puppycrawl.tools.checkstyle.checks.regexp.RedundantThrowsCheck, com.puppycrawl.tools.checkstyle.checks.sizes.RedundantThrowsCheck, com.puppycrawl.tools.checkstyle.checks.whitespace.RedundantThrowsCheck, com.puppycrawl.tools.checkstyle.checks.RedundantThrowsCheck, com.puppycrawl.tools.checkstyle.filters.RedundantThrowsCheck, com.puppycrawl.tools.checkstyle.RedundantThrowsCheck. そのクラス名が正規名として指定されている再確認または短い名前の使用 http://checkstyle.sourceforge.net/config.html#Packages を設定する方法をお読みください。また、チェッカーへの提供クラスローダが正しく設定されて再確認してください。
        at com.puppycrawl.tools.checkstyle.PackageObjectFactory.createModule(PackageObjectFactory.java:99)
        at com.puppycrawl.tools.checkstyle.TreeWalker.setupChild(TreeWalker.java:153)
        at com.puppycrawl.tools.checkstyle.api.AutomaticBean.configure(AutomaticBean.java:138)
        at com.puppycrawl.tools.checkstyle.Checker.setupChild(Checker.java:402)
        ... 61 more
```

gradleがバージョンアップしたことで、checkstyleのバージョンが変わり、設定ファイルに修正が必要なようです。
monstar-lab/gradle-android-ci-check リポジトリの方は後で修正することにして、一旦設定ファイルを手元で修正できるようにします。

READMEに記載の通り、 `gradle.properties` に `checkStyleConfigFile=../config/quality/checkstyle/checkstyle.xml` を追加し、内容は
https://github.com/monstar-lab/gradle-android-ci-check/blob/d4a8ce6d6b1d54f5ab60882ef1449e91a980988f/config/checkstyle/checkstyle.xml
の内容をコピーし、再度実行しても、同様のエラーになりました。

http://eclipse-cs.sourceforge.net/#!/releasenotes
6.2 と 6.4のところに、

> Please further note that with Checkstyle 6.2 the `StrictDuplicate` and `RedundantThrows` check have been removed without replacement.

とあったので、 `RedundantThrows` の記述を削除しました。

```diff
diff --git a/config/quality/checkstyle/checkstyle.xml b/config/quality/checkstyle/checkstyle.xml
index 43840e6..45c65c9 100644
--- a/config/quality/checkstyle/checkstyle.xml
+++ b/config/quality/checkstyle/checkstyle.xml
@@ -148,9 +148,6 @@
         </module>
         <module name="IllegalInstantiation" />
         <module name="InnerAssignment" />
-        <module name="RedundantThrows">
-            <property name="suppressLoadErrors" value="true" />
-        </module>
         <module name="SimplifyBooleanExpression" />
         <module name="SimplifyBooleanReturn" />
```

これで、ビルドが通るようになりました。
ようやく、開発に戻れます。