Xamarin.FormsにFirebase Analytics 実装（iOS）

# はじめに
本記事はXamarin Advent Calendar 2018の11日目として、Xamarin.FormsでFirebase Analyticsの実装（iOS）を紹介します。

# 環境
Visual Studio for Mac ver7.6.9
Xamarin.Forms
ターゲットフレームワーク：PCL

## プロジェクトの作成
[Firebase Consoleのトップページ](https://console.firebase.google.com/)から、新規プロジェクトを作成します。 
※[Google Cloud Platform のプロジェクト指定](https://support.google.com/firebase/answer/6399760)できるようです。
Firebase を使い始めるには、ひとまずプロジェクトを作成するだけでOKです。

## iOS アプリへの導入
### アプリにFirebaseを追加
1.新規プロジェクト作成後、トップページにある「アプリにFirebaseを追加して利用を開始しましょう」から設定手順に沿って操作します。Bundle IDが必要となりますので、XamarinのプロジェクトのInfo.plistから取ってきます。

<img width="638" alt="スクリーンショット 2018-12-10 18.21.00.png" src="https://qiita-image-store.s3.amazonaws.com/0/100644/4c8f9587-97a7-4c83-4506-fb62c8b03a4f.png">
2. 設定が終わると`GoogleService-Info.plist` がダウンロードできます。
このPlistファイルをiOSプロジェクトのinfo.plistファイルと同じ場所に追加します。
3. 追加したファイルを右クリックして, ビルドアクション -> BundleResource と選択しチェックします。
<img width="595" alt="スクリーンショット 2018-12-10 18.43.52.png" src="https://qiita-image-store.s3.amazonaws.com/0/100644/a0b4cec4-9ba4-7341-3e9f-2eef20ae1301.png">
4. `GoogleService-Info.plist`内の`IS_ANALYTICS_ENABLED`の`NO`となっている部分をYESに書き換えます。
<img width="445" alt="スクリーンショット 2018-12-10 18.50.13.png" src="https://qiita-image-store.s3.amazonaws.com/0/100644/a5066687-ca4b-9fd0-a770-fcf1dee50b9c.png">

### nuget packagesを追加
「パッケージの追加」から以下のパッケージを追加します。
<img width="346" alt="スクリーンショット 2018-12-10 18.23.53.png" src="https://qiita-image-store.s3.amazonaws.com/0/100644/a22f56a2-3080-35c1-fd8b-ac267c22d7f3.png">

 - Xamarin.Firebase.iOS.Analytics
 - Xamarin.Firebase.iOS.Core
 - Xamarin.Firebase.iOS.InstanceID

### アプリで Firebase を初期化する
AppDelegate.csのFinishedLaunchingで、コンポーネントを初期化します。

```
// Firebase component initialize
Firebase.Core.App.Configure();
```
※最初は　`base.FinishedLaunching`　の直前で初期化していたのですがビルドすると`Event not logged. Call +[FIRApp configure]`のエラーが出てしまいました。どうやら`Firebase.Core.App.Configure();`を呼ぶ所がダメらしいのでFinishedLaunchingの最初の方で呼ぶようにしました。

これでFirebaseが標準で定めているイベントに関して取得できるようになりました。
※一度ビルドしてみてビルドができなかったら以下をやってみてください。
1. iOSのプロジェクトのオプションを開く
2. iOSビルドの中の「インクリメンタルビルドを有効にする」のチェックを外す

## カスタムイベントを取る場合
カスタムイベントを取る場合はイベントを保存するための "LogEvent"メソッドを使うのですが、パッケージがPCLに対応していないのでプラットフォーム固有機能を呼ぶようにインターフェースを作ります。

```
using System;
using System.Collections.Generic;
using System.Text;
using Firebase.Analytics;
using Firebase.Core;
using Foundation;
using sumple.iOS;
using Xamarin.Forms;

[assembly: Dependency(typeof(AnalyticsServiceIOS))]
namespace sumple.iOS
{
    public class AnalyticsServiceIOS : IAnalyticsService
    {
        public void LogEvent(string eventId)
        {
            LogEvent(eventId, (IDictionary<string, string>)null);
        }

        public void LogEvent(string eventId, string paramName, string value)
        {
            LogEvent(eventId, new Dictionary<string, string>
            {
                { paramName, value }
            });
        }

        public void LogEvent(string eventId, IDictionary<string, string> parameters)
        {
            if (parameters == null)
            {
                foreach (var item in parameters)
                {
                    new Dictionary<object, object>().Add(item.Key, item.Value);
                }
                Analytics.LogEvent(eventId, new Dictionary<object, object>());
                return;
            }

            var keys = new List<NSString>();
            var values = new List<NSString>();
            foreach (var item in parameters)
            {
                keys.Add(new NSString(item.Key));
                values.Add(new NSString(item.Value));
            }

            var parametersDictionary =
                NSDictionary<NSString, NSObject>.FromObjectsAndKeys(values.ToArray(), keys.ToArray(), keys.Count);
            Analytics.LogEvent(eventId, parametersDictionary);
        }
    }
}
```

PCLのカスタムイベントを取りたい場所に以下のコードをセットします。

```
 var an = DependencyService.Get<IAnalyticsService>();
 IDictionary<string, string> dic = new Dictionary<string, string>();
 string {EventId(変数)} = "{id}";
 string {EventValue(変数)} = "{value}";
 dic.Add(EventId, EventValue);
 an.LogEvent("{eventInfo}", dic);
```

ビルドして操作してみるとセットしたイベントがFirebaseコンソールにて確認できます。
※ ただし、コンソールにはすぐに反映されません。だいたい翌日にはコンソールにてイベントが確認できます。

# まとめ
Xamarinをやり始めて１年も経っていないのでとにかく調べまくりなんとか実装しダッシュボードにも反映されイベントもちゃんと取れるようになりました。本当はAndroidも書こうと思いましたが、書いているうちにすごく長くなったので、今回はiOSだけでAndroidは分けて書くことにしました。また、近いうちにAndroid版を書きます。Xamarin初心者なので記事内容に誤りがあれば教えてください。よろしくお願いします。

# 参考文献
[Firebase を iOS プロジェクトに追加する](https://firebase.google.com/docs/ios/setup)
[XamarinでFirebaseを使ってみる（iOS版）](https://qiita.com/yamachu/items/cee6104ac579ea657deb)
[FirebaseでFirebaseApp.configure()の位置で躓いた時](https://qiita.com/nakagawa1017/items/44d206c2d4bee8511818)
[Xamarin.FormsでPrism.Formsを使ってPCLに非対応なライブラリを使う方法](https://blog.okazuki.jp/entry/2016/12/09/092052)
[Firebase Analyticsでログを取得する（iOS）](https://qiita.com/kazu14m1/items/3da746522ec41a8d5d2c)
[Firebase Analytics in Xamarin Forms](https://stackoverflow.com/questions/48774378/firebase-analytics-in-xamarin-forms)