สำหรับบทความนี้จะพานักพัฒนามาใส่ลูกเล่นในแอปด้วยการทำให้แอปรองรับ Secret Code บนแอนดรอยด์กัน

Secret Code คืออะไร?

โดยปกติแล้วเวลาผู้ใช้แอนดรอยด์ซื้อเครื่องใหม่ก็จะต้องทดสอบการทำงานของอุปกรณ์ว่าสามารถทำงานได้ครบถ้วนหรือไม่ เครื่องมีปัญหาตรงจุดไหนหรือป่าว ด้วยการทดสอบจากแอปที่ฝังมาในเครื่อง และแอปดังกล่าวก็จะต้องเปิดขึ้นมาด้วยการกดเบอร์โทรออกตามที่แต่ละรุ่นกำหนดไว้

เช่น

  • Samsung กดเบอร์ *#0*#
  • Google Pixel กดเบอร์ *#*#4636#*#*

และรู้หรือไม่ว่า Secret Code แบบนี้ ก็สามารถใช้กับแอปของผู้ที่หลงเข้ามาอ่านได้เหมือนกันนะ

ทำให้แอปรองรับ Secret Code

เวลาที่ผู้ใช้กดเบอร์โทรในรูปแบบของ *#*#<number>#*#* แอป Dialer ของแอนดรอยด์ก็จะบอกระบบแอนดรอยด์ทันที เพื่อให้แอปใดๆก็ตามที่รองรับ Secret Code และหมายเลขนั้นๆสามารถทำงานได้

โดยเบื้องหลังการทำงานที่ว่านี้ก็คือการ Broadcast นั่นเอง โดยเป็น Broadcast ที่มี Action ชื่อว่า  android.provider.Telephony.SECRET_CODE นั่นเอง

ดังนั้นแอปที่ต้องการดัก Secret Code ก็สามารถสร้าง Broadcast Receiver เพื่อดัก Event ที่ว่าได้เลย

// SecretCodeBroadcastReceiver.kt
class SecretCodeBroadcastReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent?) {
        // Do something
    }
}

โดยหัวใจสำคัญของการสร้าง Broadcast Receiver ให้รองรับกับ Secret Code นั้นคือการกำหนด Action ใน <intent-filter> ให้รองรับ android:name="android.provider.Telephony.SECRET_CODE

และจะต้องกำหนด <data> ที่มี android:scheme เป็น android_secret_code แล้วตามด้วย android:host ที่กำหนดเป็นเลขอะไรก็ได้ที่นักพัฒนาต้องการ

<!-- AndroidManifest.xml -->
<manifest>
    <application>
        <receiver android:name=".SecretCodeBroadcastReceiver">
            <intent-filter>
                <action 
                	android:name="android.provider.Telephony.SECRET_CODE" />
                <data
                    android:host="555"
                    android:scheme="android_secret_code" />
            </intent-filter>
        </receiver>
    </application>
</manifest>

จะเห็นว่าระบบแอนดรอยด์ใช้คุณสมบัติของ Deep Linking มาทำเป็น Secret Code (ด้วยการใช้ <data>) โดยใช้ควบคู่กับ Intent Filter

ดังนั้น URI ของ Deep Linking ของ Secret Code ในตัวอย่างนี้ก็จะเป็น android_secret_code://555 นั่นเอง

ถ้าอยากจะดึง URI ที่ได้ไปใช้ก็สามารถดึงได้จาก Intent ที่ส่งเข้ามาใน onReceive(...) ได้เช่นกัน

// SecretCodeBroadcastReceiver.kt
class SecretCodeBroadcastReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent?) {
        val uri: Uri? = intent?.data
    }
}

หลังจากนั้นอยากจะให้ทำคำสั่งอะไร ก็กำหนดได้ตามใจชอบเลยจ้าาาาา

ดัก Secret Code ทุกตัว โดยไม่ต้องสนใจตัวเลขได้มั้ย?

ได้สิ เพราะเบื้องหลังของ Secret Code เป็นการใช้ Deep Linking เข้ามาช่วย นั่นหมายความว่าถ้านักพัฒนากำหนดแค่ Scheme แต่ไม่กำหนด Host ก็สามารถดัก Secret Code จากทุกๆหมายเลขได้ทันที

<!-- AndroidManifest.xml -->
<manifest>
    <application>
        <receiver android:name=".SecretCodeBroadcastReceiver">
            <intent-filter>
                <action  android:name="android.provider.Telephony.SECRET_CODE" />
                <data android:scheme="android_secret_code" />
            </intent-filter>
        </receiver>
    </application>
</manifest>

แต่ในกรณีที่กำหนดเลขทับซ้อนกับ System App ที่มีอยู่ในเครื่อง ระบบแอนดรอยด์จะเลือกแอปนั้นๆให้โดยทันที ไม่ได้ขึ้นหน้าต่างเพื่อให้ผู้ใช้เลือกแอปหรอกนะ