ローミングとトースト

 Metro スタイルアプリには、同じ Microsoft アカウントWindows Live ID)でログオンしてアプリを使った時にデータを同期させるローミング機能があります。
 この機能を使って複数マシンでデータを同期させてみたいと思います。
 また、画面上の通知を行うトースト機能も使ってみます。

サンプルの仕様

  • TextBoxに入力したテキストをローミング設定として保存できる。
  • ローミング設定からテキストを読み込んで表示できる。
  • ローミング設定が更新されたらトースト通知する。

基本構成

 今回は“新しいアプリケーション”のテンプレートを使って作成します。
 作成したアプリに“基本ページ”を追加し、起動時に追加したページが表示されるようにしておきます(App.xaml.cs を変更)。

protected override void OnLaunched(LaunchActivatedEventArgs args)
{
    var rootFrame = new Frame();
    rootFrame.Navigate(typeof(BasicPage));

    Window.Current.Content = rootFrame;
    Window.Current.Activate();
}

画面設計

 タイトルの下に保存、読み込みを行うためのボタンと入力用の TextBox を追加します。

<Grid Grid.Row="1" Margin="120,0,120,46">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>

    <Grid Grid.Row="0" Margin="0, 0, 0, 20">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>

        <Button x:Name="saveButton" Grid.Column="0" Content="保存" Width="150" Margin="0, 0, 20, 0" Click="saveButton_Click"/>
        <Button x:Name="loadButton" Grid.Column="1" Content="読込" Width="150" Click="loadButton_Click"/>
    </Grid>

    <TextBox Grid.Row="1" x:Name="bodyText" TextWrapping="Wrap" AcceptsReturn="True" />
</Grid>

アプリケーションマニフェスト

 トーストを使用するためにアプリケーションマニフェストの設定を行います。
 マニフェストを開いて、“アプリケーション UI”タブの“通知”のところにある“トースト対応”を“はい”に変更します。

 この設定を行わないとトースト通知を呼び出しても何も表示されないので注意が必要です(例外も発生せず表示されないだけなので気付きにくいです)。
 なお“タイル”の“背景色”も変更しています。この色がトーストの背景でも使用されます。

トースト通知

 トースト通知を行う処理を追加します。

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    ApplicationData.Current.DataChanged += Current_DataChanged;
}

void Current_DataChanged(ApplicationData sender, object args)
{
    NotifyUpdate(false);
}

private void NotifyUpdate(bool isLocal)
{
    string text1 = "データを更新しました";
    if (!isLocal)
    {
        text1 = "データが更新されました";
    }

    string test2 =
        String.Format("RoamingStorage : Usage = {0} KB / Quota = {1} KB",
            ApplicationData.Current.RoamingStorageUsage,
            ApplicationData.Current.RoamingStorageQuota);

    // データ更新をトーストで通知
    NotifyToast(text1, test2);
}

private void NotifyToast(string test1, string test2)
{
    // 文字列を2行表示するトーストテンプレートを取得
    var toastXml = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastText02);

    // テキストノードを追加
    var textNodes = toastXml.GetElementsByTagName("text");
    textNodes[0].AppendChild(toastXml.CreateTextNode(test1));
    textNodes[1].AppendChild(toastXml.CreateTextNode(test2));

    // トースト表示
    var toast = new ToastNotification(toastXml);
    ToastNotificationManager.CreateToastNotifier().Show(toast);
}

 まず、ページ表示時の OnNavigatedTo で DataChanged イベントのハンドラを登録します。
 このイベントはローミングデータが更新された時に発生します。

 イベントが発生したらトースト通知を行います。
 トースト通知を行うために通知用のテンプレートを取得します。今回はテキストが2行表示できる物を使用します。
 取得したテンプレートにテキストを追加して、ToastNotifier を使って表示します。

ローミング設定

 ローミング設定を使ってテキストの保存や読み込みを行います。
 自分で保存した時もトースト通知を行います。

private void saveButton_Click(object sender, RoutedEventArgs e)
{
    // ローミング設定にテキストを保存
    ApplicationData.Current.RoamingSettings.Values["bodyText"] = bodyText.Text;

    NotifyUpdate(true);
}

private void loadButton_Click(object sender, RoutedEventArgs e)
{
    // ローミング設定から読み込んだテキストを反映
    var text = ApplicationData.Current.RoamingSettings.Values["bodyText"] as string;

    if (String.IsNullOrEmpty(text))
    {
        bodyText.Text = "";
    }
    else
    {
        bodyText.Text = text;
    }
}

 ここでは、RoamingSettings を使って保存していますが RoamingFolder を取得してファイルを作成する事もできます。

実行

 同じ Microsoft アカウント でログオンした2台のマシンで作成したアプリを実行します。

 まず、片方のマシンでテキストを入力し保存します。
 すると、保存した事がトーストで通知されます。

 保存したマシンとは別のマシンでアプリを起動したまましばらく待っていると、更新された事が通知されます。

 通知された後で読み込みを行うと、別マシンで保存したテキストが表示されます。

ローミングの動作について

 ローミングについて動作させた結果からわかった事、推測できる事をまとめます。

  • アプリから保存したローミングデータはまずローカルに保存され、その後OSがクラウド上のデータを更新しているようです。他マシンでデータ更新を行った場合、クラウド上のデータ更新が行われるまでは、ローカルにある以前のデータが取得されます。
  • 保存したデータが実際にクラウド上に反映されるまでにはしばらくかかります。試した範囲では、アプリで保存後10分程度たってから他マシンで更新イベントが発生しました。また、保存後にマシンをスリープして再開すると、そのタイミングでデータ更新イベントが発生しました(10分たっていなくても)。
  • 更新イベントは自マシンで保存した場合でも発生します。

 以上のように、ローミング設定は瞬時に反映されるような物ではありませんので、それを考慮して使用する必要があります。
 短い間隔で2台のマシンで更新すれば上書きされてどちらかの更新結果が反映されないという状態が比較的簡単に発生しますので、絶対に上書きされてはいけないようなデータの保存には使用できないと思います。

トーストの動作について

 トーストについてもわかった事をまとめます。

  • PCの詳細設定に通知に関する設定があり、アプリ毎に通知を表示するかどうかをオン/オフできます。オフにするとトーストが表示されなくなります。

 トーストはユーザーがオフにできますので、重要な情報の通知には使用できません。