3 ポイント 投稿者 GN⁺ 11 시간 전 | 1件のコメント | WhatsAppで共有
  • 旅行日程・宿泊情報・PDFを表示する Travelbound は、実質的にはWebから受け取ったコンテンツを表示しているだけなのに、トラッキングや旅行広告まで含んでいたため、同じ情報を提供するWebページで置き換えてみた
  • Android仮想デバイスをroot化し、HTTP Toolkitでトラフィックを傍受したところ、ユーザー名とパスワードをURLに組み込んだAPIが、アプリの全コンテンツをJSONで返していることを確認した
  • RubyスクリプトとCronで最新のJSONを定期的に取得してHTMLを生成し、広告データは除外したうえで、日程やPDFなど必要なファイルだけを公開した
  • Web版ではコピー・印刷・保存・ブックマーク・検索が可能で、より多様なデバイスで動作し、元のアプリのトラッキングコードと広告も取り除いた
  • 元のアプリは43MBで、コンテンツのダウンロード後には124MBまで増えるが、Webページは0.05MBで、任意の画像を含めても35MBにとどまるため、HTMLとHTTPで配信される文書型コンテンツにはWebのほうが適している

Webページで十分だったTravelbound

  • 子どもが通う舞台芸術学校のDisneyland旅行の日程、交通手段、宿泊情報を確認するには、Travelboundアプリをインストールする必要があった
  • アプリの中核コンテンツは、Webで配信されるテキスト・画像・PDFリンクだった
  • Webページと異なる機能は、ユーザーにとって不利な次の2点だった
    • Google Accountに紐づいたトラッキングデータを開発者へ送信する
    • 同じ旅行会社が運営する別の旅行商品をinspirationsという名前で宣伝する
  • Webページであれば、コンテンツをコピー・印刷・保存・ブックマーク・検索でき、ほぼあらゆるデバイスで利用でき、アクセシビリティも高められる可能性がある

Androidアプリのトラフィック傍受

  • Android StudioのVirtual Device Managerで新しい仮想デバイスを作成し、adb shellが動作することを確認した
  • rootAVDを使ってAndroid 33の仮想デバイスをroot化した
    ./rootAVD.sh system-images/android-33/google_apis_playstore/x86_64/ramdisk.img  
    
  • root化は、**証明書ピンニング(Certificate Pinning)**を使うアプリに、中間者プロキシの自己署名TLS証明書を信頼させるために必要だった
    • root化していない場合、Travelboundのようなアプリは証明書を無効と判断して通信を拒否する
  • コールドブート後にMagiskを起動し、要求してきたアプリにsuアクセスを自動許可するよう設定した
    • 自動許可しないと、HTTP Toolkitはユーザーの応答を待たずに非特権モードで実行された
  • HTTP ToolkitでAndroid仮想デバイスのトラフィックを傍受した
    • 偽のVPNプロバイダーをインストールして、デバイスのトラフィックをプロキシへ転送する
    • Androidのセキュリティ制約により、インストールされたルートCA証明書は手動で追加する必要があった
  • Play StoreからTravelboundをインストールした後、ノイズを減らすため、そのアプリのトラフィックだけをプロキシするよう構成した

API呼び出しとデータ構造

  • アプリは旅行グループのユーザー名とパスワードを連結し、次の形式のAPI URLを呼び出していた
    https://travelbound.api.vamoos.com/api/itineraries/…}  
    
  • ユーザー名とパスワードは旅行グループ全体で共有される認証情報だった
  • APIレスポンスのJSONには、アプリが表示するすべてのコンテンツが入っていた
    • 旅行日程の各区間を含む配列
    • inspirations広告の配列
    • 他のセクションから参照される画像などのファイルを含む相互参照配列
  • アプリが表示するHTMLコードまでデータに含まれており、コンテンツの配信方式自体はWebページに似ていた
  • S3画像URLは有効期限が比較的短いため、コンテンツが変わらなくてもJSONを定期的に再取得する必要があった
    • 別の方法は画像をローカルにキャッシュすることで、元のアプリはこの方式を使っているように見えた

JSONをHTMLに変換

  • Rubyスクリプトを書き、Cronスケジュールに従って最新のJSONを取得し、HTMLページを生成するよう構成した
  • 生成過程で、データスキーマのoverlayRowsに相当するinspirations広告を完全に除外した
  • Webページには次の情報だけを表示した
    1. 旅行日程の項目
    2. 広告や日程から参照されていないすべてのファイル
  • 2つ目のリストは、PDFダウンロードリンクを1か所に集める簡単な方法として利用した
  • 生成されたページは、既存の旅行グループに提供されていたものと同じパスワードで保護した
  • 元のJSONを<details>要素に入れ、既存のスクリプトが把握していないスキーマデータが後から現れるか確認できるようにした

より小さく柔軟になったWeb版

  • Webページは元のアプリほど華やかではないが、サイズがはるかに小さく、Webの基本機能を追加実装なしで提供する
  • コンテンツをコピー・印刷・保存・ブックマーク・検索でき、より多様なデバイスからアクセスできる
  • トラッキングコードと広告を取り除き、元のアプリにあった2つの不要な機能もなくした
  • アクセシビリティを正式に監査したわけではないが、元のアプリには、単純なWeb版よりも支援技術で使いにくそうな要素があった

サイズと配布方式の比較

  • 元のTravelboundアプリは初期状態で43MBあり、追加コンテンツをダウンロードした後は124MBまで大きくなる
  • 代替Webページは0.05MBで、画像を任意ですべてダウンロードすると35MBが追加される
  • 旅行グループには両方の方法を共有し、ユーザーがアプリとWebページのどちらでも好きな方法を選べるようにした
  • 一部の作業にはアプリが適しているが、すでにHTMLで書かれHTTPで配信されているTravelboundのコンテンツは、アプリが必要な例ではない
  • アプリストア配布はコストと開発負担を増やすもので、このような文書型コンテンツをアプリに限定すると、Webに直接公開する場合よりも利用できる人と基本機能が減ってしまう

1件のコメント

 
Lobste.rsの意見
  • 本質的には単なるWebページにすぎないサービスがアプリ肥大化につながる状況にはうんざりしていたが、自分だけではなくてよかった。
    AndroidではWebページのショートカット作成がユーザーにあまり分かりやすく提示されないので、企業がアプリを好むのも理解はできる。だが、パスワードをアプリへのリンクと一緒にSMSで送るようなサービスなら、Webアプリが最適だ。パスワードページへ直接リンクすればそれで済む。
    /e/OSのアプリストアには、Google MapsのWeb版のような項目を集めた「web apps」セクションもある。PWA自体は使いやすいが、標準のChromeやメーカー製Androidがショートカット作成をどれだけ積極的に案内し、目立つ形で提供しているのかは分からない。
    今のやり方がユーザーのためでないのは明らかで、どう改善すべきか考える必要がある。

  • 一般ユーザー、特にコンピューターに慣れていない人にとって、アプリとWebページの違いは実質的にはデスクトップやホーム画面のショートカットくらいしかない。
    Webページのショートカットをそのまま配布できさえすれば、非常に低コストなアプリ開発手法になり、多くのアプリは実際それで作られていたかもしれない。

    • iOSのSafariでWebページを開いたあと、共有ボタンから「View More」を経て「Add to Home Screen」を選ぶと、ホーム画面にアイコンを追加できる。
      このアイコンを押すと、新しいブラウザータブではなく、通常のアプリのような独立したウィンドウが開く。私はApp Storeに公開せず、この方法で自作の家族向け支出管理ツールを配布している。
  • 数多くの「アプリ」は、単なるWebページで十分だ。大した理由もないのに、些細な機能を使うためだけにまずアプリをインストールしなければならない状況が多すぎてうんざりする。
    ローカル機器との接続のためにアプリを使うのは理解できるが、実際にはアプリが中央サーバーを経由してローカル機器と通信するように作られているシステムもある。そうなると、アプリをインストールしなければならない唯一の名分すら消えてしまう。
    初期のiPhoneはWebページをアプリプラットフォームにしようとしていたが、結局は今のようなひどいエコシステムになってしまった。