ストアアプリで自分のアプリからデータを共有する #win8dev_jp #wpdev_jp
前回は共有を呼び出すまででしたので、今回は実際にデータを共有します。
データを共有する
共有できるデータはタイトルやテキスト、URL、ファイルなど様々で、共有操作を行うと対応している(そのデータ受け取れるよ!と宣言してくれている)アプリが一覧に表示されます。
ここで注意しないといけないのは、その場面にもっとも適切なデータのみを共有してください。共有したデータがどのように使われるかは相手のアプリ次第です。例えば、画像のみを渡すとアルバムに保管してくれるのに、URLも一緒に渡すと、画像には一切触れられずにURLのみを処理されるなんてことも起こりえます。
- ユニバーサルアプリプロジェクトを準備
- DataTransferManagerを利用して共有を行う
ユニバーサルアプリプロジェクトを準備
プロジェクトを作成します。前回と同じものです。
DataTransferManagerを利用して共有を行う
イベントのハンドル
// 任意の場所で購読
DataTransferManager.GetForCurrentView().DataRequested += OnDataRequested;
これは画面毎ではなく、どこで記述しても構いません。逆に、一度購読すると、解除するまでは一番最初に購読した処理が動作し続けます。画面毎に共有するデータが違う場合は画面遷移の前後で購読と解除を行うと簡単です。
/// <summary> /// このページがフレームに表示されるときに呼び出されます。 /// </summary> /// <param name="e"></param> protected override void OnNavigatedTo(NavigationEventArgs e) { DataTransferManager.GetForCurrentView().DataRequested += OnDataRequested; } /// <summary> /// Page がアンロードされて親 Frame の現在のソースではなくなった直後に呼び出されます。 /// </summary> /// <param name="e"></param> protected override void OnNavigatedFrom(NavigationEventArgs e) { DataTransferManager.GetForCurrentView().DataRequested -= OnDataRequested; }
アプリの状態管理がきちんと行えているのであれば、起動時に一度購読して、あとはアプリの状態に合わせてセットする共有データを切り替えれば良いでしょう。
データのセット
DataRequestedEventArgs.Request.Data
のたくさんあるプロパティに対して任意のデータをセットします。
private void OnDataRequested(DataTransferManager sender, DataRequestedEventArgs e) { e.Request.Data.Properties.Title = "データのタイトル"; e.Request.Data.Properties.Description = "データの説明"; e.Request.Data.SetText("共有するテキスト!"); }
ただし、タイトルは必須です。タイトルがない場合やデータがない場合はエラーになります(Windows Phoneはうんともすんとも言わなくなります)。
時間がかかるデータやリソースを消費するデータのセット
時間がかかるデータやリソースを消費するデータを共有する場合は、デリゲートを共有して、必要に応じて処理することができます。例えば、ファイルを共有するときに、ファイルが共有できることだけ(デリゲートのみ)を伝えて(ファイルを受け取れるアプリを含む)相手のアプリ一覧を表示し、ファイルが使われる場合はデリゲートの実行、ファイルが使われない場合は時間やリソースがかかるデータを扱わずに済むといったことができます。
// ファイルをデリゲートで共有するサンプル // 共有データの拡張子 e.Request.Data.Properties.FileTypes.Add(".jpg"); // デリゲートの共有 e.Request.Data.SetDataProvider( StandardDataFormats.StorageItems, this.OnDeferredImageRequestedHandler); // 実際の処理 async void OnDeferredImageRequestedHandler(DataProviderRequest request) { // 非同期処理の開始(非同期の場合に必要) var deferral = request.GetDeferral(); try { // マニフェストの[機能]で[画像ライブラリ]の指定が必要 #if WINDOWS_APP // 適当なファイルを用意 var files = (await KnownFolders.PicturesLibrary.GetFilesAsync()) .Where(x => Path.GetExtension(x.Name) == ".jpg") .Take(1); #else // 適当なファイルを用意 var files = (await KnownFolders.CameraRoll.GetFilesAsync()) .Where(x => Path.GetExtension(x.Name) == ".jpg") .Take(1); #endif // 共有データをセット request.SetData(files); } finally { // 非同期処理の終了(非同期の場合に必要) deferral.Complete(); } }
このコードでは、Windows ストアアプリではピクチャライブラリから、Windows Phoneではカメラロールから、それぞれ写真を1枚取得して共有しています。シナリオが適当ですが、共有の雰囲気。雰囲気、大事。