# ความรู้พื้นฐาน

บทนี้จะแนะนำความรู้พื้นฐานที่เกี่ยวข้องกับ Android Automation โปรดอ่านคำอธิบายในบทนี้ให้จบ เนื่องจากจะไม่กล่าวถึงซ้ำอีกในภายหลัง Android Automation มีความแตกต่างอย่างมากกับ Web Automation ทั่วไป แต่ก็มีหลายส่วนที่คล้ายคลึงกัน ใน Web Automation ทั่วไป เราสามารถใช้เครื่องมือสำหรับนักพัฒนา F12 เพื่อดูโครงสร้าง (layout) ของหน้าเว็บและข้อมูลเช่น ID ของ element ได้อย่างง่ายดาย จากนั้นใช้ XPATH เพื่อดึง element มาทำการคลิก, รอ และการดำเนินการอื่นๆ ใน Android ก็มีตรรกะที่คล้ายกัน คุณสามารถใช้สิ่งที่เรียกว่า "selector" เพื่อเลือก element และทำการคลิก, ตรวจสอบ และการดำเนินการอื่นๆ ได้ ดังนั้นคุณไม่ต้องกังวลว่าจะเริ่มต้นได้ยาก

## ความเหมือนและความแตกต่างระหว่าง Mobile Automation และ Web Automation

Mobile Automation และ Web Automation มีความคล้ายคลึงกันหลายอย่าง แต่ก็มีความแตกต่างมากมายเช่นกัน เราจะยกตัวอย่างด้วย Selenium โดยปกติแล้ว การใช้ Selenium เพื่อควบคุมหน้าเว็บ คุณต้องมีสามสิ่ง คือ 1. เบราว์เซอร์ 2. webdriver และ 3. selenium แน่นอนว่าในฝั่งมือถือก็เช่นเดียวกัน โทรศัพท์มือถือเปรียบเสมือนเบราว์เซอร์, FIRERPA เปรียบเสมือน webdriver, และไลบรารี Python ของ FIRERPA หรือก็คือ lamda เปรียบเสมือน selenium และพวกมันมีเป้าหมายเดียวกัน คือการจำลองการกระทำของผู้ใช้ เพื่อทำการทดสอบ, รวบรวมข้อมูล หรือทำงานอัตโนมัติ และทั้งหมดนี้ขับเคลื่อนด้วยสคริปต์, ทำการระบุตำแหน่ง element, คลิก, จับภาพหน้าจอ, ตรวจสอบ และการดำเนินการอื่นๆ เมื่อมองแบบนี้แล้ว จริงๆ ก็ค่อนข้างคล้ายกัน

แต่พวกมันก็แตกต่างกัน อย่างแรก Mobile Automation ต้องการให้คุณมีโทรศัพท์มือถือหนึ่งเครื่องและคอมพิวเตอร์หนึ่งเครื่อง ในขณะที่ Web Automation สามารถทำได้บนคอมพิวเตอร์ของคุณเอง และพวกมันไม่ได้ใช้โซลูชันชุดเดียวกัน สำหรับฝั่งเว็บ เครื่องมือที่ใช้กันทั่วไปคือ Selenium, Puppeteer, Playwright สำหรับฝั่งมือถือ โดยทั่วไปจะเป็น FIRERPA, AutoJS, Appium, uiautomator เป็นต้น

สำหรับฝั่งเว็บ วิธีการระบุตำแหน่งที่ใช้กันทั่วไปจะขึ้นอยู่กับโครงสร้าง HTML DOM เช่น xpath หรือ csspath ซึ่งลำดับชั้นของ element ค่อนข้างจะมองเห็นได้ชัดเจน แต่สำหรับฝั่งมือถือ วิธีการระบุตำแหน่งที่ใช้กันทั่วไปคือ selector แน่นอนว่าหน้าจอแอปพลิเคชัน Android ก็ใช้ XML layout เช่นกัน คุณจึงสามารถใช้ XML เพื่อเลือกด้วย xpath ได้ โดยปกติแล้ว Web Automation ไม่จำเป็นต้องพิจารณาปัญหาความเข้ากันได้ (compatibility) มากนัก ในกรณีส่วนใหญ่สามารถหลีกเลี่ยงปัญหาความเข้ากันได้ที่เกิดจากอุปกรณ์ได้โดยการกำหนดเบราว์เซอร์และความละเอียดหน้าจอให้คงที่ แต่สำหรับฝั่ง Android เนื่องจากอุปกรณ์แต่ละยี่ห้อและรุ่นมีความแตกต่างกัน ขนาดหน้าจอ, เวอร์ชันของระบบ ฯลฯ ล้วนอาจส่งผลต่อความเข้ากันได้ของโค้ด automation ได้ แต่ก็ไม่ต้องกังวลไป แม้จะมีผลกระทบแต่ก็ไม่มากนัก

## ความแตกต่างของเครื่องมือ Automation ต่างๆ

ดังที่กล่าวไว้ข้างต้น เครื่องมือ Android Automation ที่เรายกตัวอย่างมานั้นก็มีความแตกต่างกันมากมาย เราขอแสดงจุดยืนก่อนว่า FIRERPA เป็นเครื่องมือ automation ที่เสถียรที่สุด, มีฟังก์ชันครบถ้วนที่สุด, ทรงพลังที่สุด และเหมาะสมที่สุดสำหรับการจัดการและประยุกต์ใช้ในระดับโปรเจกต์

```{note}
จุดยืนของเราไม่ใช่ความลำเอียง แต่เกิดจากการสำรวจและปรับปรุงอย่างต่อเนื่องมาเป็นเวลา 6 ปี เส้นทางที่คุณเดินและหลุมพรางที่คุณเจอ เราล้วนเคยผ่านมาแล้วทั้งสิ้น
```

### AutoJS

ผลิตภัณฑ์ที่เกี่ยวข้องกับ AutoJS ที่ใช้กันทั่วไป เป็นประเภทควบคุมตัวเอง (self-control) ซึ่งต้องติดตั้ง APK บนอุปกรณ์และเขียนสคริปต์ด้วย js เพื่อดำเนินการ โดยปกติ AutoJS สามารถทำการดำเนินการในระดับ automation เท่านั้น ข้อดีคือเหมาะสำหรับผู้เริ่มต้นหรือผู้ใช้งานทั่วไป มีเกณฑ์การเริ่มต้นที่ต่ำ แต่การออกแบบของมันไม่เหมาะสำหรับการควบคุม, จัดการ และอัปเดตสคริปต์จำนวนมาก อยู่ในสถานะที่ไม่มีศูนย์กลางและไม่มีการจัดการ ไม่สามารถทำการควบคุมขนาดใหญ่ที่แม่นยำได้

### Appium

Appium ที่นักทดสอบนิยมใช้ เป็นสถาปัตยกรรมแบบ C/S (Client-Server) ซึ่งเหมาะกับการควบคุมแบบคลัสเตอร์มากกว่า AutoJS แต่ก็มีข้อเสียที่ชัดเจน เนื่องจากมันรองรับ automation สำหรับระบบส่วนใหญ่ นอกจาก Android แล้วยังรองรับ iOS ด้วย ทำให้มีขนาดใหญ่และเทอะทะ ไม่เหมาะอย่างยิ่งสำหรับการใช้งานในวงกว้าง

### u2

สุดท้ายคือ uiautomator2 ซึ่งก็เป็นสถาปัตยกรรมแบบ C/S เช่นกัน เมื่อเทียบกับ Appium แล้วมีความแม่นยำกว่า และกระชับพอสมควร ไม่มีส่วนเกินมากนัก ฟังก์ชันต่างๆ ก็พอดี แต่เหตุผลที่เราเลิกใช้คือ มันไม่ค่อยเสถียรเมื่อใช้งานกับอุปกรณ์หลายเครื่อง นอกจากนี้ ตรรกะการติดตั้งอัตโนมัติเหมาะสำหรับผู้เริ่มต้น แต่สำหรับการควบคุมคลัสเตอร์ระดับมืออาชีพแล้ว กลับดูเหมือนเป็นส่วนเกินและควบคุมได้ยาก และไม่มีการบำรุงรักษา

แน่นอนว่าเครื่องมือเหล่านี้เหมาะสำหรับการใช้งานทั่วไป แต่เส้นทางที่เราเลือกเดินนั้นไม่ธรรมดา เพราะในทางธุรกิจ โดยปกติแล้วเป็นไปไม่ได้ที่จะทำแค่ automation เพียงอย่างเดียว ตัวอย่างเช่น มีงานที่ต้องทดสอบแอปฯ หนึ่ง ซึ่งต้องบันทึก request และ response, เวลาที่ใช้ในการ request ฯลฯ ลองคิดดูว่าคุณจะทำอย่างไร ผมคิดว่าในแผนของคุณ อาจจะมีการดำเนินการด้วยตนเองเพิ่มเติมจำนวนมาก หรือไม่ก็มีความไม่เสถียรหรือปัญหาความเข้ากันได้สูง แต่ในโลกของ FIRERPA คุณสามารถใช้โค้ดเพื่อดำเนินการทั้งหมดได้ สิ่งที่คุณต้องจัดการมีเพียงโค้ดเท่านั้น ส่วนความเสถียรและความเข้ากันได้ ปล่อยให้เป็นหน้าที่ของ FIRERPA จริงๆ แล้วเราไม่ควรเปรียบเทียบกับสิ่งเหล่านี้ เพราะในแง่ของฟังก์ชัน FIRERPA เป็น superset ของโซลูชันทั้งหมดข้างต้น มันครอบคลุมทุกหลุมพรางและทุกเส้นทางที่เราเคยผ่านมา

## ขั้นตอนพื้นฐานของ Automation

โดยปกติคุณต้องทำการวิจัยและวางแผนก่อน ว่าจะทำแค่ automation ทั่วไป หรือต้องการดึงข้อมูลการทำงานของแอปพลิเคชันไปพร้อมกับ automation ด้วย โดยทั่วไปแล้ว คุณมีสองวิธีในการดึงข้อมูล วิธีแรกคือการดักจับการสื่อสาร HTTP/s ผ่าน Man-in-the-Middle วิธีที่สองคือการดักจับข้อมูลผ่าน Hook วิธี Man-in-the-Middle ค่อนข้างง่าย เหมาะสำหรับการใช้งานทั่วไป แต่อาจใช้ไม่ได้ผลกับบางแอปพลิเคชัน วิธี Hook ต้องการความรู้ด้านวิศวกรรมย้อนกลับ (reverse engineering) จำนวนมาก การเริ่มต้นทำได้ยาก ไม่เหมาะสำหรับผู้เริ่มต้น เหมาะสำหรับใช้ในสถานการณ์เฉพาะทาง

### การดักจับข้อมูลแบบ Man-in-the-Middle

วิธี Man-in-the-Middle ค่อนข้างง่าย คุณเพียงแค่ต้องหาเนื้อหาเกี่ยวกับการติดตั้งใบรับรอง Man-in-the-Middle และการตั้งค่าพร็อกซีในเอกสาร แล้วใช้งานร่วมกับ mitmproxy ก็สามารถทำได้ หากคุณไม่เข้าใจเลย คุณสามารถดูสคริปต์ startmitm.py ที่เป็นทางการของเราได้ ซึ่งเราได้เขียนตรรกะทั้งหมดไว้ให้คุณแล้ว คุณสามารถคัดลอกหรือนำไปใช้ใหม่ได้ตลอดเวลา

### การดักจับข้อมูลด้วย Hook

วิธี Hook ต้องการให้คุณมีความสามารถด้านวิศวกรรมย้อนกลับระดับเริ่มต้นขึ้นไป หากคุณไม่เคยได้ยินเรื่องนี้มาก่อน คุณยังไม่จำเป็นต้องพิจารณาวิธีนี้ในตอนนี้ โดยรวมแล้ว วิธี Hook คือการเขียนสคริปต์ frida เพื่อดักจับ (hook) การเรียกใช้ฟังก์ชันที่เกี่ยวข้อง, รับพารามิเตอร์หรือค่าที่ส่งคืนแล้วส่งต่อ, และฉีดเข้าไปในแอปพลิเคชัน คุณสามารถดู Demo และวิธีการใช้งานเบื้องต้นได้ในบท "การใช้ Frida เพื่อส่งข้อมูล"

### โค้ด Automation

แน่นอนว่าโค้ด automation ก็เป็นส่วนที่ขาดไม่ได้ เพราะคุณต้องใช้ automation เพื่อกระตุ้นตรรกะที่เกี่ยวข้อง สำหรับการเขียนโค้ด automation โดยปกติแล้วคุณควรทำตามขั้นตอนต่อไปนี้ ก่อนอื่นคุณควรเปิดรีโมทเดสก์ท็อปของ FIREPRA คุณควรจะเห็นหน้าจอตามภาพด้านล่าง

![รีโมทเดสก์ท็อป](/assets/images/frida-remote-desktop.png)

ตอนนี้ โปรดเปิดแอปฯ ที่คุณต้องการทำ automation จากนั้นคลิกที่ไอคอน "รูปตา" ที่มุมขวาบนของรีโมทเดสก์ท็อป คุณจะเห็นหน้าจอตามภาพด้านล่าง ตอนนี้ให้เลือก element ที่คุณต้องการดำเนินการ คลิกเพื่อดูข้อมูลของ element นั้น

```{tip}
แน่นอนว่าสามารถใช้โค้ดเปิดได้เช่นกัน เรื่องเหล่านี้จะอธิบายในภายหลัง
```

![เลือก element](/assets/images/auto-eyeselect.png)

คุณจะเห็นข้อมูลของ element ทางด้านขวา เช่น text, resourceId ฯลฯ ตอนนี้เราต้องการคลิกที่ element นี้ ให้เขียนโค้ดดังต่อไปนี้ ความหมายของโค้ดนี้คือ "คลิก element ที่มี text เป็น 'ตกลง'"

```python
d(text="ตกลง").click()
```

```{note}
นี่เป็นเพียงตัวอย่าง วิธีการเขียน selector มีหลายแบบ ตัวอย่างนี้แนะนำเฉพาะวิธีที่ง่ายที่สุด
```

เอาล่ะ คุณได้เรียนรู้วิธีการเขียนที่ง่ายที่สุดแล้ว ตอนนี้โปรดเขียนตรรกะควบคุมเช่น if else ร่วมกับ interface อื่นๆ เช่น exists คุณก็จะสามารถสร้างกระบวนการ automation ทั้งหมดได้แล้ว เห็นไหมครับ ไม่ได้ยากขนาดนั้น

## การตรวจสอบ Layout ของหน้าจอ

โดยปกติแล้ว การเขียนโค้ด automation ไม่สามารถทำได้หากไม่มีการตรวจสอบ layout ของหน้าจอ ซึ่งเป็นหนทางเดียวที่คุณจะได้รับเงื่อนไขสำหรับ selector ก่อนอื่นคุณต้องเปิดรีโมทเดสก์ท็อปของอุปกรณ์ในเบราว์เซอร์ จากนั้นคลิกไอคอนรูปตาที่มุมขวาบนของรีโมทเดสก์ท็อปเพื่อเข้าสู่โหมดตรวจสอบ layout ตอนนี้คุณสามารถคลิกที่กรอบเส้นประบนหน้าจอด้านซ้ายเพื่อดูข้อมูลของ element ที่เกี่ยวข้อง คุณสามารถใช้คุณสมบัติในนั้นเป็นพารามิเตอร์สำหรับ selector ได้ การคลิกไอคอนรูปตาอีกครั้งจะเป็นการปิดโหมดตรวจสอบ layout โหมดตรวจสอบ layout จะไม่รีเฟรชตามการเปลี่ยนแปลงของหน้าจอ มันจะคงเป็น layout ของหน้าจอ ณ ขณะที่คุณกดปุ่มลัดเสมอ หากต้องการรีเฟรช layout โปรดกดปุ่มลัด `CTRL + R` ด้วยตนเอง

![ตรวจสอบ element](/assets/images/inspect-demo.gif)

```{hint}
คุณยังสามารถกดปุ่ม TAB ในหน้าจอตรวจสอบ layout เพื่อวนดู element ทั้งหมดได้
```

## Selector ของหน้าจอ

Selector ของหน้าจอใช้สำหรับดำเนินการกับ element ของ Android คุณสามารถเข้าใจว่ามันเหมือนกับกฎของ Xpath แม้ว่าจะแตกต่างกันแต่จุดประสงค์การใช้งานโดยรวมเหมือนกัน ใน FIRERPA, selector คือ `Selector` ในกรณีส่วนใหญ่ คุณไม่จำเป็นต้องยุ่งกับคลาสนี้โดยตรง จากที่กล่าวมาข้างต้น คุณน่าจะเคยเห็นสิ่งนี้มาแล้ว รูปแบบเต็มของมันประกอบด้วยพารามิเตอร์ที่เป็นทางเลือกดังต่อไปนี้

| ประเภทการจับคู่         | คำอธิบาย                               |
|----------------------|----------------------------------------|
| text                 | ข้อความตรงกันทุกตัวอักษร                |
| textContains         | ข้อความมีคำที่ตรงกัน                    |
| textStartsWith       | ข้อความขึ้นต้นด้วยคำที่ตรงกัน            |
| className            | ชื่อคลาสตรงกัน                         |
| description          | คำอธิบายตรงกันทุกตัวอักษร               |
| descriptionContains    | คำอธิบายมีคำที่ตรงกัน                  |
| descriptionStartsWith  | คำอธิบายขึ้นต้นด้วยคำที่ตรงกัน           |
| clickable            | สามารถคลิกได้                          |
| longClickable        | สามารถกดค้างได้                        |
| scrollable           | สามารถเลื่อนได้                         |
| resourceId           | Resource ID ตรงกัน                     |

ในกรณีส่วนใหญ่จะใช้ `resourceId`, `text`, `description`, `textContains` เป็นพารามิเตอร์ หาก element มี `resourceId` ที่ปกติ ควรใช้เป็น Selector ก่อน เช่น `d(resourceId="com.xxx:id/mobile_signal")` มิฉะนั้นจะใช้ `text` เช่น `d(text="คลิกเพื่อเข้าสู่")` หรือแบบกว้างขึ้น `d(textContains="คลิก")` ส่วน `description` ก็เช่นเดียวกับ `text` แต่จะใช้น้อยกว่า

```{hint}
Selector ถูกสร้างขึ้นโดยคุณจากการนำพารามิเตอร์หลักๆ ที่ได้จากฟังก์ชันตรวจสอบ layout ของหน้าจอดังที่กล่าวไว้ข้างต้นมาประกอบกัน
```

## การกำหนดพิกัดหน้าจอ

ในระหว่างการทำ automation หลีกเลี่ยงไม่ได้ที่จะต้องมีการดำเนินการโดยใช้พิกัดที่ละเอียดหรือพิกัดพื้นที่ แต่เนื่องจากหลายคนอาจไม่ค่อยเข้าใจเรื่องพิกัด เราจึงจะมาแนะนำความรู้เกี่ยวกับพิกัดหน้าจอของ Android ที่นี่

เป็นที่ทราบกันดีว่ารูปภาพมีความละเอียด และหน้าจอก็เช่นกัน สำหรับหน้าจอของ Android ไม่ว่าจะเป็นแนวตั้ง แนวนอน หรือหน้าจอที่หมุนอัตโนมัติ จะใช้มุมซ้ายบนเป็นจุดกำเนิด (origin) 0,0 และขยายไปทางขวาและลงล่าง โดย X เป็นแกนแนวนอน และ Y เป็นแกนแนวตั้ง ดังรูป

<p align="center">
<img src="/assets/images/screen-rect.png" alt="พิกัดหน้าจอ" width="200">
</p>

จากรูปด้านบน จะเห็นได้ว่าพิกัดของมุมซ้ายบนของหน้าจอคือ 0,0, มุมขวาบนคือ 1080,0, มุมซ้ายล่างคือ 0,1920, และมุมขวาล่างคือ 1080,1920 คุณสามารถใช้ข้อมูลนี้ในการคำนวณพิกัดของจุดใดๆ บนหน้าจอได้

```{note}
ไม่ว่าหน้าจอเดิมจะเป็นแนวตั้งหรือแนวนอน หรือหมุนอัตโนมัติ จะใช้มุมซ้ายบนของทิศทางปัจจุบันของหน้าจอเป็นจุดกำเนิดเสมอ
```

### จุดบนหน้าจอ

ใน FIRERPA มีการกำหนดเกี่ยวกับหน้าจอสองแบบ การดำเนินการบางอย่างเช่นการคลิกหรือการจับภาพหน้าจอต้องการให้คุณระบุข้อมูลพื้นที่หรือพิกัด สำหรับจุดพิกัดทั่วไป เราใช้การกำหนดดังต่อไปนี้ ซึ่งหมายถึงจุดที่พิกัด 100,100 บนหน้าจอ

```python
Point(x=100, y=100)
```

### การกำหนดพื้นที่

การกำหนดพื้นที่หมายถึงพื้นที่สี่เหลี่ยมบนหน้าจอ การกำหนดค่อนข้างซับซ้อนโปรดอ่านอย่างละเอียด เราใช้ `Bound` เพื่อแทนพื้นที่บนหน้าจอ ซึ่งต้องการให้คุณระบุพารามิเตอร์สี่ตัว ได้แก่ `top`, `left`, `bottom`, `right` คุณอาจจะสับสนเล็กน้อย โปรดทำความเข้าใจอย่างละเอียดดังนี้: `top` หมายถึงระยะห่าง (เป็นพิกเซล) จากขอบบนของสี่เหลี่ยมถึงขอบบนของหน้าจอ, `left` หมายถึงระยะห่างจากขอบซ้ายของสี่เหลี่ยมถึงขอบซ้ายของหน้าจอ, `right` หมายถึงระยะห่างจากขอบขวาของสี่เหลี่ยมถึงขอบซ้ายของหน้าจอ, `bottom` หมายถึงระยะห่างจากขอบล่างของสี่เหลี่ยมถึงขอบบนของหน้าจอ โดยสรุปคุณสามารถเข้าใจได้ว่าระยะทางทั้งหมดเป็นระยะทางจากแกน X และ Y ที่แผ่ออกจากจุดกำเนิด ด้านล่างนี้เราจะใช้รูปภาพเพื่อช่วยให้คุณเข้าใจ โดยหน้าจอโทรศัพท์ยังคงเป็น 1080x1920 และอุปกรณ์อยู่ในสถานะแนวตั้ง

<p align="center">
<img src="/assets/images/screen-bound.png" alt="พื้นที่หน้าจอ" width="200">
</p>

ตอนนี้เราสมมติว่าหน้าจอถูกแบ่งออกเป็นสี่ส่วนเท่าๆ กัน และต้องการกำหนดพื้นที่สองส่วนดังรูป คือมุมซ้ายบนและมุมขวาล่าง ตามกฎแล้ว พื้นที่ 1 ขอบบนของสี่เหลี่ยมห่างจากขอบบนของหน้าจอ 0 พิกเซล, ขอบซ้ายห่างจากขอบซ้ายของหน้าจอ 0 พิกเซล, ขอบล่างห่างจากขอบบนของหน้าจอ 960 พิกเซล (1920÷2), ขอบขวาห่างจากขอบซ้ายของหน้าจอ 540 พิกเซล (1080÷2) ดังนั้นการกำหนดของมันควรเป็น

```python
Bound(top=0, left=0, right=540, bottom=960)
```

ในทำนองเดียวกัน ขอบบนของสี่เหลี่ยมพื้นที่ 2 ห่างจากขอบบนของหน้าจอ 960 พิกเซล, ขอบซ้ายห่างจากขอบซ้ายของหน้าจอ 540 พิกเซล, ขอบขวาห่างจากขอบซ้ายของหน้าจอ 1080 พิกเซล, ขอบล่างห่างจากขอบบนของหน้าจอ 1920 พิกเซล จะเห็นได้ว่าการกำหนดสี่เหลี่ยมที่สองคือ

```python
Bound(top=960, left=540, right=1080, bottom=1920)
```

## ข้อมูลของแอปพลิเคชัน Android

แอปพลิเคชัน Android แต่ละตัวมีไดเรกทอรีเฉพาะบนอุปกรณ์สำหรับจัดเก็บข้อมูลของแอปฯ โดยปกติแล้วข้อมูลที่เกี่ยวข้องกับแอปฯ จะถูกเก็บไว้ในไดเรกทอรี `/data` คุณสามารถเรียกใช้ `d.application("com.example").info()` เพื่อรับไดเรกทอรีข้อมูลของแอปฯ ได้ ในกรณีส่วนใหญ่ คุณยังสามารถ `cd` ไปที่ไดเรกทอรี `/data/user/0/com.example.test` เพื่อไปยังไดเรกทอรีของผู้ใช้ได้โดยตรง นอกจากไดเรกทอรี `/data` ทั่วไปแล้ว บางแอปฯ ยังเก็บไฟล์มัลติมีเดียและไฟล์อื่นๆ ในไดเรกทอรี `/sdcard/Android` ด้วย

### การดูฐานข้อมูล SMS

บางครั้งคุณอาจต้องการดูว่า SMS ที่ได้รับในเครื่องถูกเก็บไว้ที่ไหน เป็นความคิดที่ดีมากและง่ายมาก แม้กระทั่งสามารถเขียน extension เพื่ออ่านเนื้อหาโดยตรงและรับข้อมูลแบบเรียลไทม์ผ่าน HTTP API ได้!
เราจะทำตามแนวทางของ Android ทั่วไป หากของคุณแตกต่างออกไป โปรดปรับเปลี่ยนตามความเหมาะสม บน Android ชื่อแอปพลิเคชัน SMS ควรจะเป็น `com.android.mms` ดังนั้นเราสามารถเปลี่ยนไปยังไดเรกทอรี `/data/user/0/com.android.mms` ได้โดยตรง จากการดำเนินการด้านล่างของเรา คุณจะเห็นว่ามีฐานข้อมูลหลายไฟล์ในไดเรกทอรี `databases` ซึ่ง `mmssms.db` คือเป้าหมายของเรา

```text
 λ 10:12 /data/user/0/com.android.mms ➥ ls -la
total 82
drwx------    7 u0_a78   u0_a78        3452 Jan  2  2021 .
drwxrwx--x  381 system   system       53248 May  2 16:46 ..
drwxrws--x    3 u0_a78   u0_a78_c      3452 Jan  2  2021 cache
drwxrws--x    2 u0_a78   u0_a78_c      3452 Jan  2  2021 code_cache
drwxrwx--x    2 u0_a78   u0_a78        3452 Jan  2  2021 databases
drwxrwx--x    7 u0_a78   u0_a78       24576 Feb 26 13:43 files
drwxrwx--x    2 u0_a78   u0_a78        3452 May  4 10:12 shared_prefs
 λ 10:12 /data/user/0/com.android.mms ➥ ls -l databases/
total 504
-rw-rw----    1 u0_a78   u0_a78       24576 Jan  2  2021 dynamic_bubble
-rw-------    1 u0_a78   u0_a78           0 Jan  2  2021 dynamic_bubble-journal
-rw-rw----    1 u0_a78   u0_a78      491520 Feb 27 04:18 mmssms.db
-rw-------    1 u0_a78   u0_a78           0 Jan  2  2021 mmssms.db-journal
 λ 10:12 /data/user/0/com.android.mms ➥
 ```

แน่นอนว่าการอ่านนั้นง่ายมาก เพราะภายใต้ Android ฐานข้อมูลของแอปฯ ทั่วไปจะเป็น SQLite แต่แอปฯ ที่มีความปลอดภัยสูงบางตัวมักจะเข้ารหัสฐานข้อมูลของตัวเองด้วย แต่ FireRPA ที่ทรงพลังขนาดนี้จะไม่มีได้อย่างไร FireRPA นอกจากจะสามารถอ่าน SQLite ทั่วไปได้แล้ว ยังรองรับ**การอ่านแบบเรียลไทม์**สำหรับฐานข้อมูลประเภทต่างๆ เช่น WeChat (sqlcipher) aes-256, WeChat Work aes-128, ฐานข้อมูลในเครือ Alibaba sqlcrypto (aes-128) (แน่นอนว่าคุณต้องหาคีย์ลับด้วยตัวเอง) ด้านล่างนี้เราจะสาธิตการอ่านเนื้อหา SMS ของระบบให้ดูง่ายๆ ง่ายมาก เพียงใช้คำสั่งเดียวก็ทำได้ หรือคุณจะเขียน extension เพื่ออ่านก็ได้

```bash
sqlite3 databases/mmssms.db .dump
```

แน่นอนว่าผลลัพธ์ที่ได้จะเยอะมาก แต่คุณสามารถหาตารางที่ต้องการข้อมูลได้อย่างรวดเร็ว แล้วเขียน SQL เองได้เลย วิธีนี้ใช้ได้กับแอปฯ Android 98% ส่วนอีก 2% เป็นฐานข้อมูลที่เข้ารหัส

### การดูฐานข้อมูลที่เข้ารหัส

สำหรับฐานข้อมูลที่เข้ารหัสเหล่านี้ คุณต้องหาคีย์ลับของฐานข้อมูลหรือวิธีการคำนวณเพื่อสร้างคีย์นั้นด้วยตัวเอง ด้านล่างนี้จะแนะนำวิธีการอ่านฐานข้อมูลของซอฟต์แวร์ที่เกี่ยวข้องอย่างง่ายๆ เราจะแนะนำเฉพาะวิธีการใช้ `PRAGMA` เพื่อตั้งค่าคีย์ล่วงหน้า หากคุณไม่เข้าใจว่านี่คืออะไร โปรดไปศึกษาเกี่ยวกับ sqlite ก่อน

> เครือ WeChat (sqlcipher)

```sql
PRAGMA cipher = "sqlcipher";
PRAGMA legacy = 1;
PRAGMA key = "database-key";
```

> WeChat Work (wxsqlite)

```sql
PRAGMA cipher = "aes128cbc";
PRAGMA hexkey = "database-key"
```

> เครือ Alibaba (sqlcrypto)

```sql
PRAGMA cipher = "sqlcrypto";
PRAGMA key = "database-key"
```

```{hint}
ฐานข้อมูลของแอปพลิเคชัน Android ไม่จำเป็นต้องอยู่ในไดเรกทอรี `databases` เสมอไปนะ
```

### การดูข้อมูลอื่นๆ

แน่นอนว่าในไดเรกทอรีข้อมูลของแอปฯ ไม่ได้มีแค่ฐานข้อมูลเท่านั้น ยังมีพารามิเตอร์, การตั้งค่า, แคช, ไฟล์ที่เกี่ยวข้องกับแอปฯ เช่น `shared_prefs` (xml) เป็นต้น แต่เราจะไม่ลงรายละเอียดมากนัก คุณสามารถสำรวจได้ด้วยตัวเอง

## มาตรการเสริมสำหรับ Automation

ในงาน automation ไม่ใช่ทุกแอปฯ ที่เหมาะกับการใช้ selector ในการระบุตำแหน่ง บางหน้าจอเช่นเกมซึ่งเรนเดอร์แบบเรียลไทม์ จะไม่มี layout ของหน้าจอในระดับ Android ดังนั้นสำหรับแอปฯ ประเภทนี้ คุณสามารถใช้ OCR หรือการจับคู่รูปภาพเพื่อตัดสินใจดำเนินการเท่านั้น เรามีโซลูชันเสริม OCR ที่สมบูรณ์แบบและโซลูชันการจับคู่รูปภาพ SIFT และการจับคู่เทมเพลตในตัว เพื่อช่วยให้บรรลุเป้าหมายทางธุรกิจเหล่านี้ คุณสามารถหา interface ที่เกี่ยวข้องและวิธีการใช้งานได้ในเอกสาร

กำลังอัปเดต...