ในบล็อกที่แล้ว "รู้จัก Samsung DeX อุปกรณ์เสริมไม้เด็ดเปลี่ยน Galaxy S8 เป็นคอมพ์ แบบทุกซอกทุกมุม" เราพูดถึง Samsung DeX ในแง่มุมของผู้ใช้ทั่วไปกันแล้ว แน่นอนว่าเราเป็นเนย เราเลยขอเขียนเพิ่มอีกบล็อก แต่คราวนี้จะขอโฟกัสไปที่ฝั่งนักพัฒนากันบ้าง
หลาย ๆ คนอาจจะสงสัยว่าเราจะทำแอป ฯ ให้ใช้บน DeX ได้อย่างไร ทำยากมั้ย ทดสอบยังไง มีอะไรที่ต้องรู้บ้าง ฯลฯ บล็อกนี้เรามีคำตอบให้จ้า
สเปคหน้าจอของ Samsung DeX
เริ่มจากเรื่องเบสิคสุด ๆ ที่จำเป็นต้องรู้อย่างสเปคหน้าจอของ DeX ก่อน โดย DeX เวลาต่อออกจอจะกลายเป็นความละเอียด Full HD (1920x1080 พิกเซล) และมี DPI ที่ 160 หรือ mdpi ครับ
วิธีทดสอบแอป ฯ บน Emulator
ก่อนจะไปเรื่องต่าง ๆ สิ่งสำคัญมากที่ต้องรู้ก่อนคือ "เราจะจำลอง DeX บนคอมพ์ของเราได้อย่างไร" เพราะคงเป็นไปไม่ได้ที่ทุกคนจะมี DeX ใช้ การทดสอบโดย Emulator เลยจำเป็นมาก ๆ เพื่อให้นักพัฒนาทุกคนสามารถทดสอบแอป ฯ ได้บนคอมพ์ของตัวเองนั่นเอง
จากที่บอกไปในบทความที่แล้วว่า DeX แท้จริงแล้วมันก็คือโหมด Freeform ของ Android 7.0 Nougat นั่นเอง ไม่ได้มีอะไรพิเศษ ดังนั้นเราเลยสามารถสร้าง Emulator จำลอง DeX ได้ด้วย Android Virtual Device (AVD) ที่มากับ Android SDK ได้ทันทีโดยไม่ต้องมีเครื่องมือพิเศษใด ๆ จากซัมซุง
วิธีการสร้าง AVD (หรือขอเรียกอีกอย่างว่า Emulator ละกันนะ) สามารถทำตามนี้ได้เลย
1) สร้าง AVD ขึ้นมาก่อนเป็นอย่างแรก โดยกดที่ Android Virtual Device Manager -> Create Virtual Device... -> New Hardware Profile แล้วกรอกข้อมูลลงไปตามนี้
Device Name: DeX
Screen size: 12 inch
Resolution: 1920 x 1080 px
ติ๊กเอา Portrait ออก คงเหลือแต่ Landscape
จากนั้นกด Finish แล้วให้สร้าง AVD จาก Hardware Profile ที่สร้างไว้ โดยการเลือก Android 7.0 (with Google APIs) เป็นระบบปฏิบัติการณ์ครับ สุดท้ายก็จะได้ DeX มาเรียบร้อย
2) รันมันขึ้นมา
3) เข้า Command Prompt หรือ Terminal แล้วพิมพ์คำสั่งตามนี้
adb shell
หากถูกต้องมันจะเข้า Shell ของ AVD ที่เปิดไว้ให้ ให้พิมพ์คำสั่งเหล่านี้ต่อเพื่อปรับแต่ง AVD ครับ
susetenforce 0settings put global enable_freeform_support 1cd /data/local/tmpmkdir permissionscd permissionscp -a /system/etc/permissions/* ./sed -e "s/live_wallpaper/freeform_window_management/" android.software.live_wallpaper.xml > freeform.xmlmount --bind . /system/etc/permissionsstopstart
แล้ว AVD จะถูกรีบูธใหม่ขึ้นมา รอจนมันบูธขึ้นมาเสร็จค่อยไปขั้นตอนต่อไป
4) เมื่อบูธขึ้นมาเรียบร้อย ให้เปิดแอป ฯ ขึ้นมาสักตัวนึง จากนั้นกดปุ่ม Recent App (ปุ่มสี่เหลี่ยม) ดู หากทุกอย่างถูกต้องจะต้องมีไอคอนที่ถูกวงไว้ด้านล่างนี้ปรากฏขึ้นมา
ซึ่งมันคือไอคอนที่ทำให้แอป ฯ เข้าสู่โหมด Freeform ซึ่งเป็นรูปแบบหนึ่งของโหมด Multi Window หรือการเปิดหลาย ๆ หน้าต่างได้พร้อมกันนั่นเอง ขอให้จำชื่อนี้ไว้ "Freeform" ครับ นี่เลย สามารถเปิดหลาย ๆ แอป ฯ หลาย ๆ หน้าต่างพร้อมกันได้
ซึ่งเราสามารถปรับขนาดของ Activity ได้ตามใจชอบ โดยการลากบริเวณริมขอบฝั่งด้านนอกของแต่ละ Activity ครับ (คือส่วนที่เป็นเงาอยู่นั่นแหละ) ลองลากดูได้เลย
เรียบร้อยยยย เราได้ DeX มาทดสอบแล้วววว แค่นี้เอง ง่ายมาก ๆ ไม่ต้องมีอะไรพิเศษเลย แค่ Android SDK ที่เรา ๆ มีกันอยู่แล้วนี่แหละ ลองดูได้เลยก๊ะะะ =D
อย่างไรก็ตาม จะมีบางส่วนที่ DeX ทำได้ แต่ AVD ทำไม่ได้ แต่ก็ไม่ใช่เรื่องใหญ่อะไรมากมาย ไว้เดี๋ยวอธิบายเพิ่มด้านล่างว่ามันคืออะไรและเราต้องจัดการยังไง
ทั้งนี้ ... เผอิญว่าเรามี DeX อยู่ในมือระหว่างเขียนบทความ เราเลยไม่ขอใช้ AVD ในการทำภาพประกอบบทความนี้นะ ขอใช้ภาพหน้าจอของ DeX จริง ๆ เลยละกัน จะได้สมจริง เนอะ =)
Fixed-Size Window vs Resizable Window
จากบทความที่แล้วก็จะเห็นว่าแอป ฯ ที่รันบน DeX จะมีอยู่สองรูปแบบด้วยกัน เราขอมา Recap อีกรอบ สองรูปแบบนั้นได้แก่
1) Fixed-Size Window
คือแอป ฯ ที่ไม่ได้เซตให้ใช้งานได้บน Freeform (ถ้าเราจะให้ใช้งานได้ เราต้องระบุไว้ใน Manifest ด้วย ถ้าไม่เซตไว้ถือว่าไม่ได้) แอป ฯ พวกนี้จะถูก Fix ขนาดไว้ชัดเจน ไม่สามารถยืดหรือขยาย Activity ได้ครับ
ส่วนใหญ่ก็จะเป็นแอป ฯ เก่า ๆ ที่ไม่ได้รับการอัปเดตมานานแล้ว ก็เลยไม่ได้เซตให้ใช้งานบน Freeform ได้ครับ
สำหรับ Fixed-Size Window นี้เป็นอะไรที่ซัมซุงทำขึ้นมาเองเพื่อแก้ปัญหาแอป ฯ ที่ไม่ได้ทำมารองรับ Freeform แต่ทำมาเพื่อมือถือเพียงอย่างเดียว อาจส่งผลให้การจัด Layout พังบน DeX ได้ ซัมซุงก็เลยจำกัดไว้ว่า แอป ฯ เหล่านี้ควรจะรันให้เหมือนบนมือถือแทน จึงเกิดเป็น Fixed-Size Window ขึ้นตามภาพด้านบน
ซึ่งแน่นอน เราเลยไม่สามารถทดสอบเจ้า Fixed-Size Window บน AVD ที่สร้างขึ้นได้ครับ เนื่องจาก Freeform ไม่มี Window ในรูปแบบนี้ทำไว้ แต่ถ้าจุดประสงค์ของเราคือต้องการให้แอป ฯ มันใช้บน Freeform ได้อยู่แล้ว เรื่องนี้ก็ไม่ใช่ปัญหา เพราะสุดท้ายแอป ฯ เราก็จะไม่ใช่ Fixed-Size นั่นเองครับ เลยไม่จำเป็นต้องทดสอบกับรูปแบบ Fixed-Size Window แต่อย่างใด =)
2) Resizable Window
คือแอป ฯ ที่ระบุไว้เรียบร้อยว่าให้ใช้งานบน Freeform (Multi Window) ได้ แอป ฯ พวกนี้จะสามารถยืดขยาย Activity ได้อย่างอิสระครับ
ยังมีแอป ฯ อยู่ไม่มากที่ทำแบบนี้ได้ เพราะก่อนหน้านี้นักพัฒนาไม่ได้ใส่ใจ Multi Window มาก เนื่องจากยังไม่ค่อยมีอุปกรณ์ไหนให้ใช้ก็เลยไม่ค่อยมีใครใส่ไว้ แต่นาทีนี้คงต้องแล้วหละ หลังจากนี้น่าจะมีคนทำให้สนับสนุนเยอะขึ้นเรื่อย ๆ
ซึ่งวิธีที่ทำให้มันทำได้เนี่ยจะบอกว่าง่ายมาก ๆ แค่บรรทัดเดียวเท่านั้นเอง ยังไงหนะหรอ ? มาดูกัน
วิธีทำให้แอป ฯ เรากลายเป็น Resizable
การทำให้แอป ฯ ที่เราทำกลายเป็น Resizable Window บน DeX นั้นง่ายมาก ๆ มีอยู่แค่สองเงื่อนไข อย่างแรกคือ
แอป ฯ เราจำเป็นต้อง targetSdkVersion ไว้ที่ 24 หรือมากกว่าเท่านั้น
หากใครยังเซตไว้ต่ำกว่านั้นจะไม่สามารถใช้งาน Freeform ได้ แต่หาก >= 24 อยู่แล้ว เราก็สามารถทำให้แอป ฯ เราเป็น Resizable Window ได้โดยเพิ่มแค่เพียงบรรทัดเดียวเท่าน้านนน โดยการใส่ android:resizableActivity="true"
ไว้ใน Tag <application>
ในไฟล์ AndroidManifest.xml
ครับ
<application android:resizableActivity="true" ...> ...</application>
เรียบร้อย เพียงเท่านี้แอป ฯ ของท่านก็จะกลายเป็น Resizable Window บน DeX แล้วครับ ใครมีแอป ฯ อยู่แล้วก็ลองแก้ Manifest ตามโค้ดด้านบนแล้วรันดูเลย สิ่งที่ท่านเห็นบน Emulator ก็จะเหมือนกับที่มันทำงานบน DeX เลยครับ
จบ ง่ายมะ =D
การจำกัดขนาดของ Resizable Window
มีเรื่องราวของขนาด Resizable Window ที่นักพัฒนาทุกคนควรรู้ดังต่อไปนี้
1) ขนาดต่ำสุดทั้งกว้างและสูงคือ 220dp - เราไม่สามารถย่อขนาดให้ต่ำกว่า 220dp ได้ครับ
ซึ่งก็เป็นเรื่องดีเพราะว่าถ้าไม่มีการจำกัดขนาดตรงนี้ไว้ หากย่อเหลือเล็กมาก ๆ ก็จะใช้งานไม่ได้แน่นอนนั่นเอง
ส่วนขนาดสูงสุดนั้นไม่มีครับ Maximize ให้เป็น Fullscreen ได้เลย
อย่างไรก็ตาม ปุ่ม Maximize ไม่มีให้ใช้ใน AVD น้า ก็ต้องลากให้มันเต็มจอเอาเอง
2) การเซตค่าความกว้างและความสูงขั้นต่ำด้วยตัวเอง - หากแอป ฯ เราออกแบบมาให้ทำงานที่ความกว้างหรือสูงที่มากกว่า 220dp เราก็สามารถเซตค่าขั้นต่ำให้กับ Activity ของเราได้ โดยกำหนดที่ AndroidManifest ดังนี้ครับ
<activity android:name=".MyActivity"> <layout android:minHeight="450dp" android:minWidth="300dp" /></activity>
ปรับเป็นค่าเท่าไหร่ก็ได้ตามต้องการ แต่ต้องไม่ต่ำกว่า 220dp นะ ไม่งั้นมันจะถูกกำหนดให้เป็น 220dp แทนครับ และก็แต่ละ Activity สามารถมีค่าของตัวเองได้ครับ จะเห็นได้จากว่า Tag <layout>
อยู่ใต้ <activity>
อีกที
3) การเซตค่าความกว้างและสูงเริ่มต้น - หากเราบอกว่าแอป ฯ เราเนี่ย ถ้ารันใน Freeform Mode อยากให้มันกว้างและสูงเท่านี้ ๆ เป็นค่าเริ่มต้น เราสามารถกำหนดได้ด้วยวิธีเดียวกับด้านบนครับ
<activity android:name=".MyActivity"> <layout android:defaultHeight="500dp" android:defaultWidth="600dp" /></activity>
แต่ถ้าไม่เซตไว้ ขนาดเริ่มต้นจะอยู่ที่ประมาณ 960dp x 653dp ครับผม
ทดสอบ UI ใน Window ขนาดต่าง ๆ
อย่างแรกที่ต้องทำหลังจากรันแอป ฯ ขึ้นมาได้แล้วคือ ... เทสต์ก่อนเลยว่า UI ไม่เละตอนอยู่ในขนาดต่าง ๆ ครับ เช่น ตอนหน้าจอแคบ ๆ ก็จะรันใน UI โหมดมือถือ
หรือตอนหน้าจอกว้าง ๆ ก็จะรันใน UI โหมด Tablet แทน
ซึ่งเอาจริง ๆ ถ้าคุณทำแบ่ง Resource ด้วย Configuration Qualifier มาอย่างถูกต้องอยู่แล้ว UI จะต้องไม่มีปัญหาเลย หากเละเนี่ยแปลว่าคุณไม่ได้ทำแอป ฯ ให้รองรับหน้าจอขนาดต่าง ๆ ซึ่งเป็นเรื่องที่บาปมากของการทำแอป ฯ แอนดรอยด์ เวลาทำต้องทำให้ใช้ได้บนทุกหน้าจอครับ
แต่หากทดสอบแล้วมีปัญหาจริง ๆ ก็ให้แก้ไข UI ให้เรียบร้อย ไม่แนะนำให้หนีปัญหาด้วยการปิด resizableActivity ทิ้งนะ เพราะถึงจะฝืนใช้งานบน DeX ได้ด้วยโหมด Fixed-Size Window แต่ถ้าเอาแอป ฯ คุณไปรันบนเครื่องรุ่นอื่นก็มีปัญหาอยู่ดี เพราะปัญหามันอยู่ที่แอป ฯ คุณหนะ ทางที่ดีแก้ไขให้เรียบร้อยครับ
ทดสอบการรองรับเม้าส์ให้เรียบร้อย
บนมือถือหรือ Tablet เราจะใช้นิ้วจิ้ม ๆ จอเอา แต่บน DeX เราจะต้องใช้ Mouse หรือ Trackpad แทน อันนี้ขอให้ทดสอบให้เรียบร้อย
ซึ่งถามว่าในทางการพัฒนา การใช้เมาส์หรือ Trackpad นั้นคืออะไร ? คำตอบ ... เราเรียกมันว่า Faketouch ครับ หรือการสร้าง Touch Event ขึ้นมาจากการกดเมาส์ให้เหมือนกับการจิ้มจอทุกประการ ซึ่งแอนดรอยด์จะทำให้อยู่แล้วเพราะมันถูกฝังมากับในระบบเลย เราไม่ต้องทำอะไรเลย ควรจะใช้งานได้เลยทันทีครับ
สำหรับการคลิก ๆ คงไม่มีปัญหาอะไรมาก แต่ที่ต้องดูเป็นพิเศษคือ การ Wheel เมาส์ ครับ โดยปกติ UI พื้นฐานของแอนดรอยด์เช่น ListView, GridView, RecyclerView หรืออะไรก็ตามที่อยู่ในกลุ่ม ScrollView จะใช้งานได้เลยทันทีโดยที่เราไม่ต้องทำอะไร
อย่างไรก็ตาม ถ้าเราทำ Custom Component ขึ้นมาหรือเผลอเขียนโค้ดบล็อค Wheel ไว้ก็อย่าลืมแก้ไขให้เรียบร้อยด้วยครับ เรื่อง UX สำคัญน้า ^ ^
แอป ฯ ที่ระบุว่าต้องใช้ Touch Screen จะรันบน DeX ไม่ได้
หากคุณมีการบังคับใน AndroidManifest ไว้ว่า Require Touchscreen ด้วยสองค่านี้
<uses-configuration android:reqTouchScreen="finger"><!-- or --><uses-feature android:name="android.hardware.touchscreen" android:required="true">
แอป ฯ ของท่านจะไม่สามารถรันบน DeX ได้นะครับ หากคุณเผอิญประกาศค่านี้ไว้และทดสอบแล้วว่าใช้เมาส์แทนได้ ให้เอาบรรทัดเหล่านี้ออกด้วย เพื่อที่มันจะได้เปิดบน DeX ได้อย่างไม่มีปัญหาครับ
การรองรับการคลิกเมาส์ขวา
การคลิกเมาส์ขวาก็เป็น UX ที่สำคัญในการใช้งานแอป ฯ บน Desktop เช่นกัน จริงมะ ? ดังนั้นเราจะมองข้ามมันไปไม่ได้ แอป ฯ เราก็ควรจะรองรับการคลิกเมาส์ขวาในจุดที่ควรจะใช้งานได้ด้วยเช่นกันครับ
โดยเราสามารถใช้ API ของแอนดรอยด์อย่างคำสั่ง registerForContextMenu
เพื่อรองรับการคลิกเมาส์ขวาและสร้าง Context Menu มาแสดงได้ทันที ดังนี้
@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); layout_main = (RelativeLayout) findViewById(R.id.layout_main); // Registers a context menu to be shown for the given view registerForContextMenu(layout_main);}@Overridepublic void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo){ // Check if it is a context menu for layout_main if (v.getId() == R.id.layout_main) { menu.setHeaderTitle("Context Menu Test"); menu.add(Menu.NONE, ONE, Menu.NONE, "Menu 1"); } super.onCreateContextMenu(menu, v, menuInfo);}@Overridepublic boolean onTouchEvent(MotionEvent event) { // Check if it is a right mouse down event if (event.getAction() == MotionEvent.ACTION_DOWN && event.getButtonState() == MotionEvent.BUTTON_SECONDARY) { layout_main.showContextMenu(event.getX(), event.getY()); } return super.onTouchEvent(event);}
ส่วนผลลัพธ์การคลิกเม้าส์ขวาจะหน้าตาประมาณนี้ครับ
อันนี้อาจจะเป็นเรื่องใหญ่นิดนึงเพราะว่าเป็นสิ่งที่มีเพิ่มเติมมาจากมือถือ แต่ก็ถือว่าสำคัญไม่น้อยเลยทีเดียว ยังไงก็อย่าลืมหาเวลามาปรับปรุงเรื่องนี้ด้วยครับ แอป ฯ จิได้สมบูรณ์ ^ ^
การรองรับ Wheel เพื่องานเฉพาะด้าน
สำหรับ UI ที่ไม่ใช่มาตรฐานแต่ควรจะ Wheel ได้ ยกตัวอย่างเช่น Maps ที่สามารถ Wheel เพื่อซูมเข้าออกได้ อันนี้เราสามารถจัดการการ Wheel ได้ด้วยโค้ด ด้วยการดักหา MotionEvent.ACTION_SCROLL
แล้วดูว่าเป็นการ Wheel Up หรือ Wheel Down ครับ
@Override public boolean onGenericMotion(View v, MotionEvent event) { int action = event.getAction(); int actionCode = action & MotionEvent.ACTION MASK; for (int i = 0; i < event.getPointerCount(); i++) { float x = event.getX(i); float y = event.getY(i); float p = event.getPressure(i); int pid = event.getPointerld(i); if (actionCode == MotionEvent.ACTION_SCROLL) { float wheelX = event.getAxisValue(MotionEvent.AXIS_HSCROLL, i); float wheelY = event.getAxisValue(MotionEvent.AXIS_VSCROLL, i); // Work with wheelY (-1 when wheel down, 1 when wheel up) return true; } }}
ซึ่งโครงโค้ดก็มีแค่นี้แหละ จะเอาค่า wheelY ไปทำอะไรต่อก็แล้วแต่ศรัทธาเลย =)
การจัดการ Configuration Change
สิ่งที่สำคัญเอามาก ๆ และเป็นหัวใจของ Resizable Window คือเรื่องของ Configuration Change หรือการรองรับการเปลี่ยนแปลง Configuration ของแอป ฯ เรา เช่น ถ้าเกิดมีการขยาย Window แอป ฯ ต้องไม่พัง เป็นต้น ซึ่งแอป ฯ ที่จะรันบน DeX ได้อย่างสมบูรณ์จะต้องรองรับ Configuration Change ทั้งหมด 7 แบบดังต่อไปนี้
1) Density จอเปลี่ยนระหว่าง xxxhdpi (มือถือ) และ mdpi (DeX)
2) ความละเอียดจอเปลี่ยนระหว่าง WQHD (มือถือ) และ Full HD (DeX)
3) หมุนแอป ฯ แนวตั้งและแนวนอน
4) Layout หน้าจอเปลี่ยน
5) ขนาดหน้าจอเปลี่ยน
6) Smallest Screen Size เปลี่ยน (มือถือ / DeX)
7) โหมดของ UI เปลี่ยนระหว่างมือถือและ Desktop
หากมีกรณีใดกรณีหนึ่งเกิดขึ้น หากเราไม่ได้ทำอะไรไว้เป็นพิเศษ Activity ก็จะถูกทำลายและสร้างใหม่โดยอัตโนมัติเพื่อโหลด Resource ให้ตรงกับ Configuration ใหม่
แต่ถ้าเกิดเรากำหนด android:configChanges
ไว้ เช่น
<activity android:name="..." android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout" ...> ...</activity>
เวลาเกิด Configuration เปลี่ยน Activity เราก็จะไม่ถูกทำลาย แต่จะเรียกคำสั่ง onConfigurationChanged
ใน Activity แทน ซึ่งก็จะเหมาะสมกว่าในหลาย ๆ กรณี เพราะว่า Activity ไม่ต้องถูกทำลาย สามารถใช้งานต่อได้เลยทันที แค่ต้องปรับเปลี่ยนค่าอะไรตามความเหมาะสมของ Configuration ใหม่นิดนึง ยังไงก็ Handle กันดี ๆ ครับ แล้วแต่ออกแบบเลย
ตอนนี้อาจจะสงสัยว่า เอ๊ะ เราสามารถสลับระหว่าง DeX และมือถือได้ด้วยหรอ ? คำตอบคือได้ครับ มีอยู่สองกรณีด้วยกันคือ
1) ดึง S8 ออกจาก DeX Station อันนี้ก็จะเป็นการออกจากโหมด DeX เข้าสู่โหมดมือถือ และถ้าเกิดเสียบกลับเข้า Station มันก็จะเข้าสู่โหมด DeX ใหม่ครับ
2) สลับจากการแสดงผล DeX เป็น Screen Mirroring แทน อันนี้สามารถกดจากบนหน้าจอได้เลยครับ ถือเป็นการออกจากโหมด DeX เช่นกัน
ก็จะเห็นว่ามันมีหลายกรณีมากที่จะเกิด Configuration Change ได้ ให้ทดสอบให้ครบทุกกรณีที่เป็นไปได้ว่าแอป ฯ คุณไม่พังครับ (ซึ่งถ้าเขียนมาอย่างเข้าใจแอนดรอยด์อยู่แล้วก็ไม่ควรจะพังนะ)
สุดท้าย หากคุณชัวร์แล้วว่าคุณรองรับทั้ง 7 กรณีอย่างไม่มีปัญหา ให้คุณใส่บรรทัดนี้เข้าไปใน Manifest ด้วย
<meta-data android:name="com.samsung.android.keepalive.density" android:value="true"/>
โดยบรรทัดนี้เป็นการบอกว่าเราทดสอบเรียบร้อยแล้วนะ ไม่มีปัญหาแน่ ๆ และผลที่เกิดขึ้นคือ แอป ฯ จะไม่ถูกทำลายทิ้งตอนที่มีการเปลี่ยนโหมดระหว่างมือถือและ DeX ครับ แต่ถ้าไม่ประกาศ meta-data ข้างต้น แอป ฯ จะถูกทำลายทิ้งตอนออกจากโหมด DeX และจะสร้างกลับมาใหม่เมื่อมีการเปลี่ยนโหมดกลับมายัง DeX ครับผม
อันนี้ทดสอบกับตัวเองเรียบร้อย เป็นแบบนั้นจริง ๆ ถ้าเกิดไม่ได้ประกาศ meta-data ไว้ ตอนออกจาก DeX แอป ฯ จะถูกทำลายทิ้งทั้งโปรเซสเลย
แน่นอนว่าพวก Activity ก็จะโดนฆ่าทิ้งไปด้วย จะเข้าสู่โหมดพินัยกรรม (โดยทำลายแต่มี Instance State) ไปทุกตัว ซึ่ง Activity เหล่านี้ก็จะถูกสร้างใหม่เพื่อใช้งานต่อได้ตอนกลับเข้าสู่โหมด DeX หาก Activity มีการรองรับ Instance State ไว้เรียบร้อยแล้ว (ซึ่งควรจะทำอยู่แล้ว) แค่โปรเซสจะถูกสร้างใหม่หมด เสียเวลาโหลดนานขึ้นเล็กน้อย
ถ้าให้เทียบ มันก็เหมือนกับบนมือถือตอนที่โปรเซสที่อยู่ Background โดนทำลายทิ้งเพื่อเคลียร์หน่วยความจำนั่นแหละ ผู้ใช้ไม่รู้หรอกว่าแอป ฯ โดนทำลายทิ้งไปแล้วเพราะยังสามารถกดสลับกลับไปยังแอป ฯ นั้น ๆ ได้อยู่ เพียงแต่ว่า Activity จะไม่ใช่ตัวเดิมแล้ว แต่จะถูกสร้างใหม่ให้ดูเหมือนเดิมเท่านั้นเอง (โดยใช้ Instance State)
เอาจริง ๆ ในแง่ของผู้ใช้อาจจะรู้สึกไม่ต่างกันครับ แต่ในแง่ของนักพัฒนา เราสามารถเอาประโยชน์ตรงนี้ในการทำให้แอป ฯ เปิดกลับมาเร็วได้เพราะโปรเซสยังไม่โดนทำลายทิ้งนั่นเอง
ยังไงก็ทดสอบ Configuration Change ให้เรียบร้อย แล้วก็ใส่ meta-data ตัวนี้ไว้ แอป ฯ คุณจะทำงานบน DeX ได้อย่างมีประสิทธิภาพสูงสุดจ้า
สิ่งที่เกิดขึ้นตอนถอด S8 ออกจาก DeX Station
แอป ฯ ที่ไม่ได้ประกาศ meta-data ด้านบนไว้จะถูกทำลายโปรเซสทิ้งทั้งหมด นั่นแปลว่า Activity ก็จะถูกทำลายทิ้งลงไปด้วย แต่ก็จะทำลายในแบบให้เราบันทึก Instance State ได้ ดังนั้นไม่ต้องกังวล ตอนเสียบ DeX กลับมาก็ใช้งานต่อได้ (แค่ต้องสร้างโปรเซสใหม่และ Activity ใหม่)
ส่วนแอป ฯ ที่ประกาศ meta-data ไว้ โปรเซสจะยังอยู่เหมือนเดิม ทุกอย่างยังอยู่เหมือนเดิมครับ ตอนสลับกลับมาโหมด DeX ก็สามารถใช้ Activity ในโปรเซสเดิมต่อได้เลย แค่ Activity อาจจะถูกทำลายแล้วสร้างใหม่แบบเดียวกับตอนหมุนจอ เพราะตอนสลับระหว่างมือถือกับ DeX มันเกิด Configuration Change ทางด้านขนาดหน้าจอนั่นเอง
ส่วนตอนเสียบ S8 กลับเข้า DeX Station แอป ฯ ต่าง ๆ ที่เคยเปิดทิ้งไว้ก็จะยังเรียงรายให้เราเห็นเป็นไอคอนอยู่ด้านล่างพร้อมให้เราเรียกกลับมาใช้ได้ทันทีจ้า ไม่ได้หายไปไหน
ซึ่งถามว่าไอคอนแต่ละตัวที่เห็นนี่คืออะไร ? ... ก็ตัวแทนของ Activity ที่เคยเปิดทิ้งไว้ยังไงหละ บางตัวก็อาจจะยัง Active อยู่ บางตัวก็อาจจะตายและนอนกอดพินัยกรรม (Instance State) ไว้ ตอนจิ้มกลับมาก็สามารถใช้งานต่อจากเดิมได้ทันทีถ้า Activity นั้น ๆ Handle พวก Lifecycle ต่าง ๆ มาดีพอ หรือสรุปง่าย ๆ ... มันก็คือหน้า Recent Apps ในโหมดมือถือนั่นเอง
ในแง่ของนักพัฒนา สิ่งที่สำคัญมาก ๆ ที่ต้องจัดการให้เรียบร้อยคือเรื่องของ Lifecycle นี่แหละ
เพราะตอนถอด S8 ออกจาก DeX Station เหล่า Activity ก็จะตายไปมากมาย หากคุณทำแอป ฯ ที่มีข้อมูลที่ต้องบันทึกเก็บไว้ เช่น แอป ฯ จดโน้ต ก็อย่าลืมบันทึกข้อมูลลง Persistant Storage ใน onPause
หรือ onStop
ด้วย เพื่อไม่ให้ข้อมูลหายไป และยังสามารถนำกลับมาให้ผู้ใช้ใช้งานต่อได้ตอนสลับกลับเข้าสู่โหมด DeX ครับ
ใครยังไม่แม่นเรื่อง Configuration Change และ Lifecycle งานนี้มีเดือดร้อนแหละ อย่าลืมจัดการทุกส่วนให้สมบูรณ์ด้วยเน้อ สำคัญนะ สำคัญ
ข้อมูลเพิ่มเติม
Samsung ทำ Documentation ของ Samsung DeX ไว้เรียบร้อย ไปอ่านเพิ่มเติมได้ที่ Samsung DeX | Samsung จ้าาา
มีอะไรเม้นต์ถามเพิ่มเติมได้นะ เดี๋ยวเอามาอัปเดตในบทความให้ครับ =)
เย้ เย จบแย้ว