他のアプリとコンテンツを共有する
アプリ間でのコンテンツの共有は、ファイルの操作やコンテンツのコピーがデスクトップ オペレーティング システムよりも直感的ではないモバイル デバイスで普及していました。 たとえば、モバイルでは、テキスト メッセージを送信して画像を友人と共有するのが一般的です。 ただし、コンテンツの共有はモバイル デバイスに予約されていません。Windows 上のアプリ間でも共有できます。
コンテンツの共有には 2 つの方向があり、双方向はプログレッシブ Web アプリ (PWA) によって処理できます。
方向 | 説明 |
---|---|
コンテンツの共有 | コンテンツを共有するために、PWA はコンテンツ (テキスト、リンク、ファイルなど) を生成し、共有コンテンツをオペレーティング システムに渡します。 オペレーティング システムを使用すると、ユーザーは、そのコンテンツを受信するために使用するアプリを決定できます。 |
共有コンテンツの受信 | コンテンツを受信するために、PWA はコンテンツ ターゲットとして機能します。 PWA は、コンテンツ共有ターゲットとしてオペレーティング システムに登録されます。 |
共有ターゲットとして登録する PWA は、ネイティブに OS に統合され、ユーザーとのエンゲージメントが高いと感じます。
コンテンツの共有
PWA は 、Web 共有 API を使用して、オペレーティング システム共有ダイアログの表示をトリガーできます。
注:
Web 共有は HTTPS 経由で提供されるサイト (PWA の場合) でのみ機能し、ユーザー アクションに応答して呼び出すことができます。
リンク、テキスト、ファイルなどのコンテンツを共有するには、次に示すように、 navigator.share
関数を使用します。
navigator.share
関数は、次のプロパティの少なくとも 1 つを持つオブジェクトを受け入れます。
-
title
: 共有コンテンツの短いタイトル。 -
text
: 共有コンテンツの詳細な説明。 -
url
: 共有するリソースのアドレス。 -
files
: 共有するファイルの配列。
function shareSomeContent(title, text, url) {
if (!navigator.share) {
return;
}
navigator.share({title, text, url}).then(() => {
console.log('The content was shared successfully');
}).catch(error => {
console.error('Error sharing the content', error);
});
}
上記のコードでは、まず、ブラウザーが Web 共有をサポートしているかどうかを確認し、 navigator.share
が定義されているかどうかをテストします。
navigator.share
関数は、共有が成功したときに解決され、エラーが発生したときに拒否する Promise オブジェクトを返します。
Promise はここで使用されるため、上記のコードは次のように async
関数として書き換えることができます。
async function shareSomeContent(title, text, url) {
if (!navigator.share) {
return;
}
try {
await navigator.share({title, text, url});
console.log('The content was shared successfully');
} catch (e) {
console.error('Error sharing the content', e);
}
}
Windows では、上記のコードによって共有ダイアログがトリガーされ、ユーザーは共有コンテンツを受け取るアプリを選択できます。 共有ダイアログを次に示します。
ユーザーが共有コンテンツを受け取るためにアプリを選択したら、選択した方法でアプリを処理するのはこのアプリ次第です。 たとえば、電子メール アプリでは、メールの件名として title
を使用し、 text
を電子メール本文として使用する場合があります。
ファイルの共有
navigator.share
関数は、ファイルを他のアプリと共有するためのfiles
配列も受け入れます。
共有する前に、共有ファイルがブラウザーでサポートされているかどうかをテストすることが重要です。 共有ファイルがサポートされているかどうかを確認するには、 navigator.canShare
関数を使用します。
function shareSomeFiles(files) {
if (navigator.canShare && navigator.canShare({files})) {
console.log('Sharing files is supported');
} else {
console.error('Sharing files is not supported');
}
}
files
共有オブジェクト メンバーは、File
オブジェクトの配列である必要があります。
ファイル インターフェイスの詳細については、こちらをご覧ください。
File
オブジェクトを構築する方法の 1 つは次のとおりです。
- まず、
fetch
API を使用してリソースを要求します。 - 次に、返された応答を使用して新しい
File
を作成します。
その方法を次に示します。
async function getImageFileFromURL(imageURL, title) {
const response = await fetch(imageURL);
const blob = await response.blob();
return new File([blob], title, {type: blob.type});
}
上記のコードでは、
-
getImageFileFromURL
関数は、URL を使用してイメージをフェッチします。 -
response.blob()
関数は、イメージをバイナリ ラージ オブジェクト (BLOB) に変換します。 - このコードでは、BLOB を使用して
File
オブジェクトを作成します。
コンテンツの共有のデモ
PWAmp は、 navigator.share
関数を使用してテキストとリンクを共有するデモ PWA です。
共有機能をテストするには:
[PWAmp] に移動します。
アドレス バーの右側にある [使用可能なアプリ] をクリックします 。PWA として ) をインストールします。
インストールされている PWAmp PWA で、ローカル オーディオ ファイルをインポートします (アプリ ウィンドウにドラッグします)。 たとえば、MicrosoftEdge/Demos リポジトリを複製した場合、
C:\Users\username\GitHub\Demos\pwamp\songs
などの (Demos リポジトリ > pwamp/songs ディレクトリ) に.mp3
ファイルのローカル コピーがあります。新しくインポートした曲の横にある [ 曲の操作 (...)] ボタンをクリックし、[ 共有] を選択します。 [Windows 共有 ] ダイアログが表示されます。
コンテンツを共有するアプリを選択します。
PWAmp ソース コードは GitHub にあります。 PWAmp アプリは、 app.js ソース ファイル内の Web 共有 API を使用します。
共有コンテンツの受信
Web 共有ターゲット API を使用すると、PWA を登録して、システム共有ダイアログにアプリとして表示できます。 その後、PWA は Web Share Target API を使用して、他のアプリから送信される共有コンテンツを処理できます。
注:
共有ターゲットとして登録できるのは、インストールされている PWA のみです。
ターゲットとして登録する
共有コンテンツを受信するには、まず PWA を共有ターゲットとして登録します。 登録するには、 share_target
マニフェスト メンバーを使用します。 アプリのインストール時に、オペレーティング システムは share_target
メンバーを使用して、アプリをシステム共有ダイアログに含めます。 オペレーティング システムは、コンテンツを共有するために、アプリがユーザーによって選択されたときに何を行うかを認識します。
share_target
メンバーには、システムが共有コンテンツをアプリに渡すために必要な情報が含まれている必要があります。 次のマニフェスト コードを考えてみましょう。
{
"share_target": {
"action": "/handle-shared-content/",
"method": "GET",
"params": {
"title": "title",
"text": "text",
"url": "url",
}
}
}
ユーザーが共有コンテンツのターゲットとしてアプリを選択すると、PWA が起動します。
GET
HTTP 要求は、action
プロパティで指定された URL に対して行われます。 共有データは、 title
、 text
、および url
クエリ パラメーターとして渡されます。 次の要求が行われます: /handle-shared-content/?title=shared title&text=shared text&url=shared url
。
他のクエリ パラメーター名を使用する既存のコードがある場合は、既定の title
、 text
、 url
クエリ パラメーターを他の名前にマップできます。 次の例では、 title
、 text
、および url
クエリ パラメーターが、 subject
、 body
、および address
にマップされます。
{
"share_target": {
"action": "/handle-shared-content/",
"method": "GET",
"params": {
"title": "subject",
"text": "body",
"url": "address",
}
}
}
GET 共有データを処理する
PWA コードの GET 要求で共有されるデータを処理するには、 URL
コンストラクターを使用してクエリ パラメーターを抽出します。
window.addEventListener('DOMContentLoaded', () => {
console url = new URL(window.location);
const sharedTitle = url.searchParams.get('title');
const sharedText = url.searchParams.get('text');
const sharedUrl = url.searchParams.get('url');
});
POST 共有データを処理する
共有データがアプリに格納されているコンテンツの一部を更新するなど、何らかの方法でアプリを変更する場合は、 POST
メソッドを使用し、 enctype
でエンコードの種類を定義する必要があります。
{
"share_target": {
"action": "/post-shared-content",
"method": "POST",
"enctype": "multipart/form-data",
"params": {
"title": "title",
"text": "text",
"url": "url",
}
}
}
POST
HTTP 要求には、multipart/form-data
としてエンコードされた共有データが含まれています。 このデータには、サーバー側のコードを使用して HTTP サーバー上でアクセスできますが、ユーザーがオフラインの場合は機能しません。 より良いエクスペリエンスを提供するには、次のように、サービス ワーカーを使用し、 fetch
イベント リスナーを使用してサービス ワーカーからデータにアクセスします。
self.addEventListener('fetch', event => {
const url = new URL(event.request.url);
if (event.request.method === 'POST' && url.pathname === '/post-shared-content') {
event.respondWith((async () => {
const data = await event.request.formData();
const title = data.get('title');
const text = data.get('text');
const url = data.get('url');
// Do something with the shared data here.
return Response.redirect('/content-shared-success', 303);
})());
}
});
上記のコードでは、
サービス ワーカーは、
POST
要求をインターセプトします。何らかの方法でデータを使用します (コンテンツをローカルに格納する場合など)。
ユーザーを成功ページにリダイレクトします。 これにより、ネットワークがダウンしている場合でもアプリを動作させることができます。 アプリでは、コンテンツをローカルにのみ保存するか、接続が復元されたときに ( バックグラウンド同期を使用するなど) 後でサーバーにコンテンツを送信することもできます。
共有ファイルを処理する
アプリでは、共有ファイルを処理することもできます。 PWA 内のファイルを処理するには、 POST
メソッドと multipart/form-data
エンコードの種類を使用する必要があります。 さらに、アプリで処理できるファイルの種類を宣言する必要があります。
{
"share_target": {
"action": "/store-code-snippet",
"method": "POST",
"enctype": "multipart/form-data",
"params": {
"title": "title",
"files": [
{
"name": "textFile",
"accept": ["text/plain", "text/html", "text/css",
"text/javascript"]
}
]
}
}
}
上記のマニフェスト コードは、アプリがさまざまな MIME 型のテキスト ファイルを受け入れることをシステムに指示します。
.txt
などのファイル名拡張子は、accept
配列で渡すこともできます。
共有ファイルにアクセスするには、前と同様に要求 formData
を使用し、次のように FileReader
を使用してコンテンツを読み取ります。
self.addEventListener('fetch', event => {
const url = new URL(event.request.url);
if (event.request.method === 'POST' && url.pathname === '/store-code-snippet') {
event.respondWith((async () => {
const data = await event.request.formData();
const filename = data.get('title');
const file = data.get('textFile');
const reader = new FileReader();
reader.onload = function(e) {
const textContent = e.target.result;
// Do something with the textContent here.
};
reader.readAsText(file);
return Response.redirect('/snippet-stored-success', 303);
})());
}
});