XamarinでFirebaseを使ってみる（Android版）

iOS版に引き続き今回はAndroidで試してみようと思います．
iOS版で触れたFirebaseのサービスに関することは省略している箇所がいくつかあるので，iOSの方も併せてご覧ください．
(iOS版はこちら)http://qiita.com/yamachu/items/cee6104ac579ea657deb


## XamarinのAndroidへのFirebaseの対応状況
本記事を書いている2016年11月4日現在，pre-release版ですがBindingライブラリが提供されています．
例えば

* アプリケーション分析の [Xamarin Firebase - Analytics](https://www.nuget.org/packages/Xamarin.Firebase.Analytics/32.940.0-beta3)
* Push通知などに利用する [Xamarin Firebase - Messaging](https://www.nuget.org/packages/Xamarin.Firebase.Messaging/32.940.0-beta3)

開発は [xamarin / GooglePlayServicesComponents](https://github.com/xamarin/GooglePlayServicesComponents/)で進められています．
現在最新が 32.961.0-beta1 ですが，依存でベータ版のsupport libraryを要求してくるので， 32.940.0-beta3 を対象に進めていきたいと思います．
Android版は特につまづく点もなく，ちょっとしたXamarin Studioのバグだったりがある程度なので，気楽にいきましょう．

## 実際に試してみる
それでは実際に試してみましょう．
以下紹介するコードなどは筆者のリポジトリの [yamachu / TryFirebaseXamarin](https://github.com/yamachu/TryFirebaseXamarin) に対応しています．

適当にXamarin.FormsまたはAndroidでプロジェクトを作ったらnugetで上記のライブラリを導入します．
nugetのマネージャで`Show pre-releases packages`のチェックが必要となるので注意してください．

その後 Firebase にアクセスしてプロジェクトを作成し，そのプロジェクトにAndoirdアプリを追加します．その時にアプリのPackage nameが必要となりますので，先ほど作ったXamarinのプロジェクトの`Properties/AndroidManifest.xml`あたりから引っ張ってきてください．
Firebaseのプロジェクトの作り方はiOSと特に変わりがないため，必要であれば前の記事や，そのリンクを参照してください．

アプリケーションの追加が完了するとアプリケーションに対応した`google-services.json`という設定ファイルがダウンロードできますので，それをダウンロードした後，Androidのプロジェクトに追加します．その後追加したファイルを右クリックしてBuild Action -> GoogleServicesJson と選択しチェックします．この時多くの場合GoogleServicesJsonという項目がありません．
その時は一度AndroidのプロジェクトをUnloadし，Reloadすると選択できるようになります．IDEの再起動が高速で出来るようなマシンをお持ちの方はエディタごと再起動してしまってもいいかもしれません．

これでFirebaseを利用する準備は大体揃いました，それではコードを書いていきましょう．

### Analyticsを試す
[Analytics向けのブランチのMainActivity.cs](https://github.com/yamachu/TryFirebaseXamarin/blob/Android/Analytics/Droid/MainActivity.cs#L29)
Analyticsは非常に試すのが簡単で，上記のリンク先のファイルのように`OnCreate`内で
`FirebaseAnalytics.GetInstance(this);`
を呼び出せば概ね初期化は完了です．
`FirebaseAnalytics.GetInstance`の戻り値は`FirebaseAnalytics`なので，MainActivityかどこかにフィールドを宣言し，そこに代入しておくと良いでしょう．
私はシングルトンのマネージャクラスを作って，そこに宣言しました．
https://github.com/yamachu/TryFirebaseXamarin/blob/sample/custom_event_service/Droid/Managers/FirebaseInstanceManager.cs

あとはこのインスタンスに対して`LogEvent`などを呼び出せばカスタムログなどを取得することができます．

    firebaseAnalytics = FirebaseAnalytics.GetInstance(this);
    Bundle bundle = new Bundle();
    bundle.PutString("Open_ID", "1234");
    // Send custom event
    firebaseAnalytics.LogEvent("PageID", parameters);

のようにユーザ定義をBundleで囲んでしまえば使用することができます（イベント名だったり数などに制限があるためドキュメントを参照してみてください）．

iOS版でも触れましたが，

* Analyticsのリアルタイム性がない
* Analyticsの数値は見れるけど，実際送られてきた値を見るには従量課金性のプランに移行しBigQueryに流す必要がある

という欠点もあります．
この記事を書いている時カスタムイベントの情報がまだBigQueryに流れ込んでません，いつになるのやら...
追記:2016/12/12
約１ヶ月経過しましたが，サンプルで作ったプロジェクトのイベントが送られてきていません（涙
追記終わり


### Cloud Messagingを試す
[Cloud Messaging向けのブランチのMainActivity.cs](https://github.com/yamachu/TryFirebaseXamarin/blob/Android/CloudMessaging/Droid/MainActivity.cs)
~~つまづく点なんて無いと言ったな，あれは嘘だ~~
本番プロダクトでは気付かず，この記事を書くために再度実装して気づいたことがありました．

__DebugビルドとReleaseビルドで挙動が違う__

めちゃくちゃつらかったですね，毎回アプリをアンインストールしてからデバイスに流し込むということをしていて気がつきませんでした．
それはともかくコードをどうぞ．

    // Debugビルドだと以下のようにDeleteInstanceId()を呼んでInstanceIdをリフレッシュしないと再起動後通知が受け取れない
    // Releaseビルドだと以下の作業は不要でSubscribeするだけでそのトピックへの通知を受け取ることができる
    #if DEBUG
			Task.Run(() =>
			{
				var instanceID = FirebaseInstanceId.Instance;
				instanceID.DeleteInstanceId();
				var iid1 = instanceID.Token;
				var iid2 = instanceID.GetToken(GetString(Resource.String.gcm_defaultSenderId), Firebase.Messaging.FirebaseMessaging.InstanceIdScope);
				FirebaseMessaging.Instance.SubscribeToTopic("all");
			});
    #else
			FirebaseMessaging.Instance.SubscribeToTopic("all");
    #endif			

~~こんなん気づくかよ...~~
Issueを見ていたらTask句を入れたら動いたぜ！みたいなコメントが残されていて，これが正しいものと思い込んでいたのですが，実際チャットアプリなどを作りたいとかなったときにInstanceIdが起動ごとに変わってしまっては使いづらいったらありゃしないわけでして，検証していたらReleaseビルドだとTask句内の処理が不要でした．

この他に，InstanceIdが変更された時にそれを受け取るサービスである `FirebaseInstanceIdService`を継承したサービスの実装や，フォアグラウンド状態で通知を受け取った時にそのデータを受け取るサービスである `FirebaseMessagingService`を継承したサービスの実装が必要となります．
https://github.com/yamachu/TryFirebaseXamarin/tree/Android/CloudMessaging/Droid/Services

またサービスをBroadcast ReceiverをAndroidManifest.xmlなどに記述する必要があるので，そのあたりも忘れないように行いましょう．


ここまで実装を行うと通知を受信することができるので，実際にテストしてみましょう．今回もcurlを仕様しました．

    curl --header "Authorization: key=YOUR_SERVER_KEY" \       
         --header Content-Type:"application/json" \
         https://fcm.googleapis.com/fcm/send  \
         -d "{\"to\": \"/topics/all\",\"priority\":\"high\",\"notification\": {\"title\": \"Azure以外でも使えるよ！\",\"body\": \"Xamarin x Firebase\",\"icon\": \"icon_for_notification\", \"color\": \"#ff0055\"}}"

みたいに送ると通知を送ることができます．ここでの`YOUR_SERVER_KEY`はFirebaseのプロジェクトの設定のクラウドメッセージングタブにあるサーバーキーを指します．
またこの通知はアプリケーションが一度でも /topics/all を[Subscribe](https://github.com/yamachu/TryFirebaseXamarin/blob/Android/CloudMessaging/Droid/MainActivity.cs#L41)している必要があります．

Android版では通知に表示するアイコンや，バックグラウンドの色を指定することができます．詳しくは[公式ドキュメント](https://firebase.google.com/docs/cloud-messaging/http-server-ref)をご覧ください．
[Android 5系以上だとアイコンが白くなる問題](http://qiita.com/syarihu/items/95788cbab9b63100c4fb)が発生したりで本番環境では苦労したこともありました．


## 最後に
簡単に導入部と実際の使い方について紹介しました．
AnalyticsやCloud Messaging以外にもCrashReportやDatabase,Authenticationについてもラップされている雰囲気があるので，是非とも試してみてください．
今回使用したしたソースコードなどは[公式リポジトリ](https://github.com/xamarin/GoogleApisForiOSComponents)のサンプルを一部流用しているため，元のソースであったり，随時修正されるドキュメントも確認してみてください．

またサンプルとして，ボタンを押したらカスタムイベントを送るような Android/iOS のインターフェースを実装したサンプルを用意してみましたので，そちらも参考にしていただければと思います．
https://github.com/yamachu/TryFirebaseXamarin/tree/sample/custom_event_service

以上お疲れ様でした．