64
69

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Last updated at Posted at 2015-11-02

とりあえずアプリは作れるけど、、、

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

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

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

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

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

って具合の、問題とまではいかないけれど、初心者だから甘んじてしまう面倒を、解消するためのメモです。

debug版とrelease版を同一端末内に共存させたい

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

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

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

で、こんな具合に共存できても、見分けつかないとやだ。
ってんで次。

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はこんな感じ。

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ってとこで指定してます。アイコンも変えた方がいいでしょうから、

src/main/AndroidManifest.xml
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"

の部分だけ削除します。

で、appフォルダにdebug用、release用のフォルダを作成し、その中に新しくAndroidManifest.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>
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を削除しましょう。

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

versionCodeのincrement

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

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

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に書いてないよって?じゃあ書きましょう。

/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を見ると、かわいいですよ。

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

64
69
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
64
69

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?