ブラウザの対応を確認中…
USB ケーブルだけでカメラロールごと吸い出し、端末のストレージを覗き、逆向きにファイルを送り返す。どちら側にも何もインストールしない。
ファイルは USB ケーブル経由で端末とこのタブの間だけを移動する。端末には何もインストールされず、どこにもアップロードされない。
ブラウザの対応を確認中…
Android を Chromium 系ブラウザに USB でつなぐと、このページが端末のストレージを読む。カメラロールとその他のメディアフォルダを、撮影日ごとにまとめて、サイズと日付はファイルシステムからそのまま表示する。必要なものにチェックを入れれば、組み立てながらディスクへ書き込む ZIP として、あるいは 1 ファイルずつ PC に落ちてくる。同じページから端末の他のディレクトリを 1 階層ずつ見て回れるし、逆向きにファイルを送ることもできる。端末には何もインストールされず、どこにもアップロードされない。これは静的なページがケーブル越しに adbd と話しているだけで、タブを閉じれば終わる。
端末をつないで「ファイル転送」を選ぶと出てくるのが MTP——2008 年のカメラ向けに設計されたプロトコルで、ファイル操作のたびに端末が持つデータベースへの往復が発生し、本当のファイルハンドルというものが無い。結果として起きるのは、誰でも見覚えのある不具合だ。フォルダの件数が合わない、3 000 件のコピーが 1 700 件で無言のまま止まる、サムネイルでエクスプローラーが固まる、同じケーブル・同じバイト列なのに ADB の 1/10 の速度しか出ない、そして抜き差しするまで PC が端末を見失う。ADB の sync プロトコルはずっと小さい。ストリームを開き、パスを言い、バイトを受け取る。メディアデータベースではなくファイルシステムを読むので、一覧に出るものは実際にあるものだし、失敗したときは転送全体を止めずに失敗したファイル名を出す。
Android 11 以降、*アプリ* は特別な権限なしに共有ストレージ内の他アプリのファイルを読めない。だから多くのファイル管理・バックアップ系アプリは使いにくくなった。ADB の shell はアプリではない。shell ユーザーとして動き、主共有ボリュームに対する広い読み取り権限を持つので、/sdcard/DCIM、/sdcard/Pictures、/sdcard/Movies、/sdcard/Download は昔と同じようにケーブル越しに読める。このページが成立するのはそのためだ。scoped storage が本当に閉めたのは /sdcard/Android/data——アプリ自身のプライベート領域で、このページが読む場所ではない。Storage Analyzer がそこを覗くときは、shell で読めるかどうかがバージョンとメーカーで違うとはっきり書いてある。
カメラロールは数十 GB ある。「全部 ZIP でダウンロード」と言いながら先にブラウザ側でファイルを集める作りは、要するに全部をタブのメモリに載せると約束しているのと同じで、実機を相手にすると持たない。だからここでは逆向きに組む。写真は端末から小さなチャンクで読み、チャンクはそのままアーカイブのエンコーダへ渡り、エンコード結果はそのまま、転送開始前に指定したディスク上のファイルへ流れていく。合計が何 GB でもピークメモリは数百 KB だ。この設計は画面にも 2 つ表れる。アーカイブは圧縮せず *格納* する——JPEG や H.264 はすでに圧縮済みで、deflate をかけても端末の時間を使って 1 % 未満しか縮まない。そして従来の ZIP はサイズとオフセットを 32 ビットで持つため、約 4 GB を超える選択は「片方の PC では開けるのに別の PC では壊れている」アーカイブにせず、番号付きのパートに分ける。どのアーカイブにも収まらない単独ファイルは、その隣に元の名前で書き出す。ディスクへ直接書くには File System Access API が必要で、これは Chromium 系のみ、しかもクリック時に保存先を尋ねる。無い場合は 1 ファイルずつ保存に切り替え、そう明言する——それでもメモリ上で ZIP は組まない。
このページが使える端末側のサムネイルは存在しない。Android は自前のプレビューをアプリ専用のキャッシュに置いており shell からは触れず、sync プロトコルにはデコード済み画像の一部を要求する手段が無い。つまりプレビュー=原本を丸ごと転送で、1200 万画素で 3〜5 MB、4800 万画素なら 10 MB を超える。12 枚並ぶ画面は数十 MB になる。だからアルバムは画像オフの省データモードで始まり、表示範囲に入ったものを最大 3 件ずつ読み、先読みはせず、デコード済みサムネイルの保持量に上限を設け、プレビューにここまで何 MB 使ったかを出し続ける。HEIC は一覧には出るがプレビューはしない。デスクトップのブラウザがデコードできないからだ。
このページは端末上の何も削除しない。このツールキットでの削除は Storage Analyzer の担当で、しかもスキャナが見つけた対象に限る——ここには自由なパス指定の削除は無く、そこへ到達する道も無い。一方、ファイルを送るのは端末を変える操作なので、他のページと同じ警告レベルの確認を通り、書き込む前に正確な宛先パスを並べて見せる。ここから先は、Web ADB のハブに端末ダッシュボードと他のツールがあり、Storage Analyzer は何が容量を食っているかを示し、APK Installer は逆方向にソフトウェアを送る。
USB デバッグを有効にした端末をつなぎ、このページにメディアフォルダをスキャンさせたら、「この日以降すべて」で日付を選ぶ(または全選択)して「フォルダを選んで開始」を押す。PC 側のフォルダを一度選ぶだけで、端末から読みながらそのフォルダへ 1 個以上の ZIP が書き出される。アーカイブに収まらないファイルは同じフォルダに素のファイルとして置かれる。File System Access API が無いブラウザ(Chrome / Edge などの Chromium 系以外)では 1 ファイルずつ保存にフォールバックする。動くが遅く、1 ファイルあたりのサイズ上限がある。
足りる。アーカイブをブラウザに溜めないからだ。各ファイルはチャンクで読まれ、チャンクはそのまま ZIP エンコーダへ、エンコーダの出力はそのままディスク上のファイルへ流れる。バックアップが 600 MB でも 60 GB でも、タブが抱えるのは常に数百 KB だ。現実に効く上限は ZIP 形式そのもので、従来のアーカイブは 4 GiB までしか指せない。だから大きな選択は番号付きのパートに分割し、それより大きい単独ファイルはアーカイブに無理に入れず隣に元の名前でコピーする。
アルバム表示は有名なメディアフォルダの固定リスト——DCIM/Camera、Screenshots、Pictures、Movies、Download、それとよくあるメッセージアプリのパスいくつか——を順に調べ、実在するものだけ出す。中身の詰まった端末で `/sdcard` を丸ごと再帰的に歩くと往復だけで数分かかるからだ。リストに無いフォルダは、任意のディレクトリを打ち込める「ブラウズ」タブで開ける。`/sdcard/Android/data` は別問題で、アプリのプライベートファイルが入っており、shell がどこまで読めるかは Android 11 で変わり、メーカーによっても違う。だからこのページはそこを扱ったふりをしない。
ファイルはボリューム上にある。まだ MediaProvider のデータベースに入っていないだけで、ギャラリー系アプリはファイルシステムではなくそのデータベースを読む。だからファイル管理アプリならすぐ見つかるのに Google フォトには出ない。push のあとこのページは `MEDIA_SCANNER_SCAN_FILE` をブロードキャストしてスキャナを促し、その出力をそのまま表示する。ただしこの intent は Android 10 で非推奨になり、無視するメーカーもある。効かなかったときの正直な選択肢は、ファイル管理アプリでそのファイルを開く(多くの場合これで索引される)か、共有ストレージを再スキャンさせるために端末を再起動することだ。
端末ダッシュボード、shell ドロワー、その他すべての Web ADB ツール。
何が容量を食っているのか、どう空けるのか。
APK / APKS / XAPK / APKM をドラッグしてインストール。
転送中の CPU・メモリ・温度・I/O をライブで確認。