ウェブアプリは幅広いユーザーにリーチできます。複数のプラットフォームで実行できます。リンクを介して簡単に共有できます。しかし、従来はオペレーティング システムとの統合が欠落していました。つい最近までは、インストールすらできませんでした。幸い、状況は変わり、この統合を利用して 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 を使用すると、アプリ内からファイルを開くことができますが、その逆はどうでしょうか?ユーザーは、お気に入りのアプリをファイルのデフォルトの開くアプリとして設定したいと考えています。ファイル処理 API は、インストールされた PWA が、ユーザーのデバイスでファイル ハンドラとして登録し、ウェブアプリ マニフェストで PWA がサポートする MIME タイプとファイル拡張子を指定できるようにする試験運用版の API です。サポートされている拡張機能にカスタム ファイル アイコンを指定できます。
登録すると、インストールされた PWA がユーザーのファイル システムのオプションとして表示され、ユーザーは 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 で機能しますが、pwa://
などのカスタム URI スキームを使用することもできます。いくつかのオペレーティング システムでは、インストール済みのアプリがスキームを登録することで、この機能を利用できます。
PWA の場合、この機能は URL プロトコル ハンドラ API を使用して有効にします。この 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 が別のアプリによって共有されたデータを受信します。
現在、この機能は Android の WebAPK と ChromeOS で利用可能で、ユーザーが PWA をインストールした後にのみ機能します。ブラウザは、アプリのインストール時にオペレーティング システム内に共有ターゲットを登録します。
マニフェストでウェブ共有ターゲットを設定するには、ウェブ共有ターゲットのドラフト仕様で定義されている share_target
メンバーを使用します。share_target
は、次のプロパティを持つオブジェクトに設定されます。
action
- 共有データを受信する予定の PWA ウィンドウに読み込まれる URL。
method
- アクションに使用される HTTP 動詞メソッド(
GET
、POST
、PUT
など)。 enctype
- (省略可)パラメータのエンコード タイプ。デフォルトは
application/x-www-form-urlencoded
ですが、POST
などのメソッドではmultipart/form-data
に設定することもできます。 params
- 共有データ(Web 共有のキー
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()
を使用して照会可能なプロパティをリクエストし、目的のプロパティのリストを使用して、1 つまたは複数の連絡先の選択をリクエストできます。
プロパティの例としては、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.
}
}