October 2015
Volume 30 Number 10
Microsoft Band - Microsoft Band SDK による Windows 10 アプリの開発
Microsoft Bing の 2015 年のテクノロジ分野のトレンド予測 (https://www.bing.com/trends/2014/jp/predictions/tekunoroj) では、パーソナル デジタル アシスタント、ホーム オートメーション、3D 印刷、仮想現実ゲームなどを抑え、ウェアラブル端末が最もホットな話題に挙げられました。
ウェアラブル端末の 1 つである Microsoft Band には、利用者の健康、フィットネス、睡眠の質などを追跡するのに必要なセンサーがほぼすべて組み込まれています。組み込まれているセンサーの数は、市場で入手できる高価な装置を上回ります。
筆者はモバイル アプリの開発者の 1 人として、Microsoft Band を使用して有益なアプリを作成することに関心がありました。今回例として取り上げるコードのいくつかは、以前に開発した Active Fitness アプリ (activefitness.co) で使用したものです。このアプリには、Windows、iOS、Android で 200 万人以上の利用者がいます。ほとんどのコンシューマー向けアプリは、利用者を最大限獲得できるように、Windows、iOS、Android など複数のプラットフォームで機能する必要があります。そこで、今回は Microsoft Band 向け Windows 10 アプリの開発方法と、クロス プラットフォームのオプションについて説明します。今回開発するアプリでは、Band SDK の公開前のバージョンを利用させてもらいました。現在は一般公開されているため、Band SDK の最新リリースや開発者コミュニティによって強化されたコード例を共有することができます。
Gravity Hero: Windows 10 サンプル アプリ
今回は、Microsoft Band の機能を紹介しながら、ほぼゲームのように動作する面白いアプリをビルドしていきます。今回作成するのは、「Gravity Hero」というユニバーサル Windows アプリです (図 1 参照)。考え方はシンプルです。Microsoft Band を着用してジャンプすると、これまで最高のジャンプだったかどうかが通知されます。ユニバーサル Windows アプリをビルドするのは、あらゆる Windows 10 デバイスで実行できるようにするためです。また、他のデバイスも簡単にターゲットできることを示すため、ネイティブ Android アプリ向けのサンプル コードも GitHub に追加しています。さらに、Microsoft Band のデベロッパー Web サイトに、ドキュメントと SDK コード サンプルへのリンクを掲載しています (developer.microsoftband.com、英語)。
図 1 Windows 10 で実行中の「Gravity Hero」サンプル アプリ
Microsoft Band チームは、Windows、iOS、および Android 向けの SDK を用意しています。また、Xamarin によるクロス プラットフォーム SDK ソリューションもあります。Xamarin は、優れたコードの再利用を可能にするテクノロジです。どちらのテクノロジを選択すべきでしょう。Band 端末向け開発では、マイクロソフトとコミュニティが以下のサポート オプションを提供しています。
- Windows、iOS、Android によるネイティブ開発向けの Microsoft Band SDK (マイクロソフト、bit.ly/1JfiFvW、英語)
- 簡単な手順だけで Web ソースから Band へと迅速に情報を配信するための Web Tile SDK (マイクロソフト、bit.ly/1h94CjZ、英語)
- 包括的なフィットネス データやヘルス データにより、使いやすい JSON 形式で RESTful API にアクセスするための Cloud API (マイクロソフト、bit.ly/1MIBOL7、英語)
- iOS、Android、Windows をターゲットにする Xamarin クロス プラットフォーム アプリで使用するためのクロス プラットフォーム SDK (Xamarin、bit.ly/1EfhqjK、英語)。Xamarin は、すべてのプラットフォームに 1 つのコード ベースを使用できるようにします。
Windows、iOS、Android 向けのアプリが既に手元にある場合は、各プラットフォーム用のネイティブ Band SDK を使用します。ゼロから開発を始める場合、または 1 つのコードですべてのプラットフォームをターゲットにする場合は、Xamarin を検討します。選択は自由です。プラットフォームに合ったアプローチを採用すれば、アプリのビルドに着手するのに必要な選択肢をすべて利用できるようになります。今回は、両方のオプションを見ていきます。
Band と Windows 10 PC とのペアリング
開発を始める前に、Band と Windows 10 PC をペアリングする必要があります。Windows 10 には Bluetooth サポートが組み込まれているため、このようなペアリングは簡単に行えます。
Band で、設定タイルにフリップし、Bluetooth アイコンをクリックしてモードを切り替え、Band をペアリング モードにします。Windows 10 PC では、[設定] に移動するか、Cortana に「Bluetooth」と指示して、Bluetooth の設定ページを開きます (図 2 参照)。Band の状態が Bluetooth のデバイス一覧に表示されます。Band の名前は、他の名前に変えない限り、通常はユーザー名とコードで始まります (今回の例では「Kevin’s Band ec:5a」)。状態が [接続済み] になっていればペアリングされています。それ以外の場合は [ペアリング] をタップして画面に表示される指示に従います。
図 2 Windows 10 PC と Microsoft Band のペアリング
Visual Studio での Windows 10 アプリの作成
GitHub (bit.ly/1U2sLup、英語) に作成したサンプル アプリから作業を始めることができます。ゼロからアプリを作成する場合、Visual Studio の既定の設定では、Bluetooth のデバイス機能がアプリケーション テンプレートに含まれていないため、マニフェストにこの機能を含める必要があります。
<Capabilities>
<DeviceCapability Name="bluetooth" />
</Capabilities>
自身のアプリに Band を追加する場合や、ゼロから Windows 10 アプリを作成する場合は、Microsoft Band NuGet パッケージも必要です。マイクロソフトが作成したパッケージや、コミュニティが追加したパッケージ (例、Xamarin.Microsoft.Band パッケージ) など、複数のパッケージがあります。ユニバーサル Windows アプリを対象とするため、今回はマイクロソフトのパッケージを追加します (図 3 参照)。
図 3 Microsoft Band NuGet パッケージ
Microsoft Band SDK を使用すると、開発者は、Band のセンサーにアクセスできるようになり、タイルの作成や更新、端末のカスタマイズが可能になります。アプリから Band に通知 (ハプティクスなど) を送信することもできます。Band 自体は、非常に洗練されたシンプルな外観を持ちます (図 4 参照)。
図 4 Microsoft Band
Band には、複数のセンサーが搭載されています (図 5 に完全な一覧を示します)。Gravity Hero サンプル アプリでは、この中から加速度計センサーに注目します。
図 5 Microsoft Band で利用可能なセンサー
センサー | 説明 |
加速度計 | X、Y、Z の加速度 (単位: g) を提供します。1 g = 9.81 (m/s2) です。 |
ジャイロスコープ | X、Y、Z の角速度 (単位: 度/秒) を提供します。 |
距離 | 合計距離 (cm)、現在速度 (cm/秒)、現在ペース (ミリ秒/m)、および現在の歩数計モード (ウォーキングまたはランニング) を提供します。 |
心拍数 | 毎分の心拍数を提供します。また、心拍数のセンサーが装着者の心拍数を完全にロックオンしているかどうかも示します。 返されるデータは、安静時モードでのみ使用する必要があります。Band SDK では、他のアクティビティ用に最適化された心拍数値にはアクセスできません。 |
歩数計 | 装着者の合計歩数を提供します。 |
体温 | 装着者の現在の体温 (摂氏) を提供します。 |
UV | 現在の紫外線照射強度を提供します。 |
Band 接触 | Band の現在状態 (装着または非装着) を提供します。 |
カロリー | 装着者の合計消費カロリーを提供します。 |
データ モデルの設計
いつものように、Visual Studio のデータ モデルから始めます (図 6 参照)。データ モデルの設計は重要で、データを個別の層に適切に分離すれば、アプリ間での共有や、クラウド バックエンドとの共有 (Web サイトでデータを表示する場合) が容易になります。今回は、センサーからデータを収集して Gravity Hero アプリで表示できるデータ モデルで十分です。データ モデルを他のアプリで再利用できるように、Visual Studio ソリューションでは、データ モデルを別のフォルダーに配置しておきます。
図 6 サンプル プロジェクトとデータ モデルを含む Visual Studio ソリューション
Gravity Hero アプリのデータ モデルは、便宜上 ViewModel というヘルパー クラスを使用しています。モデル - ビュー - ビューモデル (MVVM: Model-View-ViewModel) の既存のヘルパー ライブラリがたくさんありますが、今回の例では、できる限りコードを透過的にするヘルパー ライブラリを単純に実装します。ViewModel クラスは、INotifyPropertyChanged インターフェイスを実装します。データ モデルの変更を UI に反映する場合、.NET アプリでは INotifyPropertyChanged インターフェイスを実装するのが標準的なアプローチです。サンプル アプリの実装では、ViewModel クラスから PropertyChanged メカニズムを利用して UI に通知するようにします。
SensorReading クラスは、Band センサーの読み取りをキャッチし、データ モデルの変更をサブスクライブしている UI メンバーに通知します。この SensorReading クラスをもう少し詳しく見ていきます。このクラスは前述の ViewModel から派生します。また、データをシリアル化してネットワーク経由で送信 (たとえば、クラウド ストレージに送信) する際に便利な属性も含みます。この役割を果たすのが SensorReading クラスの DataContract 属性です。また、各データ メンバーの DataMember 属性では、シリアライザーに応じて JSON 形式または XML 形式でデータをシリアル化できます。SensorReading クラスのもう 1 つのメリットは、3D ベクトルの読み取り (Vector3) を保持しているため、正規化された形式で提供できることです。正規化したベクトル (3D 計算を扱う場合に非常に便利なベクトル) を返す Value メンバーも提供します (図 7 参照)。
図 7 センサーのデータ モデルの SensorReading クラス
[DataContract]
public class SensorReading : ViewModel
{
DateTimeOffset _timestamp;
[DataMember]
public DateTimeOffset Timestamp
{
get { return _timestamp; }
set
{
SetValue(ref _timestamp, value, "Timestamp");
}
}
double _x;
[DataMember]
public double X
{
get { return _x; }
set
{
SetValue(ref _x, value, "X", "Value");
}
}
double _y;
[DataMember]
public double Y
{
get { return _y; }
set
{
SetValue(ref _y, value, "Y", "Value");
}
}
double _z;
[DataMember]
public double Z
{
get { return _z; }
set
{
SetValue(ref _z, value, "Z", "Value");
}
}
public double Value
{
get
{
return Math.Sqrt(X * X + Y * Y + Z * Z);
}
}
}
BandModel を使用して Band を管理します (図 8 参照)。これは、PC にBand 端末が複数ペアリングされている場合に役立つマネージャ クラスで、Band がペアリングされているかどうかも通知できます。
図 8 Band を管理する BandModel
public class BandModel : ViewModel
{
static IBandInfo _selectedBand;
public static IBandInfo SelectedBand
{
get { return BandModel._selectedBand; }
set { BandModel._selectedBand = value; }
}
private static IBandClient _bandClient;
public static IBandClient BandClient
{
get { return _bandClient; }
set
{
_bandClient = value;
}
}
public static bool IsConnected
{
get {
return BandClient != null;
}
}
public static async Task FindDevicesAsync()
{
var bands = await BandClientManager.Instance.GetBandsAsync();
if (bands != null && bands.Length > 0)
{
SelectedBand = bands[0]; // Take the first band
}
}
public static async Task InitAsync()
{
try
{
if (IsConnected)
return;
await FindDevicesAsync();
if (SelectedBand != null)
{
BandClient =
await BandClientManager.Instance.ConnectAsync(SelectedBand);
// Connected!
BandModel.BandClient.NotificationManager.VibrateAsync(
Microsoft.Band.Notifications.VibrationType.ExerciseRunLap);
}
}
catch (Exception x)
{
Debug.WriteLine(x.Message);
}
}
}
AccelerometerModel は、Gravity Hero ゲーム専用に設計しています。重力は、Band 組み込みの加速度計センサーで効果的に測定できます。ここまではデータ モデルのクラスを作成する方法について見てきました。この他にも、アプリで使用する Band センサー用のクラスを追加することもできます。Init メソッドで Accelerometer クラスを初期化する必要があります。この初期化時に Band SDK が便宜上提供しているイベントをいくつかサブスクライブします。
if (BandModel.IsConnected)
{
BandModel.BandClient.SensorManager.
Accelerometer.ReadingChanged +=
Accelerometer_ReadingChanged;
BandModel.BandClient.SensorManager.
Accelerometer.ReportingInterval =
TimeSpan.FromMilliseconds(16.0);
BandModel.BandClient.SensorManager.
Accelerometer.StartReadingsAsync(
new CancellationToken());
totalTime = 0.0;
}
最初のイベントは ReadingChanged です。これは、開発者が定義する ReportingInterval 期間に基づいて加速度計センサーのデータを返すイベントです。Accelerometer 値を読み取る際、16 ミリ秒のしきい値を使用します。できる限りレポート間隔を短くして精度を高めることも重要ですが、この頻度を上げるとバッテリーの使用率が上昇することも考慮する必要があります。次に、センサー値の読み取りを開始して読み取った値をアプリに返す、StartReadingsAsync メソッドを呼び出します。StartReadingsAsync メソッドは、センサー データ読み取り用のリスナーを起動するだけです。読み取ったデータは ReadingChanged イベントに渡されます。
ReadingChanged イベントでは、読み取った値をキャプチャして、データ モデル内の値を再計算します。
void Accelerometer_ReadingChanged(object sender,
BandSensorReadingEventArgs<IBandAccelerometerReading> e)
{
SensorReading reading = new SensorReading {
X = e.SensorReading.AccelerationX, Y = e.SensorReading.AccelerationY,
Z = e.SensorReading.AccelerationZ };
_prev = _last;
_last = reading;
Recalculate();
}
Recalculate モデルのメソッドは、今回のロジックの大部分を起動する場所です (図 9 参照)。以前のゲームで獲得した値を上回った場合、Changed イベントを起動してアプリに通知します。Gravity Hero ゲームは、最高記録の更新を目指します。Band センサーのイベントは UI スレッド以外からトリガーされる可能性があるため、Dispatcher クラスを使用して、Changed イベントのコードを UI スレッドにマーシャリングする必要があります。
図 9 Recalculate モデル メソッド
DateTimeOffset _startedTime = DateTimeOffset.MinValue;
double totalTime = 0.0;
double lastTime = 0.0;
SensorReading _prev;
SensorReading _last;
double MIN = 0.4;
void Recalculate()
{
if (_last.Value <= MIN)
{
if (_startedTime > DateTimeOffset.MinValue)
lastTime = (DateTimeOffset.Now - _startedTime).TotalSeconds;
else
_startedTime = DateTimeOffset.Now;
}
else
{
if (_startedTime > DateTimeOffset.MinValue)
{
lastTime = (DateTimeOffset.Now - _startedTime).TotalSeconds;
totalTime += lastTime;
lastTime = 0.0;
_startedTime = DateTimeOffset.MinValue;
CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(
CoreDispatcherPriority.Normal, () =>
{
if (Changed != null)
Changed(_last.Value);
});
}
}
}
¡ }
}
Band からイベントが返されたら、UI を更新します (図 10 参照)。これは、MainPage.xaml でサブスクライブする Changed イベントで実行されます。重力を表示して成績を求めます。また、VibrateAsync メソッドを使用して Band のハプティクス フィードバックも呼び出します。何か月も Band ユーザーとして端末を利用してきて、ハプティクス通知を送信する機能が非常に気に入りました (ハプティクス通知は乱用を避け、適切な場合のみユーザーに通知するよう心がけます)。
図 10 Changed イベントで更新される UI
void _accelerometerModel_Changed(double force)
{
bandCount++;
UpdateCount();
if (force > maxForce)
{
maxForce = force;
heroText.Text = String.Format("Intensity {0:F2}G", maxForce);
}
if (!isAchievementUnlocked && bandCount >= maxCount*0.2)
{
Speak("Just a few more!");
isAchievementUnlocked = true;
}
if (!isSecondAchievementUnlocked && isAchievementUnlocked &&
bandCount >= maxCount * 0.8)
{
Speak("Almost there!");
isAchievementUnlocked = true;
}
BandModel.BandClient.NotificationManager.VibrateAsync(
Microsoft.Band.Notifications.VibrationType.ExerciseRunLap);
// Speak(bandCount.ToString()+"!");
}
お楽しみはこれから
すべての準備が整いました。お楽しみはこれからです。アプリのビルドして起動します。このアプリはすべての Windows 10 デバイスで実行できます。Band のセンサーを使用しているため、PC やスマートフォンが加速度計をサポートするかどうかは問題ではありません。PC を使用して Band の情報を表示しますが、センサー関連の処理はすべて Band が行います。
Visual Studio またはタイルからアプリを初めて実行する場合、Windows 10 では、Gravity Hero アプリに Band へのアクセス許可を与えるかどうかを問い合わせるダイアログが自動的に表示されます (図 11 参照)。
図 11 Band へのアクセスを自動的に要求する Windows 10 ダイアログ
Gravity Hero から Band に接続すると、Band が振動します。これは、ジャンプの準備がすべて整ったことを知らせます。また、操作を開始できることを音によって通知する機能も追加しています。
BandModel.BandClient.NotificationManager.VibrateAsync(
Microsoft.Band.Notifications.VibrationType.ExerciseRunLap);
ここで、ジャンプします。このアプリは、ジャンプ回数をカウントして、毎回の成績を称賛します。
本稿付属のサンプル コードはすべて GitHub (bit.ly/1MIKIIK、英語) からダウンロードできます。このソース コードを利用するには、Visual Studio 2015 と Windows 10 を使用します。このプロジェクトでは、Microsoft Band SDK NuGet パッケージを使用します。
まとめ
Microsoft Band は、Windows、Android、iOS など、複数のプラットフォーム向けに、強力な SDK とコミュニティ サポートを提供します。開発者は、Xamarin、GitHub、開発者コミュニティを通じて Microsoft SDK やコミュニティのコンポーネントを利用してアプリを拡張し、Microsoft Band を使用できるようにします。本稿のコードを使用して、Windows 10 対応の独自のアプリに Microsoft Band を統合できます。
Kevin Ashleyはマイクロソフトの上級ゲーム開発者エバンジェリストです。『Professional Windows 8 Programming』(Wrox、2012 年) の共著者であり、人気アプリやゲームの開発者でもあります。代表的なアプリは、200 万人以上のユーザーを抱える Active Fitness (activefitness.co、英語) です。Kevin はさまざまなイベント、産業展覧会や Web キャストで技術発表をよく行っています。新興企業やパートナーに協力し、ソフトウェア設計、ビジネスとテクノロジ戦略、アーキテクチャ、および開発に関するアドバイスを行っています。Ashley のブログは kevinashley.com (英語) で、Twitter は @kashleytwit (英語) でフォローできます。
この記事のレビューに協力してくれたマイクロソフト技術スタッフの Jaime Rodriguez に心より感謝いたします。