ByteScope

settings put

會改變裝置

把值寫進設定提供者——多數開發者選項小技巧背後的機制。

指令
adb shell settings put
指令
設定提供者
風險
會改變裝置

語法

settings put <system|secure|global> <key> <value>

旗標與參數

token意義
system | secure | global命名空間。把 key 寫進錯的那一個,會產生一個沒有人會讀的 key,而且失敗是無聲的。

範例

  • settings put global window_animation_scale 0.0

    關掉一種動畫。開發者選項實際上會設三個倍率,另外兩個是 `transition_animation_scale` 與 `animator_duration_scale`。

  • settings put system show_touches 1

    在螢幕被觸碰的位置畫一個點,錄示範影片時很好用。

  • settings put global http_proxy 10.0.0.5:8080

    把手機的 HTTP 堆疊指向你機器上的 proxy。

  • settings put global http_proxy :0

    清掉 proxy。`:0` 是平台自己的設定介面會寫入的值。

輸出怎麼讀

成功時什麼都沒有。沒有輸出就是答案,所以請用 `settings get` 確認,而不是相信「沒有輸出」。寫進錯誤命名空間也一樣安靜。

輸出欄位

欄位意義
(no output)寫入被接受了。
Exception / Permission Denial這個版本不允許 shell 使用者寫那個 key。

需要什麼權限

不用 root、也不用 `adb root`,但這是這一家族裡真正靠一個平台權限撐著的那一半。`settings` 是一行的 shell 腳本,跑的是 `cmd settings "$@"`(AOSP 的 `cmds/settings/settings.sh`),所以寫入是以 `shell` 使用者的身分嘗試的,而那個使用者所屬的套件 `com.android.shell`,在自己的資訊清單裡同時被授予 `android.permission.WRITE_SETTINGS` 與 `android.permission.WRITE_SECURE_SETTINGS`。這就是為什麼一條已授權的線可以改一般 app 碰不到的 `secure` 與 `global` key,也是為什麼除了 USB 偵錯本身,開發者選項裡沒有東西在管它。這個授權沒給你的,是「每個 key 都會成功」的保證:個別的 key 還是可能被提供者拒絕,而拒絕來的樣子是一段例外標題加底下一串堆疊,不是一行漂亮的錯誤。再來是串流的問題,這一頁比站上任何一頁都在乎它,因為成功的寫入完全不會印任何東西。值走 stdout、解析器的抱怨走 stderr,而沉默就是成功訊號——所以「它成功了」、「它被拒絕而你把拒絕丟掉了」與「它寫進了一個沒人會讀的命名空間」,在你留下 stderr 並事後把 key 讀回來之前,是同一個觀察結果。

失敗訊息對照

訊息意義
Bad arguments指令列在湊出完整請求之前就結束了。對 `put` 來說那代表少了值:光是 `settings put global http_proxy` 就會落在這裡。什麼都沒寫進去,而且沒有東西會指名少了哪一塊,所以請檢查整行。
Too many arguments`put` 接受命名空間、key、值、一個可選的 tag,然後就只接受 `default` 這個字面字,超過的一律拒絕。陷阱在這個錯誤前一步:一個沒加引號、中間只有一個空白的值不會失敗,它會把第一個字寫成值,然後默默把第二個字當成 tag。把值加上引號,然後讀回來確認。
Argument expected to be 'default'給了五個位置參數,而第五個不是 `default`。解析器在那個位置只允許 `default`,那個開關同時會讓這個值變成新的平台預設值。什麼都沒寫進去。
Exception occurred while executing 'put':shell 指令處理器接到一個 `Throwable`,把這行標題加上堆疊寫到 stderr。它的下一行會說出原因:`java.lang.SecurityException` 代表提供者拒絕的是那個特定的 key,而不是值的格式有問題。只有你留著 stderr 才看得到這一切,而且寫入沒有發生。
Invalid namespace 'gobal'命名空間必須是 `system`、`secure` 或 `global`,比對不分大小寫。解析立刻停止,所以什麼都沒寫進去——而這是好結果,因為另一種下場是有個 key 躺在一張沒人會讀的表裡。

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

沒有可以推導出來的解藥:平台不會記住原本的值,所以請在寫入「之前」用 `settings get` 讀一次並把那個值留著。最會咬人的是 proxy 那個 key——一台帶著 `global http_proxy` 出門的手機,在任何網路上都沒有可用的網際網路,而手機上沒有任何東西會解釋原因。清除要用 `settings put global http_proxy :0`,不要用空字串。

版本與廠商注意事項

  • 還原就是把舊值寫回去,而那代表你得先讀過。這個指令本身沒有復原。
  • 用空字串清 proxy 並不可靠:有幾種版本會把那兩個引號原樣存下來,手機還是指著一個沒用的目標。該寫的值是 `:0`。
  • 「關掉動畫」是三個 key 而不是一個。只設 window 的倍率,transition 與 animator 還是照跑。

這個我們有 UI

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

開啟 Android ADB Toolbox

相關指令

和 settings put 會在同一次作業裡出現的指令。

指令做什麼
settings get從手機的設定提供者讀出一個值。
am broadcast送出廣播 intent,這是從 shell 驅動 SystemUI demo mode 等平台接收器的方法。
wm size回報顯示器的解析度,或覆寫它,讓手機假裝自己是另一塊螢幕。

這些行為是在撰寫 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 執行這類指令。或者瀏覽全部指令。