エンドユーザーを識別するには?[ユニバーサルWindowsアプリ開発]:WinRT/Metro TIPS
AppReceiptを使用して、ユニバーサルアプリを使用しているユーザーを識別する方法を解説する。
powered by Insider.NET
アプリを実行しているエンドユーザーを識別したいと思ったことはないだろうか? エンドユーザーごとの設定ならローミングで実現できて、その場合にはエンドユーザーを識別する必要もない。しかし例えば、クラウドのサービスとしてエンドユーザーごとにカスタマイズした情報を提供するというようなことは、エンドユーザーが識別できなければ実現できない。それはユーザー認証を行えば可能ではあるが、もっと簡単にエンドユーザーを識別する方法もある。本稿では、アプリとエンドユーザーごとに一意になるIDを取得する方法を解説する。なお、本稿のサンプルは「Windows Store app samples:MetroTips #90」からダウンロードできる。
事前準備
ユニバーサルプロジェクトを使ってユニバーサルWindowsアプリを開発するには、以下の開発環境が必要である。本稿では、無償のVisual Studio Express 2013 for Windowsを使っている。
- SLAT対応のPC*1
- 2014年4月のアップデート*2適用済みの64bit版Windows 8.1 Pro版以上*3
- Visual Studio 2013 Update 2(またはそれ以降)*4を適用済みのVisual Studio 2013(以降、VS 2013)*5
*1 SLAT対応ハードウェアは、Windows Phone 8.1エミュレーターの実行に必要だ。ただし未対応でも、ソースコードのビルドと実機でのデバッグは可能だ。SLAT対応のチェック方法はMSDNブログの「Windows Phone SDK 8.0 ダウンロードポイント と Second Level Address Translation (SLAT) 対応PCかどうかを判定する方法」を参照。なお、SLAT対応ハードウェアであっても、VM上ではエミュレーターが動作しないことがあるのでご注意願いたい。
*2 事前には「Windows 8.1 Update 1」と呼ばれていたアップデート。スタート画面の右上に検索ボタンが(環境によっては電源ボタンも)表示されるようになるので、適用済みかどうかは簡単に見分けられる。ちなみに公式呼称は「the Windows RT 8.1, Windows 8.1, and Windows Server 2012 R2 update that is dated April, 2014」というようである。
*3 Windows Phone 8.1エミュレーターを使用しないのであれば、32bit版のWindows 8.1でもよい。
*4 マイクロソフトのダウンロードページから誰でも入手できる(このURLはUpdate 3のもの)。
*5 本稿に掲載したコードを試すだけなら、無償のExpressエディションで構わない。Visual Studio Express 2013 with Update 3 for Windows(製品版)はマイクロソフトのページから無償で入手できる。Expressエディションはターゲットプラットフォームごとに製品が分かれていて紛らわしいが、Windowsストアアプリの開発には「for Windows」を使う(「for Windows Desktop」はデスクトップで動作するアプリ用)。
用語
本稿では、紛らわしくない限り次の略称を用いる。
- Windows:Windows 8.1とWindows RT 8.1(2014年4月のアップデートを適用済みのもの)
- Phone:Windows Phone 8.1
サンプルコードについて
Visual Studio 2013 Update 2(およびUpdate 3)では、残念なことにVB用のユニバーサルプロジェクトのテンプレートは含まれていない*6。そのため、本稿で紹介するコードはC#のユニバーサルプロジェクトだけとさせていただく*7。
*6 VB用のユニバーサルプロジェクトは、来年にリリースされるといわれているVisual Studio「14」からの提供となるようだ。「Visual Studio UserVoice」(英語)のリクエストに対する、6月18日付けの「Visual Studio team (Product Team, Microsoft)」からの回答による。
*7 Visual Studio 2013 Update 2(またはUpdate 3)のVBでユニバーサルWindowsアプリを作る場合のお勧めは、「The Visual Basic Team」のブログ記事(英語)によれば、PCLを使う方法のようである。しかし、本稿で説明するような「#if」ディレクティブを使ってWindowsとPhoneのコードを切り分ける方法は、PCLでは利用できない。
ユーザー名は使えない
エンドユーザーを識別しようと思ったとき、最初に思いつくのはマイクロソフトアカウントだろう。マイクロソフトアカウントのメールアドレスが取得できれば、エンドユーザーを一意に識別できることになる。しかし、それを取得するAPIは用意されていない。
Windowsではエンドユーザーの表示名を取得できるのだが、しかしそれはエンドユーザーが許可した場合だけだ(次の画像)。PhoneではAPIは存在するものの取得できないようである。
従って、(明示的にユーザー認証を行わない限り)ユーザー名はエンドユーザーの識別には使えない。
プライバシーオプションの変更画面(一部)
Windowsの[設定チャーム]−[PC設定の変更]−[プライバシー]で表示される。ここで[自分の名前、画像、その他のアカウント情報にアプリがアクセスできるようにする](赤枠内)をオンに設定してあると、アプリからエンドユーザーの表示名が取得できる。
ただし、エンドユーザーの表示名は、エンドユーザーが変更可能である(Webの「Microsoftアカウントの基本情報」ページで表示名を編集する)。
AppReceiptについて
アプリが購入できることを思い出してもらいたい。あるデバイスでエンドユーザーが購入したアプリは、別のデバイスでも利用できる。アプリ内購入したもの(例えば、ゲーム内で購入したアイテムなど)も、複数のデバイスにまたがって利用できる。このことから、アプリとエンドユーザーごとにその結び付きを一意に管理している仕組みがあると分かる。また、アプリ内購入ではアプリ側の対応も必要なのだから、この結び付きを一意に管理している仕組みをアプリからも利用できているはずだ*8。そのデータが「AppReceipt」であり、アプリを購入したときにストアから発行される領収書に相当するものである。そのIDは、アプリとエンドユーザーごとに一意に振られている。また、無料のアプリであっても、「0円で購入した」という扱いでAppReceiptが割り当てられる。
*8 アプリの購入の実装方法については「連載:Windowsストア・アプリ開発入門:第11回 アプリに広告を出す(前編:基礎知識編)」をご覧いただきたい。本稿では、そこまでの知識は必要としない。
エンドユーザーを識別するには?
AppReceiptのIDを利用すればよい。CurrentAppクラス(Windows.ApplicationModel.Store名前空間)のGetAppReceiptAsyncメソッドでAppReceiptが得られるので、それを解析してIDを取り出す。
実際のコードはちょっと複雑である。まず、AppReceiptの取得から説明しよう。CurrentAppクラスはWindowsの開発環境で使えず、開発時には代わりにCurrentAppSimulatorクラスを利用しなければならない(Phoneでは常にCurrentAppクラスを利用できる)。本番環境(ストアからインストールされた状態)だけのことなら1行で済むのだが、開発中のテストのことを考えると「#if」ディレクティブで切り分けた次のようなコードを書くことになる。
#if WINDOWS_APP
private static async System.Threading.Tasks.Task<string> GetAppReceiptInternalAsync()
{
// Windowsでは、開発環境と本番環境で取得方法が異なる
#if DEBUG
// 開発時のテストにはDEBUGビルドを使うものとする
// 開発環境ではCurrentAppSimulatorクラスから取得する
return await Windows.ApplicationModel.Store.CurrentAppSimulator.GetAppReceiptAsync();
#else
// 本番環境ではCurrentAppクラスから取得する
return await Windows.ApplicationModel.Store.CurrentApp.GetAppReceiptAsync();
#endif
}
#endif
#if WINDOWS_PHONE_APP
private static async System.Threading.Tasks.Task<string> GetAppReceiptInternalAsync()
{
// Phoneでは常にCurrentAppクラスから取得する
return await Windows.ApplicationModel.Store.CurrentApp.GetAppReceiptAsync();
}
#endif
WindowsもPhoneも、CurrentAppクラスのGetAppReceiptAsyncメソッドで取得できる。
ただし、Windowsでの開発時にはCurrentAppSimulatorクラスに置き換えなければならないため、このように「#if」ディレクティブで切り分ける。
取得できたAppReceiptは、XMLの文字列である。XMLを解析して、AppReceiptのIDを取り出す。XmlDocumentクラス(Windows.Data.Xml.Dom名前空間)を利用すると、次のようなコードになる。
private static async System.Threading.Tasks.Task<string> GetAppReceiptId()
{
// GetAppReceiptAsyncメソッドの呼び出し(前述)
string receipt = await GetAppReceiptInternalAsync();
// XmlDocumentオブジェクトを作り、GetAppReceiptAsyncメソッドで取得したデータを読み込ませる
var doc = new Windows.Data.Xml.Dom.XmlDocument();
doc.LoadXml(receipt);
// XmlDocumentオブジェクトから「AppReceipt」要素の「Id」属性の内容を取り出して返す
var appReceipt = doc.GetElementsByTagName("AppReceipt");
if (appReceipt == null || appReceipt[0] == null)
return null;
return appReceipt[0].Attributes.GetNamedItem("Id").InnerText;
}
なお、開発環境で取得されるIDは、本番環境で得られる値とは異なっている。
実行結果
C#の共有プロジェクトにユーザーコントロールを置き、そこにTextBlockコントロール(Windows.UI.Xaml.Controls名前空間)を配置し、前出のGetAppReceiptIdメソッドを使って取得したAppReceiptのIDを表示するようにコードを作成した。また、エンドユーザーの表示名の取得可否状態と、取得できた場合にはエンドユーザーの表示名も表示するようにした(次の画像)。詳細は、別途公開のサンプルコードをご覧いただきたい。
作成したサンプルアプリ(上:Windows 8.1、下:Windows Phone 8.1エミュレーター)
Windowsでは、アカウント情報にアプリがアクセスできるようにする設定(前述)をONにしてあるため、[NameAccessAllowed](名前へのアクセス許可)はTrueであり、[UserDisplayName](エンドユーザーの表示名)が取得できている。Phoneでは、APIは存在するのだが、常に取得できないようである。
それに対して、AppReceiptのIDはWindowsとPhoneの両者で常に取得できる(ただし、開発環境で得られる値は、本番環境とは異なる)。
まとめ
エンドユーザーを識別するためにAppReceiptを利用できる。ただし、アプリをまたいでの追跡には利用できない。
AppReceiptに含まれているその他の情報については、次のドキュメントを参照してほしい。
- MSDN:CurrentApp.GetAppReceiptAsync(英語、本稿執筆時点での日本語ページは旧版)
Copyright© Digital Advantage Corp. All Rights Reserved.