EST. 2026 — บันทึกงานเซิร์ฟเวอร์จริง SYSADMIN · SECURITY · AI · DIRECTADMIN เล่มที่ 01
THE SYSADMIN ALMANAC
หน้าหลัก / Linux / ทำ Android dev บน MIUI/HyperOS แล้ว adb ทำงานไม่ได้ — กับดักบน Windows
Linux

ทำ Android dev บน MIUI/HyperOS แล้ว adb ทำงานไม่ได้ — กับดักบน Windows

โดย Ton-Or ·23 ก.ค. 2026·อ่าน 8 นาที
ทำ Android dev บน MIUI/HyperOS แล้ว adb ทำงานไม่ได้ — กับดักบน Windows

adb ขึ้น INSTALL_FAILED, ไฟล์ screenshot เป็น 0 ไบต์, path /sdcard เพี้ยนไปโผล่ในโฟลเดอร์ Git — สามอาการนี้ไม่ได้แปลว่าเครื่องพัง แต่คือ Windows, Git Bash, PowerShell และ MIUI ต่างคนต่างแทรกมือใส่ adb กันคนละจุด

สรุปใน 1 นาที

อาการ/ปัญหา
adb push ไฟล์หาย screenshot เป็น 0 ไบต์ และ MIUI บล็อกการติดตั้งครั้งแรก ทั้งที่ adb ไม่ได้พัง
ใครควรอ่าน
คนพัฒนาแอป Android บน Windows ที่ใช้ adb ผ่าน Git Bash หรือ PowerShell และทดสอบบนเครื่อง MIUI หรือ HyperOS
ทางแก้แบบสั้น
รัน build และ push ใน PowerShell ไม่ใช่ Git Bash หรือตั้ง MSYS_NO_PATHCONV=1 ใช้ adb exec-out ทำ screenshot และเปิด Install via USB บนเครื่อง
ข้ามไปขั้นตอน

พอดีช่วงนี้ผมทำแอป Android ที่เขียนด้วย Jetpack Compose มี backend เป็น Laravel แล้วยิงลงเครื่องทดสอบเป็น Xiaomi ที่รัน MIUI/HyperOS โดยมี dev box เป็น Windows — พอเริ่มจริงก็เจอว่า adb "ทำงานไม่ได้" อยู่หลายจุด ทั้งที่ตัว adb เองปกติดี ปัญหาคือ Windows, Git Bash, PowerShell และ MIUI ต่างคนต่างเข้ามาแทรกกลางระหว่างคำสั่งกับเครื่องคนละท่า กว่าจะไล่ครบผมเสียเวลาไปเยอะ เลยรวมกับดักที่เจอจริงมาเล่าให้ฟัง พร้อมคำสั่งที่ใช้แล้วผ่าน

ชื่อ package (com.example.pos), serial เครื่อง และ path ในบทความเป็นตัวอย่าง ส่วนคำสั่งกับอาการคือของจริงทั้งหมด

กับดักที่ 1: Git Bash แปลง /sdcard/ ให้เพี้ยน

อาการแรกคือสั่ง adb push ลง /sdcard/Download/ แล้วไฟล์หายไปเฉยๆ ไม่ได้อยู่บนเครื่อง พอไปไล่ดูถึงเจอว่ามันไปโผล่บนดิสก์ที่ C:/Program Files/Git/sdcard/Download/ แทน สาเหตุคือ Git Bash (MSYS) แปลง path แบบ POSIX ให้อัตโนมัติ พอเจอ /sdcard/... มันเข้าใจว่าเป็น absolute path บน Windows เลยเติม prefix ของ Git ให้

ทำไม path เพี้ยนadb push ... /sdcard/พิมพ์ใน Git Bash→MSYS แปลง POSIX pathอัตโนมัติ→ไปโผล่ C:/Program Files/Git/sdcard/ผิดที่

ทางที่ผมใช้คือย้ายไปยิง adb push จาก PowerShell แทน — path ฝั่งอุปกรณ์ไม่โดนแปลงเลย:

$device = "abc123def456"
$apk = "app\build\outputs\apk\debug\app-debug.apk"
adb -s $device push $apk /sdcard/Download/app-beta.apk

ถ้าจำเป็นต้องอยู่ใน Git Bash จริงๆ ให้ปิดการแปลง path ด้วยตัวแปร MSYS_NO_PATHCONV เฉพาะคำสั่งนั้น:

MSYS_NO_PATHCONV=1 adb -s "$device" push "$apk" /sdcard/Download/app-beta.apk

ส่วนตัวผมเลือกทำงาน adb ทั้งหมดใน PowerShell ไปเลย จำกฎน้อยกว่า ไม่ต้องมานั่งจำว่าคำสั่งไหนมี path ฝั่งเครื่องบ้าง

กับดักที่ 2: PowerShell ทำไฟล์ screenshot เป็น 0 ไบต์

พอจะเก็บภาพหน้าจอเครื่องมาแนบรายงานเทสต์ ผมสั่งตามที่เคยชินบน Linux:

adb exec-out screencap -p > .tmp\screen.png

ได้ไฟล์ออกมาแต่เปิดไม่ขึ้น บางทีก็ 0 ไบต์ ต้นเหตุคือเครื่องหมาย > ใน PowerShell มันคือ Out-File ที่ยัด text encoding ให้ทุกอย่างที่ไหลผ่าน — พอเป็นสตรีมไบนารีอย่าง PNG ไบต์เลยถูกแปลงพัง ไม่ใช่ไฟล์ภาพเดิมอีกต่อไป

ที่พังบ่อย

ไพป์ผ่าน PowerShell ตรงๆ

ให้ไบต์ของ PNG ไหลผ่าน > ของ PowerShell — โดน text encoding เหยียบทุกไบต์ ได้ไฟล์ 0 ไบต์หรือเปิดไม่ขึ้น

ที่ใช้ได้จริง

ให้เครื่องเซฟเองแล้วค่อยดึง

screencap เขียนลง /sdcard บนเครื่องก่อน แล้ว adb pull กลับมา — ไบต์ไม่ผ่านมือ PowerShell เลย ภาพครบทุกครั้ง

วิธีที่ผมใช้แล้วได้ภาพครบทุกครั้งคือให้เครื่องเซฟลง /sdcard ก่อน แล้วค่อย adb pull กลับมา ไบต์ไม่ต้องผ่านมือ PowerShell เลย:

adb -s $device shell screencap -p /sdcard/screen.png
adb -s $device pull /sdcard/screen.png .tmp\screen.png
adb -s $device shell rm /sdcard/screen.png

ถ้าอยากไพป์ตรงจริงๆ ให้ใช้ redirect ของ cmd.exe แทน เพราะ cmd ไม่ยุ่งกับ encoding ของสตรีม:

adb exec-out screencap -p > screen.png

อีกจุดที่พลาดกันบ่อยคืออย่าเซฟลง C:\temp เพราะโฟลเดอร์นั้นอาจไม่มีอยู่จริง แล้ว PowerShell สร้างให้ไม่เหมือน Git Bash — เซฟลงโฟลเดอร์ในโปรเจกต์ (เช่น .tmp\) ที่มีอยู่แน่ๆ จะชัวร์กว่า

กับดักที่ 3: MIUI บล็อกการติดตั้งครั้งแรก

พอ build เสร็จจะติดตั้งลงเครื่องรอบแรก MIUI/HyperOS เด้งกลับมาแบบนี้:

adb: failed to install fresh.apk: Failure [INSTALL_FAILED_USER_RESTRICTED: Install canceled by user]

ทั้งที่ป๊อปอัปยืนยันบนเครื่องยังไม่ทันโผล่ด้วยซ้ำ สาเหตุคือ toggle "Install via USB" ใน Developer options ปิดอยู่ พอปิดไว้ MIUI จะบล็อกการติดตั้งครั้งแรกผ่าน adb ทุกกรณี ตัว toggle นี้ต้องล็อกอิน Mi Account และมีซิมในเครื่องถึงจะเปิดได้ ซึ่งเครื่องเทสต์บางเครื่องไม่มีซิมเสียบ ทางที่ผมใช้เลยเป็นการหลบด่านแทน — push APK ลง /sdcard แล้วแตะติดตั้งด้วยมือผ่านแอป Files บนเครื่อง เพราะการติดตั้งที่ผู้ใช้กดเองไม่ติดด่านนี้

  1. สั่ง assembleDebugAndroidTest ให้ได้ทั้ง APK แอปและ APK เทสต์ออกมา
  2. ติดตั้งครั้งแรกด้วยมือ — push APK ลง /sdcard แล้วแตะติดตั้งผ่านแอป Files บนเครื่อง (ข้ามด่าน MIUI)
  3. ครั้งต่อไปใช้ adb install -r ทับได้เงียบๆ ไม่โดนบล็อกอีก
  4. ยิงเทสต์ตรงด้วย am instrument ไม่ต้องพึ่ง gradle task

พอติดตั้งผ่านรอบแรกไปแล้ว การอัปเดตครั้งถัดไปใช้ธง -r (reinstall ทับ) ได้เงียบๆ MIUI ไม่ถามอีก:

.\gradlew.bat assembleDebugAndroidTest
# รอบแรก: push ให้ผู้ใช้ติดตั้งด้วยมือผ่าน Files
adb -s $device push app\build\outputs\apk\androidTest\debug\app-debug-androidTest.apk /sdcard/Download/
# รอบถัดไป: ทับได้เลยด้วย -r
adb -s $device install -r app\build\outputs\apk\androidTest\debug\app-debug-androidTest.apk

ที่สำคัญคืออย่าใช้ gradle task connectedAndroidTest บน MIUI — ให้ยิง am instrument ตรงแทน:

# รันทั้งชุด
adb -s $device shell am instrument -w -r -e debug false com.example.pos.test/androidx.test.runner.AndroidJUnitRunner
# รันเฉพาะคลาสเดียว
adb -s $device shell am instrument -w -r -e class com.example.pos.OwnerHomeTest com.example.pos.test/androidx.test.runner.AndroidJUnitRunner

-w คือรอจนจบ, -r คือ raw output ที่ parse ต่อได้

อย่าใช้ gradle connectedAndroidTest บน MIUI

task นี้จะถอนแอปหลักออกก่อนแล้วค่อยติดตั้งใหม่ พอการติดตั้งใหม่โดนด่าน MIUI ปัดตก เครื่องจะเหลือทั้งแอปหลักและแอปเทสต์ หายไปทั้งคู่ — ต้องมานั่งติดตั้งด้วยมือใหม่หมด ผมโดนมาแล้ว ให้ยิง am instrument ตรงแทนตั้งแต่แรก

อีกจุดที่เจอตอนรันชุดเทสต์ยาวเกินห้านาที คือ MIUI พักหน้าจอแล้ว activity หลุด focus ทำให้เทสต์ที่แตะหรือ scroll ล้มเป็นชุด กันด้วยการปลุกจอค้างไว้ก่อนเริ่ม:

adb -s $device shell input keyevent KEYCODE_WAKEUP
adb -s $device shell svc power stayon true

กับดักที่ 4: here-string ของ PowerShell กลืน backslash เวลาปั้นโค้ด PHP

กับดักตัวสุดท้ายอยู่ฝั่ง backend เวลาจะปั้น seed / test fixture ของ Laravel แล้วส่งขึ้นเซิร์ฟเวอร์ ผมเคยลองยัดโค้ด PHP หลายบรรทัดผ่าน here-string ของ PowerShell แล้ว pipe ขึ้น ssh — ปรากฏว่า backslash ในโค้ดโดนกลืนหายตั้งแต่ต้นทาง พอขึ้นไปถึงเซิร์ฟเวอร์ PHP จึงเป็น parse error แบบงงๆ ที่หาต้นเหตุยากมาก เพราะไฟล์ในเครื่องกับที่ส่งขึ้นไปหน้าตาไม่เหมือนกัน

อย่าปั้นโค้ด PHP ผ่าน here-string ของ PowerShell

backslash และตัว escape ในโค้ดจะโดนกลืน พอส่งขึ้นเซิร์ฟเวอร์ PHP จะ parse error แบบไล่ต้นเหตุยาก เพราะโค้ดต้นทางกับปลายทางไม่ตรงกัน — เขียนลงไฟล์ในเครื่องก่อนแล้วค่อย scp ขึ้นไปรัน ปลอดภัยกว่ามาก

วิธีที่ผมใช้คือเขียนโค้ดลงเป็นไฟล์จริงในเครื่องก่อน (ผ่าน editor ไม่ผ่าน here-string) แล้วค่อย scp ขึ้นไปรัน เสร็จแล้วลบไฟล์ชั่วคราวทิ้งทุกครั้ง:

scp .\scripts\seed.php host:/home/deploy/seed.php
ssh host "php /home/deploy/seed.php && rm -f /home/deploy/seed.php"

จุดที่ต้องระวังในไฟล์นั้นคืออย่าใส่ path แบบ Windows (D:\... หรือ C:\...) ลงในสคริปต์ที่จะไปรันบน Linux เด็ดขาด เพราะ backslash จะกลายเป็นชื่อไฟล์ประหลาดใน /tmp แล้วบางเซิร์ฟเวอร์มี monitor คอยจับชื่อไฟล์แปลกๆ อยู่ ใช้ path แบบ Linux ให้หมด แล้วเก็บกวาดไฟล์ชั่วคราวทุกครั้งหลังรันเสร็จ

สรุปลำดับที่ยิงแล้วไม่พลาด

พอไล่ครบทั้งสี่จุดแล้ว pipeline ที่ผมใช้ประจำจะเป็นแบบนี้ — เลือกเครื่องมือให้ถูกตัวในแต่ละสเต็ป ไม่สลับไปมา:

ลำดับที่ยิงแล้วไม่พลาดbuild + push ใน PowerShellไม่ใช่ Git Bash→ติดตั้งด้วยมือรอบแรกข้ามด่าน MIUI→adb install -r รอบถัดไป→am instrument ยิงเทสต์ไม่ใช้ gradle task→screencap ลงเครื่อง + pull

หัวใจของทุกกับดักคือเรื่องเดียวกันหมด — คำสั่ง adb ไม่ได้วิ่งตรงถึงเครื่องอย่างที่คิด แต่มีชั้นของ Windows, Git Bash และ PowerShell แทรกอยู่ตรงกลาง แล้ว MIUI ก็มีด่านของมันอีกชั้น พอรู้ว่าใครแทรกตรงไหนก็เลี่ยงได้หมด ใครจะปรับ flow ตามเครื่องและ ROM ของตัวเองก็ได้ตามสะดวกครับ ตรงไหนผมอธิบายตกหล่นหรือพิมพ์ผิด เดี๋ยวกลับมาแก้เพิ่มให้ภายหลังครับ

ชั้นที่แทรกอยู่ระหว่างคำสั่งกับเครื่องคำสั่ง adbบน WindowsGit Bashแปลง /sdcard ให้เพี้ยนPowerShell> ทำไบต์ PNG พังadbเครื่อง MIUIบล็อกติดตั้งครั้งแรกติดตั้งมือรอบแรกadb เองไม่ได้พัง แต่ละชั้นที่แทรกอยู่กลางทางต่างหากที่ทำให้ผลเพี้ยน
Git Bash แปลง path PowerShell ทำไบต์ไบนารีพัง และ MIUI บล็อกการติดตั้งครั้งแรก

เคยเจองานแบบนี้ไหม? ติดตรงไหน?

มาแลกวิธีกันต่อในบอร์ด LinuxThai

→ คุยต่อในบอร์ด

ความคิดเห็น 0

ยังไม่มีความคิดเห็น — เป็นคนแรกเลย