Unity IAP v1.9.2 を使うと、Android で ActivityNotFoundException が起きることがある件について

# はじめに

この記事は [Unity Advent Calendar 2016](http://qiita.com/advent-calendar/2016/unity) の9日目の記事になります。

通称 (？) **ビルドおじさん** として Unibook を執筆させていただいたり、勉強会で発表させていただいたりしている関係から、「今年はビルドネタを書こう！」と思っておりました。
そんな矢先に [本業](https://www.kidsstar.co.jp/) のほうで開発しているプロダクトで表題の問題が発生したため、渡りに船ってコトで本記事を執筆するに至っております。

# 結論

出力された Android Project の `AndroidManifest.xml` の `application` ノードの下に以下のノードを追加しましょう。

```xml
<activity
        android:name="com.unity.purchasing.googleplay.PurchaseActivity"
        android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen"
        android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen" />
```

`manifest` &gt; `application` &gt; `activity` ってな関係になっていれば OK！
元々ある `activity` ノードの直下にでも書けば良いんじゃないかな？

# 環境

* OS: OS X El Capitan 10.11.6
* Unity: 5.3.6p6
    * **Unity IAP v1.9.2**
* gradle: 2.10
* Java: 1.8.0_66

# 前提

* Unity からの出力は APK ビルドではなく、 `Export Project` にて実行
* [PostProcessBuild](https://docs.unity3d.com/ja/current/Manual/BuildPlayerPipeline.html) にて `build.gradle` ファイルを出力先に配置しつつ、 `gradle` コマンドをキック

# 現象

`AndroidManifest.xml` に手を入れずに gradle コマンドでビルドしてあげると、ビルド自体は成功する。
が、実際に課金処理を実行しようとすると以下のような Exception を吐いて課金処理が実行されない。

```
I/Unity: AndroidJavaException: android.content.ActivityNotFoundException: Unable to find explicit activity class {$ProjectPackageName$/com.unity.purchasing.googleplay.PurchaseActivity}; have you declared this activity in your AndroidManifest.xml?
```

※ `$ProjectPackageName$` んトコは、実際のプロダクトのパッケージ名が入る。

実際に `aapt` コマンドでビルドされた APK をチェックしてみても、そのような Activity は定義されていない。

```
$ aapt dump xmltree path/to/APK.apk AndroidManifest.xml
```

# 原因

gradle を使ってビルドする際に、 `AndroidManifest.xml` のマージが巧いこと行われなくなってしまったコトが原因っぽい。
もう少し詳しく書くと、出力先のディレクトリにプロジェクト本体とは別に Unity IAP によって生成される `GoogleAIDL`, `GooglePlay`, `common` とかのディレクトリが出力されているが、その中にある `AndroidManifest.xml` がマージされていない。
元々は `.aar` ファイルが配置されてた、とかだったのかな…？覚えてないけど。
少なくとも Unity IAP v1.9.0 の時点では、ヨシナにマージされていた模様。

# 対処

本当は、 `build.gradle` とかを修正するコトで対応したかったが、どうやっても `GooglePlay` とかのディレクトリをプロジェクトとして認識させることが出来なかった。
仕方が無いので、 `GooglePlay/libs/` 以下の `jar` ファイルを `dependencies` に追加して、 `AndroidManifest.xml` を手修正するコトにした。
(もっと gradle について勉強しないとダメだな…。)

`build.gradle` は以下のような感じになった。

```build.gradle
// (前略)

allprojects {
    repositories {
        mavenCentral()
        maven { url 'file://' + new File(System.getProperty('user.home'), '.m2/repository').absolutePath }
        flatDir {
            dirs '__APP_NAME__/libs'
        }
    }
}

apply plugin: 'com.android.application'

android {
    // (中略)

    dependencies {
        compile fileTree(dir: '__APP_NAME__/libs', include: '*.jar')

        // unity の classes.jar は Maven のローカルリポジトリに突っ込んでおく
        compile 'com.unity3d:unity3d:__UNITY_VERSION__'

        // この辺は mavenCentral にある…んだと思う
        compile 'com.android.support:support-v4:23.0.+'
        compile 'com.google.android.gms:play-services:6.5.87'

        // ↓がポイント
        compile fileTree(dir: 'common/libs', include: '*.jar')
        compile fileTree(dir: 'GoogleAIDL/libs', include: '*.jar')
        compile fileTree(dir: 'GooglePlay/libs', include: '*.jar')
    }

    // .aar ファイルが配置されなくなったので意味無いけど、一応書いておく
    fileTree(dir: '__APP_NAME__/libs', include: '**/*.aar').each { File file ->
        dependencies.add("compile", [name: file.name.lastIndexOf('.').with { it != -1 ? file.name[0..<it] : file.name }, ext: 'aar'])
    }
}
```

# おわりに

そんなわけで、直近でドハマりした事象をまとめてみました。
「こんな方法で `AndroidManifest.xml` マージできるよ！」とか「この `build.gradle` を書いたのは誰だぁっ！」とか「 [monry さんの会社](https://www.kidsstar.co.jp/) に興味あるんで、遊びに行きたい！」とかあれば、コメ欄なり [Twitter](https://twitter.com/monry) なり [Facebook](https://www.facebook.com/monry84) なりでドシドシどうぞ！

明日の [Unity Advent Calendar 2016](http://qiita.com/advent-calendar/2016/unity) は、 @lycoris102 さんの「[GO MAPの世界におもむろに雨とか雪とか降らす](http://qiita.com/lycoris102/items/a6ddc468575b624b2630)」です！