XamarinでFirebaseを使ったリアルタイムチャットの原形を作ってみた with FireSharp


Firebaseがとてつもなく便利、という話を聞いて、Xamarinから触ってみることにしました。iOSネイティブでもAndroidネイティブでもJSでもなくXamarin、という流れに、かなり回り道な感がありますが、Xamarinへの愛があればなんてことないよね。


## Firebaseの設定

そういう訳で、まずはFirebaseの設定から。Firebaseのアカウントを作って、最初のプロジェクトを作ると、こんなページが表示されます。この例ではプロジェクトの名前を「xamarin-chat-sample」としました。

![Firebase_Console.png](https://qiita-image-store.s3.amazonaws.com/0/5877/2356d677-2f93-84ec-3b1b-081577918665.png "Firebase_Console.png")


### データベースへのアクセスキーの取得

まずはデータベースにアクセスするためのキーを取得します。あとでデータベースへのアクセス時に利用するので、控えておいてください。

左上の設定アイコンから「プロジェクトの設定」を選択し、

![Firebase_Console.png](https://qiita-image-store.s3.amazonaws.com/0/5877/e82aaae2-fce8-4735-cba2-050078750a99.png "Firebase_Console.png")

「データベース」タブを選択し、●印で隠れているトークンの場所にカーソルをあわせると表示される「表示する」リンクをクリックし、アクセスキーを取得します。

![Firebase_Console.png](https://qiita-image-store.s3.amazonaws.com/0/5877/b943ac17-902c-d129-33fe-ac08468c2533.png "Firebase_Console.png")


### データベースへのアクセス権限を公開状態にする

検証を簡単にするため、データベースへのアクセス権限を公開状態にします。

![Firebase_Console.png](https://qiita-image-store.s3.amazonaws.com/0/5877/521f8d5b-3c3d-0a29-a7e9-7db8c2cef57b.png "Firebase_Console.png")

上図のように、「Database」メニューから「ルール」タブを選択し、内容を以下のように変更します。

```json
{
  "rules": {
    ".read": true,
    ".write": true
  }
}
```

これでFirebase側の設定は完了です。

## Xamarin側のコード

今回はXamarin.Formsのソリューションとして、XamarinChatSampleという名前でソリューションを作成しました。ウィザードでの設定はデフォルト通りです。一部、プロジェクトオプションを以下のように変更しています。最初に参考にしたコードがこの設定で書かれていたので、踏襲しているだけです。

![プロジェクト_オプション_-_XamarinChatSample.png](https://qiita-image-store.s3.amazonaws.com/0/5877/e3b7fce6-f7d5-6d91-cb53-f7d59de639e4.png "プロジェクト_オプション_-_XamarinChatSample.png")

参考にした本：[Mastering Xamarin.Forms](https://www.amazon.co.jp/dp/B013R02C00/)


### FireSharpパッケージを追加する

プロジェクトツリー上の「パッケージ」を右クリックして、「Add Packages...」を選択します。そこで「FireSharp」パッケージを検索し、プロジェクトに追加します。

![XamarinChatSample_-_Views_ChatPage_xaml_cs_-_Xamarin_Studio_Community.png](https://qiita-image-store.s3.amazonaws.com/0/5877/8c4350d0-29c1-1ba7-9e11-05a415b99038.png "XamarinChatSample_-_Views_ChatPage_xaml_cs_-_Xamarin_Studio_Community.png")

Xamarin.Forms側とあわせて、ビルドするOS側にも追加しておきましょう。

![XamarinChatSample_-_Views_ChatPage_xaml_cs_-_Xamarin_Studio_Community.png](https://qiita-image-store.s3.amazonaws.com/0/5877/a0676c35-e351-61fe-4e33-81a569253bf4.png "XamarinChatSample_-_Views_ChatPage_xaml_cs_-_Xamarin_Studio_Community.png")

Newtonsoft.Jsonなどの依存パッケージは、FireSharpパッケージを追加するとあわせて自動的に追加されます。

参考：[FireSharp](https://github.com/ziyasal/FireSharp)

### Viewを書こう

投稿したメッセージが表示されれば良いや、という訳でこんな画面を作ってみます。

![スクリーンショット_2016_06_30_17_51.png](https://qiita-image-store.s3.amazonaws.com/0/5877/14ead622-11f3-d846-c774-2da53538bc4a.png "スクリーンショット_2016_06_30_17_51.png")

Xamarin.Formsプロジェクトに「Views」というディレクトリを追加し、その中にForms ContentPage Xamlを追加します。ここでは「ChatPage」という名前にしておきましょう。

![新しいファイル.png](https://qiita-image-store.s3.amazonaws.com/0/5877/e689fecb-b185-f52f-18b9-98fbdd2e422e.png "新しいファイル.png")

ChatPage.xamlの中身はこんなコードになります。

```xaml
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="XamarinChatSample.Views.ChatPage">
	<ContentPage.Content>
		<StackLayout>
			<ListView x:Name="messagesView" VerticalOptions="FillAndExpand"></ListView>
			<StackLayout Orientation="Vertical" VerticalOptions="End">
				<Entry x:Name="content" Placeholder="Write something here..." Keyboard="Chat" />
				<Button Text="Send" WidthRequest="80" Clicked="OnSendTapped" />
			</StackLayout>
		</StackLayout>
	</ContentPage.Content>
</ContentPage>
```

ここで忘れないうちに、アプリを開いたときにChatPageが開かれるよう、App.xaml.csを編集しておきます。

```csharp
using Xamarin.Forms;
using XamarinChatSample.Views;

namespace XamarinChatSample
{
	public partial class App : Application
	{
		public App()
		{
			InitializeComponent();

           // ここを変更↓
			MainPage = new NavigationPage(new ChatPage());
		}

		protected override void OnStart()
		{
			// Handle when your app starts
		}

		protected override void OnSleep()
		{
			// Handle when your app sleeps
		}

		protected override void OnResume()
		{
			// Handle when your app resumes
		}
	}
}
```

この時点でChatPage.xaml.csに空のOnSendTappedメソッドを実装してから、ビルドしてiOSシミュレータで起動すると、まっさらなリストビューが表示されると思います。

### Firebaseと連携させよう

そういうわけでやっとFirebaseとの連携です。ChatPage.xaml.csの内容はこんな感じにしてみました。

```csharp
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using FireSharp;
using FireSharp.Config;
using FireSharp.Interfaces;
using FireSharp.Response;
using Xamarin.Forms;
using XamarinChatSample.Models;

namespace XamarinChatSample.Views
{
	public partial class ChatPage : ContentPage
	{
		private IFirebaseClient firebaseClient = new FirebaseClient(new FirebaseConfig {
			AuthSecret = "(先ほど取得したデータベースへのアクセスキーをここに入力します)",
			BasePath = "https://xamarin-chat-sample.firebaseio.com"
		});

		private ObservableCollection<string> messages = new ObservableCollection<string>();

		public ChatPage()
		{
			InitializeComponent();
			Title = "Message";
			messagesView.ItemsSource = messages;
			ListenChatStream();
		}

		void OnSendTapped(object sender, EventArgs args)
		{
			AddMessage();
		}

		async void AddMessage()
		{
			var message = new Message { body = content.Text };
			await firebaseClient.PushAsync("messages/push", message);
			content.Text = "";
		}

		async void ListenChatStream()
		{
			await firebaseClient.OnAsync("messages", (sender, args, context) =>
			{
				messages.Add(args.Data);
			});
		}
	}
}
```

AuthSecretには先ほど取得したデータベースへのアクセスキーを入力します。BasePathはFirebaseコンソール上の以下の画面から確認することができます。

![Firebase_Console.png](https://qiita-image-store.s3.amazonaws.com/0/5877/7c590ba7-0450-457c-e762-20977386242d.png "Firebase_Console.png")

Firebaseにpushしているモデルは、以下のように定義しています。

```csharp
using System;

namespace XamarinChatSample.Models
{
	public class Message
	{
		public string body { get; set; }
	}
}
```

上記までの実装で、テキストフィールドに何か入力してSendボタンをタップすると、Firebaseにデータが送信されて、そのデータが`OnAsync`メソッドでListenされ、アプリ画面上に表示されるところまでの流れができました。ほぼリアルタイムに同期されるので、チャットぽい動作になります。

適当に何か入力してFirebaseコンソールでデータベースの内容を確認すると、以下のようにデータがちゃんと連携されているのがわかります。

![Firebase_Console.png](https://qiita-image-store.s3.amazonaws.com/0/5877/c5d040f9-f687-495e-9c4d-b7fc578adade.png "Firebase_Console.png")


## あとがき

個人的にサクッとFirebaseとの連携を試してみようと思ったのですが、Firebaseコンソールの見方がよく分からなくてちょっとハマってしまったので、こんな記事を書いてみました。サクッと触ってみたい人の助けになれば幸いです。

Firebaseにはその他にも認証機能や通知機能といったものがあるので、こちらもXamarinで作例が作れれば良いなーと思っています。