เจ้าของบล็อกต้องการเขียนโค้ดเพื่อเช็คขนาดของหน้าจอ แล้วพบว่าคำสั่งสำหรับเช็คขนาดหน้าจอมี 2 แบบ
// Android 4.2 Jelly Bean (API 17) or higher
val windowManager = /* ... */
val display = windowManager.defaultDisplay
val metrics = DisplayMetrics()
display.getRealMetrics(metrics)
Pair(metrics.widthPixels, metrics.heightPixels)
// Lower than Android 4.2 Jelly Bean (API 17)
val windowManager = /* ... */
try {
val rawHeight: Method = Display::class.java.getMethod("getRawHeight")
val rawWidth: Method = Display::class.java.getMethod("getRawWidth")
Pair(rawWidth.invoke(display) as Int, rawHeight.invoke(display) as Int)
} catch (e: Exception) {
val display = windowManager.defaultDisplay
Pair(display.width, display.height)
}
จะเห็นว่าคำสั่งระหว่าง 2 เวอร์ชันนั้นมีโค้ดที่แตกต่างกันโดยสิ้นเชิง นั่นก็เพราะว่าใน API 17 ได้มีการเพิ่มคำสั่งใหม่ๆเข้ามา รวมไปถึงการเช็คขนาดหน้าจอด้วยเช่นกัน
และนักพัฒนาก็จะต้อง
แยกโค้ดตามเวอร์ชันนั่นเอง
ด้วยการใช้ If-else เพื่อเช็คว่าแอปกำลังทำงานอยู่บนอุปกรณ์แอนดรอยด์เวอร์ชันอะไร เพื่อให้คำสั่งทำงานตรงกับเวอร์ชันนั้นๆ
fun getScreenResolution(windowManager: WindowManager): Pair<Int, Int>? {
val display = windowManager.defaultDisplay
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
val metrics = DisplayMetrics()
display.getRealMetrics(metrics)
Pair(metrics.widthPixels, metrics.heightPixels)
} else {
try {
val rawHeight: Method = Display::class.java.getMethod("getRawHeight")
val rawWidth: Method = Display::class.java.getMethod("getRawWidth")
Pair(rawWidth.invoke(display) as Int, rawHeight.invoke(display) as Int)
} catch (e: Exception) {
Pair(display.width, display.height)
}
}
}
ซึ่งโค้ดในลักษณะนี้สามารถพบเจอได้บ่อยมาก เพราะมีคำสั่งอีกมากมายที่ถูกเปลี่ยนแปลงในแอนดรอยด์แต่ละเวอร์ชัน
API Reference จึงเป็นสิ่งสำคัญสำหรับนักพัฒนา
การศึกษาคำสั่งต่างๆใน API Reference ในเว็ป Android Developers จึงเป็นสิ่งสำคัญมากๆสำหรับนักพัฒนาแอนดรอยด์
นอกจากจะบอกคำสั่งที่มีในแต่ละคลาสของแอนดรอยด์แล้ว ยังมีบอกอีกด้วยว่าคำสั่งแต่ละตัวนั้นถูกเพิ่มเข้ามาในแอนดรอยด์เวอร์ชันอะไร หรือยกเลิกใช้งานเมื่อไร รวมไปถึงแนะนำ Best Practice สำหรับการใช้งานคำสั่งนั้นๆอีกด้วย
แต่ไม่ใช่ทุกคำสั่งที่จะทำงานได้ในทุกเวอร์ชัน
ก็ต้องมีบ้างที่ฟีเจอร์ใหม่ๆมาพร้อมกับแอนดรอยด์เวอร์ชันใหม่ๆ ดังนั้นเวอร์ชันเก่าๆจึงไม่ต้องพูดถึง
เมื่อเจอกับกรณีที่ต้องเรียกใช้คำสั่งที่มีแค่ใน API เวอร์ชันใหม่ๆ ก็ควรใส่ Annotion ที่ชื่อ @RequireApi
ไว้ที่คำสั่งนั้นๆด้วย เพื่อให้ Android Studio (และนักพัฒนา) รู้ว่า Method ดังกล่าวมีการเรียกใช้คำสั่งของ API เวอร์ชันใหม่ๆ
@RequiresApi(Build.VERSION_CODES.O)
fun initNotificationChannel(context: Context) { /* ... */ }
เมื่อมีการเรียกใช้งานคำสั่งนี้ที่ไหนก็ตาม Android Studio จะทำการเช็คทันทีว่าโค้ดในจุดนั้นมีโอกาสที่จะทำงานบนแอนดรอยด์เวอร์ชันที่ต่ำกว่านั้นหรือไม่ แล้วจะแจ้งเตือนให้นักพัฒนารู้ว่าต้องเขียนโค้ดเพื่อป้องกันกรณีนี้ด้วย
ซึ่งจริงๆแล้ว Android API ที่ใช้งานกันอยู่ทุกวันนี้ก็มีการใส่ @RequireApi
ไว้เพื่อให้นักพัฒนารู้ว่าคำสั่งนั้นๆใช้ได้เฉพาะบนแอนดรอยด์เวอร์ชันไหน
และสำหรับกรณีที่ต้องการแยก Android Resource ตามเวอร์ชันของแอนดรอยด์ ก็สามารถใช้ Configuration Qualifier เพื่อแยกตามเวอร์ชันที่ต้องการได้เลย
+-- java
+-- AndroidManifest.xml
\-- res
+-- values
| +-- colors.xml
| +-- strings.xml
| \-- themes.xml
+-- values-v21
| \-- themes.xml
\-- values-v27
\-- themes.xml
ทั้งนี้การเขียนโค้ดเพื่อรับมือกับเวอร์ชันแอนดรอยด์ที่มีหลากหลายมากเกินไป ควรดูว่าคำสั่งดังกล่าวจำเป็นต้องเขียนโค้ดแยกเวอร์ชันหรือไม่ ถ้าทำได้ก็ดี แต่ถ้าทำไม่ได้ก็ควรเขียนโค้ดเผื่อสำหรับกรณีที่ใช้งานฟีเจอร์นั้นๆไม่ได้ด้วยนะ