Unity Android/iOSでFCMの処理を拡張する方法

# はじめに
Unityで、FirebaseCloudMessagingの処理をAndroid,iOSで拡張する機会があったので記事にざっくりまとめたいと思いました。
詳細なコード載せられないのと、必ずうまくいくとは言い切れないので要点だけまとめます。

# iOSの通知拡張について
iOSで通知に画像をつけるために色々対応する必要があるのですが、手順が複雑で、プロジェクトやビルド環境によってセットアップが変わってくるため、一概にこうすればうまくいきますと言えないので詰まったところだけまとめておきます。
結果的には通知に画像をつけることは可能でした。

## PostBuildProcessでiOSのXCodeプロジェクト設定

詳細なコードは載せられないので、大きく要点だけ...

大きく以下の追加が必要になります
- PBXProject.AddAppExtensionで通知拡張サービスの追加
    - 下に記載してあるinfo.plistも一緒に登録
- PBXProject.AddFileToBuildで拡張コードファイルの登録
- PBXProject.SetBuildPropertyでProvisionの設定等...

<details><summary>info.plistの中身</summary>

``` info.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
    <dict>
        <key>CFBundleDisplayName</key>
        <string>NotificationService</string>
        <key>CFBundleExecutable</key>
        <string>$(EXECUTABLE_NAME)</string>
        <key>CFBundleIdentifier</key>
        <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
        <key>CFBundleName</key>
        <string>$(PRODUCT_NAME)</string>
        <key>NSExtension</key>
        <dict>
            <key>NSExtensionPointIdentifier</key>
            <string>com.apple.usernotifications.service</string>
            <key>NSExtensionPrincipalClass</key>
            <string>NotificationService</string>
        </dict>
    </dict>
</plist>
```
</details>

使用したプロパティ名まとめておきます

**追加のplistプロパティ**
上のinfo.plistにC#側から追加でプロパティ追加しました
|名前|説明|
|---|---|
|CFBundleShortVersionString|PlayerSettings.bundleVersionを設定|
|CFBundleVersion|PlayerSettings.iOS.buildNumberを設定|

**ビルドプロパティ**
|名前|説明|
|---|---|
|IPHONEOS_DEPLOYMENT_TARGET|PlayerSettings.iOS.targetOSVersionStringを設定詳細は後述|
|PROVISIONING_PROFILE_SPECIFIER|ProvisioningProfileの名前|
|CODE_SIGN_IDENTITY|ProvisioningProfileの"iPhone Distribution: ***Corporation"な感じのやつ|
|DEVELOPMENT_TEAM|ProvisioningProfileの開発チーム名|
|CLANG_ENABLE_MODULES|YESにしました|
|TARGETED_DEVICE_FAMILY|"1,2"　iPhoneとiPad|
|ARCHS|"$(ARCHS_STANDARD)"に設定しました|
|ENABLE_BITCODE|"NO"に設定しました|

## BuildPhaseの順番を変えないとビルドが通らない
Unityビルド時にこのあたりのカスタマイズする方法がないので、UnityForumを参考に無理やり順番を変えました。

https://forum.unity.com/threads/xcode-15-cycle-inside-unity-iphone-building-could-produce-unreliable-results.1496747/

Crashlyticsをプロジェクトに入れていたので、このあたりの相性が悪かったみたいです。

## Podファイル無理やりいじらないとFirebaseのUtility処理が使えない

https://firebase.google.com/docs/cloud-messaging/ios/send-image?hl=ja

にある

```
FIRMessaging extensionHelper
```

を呼び出すために

```
#import "FirebaseMessaging.h"
```

が必要なのでPodファイルに

```
target 'NotificationService' do
    pod 'GoogleUtilities/AppDelegateSwizzler'
    pod 'GoogleUtilities/MethodSwizzler'
    pod 'GoogleUtilities/Network'
    pod 'GoogleUtilities/NSData+zlib'
    pod 'GoogleUtilities/AppDelegateSwizzler'
    pod 'GoogleUtilities/Environment'
    pod 'GoogleUtilities/Logger'
    pod 'GoogleUtilities/UserDefaults'
    pod 'GoogleUtilities/Reachability'
    pod 'Firebase/Messaging'
end
```

を追記する必要がありましたが、Unityで拡張したターゲットのパッケージを設定する方法が見当たらなかったので、ビルドのシェルスクリプト内で無理やり追加しました。

Firebase/Messagingだけだとビルドが通らず、GoogleUtilities/*を追記すれば通るぜという情報を見つけたので追加したらうまくいきました。

(無理やり編集したときはpod install実行必要です)

## TargetMinimumiOSVersionを合わせる

思わぬ落とし穴でした。
Unityで設定している、TargetMinimumiOSVersionと自前で追加したTargetのバージョンが異なると、拡張が有効になりません。
以下のようにして、同じバージョンを指定することができます。

```csharp
project.SetBuildProperty(extensionGuid, "IPHONEOS_DEPLOYMENT_TARGET", PlayerSettings.iOS.targetOSVersionString);
```

# Android通知拡張について
Firebaseが用意している処理で良ければ特に拡張する必要はなく、セットアップがしっかりできていれば画像付き通知も問題なくでます。
しかし、今回拡張が必要になった理由が、通知を展開した時に画像が大きく表示されるのをやめたかったからです。
画像を大きく表示するのではなくて、テキスト全文を表示するということがやりたいことでした。
SDK側で用意してほしい...

iOSと比べて手順はシンプルなので書いていきます。
(セットアップが終わっていて、通知が確認できる状態になっているの前提で話を進めます)

## AndroidManifest.xmlにサービスを追加

```xml
    <application>
        <!-- カスタム Firebase Messaging Service を有効化 -->
        <service android:name="[アプリID].CustomFirebaseMessagingService" android:exported="false">
            <intent-filter>
                <action android:name="com.google.firebase.MESSAGING_EVENT"/>
            </intent-filter>
        </service>
    </application>
```

アプリIDは、com.example.appみたいな感じのやつです

## FirebaseMessagingServiceを拡張したファイルを追加
Assets/Plugins/Androidあたりに以下のjavaファイルを追加

```CustomFirebaseMessagingService.java
package com.example.app;

import com.google.firebase.messaging.FirebaseMessagingService;
import android.content.Intent;

public class CustomFirebaseMessagingService extends FirebaseMessagingService {
    @Override
    public void handleIntent(Intent intent) {
        // 通知が届いた時に呼ばれる
        // 拡張したい処理を書く
    }
}
```

本家の処理を参考にコピペしつつ変えたい部分だけを変えて拡張していきました。
しかし、SDKのクラスに外からアクセスできないものがあるので工夫が必要です。

https://github.com/firebase/firebase-android-sdk/blob/master/firebase-messaging/src/main/java/com/google/firebase/messaging/FirebaseMessagingService.java

実際の通知UI表示部分はこちらを参考にしました

https://developer.android.com/develop/ui/views/notifications/expanded?hl=ja

補完が効かない環境でjavaを書くのは大変なので、一度プロジェクトをエクスポートしてAndroidStudioで開いて編集することをおすすめします。

# 最後に
プッシュ通知拡張は対応が大変な割には見た目の変化はそこまでなく、コスパの悪い対応でした。
情報も断片的なものはありますが、少なかったです。
しかし、一度対応ができれば２回目の対応はそこまで大変ではないと思います。
本記事がプッシュ通知拡張の手助けになれば幸いです。