脱・初心者のためのAndroidのGradle設定


## とりあえずアプリは作れるけど、、、
androidアプリからプログラミングを初めて、ある程度アプリは作れるようにはなった。
で、いろいろやってると

- debug版とrelease版を同時に端末に入れたい
- AndroidManifestをdebugとreleaseで分けたい
- apkをストアに上げる度に、同じversionCodeが存在しますエラー食らう

ってな思いが出てきます。
これらは、初心者用の教科書とかには載っていないけど、実際開発やってると、結構重要だったりすると思います。

デバッグ版とリリース版が実機内に両立できない問題は、片方をアンインストールしてもう一方をインストールとかやってると、結構めんどくさいです。

同じく、versionCode問題も、手動で出来るっちゃできるんだけど、それって面倒だし、ダサい。

って具合の、問題とまではいかないけれど、初心者だから甘んじてしまう面倒を、解消するためのメモです。
## debug版とrelease版を同一端末内に共存させたい

まず、プロジェクト作製時のapp/build.gradleがこんな感じ。

```groovy:build.gradle
apply plugin: 'com.android.application'

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.1"

    defaultConfig {
        applicationId "com.exercise.sample"
        minSdkVersion 15
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.1.0'
    compile 'com.android.support:design:23.1.0'
}
```

今回いじるのは、buildTypes

```groovy:build.grale
buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
        debug {
            applicationIdSuffix '.debug'
            versionNameSuffix 'd'
        }
    }
```

こんな感じにします。
applicationIdSuffixってのは、debug版のapplicationIdの接尾辞ってことね。要はお尻に.debugってつけてね、ってGradleさんにお願する訳です。
versionNameSuffixも同じ。ただ、applicationIdの方はidだから、勝手に書けない（たぶん、ピリオドと英数字だけ。たぶんね。違ったら教えてください）けど、versionNameの方はいろいろ自由。
たぶんね。

![Screenshot_20151102-213843.png](https://qiita-image-store.s3.amazonaws.com/0/75088/a92ed079-48eb-daf0-1b7a-36b133b62129.png "Screenshot_20151102-213843.png")

で、こんな具合に共存できても、見分けつかないとやだ。
ってんで次。
## AndroidManifestをdebug, releaseで分ける

アイコンとアプリ名くらいは、debug,　releaseで分けたい。
で、それってAndroidManifestをそれぞれで使い分けたいってことですよね。
ここでは、

app/src/debug/AndroidManifest.xml
app/src/release/AndroidManifest.xml

を自分で作成して、デフォルトでAndroid Studioが用意してくれる

app/src/main/AndroidManifest.xml

にビルド時にマージしてもらいましょう。
その際、debugビルド時ならdebug配下の、releaseならrelease配下のAndroidManifestを、Gradleが勝手にマージしてくれます。

今言ったように、mainのAndroidManifestに、各AndroidManifestをくっつけてくれる訳ですから、新たに作成するdebug/AndroidManifest, release/AndroidManifestには、書き分けたいとこだけを書けばいいんです。

あるpermissionを、デバッグ時には欲しいけどリリース版では要らないんだよねーってのも、この方法で解決できるかと思います。
例えば、deployGateのSDKで、ログをリモートで取得することができますが、debug版でだけpermissionタグを書いておけば、毎度リリース版ビルドの度にこの部分を削除しなくて済みます。
https://deploygate.com/docs/sdk

現状のmain/AndroidManifestはこんな感じ。

```xml:main/AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.exercise.sample.debug"
    android:versionCode="1"
    android:versionName="1.0d" >

    <uses-sdk
        android:minSdkVersion="15"
        android:targetSdkVersion="23" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.exercise.sample.MainActivity"
            android:label="@string/app_name"
            android:theme="@style/AppTheme.NoActionBar" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
```
アプリ名は、applicationタグの、labelってとこで指定してます。アイコンも変えた方がいいでしょうから、

```xml:src/main/AndroidManifest.xml
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
```
の部分だけ削除します。

で、appフォルダにdebug用、release用のフォルダを作成し、その中に新しくAndroidManifest.xmlファイルを作り、以下のように書きます。

```xml:src/debug/AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.exercise.sample" >

    <application
        android:icon="@color/colorPrimary"
        android:label="@string/debug_app_name">
    </application>
</manifest>
```

```xml:src/release/AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.exercise.sample" >

    <application
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name">
    </application>
</manifest>
```
アイコン作るの面倒なんで、debug版ではcolorPrimaryにしてます。
で、これでOKだと思ってたんですけど、applicationタグのandorid:labelって、ランチャーの名前ではないようでした。
設定画面とかで表示される名前ではあるんですけど、、、

よくわかんないけど、ここでは深入りせずに、main/AndroidManifest.xmlのMainActivityからlabelを削除しましょう。

```xml:src/main/AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.exercise.sample" >

    <application
        android:allowBackup="true"
        android:supportsRtl="true"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:theme="@style/AppTheme.NoActionBar" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
```
はい、こんな感じ。

![Screenshot_20151102-224533.png](https://qiita-image-store.s3.amazonaws.com/0/75088/bbd4d5b0-c759-3b5b-abf4-9003f0df8b22.png "Screenshot_20151102-224533.png")
## versionCodeのincrement

GooglePlayにいよいよ上げようって時に、リリース版でいろいろいじってたらバグみっけて、直してもっぺん署名付きリリース版ビルドしてよしOK!ってなってストアにapkアップロードしたら、同じバージョンコードのapkが存在します、ってなってうあああああ、ってなりながら再ビルド

ってなことよくあると思います。
そんな時にうあああああああああってならないために、Gradleにバージョンコードを毎度1ずつ足してもらいましょう。
おなじみapp/build.gradleです。

```groovy:app/build.gradle
import java.util.regex.Pattern

apply plugin: 'com.android.application'

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.1"

    task('incrementVersionCode') << {
        // AndroidManifest.xmlを取得
        def manifestFile = file("src/release/AndroidManifest.xml")
        def manifestText = manifestFile.getText()
        // versionCodeの記述を探す
        def pattern = Pattern.compile("versionCode=\"(\\d+)\"")
        def matcher = pattern.matcher(manifestText)
        matcher.find()
        def versionCode = Integer.parseInt(matcher.group(1))
        // AndroidManifest.xmlの記述を更新
        def manifest = matcher.replaceAll("versionCode=\""
                + ++versionCode + "\"")
        manifestFile.write(manifest)
    }

    tasks.whenTaskAdded { task ->
        if (task.name == 'generateReleaseBuildConfig') {
            task.dependsOn 'incrementVersionCode'
        }
    }

    defaultConfig {
        applicationId "com.exercise.sample"
        minSdkVersion 15
        targetSdkVersion 23
        versionName "1.0"
    }
    // ~~ 省略 ~~
}
```
読めばだいたいわかるんですけど、releace/AndroidManifest.xmlからversionCodeの記述を探してきて、それをインクリメントして書きなおす、って感じね。

でもversionCodeなんてAndroidManifestに書いてないよって？じゃあ書きましょう。

```xml:/release/AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.exercise.sample"
    android:versionCode="1">

    <application
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name">
    </application>
</manifest>
```

これで、リリース版をビルドする度にここのversionCodeがインクリメントされていきます。
あ、defaultConfig内のversionCodeを削除するのを忘れないでください。
本来、versionCodeは、AndroidStudioだとbuild.gradleが管理してるんですけど、この方法だと、AndroidManifest.xmlに持たせてるんで、build.gradle内にもversionCodeがあると競合してしまうので。

署名付きapkを作成する度に更新されていくversionCodeを見ると、かわいいですよ。

まだまだペーペーなんでここはこうせい！みたいなのいただけると嬉しいです。
よろしくお願いします。