XamarinでAndroid Wearサンプルを動かしてみる


先月末にPreview版が発表されたAndroid Wearですが、XamarinのComponent StoreにもAndroid Wear Developer Previewがありましたので、Android Studio用のプロジェクトをXamarin用に書き直してみました。

今回書き直したのはプレビュー版サンプルは *WearableNotificationsSample* です。ソースコードは[GitHub](https://github.com/droibit/AndroidWearSamples.Xamarin "GitHub")にあります。
別サンプルのXamarin版もあります。

* [Recipe Assistant](http://qiita.com/droibiter/items/18504925d9546499ccdc#2-1 "Recipe Assistant")

  
Android Wearの使い方を備忘録がてらメモっておきます。

##Android Wear Preview APIs
Android Wearに通知するために用意されたのはクラスは次の7クラス。

* [NotificationManagerCompat](https://developer.android.com/reference/android/preview/support/v4/app/NotificationManagerCompat.html)  
NotificationManagerの互換クラスで通知を行うクラス。
* [WearableNotifications](https://developer.android.com/reference/android/preview/support/wearable/notifications/WearableNotifications.html) + [WearableNotifications.Builder](https://developer.android.com/reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html)  
Notification へAndroid Wearに通知する情報を付加するためのクラス。  
* [RemoteInput](https://developer.android.com/reference/android/preview/support/wearable/notifications/RemoteInput.html) + [RemoteInput.Builder](https://developer.android.com/reference/android/preview/support/wearable/notifications/RemoteInput.Builder.html)  
Android Wearからの入力（音声、選択肢など）を受け取るためのクラス。  
* [WearableNotifications.Action](https://developer.android.com/reference/android/preview/support/wearable/notifications/WearableNotifications.Action.html) + [WearableNotifications.Action.Builder](https://developer.android.com/reference/android/preview/support/wearable/notifications/WearableNotifications.Action.Builder.html)  
Android Wear用のNotificationのアクションを作成するためのクラス。  

##APIの使い方
次にこれらのクラスの使い方をサンプルから見ていきます。

### NotificationManagerCompat
機能はNotificationManagerと同じですが、使い方が若干異なります。

``` c#:MainActivity.cs
// Managerの取得
var nm = NotificationManagerCompat.From(context)

// 通知の発行
nm.Notify(notification);
// 通知のキャンセル
nm.Cancel(id);
```

NotificationManagerCompatクラスの取得方法がSystemServiceからではなく、スタティックメソッドからになっています。

### WearableNotifications with Builder
Andoid WearではJelly Beansから追加されたNotificationのスタイルが使えます。
サンプルにはそれ以外の独自のUIが2種類ありますが、どちらも既存の Notificationを拡張していきます。

#### Stack型
![Stack](http://cl.ly/image/0N0L2v1C2B1v/download/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%202014-04-14%2019.32.10.png)

Stack型のように通知をグルーピングして表示する場合は次のようにします。

``` c#:NotificationPresents.cs
// 通知をグルーピングするためのキー
var EXAMPLE_GROUP_KEY = "example";

// 1つ目の通知を作成
var childBuilder1 = new NotificationCompat.Builder(context)
		.SetContentTitle(title)
		.SetContentText(text);
var child1 = new WearableNotifications.Builder(childBuilder1)
					.SetGroup(groupKey=EXAMPLE_GROUP_KEY, groupOrder=0)
					.Build();
// 2つ目の通知を作成
// Actionを設定している場合、2つ目の通知を表示後、右スワイプするとアクションが行える
var childBuilder2 = new NotificationCompat.Builder(context)
		.SetContentTitle(title)
		.SetContentText(text)
		.AddAction(action);
var child2 = new WearableNotifications.Builder(childBuilder2)
		.SetGroup(groupKey=EXAMPLE_GROUP_KEY, groupOrder=1)
		.Build();

// 概要は引数のgroupOrderに WearableNotifications.GroupOrderSummary(-1) を設定
var summary = BuildBasicNotification(context, options)
		.SetGroup(EXAMPLE_GROUP_KEY, WearableNotifications.GroupOrderSummary)
		.Build();

// 後は通知する
...
```

#### Page型
![Page](http://cl.ly/image/2G2M2u1K0s1l/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88_2014-04-14_19_31_23.png)

Page型のように左右にスワイプすることで情報を切り替える場合は次のようにします。

``` c#:NotificationPresents.cs
// WearableNotifications.Builder#AddPage(Notification) 
// を呼ぶことで複数のページを追加することができる
var secondPage = new NotificationCompat.Builder(context)
		.SetContentTitle(title)
		.SetContentText(text)
		.Build();
var notification = BuildBasicNotification(context, options)
		.AddPage(secondPage)
		.Build();
// 後は通知する
...
```

#### WearableNotificationsの作成
Stack, Page型どちらの種類も共通ですが、 *WearableNotifications* クラスを作成する場合は *WearableNotifications.Builder* クラスを使用します。

``` c#
var builder = new NotificationCompat.Builder(context);
var wearableBuilder = new WearableNotifications.Builder(builder)
		.SetHintHideIcon(hintHideIcon) // アイコンを表示するかどうか
		.SetLocalOnly(localOnly);		// 端末のみに通知するかどうか
		// ... その他追加処理

// NotificationCompat.Builderも取得可能
var builder2 = wearableBuilder.CompatBuilder;
		
```

### Actionの設定
Android Wearから音声などの入力結果を受け取るには *RemoteInput* や 既存の *NotificationCompat.Action* クラスが使えます。
エミュレータでは音声入力ができませんが、それ以外の方法でRemoteInputの動作を確認できます。

#### 選択肢の入力
![ChoiceInput](http://cl.ly/image/1V3Q0i2m2g0c/download/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%202014-04-14%2020.54.41.png)
選択肢の入力用のRemoteInputをNotificationに追加する方法は次のようになります。

``` c#:ActionPresents.cs
var pendingIntent = ...;
var remoteInput = new RemoteInput.Builder(returnKey=EXTRA_REPLY)
		.SetLabel(label="Example Replay Action")
		.SetChoices(choices = new String[] {"Yes", "No", "Maybe"})
		.Build();
var action = new WearableNotifications.Action.Builder(..., intent=pendingIntent)
		.AddRemoteInput(remoteInput=remoteInput)
		.Build();
// WearableNotification.Builderに追加する
builder.AddAction(action);
```

#### 音声の入力
![VoiceInput](http://cl.ly/image/2a1G0v0V1R0m/download/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%202014-04-14%2020.55.08.png)
動作確認はできませんが、音声入力用のRemoteInputをNotificationに追加する方法は次のようになります。

``` c#:ActionPresents.cs
var pendingIntent = ...;
var remoteInput = new RemoteInput.Builder(returnKey=EXTRA_REPLY)
		.SetLabel(label="Example Replay Action")
		.Build();
var action = new WearableNotifications.Action.Builder(..., intent=pendingIntent)
		.AddRemoteInput(remoteInput=remoteInput)
		.Build();
// WearableNotification.Builderに追加する
builder.AddAction(action);
```

#### 入力値の受取方法
入力が確定すると *WearableNotifications.Action.Builder* のコンストラクタに指定する *PendingIntent* が実行されますので、受け取った *Intent* から入力値を取得します。

``` c#:NotificationIntentReceiver.cs
// RemoteInputのコンストラクタに指定したキーを使用する
var replyMessage = intent.GetStringExtra(EXTRA_REPLY);

```

#### その他
単純にアイコンをクリックする場合は既存の *NotificationCompat.Action* クラスを使用します。

Big Picture example の通知を出すとエミュレータが再起動する可能性があります。
現在原因を調査中です。
　　
*WearableNotificationsSample* を元にAndroid Wearの通知方法を簡単にまとめると以上のようになります。