wheatandcatの開発ブログ

技術系記事を投稿してます

Androidで使用できるWeb Share Target APIを実装

概要

以前、iOSでショートカット経由で共有シートからAPIを実行する方法を紹介した。今回はそのAndroid版をまとめる。
www.wheatandcat.me

Androidでは Web Share Target API を実装するのが手軽なので、PWA化したWebサイトに組み込んで検証した。

Web Share Target API

w3c.github.io

Web Share Target API は共有ボタン押下時に共有先としてWebアプリを選べる仕組み。選択されたURLやタイトルなどの情報を受け取れる。実装すると画像の赤枠で選択できるようになる。

ネイティブで同様のことをする場合は Android アプリを作成し Intent を実装する必要があり開発コストがかかる。
developer.android.com

そこで今回は PWA に Web Share Target API を実装。
※PWA の Web Share Target は iOS では非対応のため、現状は Android のみ動作。

リポジトリ

github.com

使用技術

  • React + PWA + Vite + Tailwind CSS

実装

以下を参考に、React + Vite でPWA環境を用意。
vite-pwa-org.netlify.app

1. manifest に share_target を追加

public/manifest.webmanifest

{
  "share_target": {
    "action": "/share-target",
    "method": "POST",
    "enctype": "application/x-www-form-urlencoded",
    "params": {
      "title": "title",
      "text": "text",
      "url": "url"
    }
  }
}

2. Service Worker で受信してリダイレクト

public/sw.js

self.addEventListener("fetch", (event) => {
  const url = new URL(event.request.url);

  if (event.request.method === "POST" && url.pathname === "/share-target") {
    event.respondWith(
      (async () => {
        const formData = await event.request.formData();
        const title = formData.get("title") || "";
        const text = formData.get("text") || "";
        const urlParam = formData.get("url") || text || "";

        const params = new URLSearchParams();
        if (title) params.set("title", title);
        if (text) params.set("text", text);
        if (urlParam) params.set("url", urlParam);

        // 受信データをクエリに載せて画面へリダイレクト
        return Response.redirect(`/?${params.toString()}`, 303);
      })()
    );
    return;
  }
});

3. React 側でクエリから取り出して表示

src/App.tsx

const getShareDataFromLocation = () => {
  const params = new URLSearchParams(window.location.search);
  return {
    title: params.get("title") ?? "",
    text: params.get("text") ?? "",
    url: params.get("url") ?? "",
  };
};

function App(): JSX.Element {
  const [shareData, setShareData] = useState<ShareData | null>(() =>
    getShareDataFromLocation()
  );
  // ...
}

動作確認(デモ)

完成物は以下で試せる。
share-target-demo.vercel.app

検証手順:

  1. Android 端末で以下の QR を読み取る → デモを開く

  2. 画面の「ホーム画面に追加」をタップ

  3. ホームにPWAが追加される

  4. 任意のWebページで共有ボタン → 「Share Target API」を選択

  5. 共有された URL などがクエリで渡り、画面に表示される

まとめ

  • Android では Web Share Target API により PWA を共有先として選べる
  • Service Worker で受け取り → 画面へリダイレクト → React でクエリを読むだけで実装は完結
  • iOS 非対応だが、Web サービスでもアプリ的な共有連携が組めるのは便利