ウェブアプリはリーチが広いため複数のプラットフォームで実行されます。リンクで簡単に共有できます。しかし、従来はオペレーティング・システムとの統合に欠けていました。つい最近までは、インストールすらできませんでした。幸いなことにそれが変更され、その統合を利用して PWA に便利な機能を追加できるようになりました。オプションをいくつか見てみましょう
ファイル システムの操作
ファイルを使用する一般的なユーザー ワークフローは次のようになります。
- デバイスでファイルやフォルダを選択して直接開きます。
- これらのファイルやフォルダに変更を加え、変更内容を直接保存します。
- 新しいファイルやフォルダを作成する。
File System Access API を使用する前は、ウェブアプリでこの作業を行うことはできません。ファイルを開くにはファイルのアップロードが必要で、変更を保存するにはユーザーがファイルをダウンロードする必要がありました。ウェブからアクセスしてユーザーのファイル システムに新しいファイルやフォルダを作成することもできません。
ファイルを開く
ファイルを開くには、window.showOpenFilePicker()
メソッドを使用します。このメソッドには、ボタンのクリックなどのユーザー操作が必要です。ファイルを開くための残りの設定は次のとおりです。
- ファイル システム アクセスのファイル選択ツール API からファイル ハンドルを取得します。これにより、ファイルに関する基本情報が得られます。
- ハンドルの
getFile()
メソッドを使用すると、File
という特別なタイプのBlob
を取得できます。これには、ファイルに関する追加の読み取り専用プロパティ(名前や最終更新日など)が含まれます。これは blob であるため、Blob メソッド(text()
など)を呼び出してそのコンテンツを取得できます。
// Have the user select a file.
const [ handle ] = await window.showOpenFilePicker();
// Get the File object from the handle.
const file = await handle.getFile();
// Get the file content.
// Also available, slice(), stream(), arrayBuffer()
const content = await file.text();
変更を保存しています
変更内容をファイルに保存するには、次のユーザー操作も必要です。
- ファイル ハンドルを使用して
FileSystemWritableFileStream
を作成します。 - ストリームに変更を加えます。更新してもファイルは更新されません。代わりに一時ファイルが作成されます。
- 最後に、変更が完了したらストリームを閉じます。これにより、変更が一時的なものから永続的なものに変わります。
次のコードで見てみましょう。
// Make a writable stream from the handle.
const writable = await handle.createWritable();
// Write the contents of the file to the stream.
await writable.write(contents);
// Close the file and write the contents to disk.
await writable.close();
ファイル処理
File System Access API を使用するとアプリ内からファイルを開くことができますが、その逆はどうでしょうか。ユーザーは、お気に入りのアプリをデフォルトで開くように設定できます。File Handling API は試験運用版の API で、インストール済みの PWA をユーザーのデバイスでファイル ハンドラとして登録できます。その際、ウェブアプリ マニフェストで PWA がサポートする MIME タイプとファイル拡張子を指定します。サポートされている拡張機能のカスタム ファイル アイコンを指定できます。
登録が完了すると、インストールした PWA がユーザーのファイル システムにオプションとして表示され、ユーザーがファイルを直接開くことができるようになります。 PWA がテキスト ファイルを読み取るためのマニフェスト設定の例を次に示します。
...
"file_handlers": [
{
"action": "/open-file",
"accept": {
"text/*": [".txt"]
}
}
]
...
URL の処理
URL 処理により、PWA はオペレーティング システムからスコープの一部であるリンクをキャプチャし、デフォルトのブラウザのタブではなく PWA ウィンドウ内にレンダリングできます。たとえば、PWA にリンクするメッセージを受信するか、PWA でディープリンク(特定のコンテンツを指す URL)をクリックすると、コンテンツがスタンドアロン ウィンドウで開きます。
この動作は、ユーザーが Chrome で PWA をインストールする場合など、WebAPK が使用されている場合、Android で自動的に有効になります。iOS と iPadOS にインストールされている PWA の URL を Safari からキャプチャすることはできません。
パソコンのブラウザ向けに、ウェブブラウザのコミュニティが新しい仕様を作成しました。この仕様は現在試験運用版で、新しいマニフェスト ファイル メンバー url_handlers
が追加されています。このプロパティには、PWA がキャプチャするオリジンの配列が必要です。PWA のオリジンは自動的に付与されます。他のオリジンは、web-app-origin-association
というファイルを使用して操作することを許可する必要があります。
たとえば、PWA のマニフェストが web.dev でホストされている場合に、app.web.dev のオリジンを追加する場合、次のようになります。
"url_handlers": [
{"origin": "https://app.web.dev"},
]
この場合、ブラウザは app.web.dev/.well-known/web-app-origin-association
にファイルが存在するかどうかを確認し、PWA スコープ URL から URL 処理を受け入れます。このファイルはデベロッパーが作成する必要があります。次の例では、ファイルは次のようになります。
{
"web_apps": [
{
"manifest": "/mypwa/app.webmanifest",
"details": {
"paths": [ "/*" ]
}
}
]
}
URL プロトコルの処理
URL 処理は標準の https
プロトコル URL で機能しますが、カスタム URI スキーム(pwa://
など)を使用することもできます。一部のオペレーティング システムでは、インストール済みのアプリがスキームを登録することで、この機能が取得されます。
PWA の場合、この機能はデスクトップ デバイスでのみ使用できる URL プロトコル ハンドラ API を使用して有効にします。モバイル デバイスにカスタム プロトコルを許可するには、アプリストアで PWA を配布する必要があります。
登録するには、registerProtocolHandler() メソッドを使用するか、マニフェストで protocol_handlers
メンバーを使用し、次のような目的のスキームと PWA のコンテキストで読み込む URL を指定します。
...
{
"protocol_handlers": [
{
"protocol": "web+pwa",
"url": "/from-protocol?value=%s"
},
]
}
...
URL from-protocol
を適切なハンドラにルーティングし、PWA でクエリ文字列 value
を取得できます。%s
は、操作をトリガーしたエスケープされた URL のプレースホルダです。<a href="web+pwa://testing">
などのリンクがある場合は、PWA で /from-protocol?value=testing
を開きます。
他のアプリへの発信
URI スキームを使用すると、どのプラットフォームでも、ユーザーのデバイスにインストールされた他のアプリ(PWA 以外も可)に接続できます。必要なのは、リンクを作成するか navigator.href
を使用して目的の URI スキームを指定し、URL エスケープされた形式で引数を渡すことだけです。
通話には tel:
、メール送信には mailto:
、テキスト メッセージには sms:
など、よく知られている標準的なスキームを使用できます。また、他のアプリの URL スキーム(よく知られたメッセージ、地図、ナビゲーション、オンライン会議、ソーシャル ネットワーク、アプリストアなど)について調べることもできます。
ウェブ共有
Web Share API を使用すると、PWA は共有チャネルを介して、デバイスにインストールされている他のアプリにコンテンツを送信できます。
API は、share
メカニズムを備えたオペレーティング システム(Android、iOS、iPadOS、Windows、ChromeOS など)でのみ使用できます。共有できるオブジェクトは次のとおりです。
- テキスト(
title
プロパティとtext
プロパティ) - URL(
url
プロパティ) - ファイル(
files
プロパティ)。
現在のデバイスが共有可能かどうかをチェックするには、テキストなどの単純なデータの場合、navigator.share()
メソッドの存在を確認します。ファイルを共有するには、navigator.canShare()
メソッドの存在を確認します。
共有アクションをリクエストするには、navigator.share(objectToShare)
を呼び出します。この呼び出しは、undefined
で解決するか、例外で拒否する Promise を返します。
ウェブ共有ターゲット
Web Share Target API を使用すると、PWA であるかどうかに関係なく、PWA をデバイス上の別のアプリからの共有操作のターゲットにできます。PWA は、別のアプリから共有されたデータを受信します。
現時点では、WebAPK と ChromeOS を使用する Android で利用できます。また、ユーザーが PWA をインストールした後にのみ機能します。アプリのインストール時に、ブラウザがオペレーティング システム内に共有ターゲットを登録します。
Web Share Target の下書き仕様で定義された share_target
メンバーを使用して、マニフェストでウェブ共有ターゲットを設定します。share_target
は、次のプロパティを持つオブジェクトに設定されます。
action
- 共有データの受け取りが想定される PWA ウィンドウで読み込まれる URL。
method
- アクションには、
GET
、POST
、PUT
などの HTTP 動詞メソッドが使用されます。 enctype
- (省略可)パラメータのエンコード型。デフォルトでは
application/x-www-form-urlencoded
ですが、POST
などのメソッドにmultipart/form-data
に設定することもできます。 params
- 共有データ(Web Share のキー
title
、text
、url
、files
から)を、ブラウザが URL(method: 'GET'
上)または選択されたエンコードを使用してリクエストの本文に渡す引数にマッピングするオブジェクト。
たとえば、マニフェストに以下を追加して、共有データ(タイトルと URL のみ)を受け取る PWA を定義できます。
...
"share_target": {
"action": "/receive-share/",
"method": "GET",
"params": {
"title": "shared_title",
"url": "shared_url"
}
}
...
前の例では、システム内のいずれかのアプリがタイトル付きの URL を共有していて、ユーザーがダイアログから PWA を選択した場合、ブラウザはオリジンの /receive-share/?shared_title=AAA&shared_url=BBB
への新しいナビゲーションを作成します。ここで、AAA は共有タイトル、BBB は共有 URL です。JavaScript を使用して、URL
コンストラクタで解析することにより、window.location
文字列からそのデータを読み取ることができます。
ブラウザは、マニフェストで指定された PWA の名前とアイコンを使用して、オペレーティング システムの共有エントリにフィードします。この目的で別のセットを選択することはできません。
詳細な例とファイルの受信方法については、Web Share Target API を使用して共有データを受信するをご覧ください。
連絡先ピッカー
Contact Picker API を使用すると、ユーザーのすべての連絡先を含むネイティブ ダイアログを表示するようデバイスにリクエストして、ユーザーが 1 つ以上の連絡先を選択できるようになります。PWA は、これらの連絡先から必要なデータを受信できます。
Contact Picker API は主にモバイル デバイスで使用でき、すべての処理は互換性のあるプラットフォームの navigator.contacts
インターフェースを通じて行われます。
navigator.contacts.getProperties()
でクエリするために使用可能なプロパティをリクエストし、目的のプロパティのリストを含む単一または複数の連絡先の選択をリクエストできます。
プロパティの例としては、name
、email
、address
、tel
などがあります。1 つ以上の連絡先を選択するようにユーザーに依頼する場合は、navigator.contacts.select(properties)
を呼び出し、取得するプロパティの配列を渡します。
次のサンプルでは、選択ツールが受け取った連絡先を一覧表示します。
async function getContacts() {
const properties = ['name', 'email', 'tel'];
const options = { multiple: true };
try {
const contacts = await navigator.contacts.select(properties, options);
console.log(contacts);
} catch (ex) {
// Handle any errors here.
}
}