pm disable-user
會改變裝置在不移除的前提下,把套件對某個 Android 使用者關掉——比解除安裝安全,而且確定能還原。
- 指令
- adb shell pm disable-user
- 指令
- 套件(pm)
- 風險
- 會改變裝置
語法
pm disable-user [--user <id>] <package>
pm enable [--user <id>] <package>旗標與參數
| token | 意義 |
|---|---|
| --user <id> | 要改哪個 Android 使用者。狀態是每個使用者各自的,還原的指令也是,所以明確寫出來是值得的。 |
範例
pm disable-user --user 0 com.manufacturer.bloat把預載 app 對主要使用者關掉。
pm enable --user 0 com.manufacturer.bloat再開回來。
pm list packages -d --user 0向平台而不是向記憶確認目前停用了哪些。
輸出怎麼讀
輸出範例
Package com.manufacturer.bloat new state: disabled-user這個指令會印出它「讀回來」的狀態,而那不一定是你要的狀態——這正是「檢查有沒有 error 這個字」不夠用的原因。對平台不願重新啟用的套件下 `pm enable`,它會印 `new state: disabled-user` 並以 0 結束。要比的是狀態本身,不是有沒有 error。
輸出欄位
| 欄位 | 意義 |
|---|---|
| disabled-user | 因為使用者(或這個指令)關掉而 off。 |
| disabled | 因為 app 自己或框架關掉而 off。 |
| disabled-until-used | 在被用到之前保持 off。 |
| enabled | 明確是 on。 |
| default | 沒有覆寫:照 app 資訊清單宣告的來,通常是 on。 |
需要什麼權限
一條授權過的 `adb` 連線;不用 root 也不用 `su`。這正是「刪不掉的預載 app 該怎麼辦」標準答案就是它的原因——啟用狀態是每個使用者各自的覆寫,而 shell 被允許設定它,所以不會寫到唯讀的系統分割區,也沒有什麼要先解鎖。有兩個和存取權有關的細節會影響你怎麼讀回覆。`--user <id>` 指的是「要改誰的覆寫」,不願意讓 shell 碰別人狀態的版本會拒絕,而不是安靜地改到你自己那份。還有,平台保留拒絕重新啟用的權利:對它不打算開回來的套件下 `pm enable`,它會印出一行狀態並以 0 結束,所以這裡的訊號不是結束碼,是那行字裡的狀態。`parseEnabledStateLine` 也會檢查回答裡的套件就是你問的那個套件,因為回答別的東西的裝置,回答的是別的問題。
失敗訊息對照
| 訊息 | 意義 |
|---|---|
| Package com.example new state: disabled-user | 這行是 `pm enable` 印的,是一次穿著成功外衣的拒絕:指令跑完了、以 0 結束,而 app 還是關著。所以 `classifyPmEnabledChange` 比的是「回來的狀態」和「你要的狀態」,而不是掃有沒有 error 這個字——會動的還原按鈕和只會嘴上說有動的還原按鈕,差別就在這裡。 |
| Warning: Unknown option | 選項迴圈沒認出某個旗標,實務上就是在太舊的版本上用了 `--user`。`isFailureLine` 就算它用的字比較溫和也算成失敗,因為一次沒看懂你旗標的執行,就沒有做你要它做的事,不管它做了什麼。 |
| Exception occurred while executing 'disable-user': | 外層抓到 `Throwable`,下一行會說是什麼。`IllegalArgumentException` 與 `NameNotFoundException` 都是這樣出現的,兩個都指向拼錯或不存在的套件;這時完全不會印狀態行,分類器就是靠這點把它和「印了一個你不想要的狀態」分開。 |
會改變什麼,以及怎麼回頭
app 不會執行、不會收到廣播,也會從那個使用者的啟動器消失;什麼都不會被刪掉。`pm enable --user <id> <pkg>` 就能開回來。停用其他 app 依賴的系統服務,壞掉的方式往往是「過一陣子才發現」,所以一次只改一個套件,並觀察什麼停止運作。
版本與廠商注意事項
- `disable-user` 設定的正是這個指令會讀回來的狀態,所以已經被別的途徑停用的套件會回答 `disabled` 或 `disabled-until-used`。三者的意思都是「它沒在跑」。
- 報出一個不是你要求的狀態的成功訊息,是一種語氣很平靜的失敗。有沒有讀這一行,就是誠實的還原按鈕與壞掉的還原按鈕之間的差別。
這個我們有 UI
Android Debloat Tool 會透過 USB 執行這個指令並解析回應——只要 Chromium 系瀏覽器,不必安裝 SDK,也不會上傳任何東西。
相關指令
和 pm disable-user 會在同一次作業裡出現的指令。
| 指令 | 做什麼 |
|---|---|
| pm uninstall | 移除套件,或只針對一個 Android 使用者移除——這是不用 root 也能處理掉預載 app 的方法。 |
| pm list packages | 列出已安裝的套件,也能一次帶出 APK 路徑、uid、版本碼與安裝來源。 |
| dumpsys package | 套件管理員知道的一切:版本、路徑、flags、安裝來源,以及每個使用者的狀態。 |
其他套件(pm)指令
| 指令 | 做什麼 |
|---|---|
| pm path | 印出組成某個已安裝套件的 APK 檔絕對路徑。 |
| pm clear | 清除某個 app 的資料——在 Android 13 之後也可以只清快取。 |
| pm trim-caches | 要求系統一直丟掉快取檔案,直到剩下你指定的空間為止。 |
| pm install | 安裝一個已經在裝置上的 APK,也就是 `adb install` 底層在做的事。 |
| pm install-create | 開一個安裝工作階段,讓 base 與它的 split 作為一個不可分割的整體一起安裝。 |
這些行為是在撰寫 Web ADB 工具背後的解析程式時,對照 AOSP、toybox 與核心原始碼查證的。真的會因 Android 版本或廠牌而異的地方,這一頁會直接說明,而不是給你一個在半數手機上都是錯的數字。