WEB+DB Vol.88 のモバイル開発最前線のコードをCIに乗せる


[WEB+DB Vol.88](http://amzn.to/1fMT8BE)に、[Elixir](http://elixir-lang.org/)の特集があったんで読みたくて買ったわけなんですね。で、まぁElixirの特集もそれなりに面白く、またMQTTとかの特集も結構良かったんですが、他の特集で「モバイル開発最前線」というのがあって、これはAndroidの開発環境回りのお話だったので、チラッとやってみるかと思ったんですが、色々手こずったのでこちらにログを。
(ちなみにAndroidは出たばかりの頃にチラッとやっただけでほぼ初心者です)

## サンプルアプリケーション

[https://github.com/yanayanalte/SampleAndroid](https://github.com/yanayanalte/SampleAndroid)
まず記事で紹介されているサンプルアプリケーションはこちらです。

おもむろに ` git clone ` してコンパイルを試みますが

    git clone git@github.com:yanayanalte/SampleAndroid.git
    cd SampleAndroid
    ./gradlew assembleDebug
    
    :app:preBuild UP-TO-DATE
    :app:preDebugBuild UP-TO-DATE
    :app:compileDebugNdk UP-TO-DATE
    :app:checkDebugManifest
    :app:preReleaseBuild UP-TO-DATE
    :app:prepareComAndroidSupportAppcompatV72211Library
    :app:prepareComAndroidSupportSupportV42211Library
    :app:prepareComCrashlyticsSdkAndroidAnswers122Library
    :app:prepareComCrashlyticsSdkAndroidBeta112Library
    :app:prepareComCrashlyticsSdkAndroidCrashlytics232Library
    :app:prepareComCrashlyticsSdkAndroidCrashlyticsCore232Library
    :app:prepareIoFabricSdkAndroidFabric133Library
    :app:prepareDebugDependencies
    :app:compileDebugAidl
    :app:compileDebugRenderscript
    :app:generateDebugBuildConfig
    [Fatal Error] :22:27: 要素タイプ"android:value"に関連付けられている属性"{1}"には、開始引用符が必要です。
    
    FAILURE: Build failed with an exception.
    
    * What went wrong:
    Cannot read packageName from path/to/SampleAndroid/app/src/main/AndroidManifest.xml
    
    * Try:
    Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
    
    BUILD FAILED
    
    Total time: 16.873 secs

あえなく失敗します。
どうやら`AndroidManifest.xml`の`android:value`がイカンとのことなので調べますと、fabricのAPI KEYの設定のようです。


## Fabric

で、[Fabric](https://get.fabric.io/)。Twitterが開発しているモバイルの開発プラットフォームというかクラッシュレポートとかをよろしくやってくれるようですが、こいつのAPI KEYがイカンと。

[https://github.com/yanayanalte/SampleAndroid/blob/master/app/src/main/AndroidManifest.xml#L22](https://github.com/yanayanalte/SampleAndroid/blob/master/app/src/main/AndroidManifest.xml#L22)

「XXXXXXXXXXX」という設定になっています。
fabric自体がよくわからないので、色々ググって、まずどうにかしてAPI KEYを手に入れる事に専念するわけですが、fabricにサインアップしても設定画面などは一向に出てこない。
設定画面から取れるという情報もあるが、そもそも以下の画面しか出てこない。

[![Gyazo](https://i.gyazo.com/fcd913c8bdda3cd3969806752d3bee7f.png)](https://gyazo.com/fcd913c8bdda3cd3969806752d3bee7f)

ので、取り敢えずAndroid Studioにプラグインを突っ込む事にする。
ここでsafariとかでやってるとプラグインのzipを勝手に解凍してしまうので注意。
基本的にはfabricのページの手順に沿ってインストール。
するとAndroidのアイコンの横にfabricのアイコンが現れる。

[![Gyazo](https://i.gyazo.com/c9be0d4a6173deb608789d263e686e49.png)](https://gyazo.com/c9be0d4a6173deb608789d263e686e49)

ので、これをクリックしてサインインして進める。

そして、サンプルアプリケーションをAndroid Studioで開いた状態からこのプラグインを起動させて進めていくと、以下のようにインストールするkitを選べとなる。

[![Gyazo](https://i.gyazo.com/55f1ee38a95943f64afde8d09c9abb95.png)](https://gyazo.com/55f1ee38a95943f64afde8d09c9abb95)

CrashlyticのUpdateをクリックすると、

[![Gyazo](https://i.gyazo.com/88e8a00298140f937f74619645062df6.png)](https://gyazo.com/88e8a00298140f937f74619645062df6)

こんな感じでAPI KEYを変更するぜ、と言われるのでApplyボタン(キャプチャでは見切れてますが)を押すと`AndroidManifest.xml`が書き換わり、API KEYが取得できる。

    $ vi ./app/src/main/AndroidManifest.xml
    $ ./gradlew assembleDebug
    :app:preBuild UP-TO-DATE
    :app:preDebugBuild UP-TO-DATE
    :app:compileDebugNdk UP-TO-DATE
    :app:checkDebugManifest
    :app:preReleaseBuild UP-TO-DATE
    :app:prepareComAndroidSupportAppcompatV72211Library UP-TO-DATE
    :app:prepareComAndroidSupportSupportV42211Library UP-TO-DATE
    :app:prepareComCrashlyticsSdkAndroidAnswers122Library UP-TO-DATE
    :app:prepareComCrashlyticsSdkAndroidBeta112Library UP-TO-DATE
    :app:prepareComCrashlyticsSdkAndroidCrashlytics232Library UP-TO-DATE
    :app:prepareComCrashlyticsSdkAndroidCrashlyticsCore232Library UP-TO-DATE
    :app:prepareIoFabricSdkAndroidFabric133Library UP-TO-DATE
    :app:prepareDebugDependencies
    :app:compileDebugAidl UP-TO-DATE
    :app:compileDebugRenderscript UP-TO-DATE
    :app:generateDebugBuildConfig UP-TO-DATE
    :app:generateDebugAssets UP-TO-DATE
    :app:mergeDebugAssets UP-TO-DATE
    :app:generateDebugResValues UP-TO-DATE
    :app:generateDebugResources UP-TO-DATE
    :app:mergeDebugResources UP-TO-DATE
    :app:processDebugManifest
    Warning: /path/to/SampleAndroid/app/src/main/AndroidManifest.xml:25:1 Warning:
      Element uses-permission#android.permission.INTERNET at AndroidManifest.xml:25:1 duplicated with element declared at     AndroidManifest.xml:5:5
    /path/to/SampleAndroid/app/src/main/AndroidManifest.xml:25:1 Warning:
      Element uses-permission#android.permission.INTERNET at AndroidManifest.xml:25:1 duplicated with element declared at     AndroidManifest.xml:5:5
    :app:fabricGenerateResourcesDebug
    :app:processDebugResources
    :app:generateDebugSources
    :app:compileDebugJava
    注意:一部の入力ファイルは非推奨のAPIを使用またはオーバーライドしています。
    注意:詳細は、-Xlint:deprecationオプションを指定して再コンパイルしてください。
    :app:preDexDebug
    :app:dexDebug
    :app:processDebugJavaRes UP-TO-DATE
    :app:validateDebugSigning
    :app:packageDebug
    :app:zipalignDebug
    :app:assembleDebug
    
    BUILD SUCCESSFUL
    
    Total time: 38.731 secs

めでたくビルド成功。

## だがしかし

この企画はgithubにpushした上でのcircleCIでのビルドを前提としているはず。
API KEYをハードコーディングした状態でpushして良いはずがなかろう....。

ということで環境変数からうまく読み込む方法を調べる。

[http://stackoverflow.com/questions/25700680/crashlytics-found-an-invalid-api-key#answer-25704532](http://stackoverflow.com/questions/25700680/crashlytics-found-an-invalid-api-key#answer-25704532)

安定のStack Overflow。
build.gradleに

    manifestPlaceholders = [name: value]

とすれば

    ${name}

で`AndroidManifest.xml`から変数で読み込める模様。
今々ではFlavorは無視するので、`/app/build.gradle`の`defaultConfig`にこの`manifestPlaceholders`を突っ込みます。

あとは`build.gradle`はそもそもgradleなので、こいつに環境変数から値が渡ればOK。

[build.gradleからの環境変数の参照 - horie1024の日記](http://horie1024.hatenablog.com/entry/2015/03/16/155309)

こちらによれば、

    ORG_GRADLE_PROJECT_

がプレフィックスにつく環境変数は`build.gradle`からそのまま読み込める模様。
なので、

    $ export ORG_GRADLE_PROJECT_FABRIC_API_KEY="YOUR KEY"
    $ vi ./app/build.gradle
    
    defaultConfig {
        ....略....
        manifestPlaceholders = [fabricApiKey: FABRIC_API_KEY]
    }

    $ vi ./app/src/main/AndroidManifest.xml
    <meta-data
        android:name="io.fabric.ApiKey"
        android:value="${fabricApiKey}" />

というような感じにすればOK。
circleCIでも上記のような`ORG_GRADLE_PROJECT_FABRIC_API_KEY`のような環境変数を充ててやればOK。