僕たちはいつまでこんな楽しいAndroid Studio設定をし続けるのか？ Android Studio 3.x時代の設定不足解消メモ

# 概要
本稿は**Android Studio 2.x**世代に開発したアプリを**Android Studio 3.x**世代でビルドするときに遭遇した事象と対策のメモです。

- Androidアプリを開発していると、頻繁に開発環境のアップデートがあります
- 開発環境をアップデートすると頻繁に古いプロジェクトがビルドできなくなります  
　（昔は通用したのに、今は通用しなくなる）

# ビルドの成否に影響を及ぼす要素

- Android Studioのバージョン
- Gradleのバージョン
- Android Pluginのバージョン
- SDK Build Toolsのバージョン
- Android Plugin Repositoryの場所
- Default Library Repositoryの場所
- Android SDK Toolsのバージョン
- Android Support Libraryのバージョン
- JDKバージョン

これらが絶妙に調合されていないとビルドは成功しません。これは(Androidかいわいに限った話でなく)宿命なのでその時代に応じて何とか乗り越えていく必要があります。

# Android Studioのバージョン
Android Studioは 3系を対象にします
https://developer.android.com/studio/?hl=ja

<hr>

# 【問題】**Gradle version**と**Android Plugin Version**と**SDK Build Tools version**の組み合わせ問題

## 起こりがちなエラー

**以下のメソッドがサポートされていませんエラー**

```
Error:Unsupported method: BaseConfig.getApplicationIdSuffix().
```

```
Error:Unsupported method: GradleProject.getProjectDirectory().
```

**古いGradleにしてくださいエラー**

```
Gradle sync failed: Gradle version 2.2 is required. Current version is 4.10.1. If using the gradle wrapper, try editing the distributionUrl in ...
```

```
Gradle sync failed: No signature of method: java.util.ArrayList.all() is applicable for argument types: ...
Possible solutions: any(), tail(), last(), last(), add(java.lang.Object), add(java.lang.Object) (10 s 345 ms)
```

## 原因
<font color=red>古いプロジェクトを開いた等で、**Gradle version**と**Android Plugin Version**と**SDK Build Tools version**の組み合わせがあっていない。</font>


## 解決策

以下に正しい組み合わせが出ているので、それを確認する

https://developer.android.com/studio/releases/gradle-plugin#updating-gradle
![image.png](https://qiita-image-store.s3.amazonaws.com/0/170905/72c3e228-020f-efd4-e5a0-155aabe79bde.png)


2019年1月現在だと以下が最新の組み合わせ

<table>
<tr><td>設定</td><td>バージョン</td></tr>
<tr><td>Gradle version</td><td>4.10.1</td></tr>
<tr><td>Android Plugin</td><td>3.3.0</td></tr>
<tr><td>Build Tools</td><td>28.0.3</td></tr>
</table>

[**Build Tools**のリリースノートはこちら](https://developer.android.com/studio/releases/build-tools#notes)

### Android Studioの**Project Structure**で**Gradle version**と**Android Plugin Version**を設定する

File>Project Structure>Project と選択して**Gradle version**を**4.10.1**、**Android Plugin Version**を**3.3.0**と入力する。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/170905/a9aad6bd-ed20-54bc-af32-1623749879c9.png)


### build.gradle (Module:app) で buildToolsVersionを設定する

bulid.gradle(appレベル)で **buildToolsVersion**を**28.0.3**とする。

```gradle:build.gradle(app)
apply plugin: 'com.android.application'

android {
    compileSdkVersion 19
    buildToolsVersion "28.0.3"

...
```

これで、**Gradle version**と**Android Plugin Version**と**SDK Build Tools version**が正しい組み合わせとなった。

**Tips**
たとえ、以下のように Gradle versionを古くするように提案されても**build.gradle**の**buildToolsVersion**を最新にあわせればたいてい問題は消える。

```
Gradle sync failed: Gradle version 2.2 is required. Current version is 4.10.1.
```

## 解説・参考サイト
https://developer.android.com/studio/releases/gradle-plugin#updating-gradle
https://developer.android.com/studio/releases/build-tools#notes

<hr>

#【問題】**Android Plugin Version**をあげようとしたらプラグインがリポジトリからみつからない


## 起こりがちなエラー

**gradle依存ライブラリがみつかりませんエラー**

```
Gradle sync failed: Could not find com.android.tools.build:gradle:3.0.
Searched in the following locations:
- https://jcenter.bintray.com/com/android/tools/build/gradle/3.0/gradle-3.0.pom
- https://jcenter.bintray.com/com/android/tools/build/gradle/3.0/gradle-3.0.jar
```

## 原因
<font color="red">Android Pluginは 3.0.0以降、jcenterではなく、google独自のmavenリポジトリから配信されているため</font>

## 解決策その1

File>Project Structure>Project と選択して**Android Plugin Repository**に `'https://maven.google.com'` を設定する

以下のようにAndroid Plugin Repositoryに `jcenter,'https://maven.google.com'`のように両方設定しておいてOK

![image.png](https://qiita-image-store.s3.amazonaws.com/0/170905/a9aad6bd-ed20-54bc-af32-1623749879c9.png)

<table>
<tr><td>設定</td><td>バージョン</td></tr>
<tr><td>Gradle version</td><td>4.10.1</td></tr>
<tr><td>Android Plugin</td><td>3.3.0</td></tr>
<tr><td>Build Tools</td><td>28.0.3</td></tr>
<tr><td>Android Plugin Repository</td><td>jcenter,'https://maven.google.com'</td></tr>
<tr><td>Default Library Repository</td><td>jcenter</td></tr>
</table>


## 解決案その2
Android Studioでなく、コード側に設定してもOK。ルート(プロジェクトレベル)の**build.gradle**に`https://maven.google.com`を追加するが、`https://maven.google.com`と書かなくても**google()**と書けば同じ意味になるので、そのようにする。

```gradle:build.gradle(プロジェクトレベル)
buildscript {
    repositories {
        jcenter()
        google()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.3.0'
    }
}

allprojects {
    repositories {
        jcenter()
        google()
    }
}
```

## 解説・参考サイト
https://developer.android.com/studio/build/dependencies#google-maven

<hr>

# 【問題】**Gradle version**を上げたら、今までは問題なかった記述がエラー扱いされる

## 起こりがちなエラーや警告

**minSdkは AndroidManifest.xml じゃなくて build.gradleに書いてねエラー**

```
ERROR: The minSdk version should not be declared in the android manifest file. You can move the version from the manifest to the defaultConfig in the build.gradle file.
Remove minSdkVersion and sync project
```

**targetSdkは AndroidManifest.xml じゃなくて build.gradleに書いてね警告**

```
WARNING: The targetSdk version should not be declared in the android manifest file. You can move the version from the manifest to the defaultConfig in the build.gradle file.
Move targetSdkVersion to build file and sync project
```

## 原因
<font color=red>Gradle 3.0.0以降、記述ルールが大きめの変更がはいっているため</font>
(https://developer.android.com/studio/build/gradle-plugin-3-0-0-migration)

## 解決策


以下の記述が AndroidManifest.xmlにあったら、それを**消して****build.gradle**に以降する。

```xml:AndroidManifest.xml
    <uses-sdk
        android:minSdkVersion="19"
        android:targetSdkVersion="19" />
...
```
↓↓↓

```gradle:build.gradle(app)
apply plugin: 'com.android.application'

android {
    compileSdkVersion 26
    buildToolsVersion "28.0.3"

    defaultConfig {
        applicationId "com.example.sony.smarteyeglass.extension.helloworld"
        minSdkVersion 19
        targetSdkVersion 26
    }
```

（Android向けのIDEの主流が**Eclipse**から**Android Studio**に変わったとき、**AndroidManifest.xml**に記述していた内容の一部が**build.gradle**に移行したが、minSdkVersionは、ついにエラー扱いになってしまったということ。）


## 解説・参考サイト
https://developer.android.com/studio/build/gradle-plugin-3-0-0-migration


<hr>

# 【問題】APKがビルドできない

## 起こりがちなエラーや警告

```
Gradle sync failed: Cannot set the value of read-only property 'outputFile' for ApkVariantOutputImpl_Decorated{apkData=Main{type=MAIN, fullName=release, filters=[], versionCode=1, versionName=1.0.0}} of type com.android.build.gradle.internal.api.ApkVariantOutputImpl.
```

## 原因
<font color=red>Androidプラグインが3.0.0以降になった影響のため</font>

https://developer.android.com/studio/build/gradle-plugin-3-0-0-migration
(新しいプラグインでは、Variant API を使用してバリアント出力を操作することができません)

## 解決策

- 修正前bulid.gradle

```gradle:build.gradle(before)
   applicationVariants.all { variant ->
        if (variant.buildType.name.equals("release")) {
            variant.outputs.each{ output ->
                if (output.outputFile != null && output.outputFile.name.endsWith('.apk')) {
                    output.outputFile = new File(output.outputFile.parent, "HelloWorld.apk")
                }
            }
        }
    }
```

- 修正後bulid.gradle

```gradle:build.gradle(after)
    android.applicationVariants.all { variant ->
        variant.outputs.all {
            outputFileName = "${variant.name}-${variant.versionName}.apk"
        }
    }
```

	
## 解説・参考サイト
https://developer.android.com/studio/build/gradle-plugin-3-0-0-migration

<hr>

#【問題】無効なJDKを参照している

## 起こりがちなエラー

```
Gradle sync failed: Could not determine java version from '9.0.1'. (1 s 411 ms)
```

```
The supplied javaHome seems to be invalid. I cannot find the java executable.
```

## 原因
<font color=red>無効(Android Studioおよびツールにとって)なJDKが指定されている</font>

## 解決策

Android Studioのメニューから **File>Project Structure>SDK Location**を選択して、**Use embedded JDK(recommended)**をチェックして有効にする。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/170905/8f0ee1d6-a57b-6732-1f86-99b542acf3e0.png)

<hr>

#【問題】Android SDK Tools が古い

## 起こりがちなエラー・警告

```
Android SDK Tools
Version 24.0.2 or later is required.
```

## 原因
<font color=red>Android SDK Toolsには、Android Emulator や ProGuard など、基本的なツールが含まれているが、これが現在の開発環境に対して古い。</font>

## 解決案
最新の Android SDK Toolsをインストールする。
- [SDK Manager経由でインストールする](https://developer.android.com/studio/intro/update#sdk-manager)
- Android Studio上からインストールする

## 解説・参考サイト
https://developer.android.com/studio/releases/sdk-tools
https://developer.android.com/studio/intro/update#sdk-manager

# まとめ
- 古い開発環境で作ったAndroidアプリプロジェクトを最新の開発環境に取り込もうとするときに発生しがちな事象と対策をまとめました。
- こういった作業はいつの時代にも必ず発生するコストなのであらかじめ見積もっておく（＋つきあう覚悟）のが良いようにおもいます。
- 1つずつ地道に対応してビルドが通ったときはとてもスッキリします。