ByteScope

pm install-create

會改變裝置

開一個安裝工作階段,讓 base 與它的 split 作為一個不可分割的整體一起安裝。

指令
adb shell pm install-create
指令
套件(pm)
風險
會改變裝置

語法

pm install-create [-r] [-g] [-d] [-t] [-S <total bytes>]
pm install-write [-S <bytes>] <session> <name> <path or ->
pm install-commit <session>
pm install-abandon <session>

旗標與參數

token意義
-S <bytes>在 `install-create` 上是整組的總大小,讓安裝器先保留空間、空間不足就早點失敗。在 `install-write` 上是這個檔案的確切大小,而當位元組來自標準輸入時它是必填的,因為讀取端沒有別的方法知道到哪裡結束。
-作為 `install-write` 的路徑參數,代表從標準輸入讀取 APK 的位元組。
-r -g -d -t安裝選項,它們屬於 `install-create`。`install-commit` 完全不接受安裝參數,所以掛在 commit 上的旗標會被默默丟掉。

範例

  • pm install-create -r -S 82345678

    為一組 82 MB 的檔案開工作階段,回覆裡帶著工作階段 id。

  • pm install-write -S 41000000 1234567 base.apk /data/local/tmp/base.apk

    把一個已推上去的檔案加入工作階段。

  • pm install-commit 1234567

    把工作階段裡的東西當成一個操作安裝完成。

  • pm install-abandon 1234567

    丟掉工作階段,釋放暫存的位元組。

輸出怎麼讀

輸出範例

Success: created install session [1234567]

`install-create` 會用方括號回覆工作階段 id,那個數字就是後續每一步的參數。每個 `install-write` 回 `Success` 或 `Failure [INSTALL_FAILED_…]`,而最要緊的是 `install-commit` 的失敗——簽章、分割組合是否完整、驗證問題都是在那一刻才浮出來的,因為在那之前根本還沒和已安裝的 app 對照過。

輸出欄位

欄位意義
Success: created install session [<id>]給 install-write 與 install-commit 用的工作階段 id。
Success那次寫入,或那次 commit,被接受了。
Error: must specify a APK size從標準輸入讀取的 `install-write` 少了 -S。
INSTALL_FAILED_INVALID_APK整組對不起來:重複的 split、不匹配的 base。
INSTALL_FAILED_ABORTED工作階段被 abandon,或裝置上的提示沒有被回應。

需要什麼權限

和 `pm install` 一樣的授權 `adb` 連線,也一樣要求手機讀得到你暫存的檔案。工作階段多出來的,是一項你現在擁有、而且必須交還的資源。已建立的工作階段會把它的部分位元組留在 `/data/app/vmdl<id>.tmp`,直到 commit、abandon,或被 `PackageInstallerService` 判定過期,所以每一次沒有配上 `install-abandon` 的嘗試都多留一份下來——一種沒有權限錯誤會宣告、也沒有對話框會提到的慢性空間流失。用 `install-write ... -` 串流也不需要額外存取權,只需要那個必填的 `-S <bytes>`,因為傳輸層沒辦法在不同時拆掉那條要帶回結果的回覆的情況下表示檔案結束。`pm install` 會跳的裝置端提示在這裡也會跳,而且是在 commit 的時候跳而不是 create 的時候,所以無人看管的執行通常死在最後一步而不是第一步。

失敗訊息對照

訊息意義
Error: must specify a APK size從標準輸入讀取的 `install-write` 少了 `-S`。這句話連同那個錯字都是平台原本的用字。要注意的是這個錯誤送到時工作階段還開著,所以它是一種你得自己用 `install-abandon` 收拾的失敗,不是會自己回捲的那種。
Failure [INSTALL_FAILED_INVALID_APK: Split lib_a was defined multiple times]整組對不起來——這裡是兩個檔案宣稱了同一個 split 名稱。這是 commit 當下才給的判決,而那就是工作階段模型本身的形狀:在每一份都寫完之前,沒有任何東西會拿去和已安裝的 app 對照,所以在寫入階段犯的錯,要到最後才浮出來。
Failure [INSTALL_FAILED_ABORTED: Failed to commit install session 731045162 with command cmd package install-commit 731045162. Error: INSTALL_FAILED_ABORTED: Session was abandoned]巢狀的那種形狀。這一行裡兩個 token 表格都解釋得了,所以辨識器回報前面那個——框架自己選的那個代碼。但還是要把括號讀到底:`Session was abandoned` 才是在告訴你那個 id 已經被 abandon 過了,再 commit 一次永遠不會成功。

會改變什麼,以及怎麼回頭

安裝本身和 `pm install` 一樣會取代既有的 app。工作階段特有的風險是「開著沒收」:已建立的工作階段會在裝置上占著暫存的位元組,直到 commit 或 abandon,所以 `pm install-abandon <session>` 是必要的收尾步驟而不是可選項。

版本與廠商注意事項

  • `install-write` 的 split 名稱是工作階段內的標籤而不是路徑,桌面版 adb 也只是把檔名本身傳進去。
  • Android 7 之後 `cmd package install-create` 是同一個指令的較短路徑,`pm` 是包在外面的 script。
  • 從標準輸入串流之所以需要 `-S`,是因為傳輸層沒辦法在不同時拆掉回覆的情況下表示檔案結束。終止讀取的是大小而不是 EOF。

這個我們有 UI

APK Installer 會透過 USB 執行這個指令並解析回應——只要 Chromium 系瀏覽器,不必安裝 SDK,也不會上傳任何東西。

開啟 APK Installer

相關指令

和 pm install-create 會在同一次作業裡出現的指令。

指令做什麼
pm install安裝一個已經在裝置上的 APK,也就是 `adb install` 底層在做的事。
pm path印出組成某個已安裝套件的 APK 檔絕對路徑。
pm uninstall移除套件,或只針對一個 Android 使用者移除——這是不用 root 也能處理掉預載 app 的方法。

其他套件(pm)指令

指令做什麼
pm list packages列出已安裝的套件,也能一次帶出 APK 路徑、uid、版本碼與安裝來源。
pm disable-user在不移除的前提下,把套件對某個 Android 使用者關掉——比解除安裝安全,而且確定能還原。
pm clear清除某個 app 的資料——在 Android 13 之後也可以只清快取。
pm trim-caches要求系統一直丟掉快取檔案,直到剩下你指定的空間為止。

這些行為是在撰寫 Web ADB 工具背後的解析程式時,對照 AOSP、toybox 與核心原始碼查證的。真的會因 Android 版本或廠牌而異的地方,這一頁會直接說明,而不是給你一個在半數手機上都是錯的數字。

常見問題

adb shell 指令要怎麼執行?

在手機上打開開發者選項與 USB 除錯、接上線,然後從裝了 platform-tools 的機器執行 adb shell <指令>——或者只執行 adb shell 取得互動提示字元,再直接打指令、不用前綴。如果指令會輸出二進位資料(例如截圖),請改用 adb exec-out 而不是 adb shell:單純的 shell 服務會配一個終端機,而它會改寫換行位元組並毀掉資料。

adb shell 指令需要 root 嗎?

這份參考裡的都不用。它們以 shell 使用者身分執行,可以針對自己的 Android 使用者管理套件、讀取大多數 dumpsys 服務、寫入設定提供者、注入輸入,以及讀取共用儲存空間。需要 root 的是這份參考刻意避開的事:讀取其他 app 的私有資料(除了對可除錯版本使用 run-as)、寫入系統分割區,或直接讀 /data/anr。

為什麼在我的手機上輸出看起來不一樣?

不是 Android 版本就是廠商。有些旗標與欄位是從特定版本才有的,那些都在各指令頁註明了。其餘是廠商改動,而受影響最深的是 dumpsys:一份 dump 是除錯輸出,它的文字就是那個服務的作者最後印了什麼,而廠商既會改它也會把改動往回移植。請用名稱而不是位置來讀欄位,並把沒見過的格式當成差異而不是失敗。

可以用瀏覽器而不是終端機來跑嗎?

很多指令可以——本站的 Web ADB 工具從 Chromium 系桌面瀏覽器透過 WebUSB 和手機對話,不必安裝 SDK,也不會上傳任何東西。每一頁在有對應工具時都會連過去。有兩個限制值得知道:同一時間只有一個程式能持有 ADB 介面,所以桌面的 adb server 要先停掉;而 adb forward 與 adb reverse 在瀏覽器裡完全無法運作。

比較想按而不是打字?Web ADB Toolkit 會從瀏覽器透過 USB 執行這類指令。或者瀏覽全部指令。