am force-stop
會改變裝置殺掉屬於某個 app 的所有行程與服務。
- 指令
- adb shell am force-stop
- 指令
- 活動與 intent(am)
- 風險
- 會改變裝置
語法
am force-stop <package>範例
am force-stop com.example在不解除安裝、也不清資料的前提下停掉一個亂跑的 app。
top -b -n 1 -m 10在停掉任何東西之前,先看清楚到底是誰在吃 CPU。
輸出怎麼讀
通常什麼都沒有。把沒有輸出當成成功,把任何 `Error:`、例外或權限相關的行當成失敗。想要證據的話,事後去 `top` 裡找找那個 app 的行程,而不是相信「沒有輸出」。
輸出欄位
| 欄位 | 意義 |
|---|---|
| (no output) | 指令執行了。 |
| Error: … | 套件無法解析,或呼叫被拒絕。 |
需要什麼權限
不用 root、不用 `adb root`、不用 `su`:一條授權過的 `adb` 連線就是全部條件。`am force-stop` 打到的是 `ActivityManagerService.forceStopPackage`,它會檢查呼叫方有沒有 `android.Manifest.permission.FORCE_STOP_PACKAGES`,沒有就丟例外;而 Shell 套件的資訊清單(`packages/Shell/AndroidManifest.xml`)宣告的正是這個權限,這也是為什麼這個指令從纜線這端能用、從幾乎其他任何地方都不能用。同一份資訊清單也讓它的預設範圍比多數人以為的更廣。它同時持有 `INTERACT_ACROSS_USERS_FULL`,而 `runForceStop` 一開始就把 user id 設成 `UserHandle.USER_ALL`,只有在你傳 `--user` 時才收窄。所以只帶一個參數的那種寫法,並不是把 app 停在看著螢幕的那個人身上——它是一次把裝置上每個 Android 使用者裡的它停掉:工作設定檔、次要使用者、同一個 app 的複製版本。你只想停眼前這個使用者的話,就要寫出來。除此之外沒有任何東西擋在你和這次強制停止之間:沒有確認、沒有試跑、沒有可以撤銷的逐套件許可,而且平台不會攔你去 force-stop 系統 app。正式版上 `adb root` 本來就會被拒絕,而且在這裡也買不到任何東西,因為 shell 早就持有這個呼叫要的權限。
失敗訊息對照
| 訊息 | 意義 |
|---|---|
| Error: Unknown option: --user0 | `runForceStop` 只接受一個選項,就是 `--user`。其他任何東西都會被寫到標準錯誤,而且這個方法會在呼叫 `forceStopPackage` **之前**就回傳 -1,所以連在一起的 `--user0`、縮寫成 `-u`,或多打一個 `--all`,都會讓 app 繼續跑,而那行字讀起來像警告而不像拒絕。要看的是結束碼,不是那行字的語氣。 |
| Exception occurred while executing 'force-stop': | 有 `Throwable` 逃出 `onCommand`;標準錯誤上是一行空白、這個橫幅與堆疊追蹤。`java.lang.IllegalArgumentException: Argument expected after "force-stop"` 代表沒給套件名稱。出現指名 `android.permission.FORCE_STOP_PACKAGES` 的 `java.lang.SecurityException`,代表這次呼叫不是來自 shell 或 root,而在纜線這一端通常表示你人在 `run-as` 裡面、已經不是 uid 2000 了。 |
| Unknown command: force stop | 連字號是子指令名稱的一部分。被引號包住或被拆開時,`am` 看到的是 `force`,`handleDefaultCommands` 會把這行印在**標準輸出**並回傳 -1,一個行程都沒碰。它和一次成功的 force-stop 所產生的沉默完全不像,這是它唯一的優點。 |
| cmd: Can't find service: activity | `am` 是包在 `cmd activity` 外面的東西,而 `cmd` 在 service manager 裡找不到那個服務。什麼都沒停掉。開機期間、`system_server` 還沒註冊 `activity` 時本來就會這樣;它不代表你的套件名稱打錯了。 |
會改變什麼,以及怎麼回頭
什麼都不會被刪,下次被啟動或被廣播喚醒時 app 就會再跑起來——但這不是唯讀操作:行程裡尚未儲存的狀態沒了,它排定的 alarm 與 job 也會被取消,直到它再次執行為止。沒有還原指令,解法是把 app 打開。
版本與廠商注意事項
- 在依 CPU 排序的行程表上按 force-stop 很容易點錯,而失去未儲存狀態的往往是你本來不想動的那個 app。
- 這和停用不同:app 隨時可以再跑起來。
這個我們有 UI
Android System Monitor 會透過 USB 執行這個指令並解析回應——只要 Chromium 系瀏覽器,不必安裝 SDK,也不會上傳任何東西。
相關指令
和 am force-stop 會在同一次作業裡出現的指令。
| 指令 | 做什麼 |
|---|---|
| top | 一次性的行程表:CPU 占用、記憶體、狀態與指令列。 |
| dumpsys meminfo | 哪些行程最吃記憶體,量的是 PSS(按比例分攤的用量)。 |
| am start | 用元件或 intent 啟動 Activity——這是驗證 deep link 能不能被接走最快的方法。 |
其他活動與 intent(am)指令
| 指令 | 做什麼 |
|---|---|
| am broadcast | 送出廣播 intent,這是從 shell 驅動 SystemUI demo mode 等平台接收器的方法。 |
這些行為是在撰寫 Web ADB 工具背後的解析程式時,對照 AOSP、toybox 與核心原始碼查證的。真的會因 Android 版本或廠牌而異的地方,這一頁會直接說明,而不是給你一個在半數手機上都是錯的數字。