[WinRT] デスクトップアプリからストアプリへアプリケーションデータを通じて連携させる

Kindle Launcher ネタの続きです。

Windows ストアアプリを公開するときのアカウントを「企業アカウント」にしておくと、デスクトップアプリもストアに紹介を載せることができます。そのために年間9.800円也を支払っていたのですが、いやいやほとんど使わないしやめようと思っていたら、つい先日無料になりました。なので、アカウント自体は放っておくことにしましょう。ちなみに今、出している moonmile solutions のアカウントは「個人アカウント」なのです。企業アカウントの場合、諸々の審査があってブランド名を変えられないので、こっちを使っています。まあ、個人上行主の屋号を変えればいいだけなんですけどね。

ストアプリからデスクトップを扱えなくて、逆にデスクトップからストアアプリへの通知はどうやるのか?という問題が諸々ありますが、ひとつは「プロトコル」を通じて送る方法です。幸いにしてストアアプリのほうはプロトコルを手軽に登録するので、アプリ特有のプロトコルを作っておいて、デスクトップからストアアプリを呼び出せば良いのです。ただし、これの場合は、いちいちストアアプリを起動することになります。
もうひとつの方法は、ストアアプリの「アプリケーションデータ」にデスクトップから直接書き込んでしまうことです。あまり見かけない方法(推奨されない方法?)なのですが、ローミング自体は OS からそういう手段を取っているし、アプリID 自体は固有で作られる(バージョンアップしても変わらない)のでこれを使うのが手軽でしょう。

■ストアアプリのパッケージファミリ名

Package.appxmanifest ファイルをダブルクリックして「パッケージ化」タブを表示させると、パッケージファミリ名が分かります。

ストアアプリをインストールしたときに使われるキーで、アプリで使うアプリケーションデータの位置にも使われています。ストアアプリのデータは、

1
C:UsersmasudaAppDataLocalPackages37659MoonmileSolutions.KindleLauncher_fjkmb51crq5v0

のように、ログインユーザーの AppData に下に作られるので、ここに直接書き込んでしまいます。Kindle Launcher は、このフォルダの LocalState に書籍の画像ファイルを保存していますが、購入一覧のツールのツールは MyBookshelf.xml で書いています。ここのパッケージ名は Kindle Launcher が公開されている限り同じものが使われるので、このファイルを他にも利用することができます。

アクセス権はユーザーの下にあるので、いくらでも書き込みが可能ですね。他のストアアプリを操作することもできます。RoamingState フォルダに書き込むと、自動的にローミングしてくれるので、適当なストアアプリの RoamingState に書いておいて自動的に同期されるようにする、という裏ワザもできます。

■ストアアプリで起動時に購入履歴を表示する

複数ページの場合は、App.xaml.cs に書くほうがいいのですが、Kindle Launcher は1枚しかないので、MainPage.xaml.cs の LoadState に書いてしまっています。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
private void navigationHelper_LoadState(object sender, LoadStateEventArgs e)
{
    // TODO: バインド可能なアイテムのコレクションを this.DefaultViewModel["Items"] に割り当てます
    GetMyBookshelf();
    vm.Title = "";
}
async void GetMyBookshelf()
{
    // MyBookshelf.xml があれば読み込む
    var folder = Windows.Storage.ApplicationData.Current.LocalFolder;
    var path = folder + "\MyBookshelf.xml";
 
    try
    {
        using (var sr = await folder.OpenStreamForReadAsync("MyBookshelf.xml"))
        {
            var se = new XmlSerializer(typeof(BookList));
            var books = se.Deserialize(sr) as BookList;
            this.vm.Books = books;
        }
    }
    catch
    {
        // 無い場合はそのまま
    }
}

ローカルのアプリケーションフォルダから読み込んでいます。ここでは XmlSerializer を使っていますが、DataContractSerializer を使ってもよいでしょう。気を付けないといけないのは、ファイル自体は「壊れていることがある」ので、必ず復帰ができるようにしておくことです。ここでは try-catch で例外を取得することと、catch した例外は無視することですね。何かエラーがあっても何事もなかったように進まないといけない「フェールセーフ」な作りになります。

カテゴリー: C#, WinRT パーマリンク