ทำ PWA ให้กลายเป็นแอปแอนดรอยด์แบบง่าย ๆ ด้วย TWA
PWA + ANDROID = PLAY STORE
บทความนี้เหมาะกับ
นักพัฒนาที่มีเว็ปที่รองรับ PWA อยู่แล้ว และต้องการทำแอปแอนดรอยด์ด้วยการเปิดเว็ปโดยใช้ TWA แทนการใช้ WebView
ถึงเวลาสร้างแอปแอนดรอยด์กันแล้ว
หลังจากที่ได้รู้เรื่องราวของ TWA หรือ Trusted Web Activity กันไปแล้ว รวมไปถึงการทำ Digital Asset Links เพื่อใช้ในการยืนยันระหว่างเว็ปกับแอปว่ามีเจ้าของเดียวกัน ถึงเวลาที่จะสร้างแอปแอนดรอยด์กันแล้ว
ในการสร้างแอปแอนดรอยด์จะใช้ Android Studio นะ (ติดตั้งลงในเครื่องกันให้เรียบร้อยด้วย)
ผมจะขอเล่าตั้งแต่การสร้างโปรเจคขึ้นมาตั้งแต่แรกเลย เพราะคิดว่าน่าจะมีผู้อ่านหลาย ๆ คนที่ไม่ใช่นักพัฒนาแอนดรอยด์
สร้างโปรเจคแอนดรอยด์
เมื่อเปิด Android Studio ขึ้นมา ให้เลือก Start a new Android Studio project
เพื่อสร้างโปรเจคแอนดรอยด์ขึ้นมาใหม่

ถ้าเปิดโปรเจคอื่นทิ้งไว้อยู่ หน้าต่างในภาพข้างบนจะไม่แสดงขึ้นมานะ สามารถเลือกไปที่ File > New > New Project…
เพื่อสร้างโปรเจคใหม่ได้เช่นกัน
การสร้างโปรเจคขึ้นมาใหม่จะต้องเลือกทุก Project Template เสมอ ซึ่งเป็นเหล่า Activity สำเร็จรูปที่ Android Studio ได้เตรียมไว้ให้
Activity เปรียบเสมือนตัวควบคุมการทำงานของ UI ในแต่ละหน้า ซึ่งเป็น Component พื้นฐานของแอนดรอยด์

อย่างที่บอกไปว่า TWA จะช่วยให้เรานำเว็ปที่เป็น PWA มาแสดงผลในแอปแอนดรอยด์ได้แบบง่าย ๆ โดยไม่ต้องแตะโค้ด Java/Kotlin เลยแม้แต่นิดเดียว ดังนั้นให้เลือก No Activity
แล้วกดปุ่ม Next
ไปได้เลย
นั่นก็เพราะว่าเรามีสิ่งที่เรียกว่า Trusted Web Activity แล้วไงล่ะ
ในหน้าถัดมาเราจะต้องกำหนดรายละเอียดต่าง ๆ ของแอปแอนดรอยด์ ซึ่งจะประกอบไปด้วย
Name : ชื่อแอป
Package name : ชื่อ Package ของแอป ต้องเป็น Unique Name ที่ไม่ซ้ำกับ Package Name ของแอปอื่น ๆ ที่อยู่บน Google Play
Save location : กำหนด Directory เพื่อเก็บโปรเจคแอนดรอยด์ที่กำลังจะสร้างขึ้นมา
Language : ภาษาโปรแกรมที่จะใช้ในโปรเจค มีให้เลือกระหว่าง Kotlin และ Java (เลือก Kotlin ไปก็ได้ เพราะยังไงก็ไม่ได้เขียนอยู่ดี)
Minimum SDK : เวอร์ชันแอนดรอยด์ขั้นต่ำที่แอปจะรองรับ (แนะนำเป็น API 21)
Use legacy android.support.libraries : ไม่ใช้ (Uncheck)

จากนั้นก็กด Finish
ได้เลย แล้ว Android Studio ก็จะทำการสร้างโปรเจคใหม่ขึ้นมาให้ ซึ่งในตอนแรกจะทำการ Build Gradle เพื่อเตรียมให้โปรเจคพร้อมใช้งาน ซึ่งจะใช้เวลามาก/น้อยขึ้นอยู่กับแต่ละเครื่อง และถ้าไม่เคยใช้ Android Studio มาก่อน Gradle ก็จะดาวน์โหลดไฟล์ต่าง ๆ ที่จำเป็นสำหรับโปรเจคด้วย ซึ่งจะใช้เวลานานมากขึ้นไปอีก

เมื่อโปรเจคสร้างขึ้นมาและ Build Gradle เสร็จเรียบร้อยแล้ว ก็ให้เปิดหน้าต่าง Project ที่อยู่ด้านซ้ายมือสุดของโปรเจคขึ้นมา ก็จะเห็นโครงสร้างไฟล์ต่าง ๆ สำหรับโปรเจคแอนดรอยด์ของเรา
เพิ่ม Library ของ TWA และเปิดใช้งานความสามารถของ Java 8
TWA นั้นถูกสร้างขึ้นมาเป็น Library แยก ดังนั้นผู้อ่านจะต้องเพิ่ม Library ของ TWA เข้าไปในโปรเจคให้เรียบร้อยเสียก่อน โดยการเพิ่ม Library จะต้องทำในไฟล์ที่ชื่อว่า build.gradle
ของ App Module
ที่หน้าต่าง Project ให้เลือกไปที่ Gradle Scripts > build.gradle (Module: app)

แล้วเพิ่มคำสั่งเข้าไปที่บรรทุดของ android { ... }
ดังนี้
คำสั่งดังกล่าวเป็นเปิดใช้งานความสามารถของ Java 8 เพราะว่า Library ของ TWA มีการใช้ความสามารถของ Java 8 อยู่ด้วย
ถึงแม้จะเปิดใช้งานความสามารถของ Java 8 แต่ Gradle มีสิ่งที่เรียกว่า Desugar เพื่อแปลงคำสั่งเหล่านั้นของ Java 8 ให้กลายเป็น Java 7 แทน เพราะว่ามีแค่ Android 7.0 Nougat ขึ้นไปเท่านั้นที่สามารถใช้ Java 8 ได้
จากนั้นให้เลื่อนลงไปที่บรรทัดข้างล่างสุด จะเห็นคำสั่ง dependencies { ... }
ซึ่งเอาไว้ใช้กำหนด Library ที่ต้องการใช้งานในโปรเจคนั่นเอง
Dependency ใน Gradle ก็เปรียบเสมือน Library นั่นเอง
ให้เพิ่ม Library ของ TWA เข้าไปที่บรรทัดสุดท้ายของ dependencies { ... }
ดังนี้
เวอร์ชันของ Library ในขณะที่เขียนบทความนี้คือ 1.2.0 ถ้ามีเวอร์ชันใหม่กว่านี้ก็ให้ใช้เวอร์ชันที่ใหม่กว่าครับ
สรุปคำสั่งที่เพิ่มเข้าไปใน build.gradle
(เปิดใช้งานความสามารถของ Java 8 และเพิ่ม Library ของ TWA)
เนื่องจากเราได้แก้ไขคำสั่งที่อยู่ข้างใน build.gradle
จึงต้อง Build Gradle ใหม่ทุกครั้ง ซึ่ง Android Studio ก็จะรู้ได้โดยอัตโนมัติและแสดงข้อความแจ้งที่ข้างบนของหน้าต่างเพื่อแนะนำให้ Build Gradle ใหม่

ให้กดที่ปุ่ม Sync Now
ที่อยู่ขวามือของข้อความนั้นได้เลย แล้วรอซักพักเพื่อให้ Gradle ทำการดาวน์โหลด Library ของ TWA เพิ่มเข้าไปในโปรเจค
เมื่อ Build Gradle เสร็จแล้ว สามารถปิดไฟล์ build.gradle
ได้เลย เสร็จเรียบร้อยแล้ว
เพิ่ม Internet Permission และ ประกาศ Activity ของ Trusted Web Activity ใน Android Manifest
เริ่มจากเปิดไฟล์ AndroidManifest.xml
ขึ้นมาก่อน
Android Manifest คือไฟล์ที่เก็บข้อมูลโดยรวมของแอป เช่น Component, Permission, Package Name และ Minimum SDK Version

เนื่องจากแอปจำเป็นต้องใช้งานอินเตอร์เนต จึงต้องประกาศ Internet Permission ไว้ใน Android Manifest ด้วย
สิ่งที่ต้องทำต่อมาก็คือการประกาศ Activity ของ TWA ซึ่งจะต้องประกาศไว้ข้างใน <appplication>
แบบนี้
เห็นเยอะ ๆ แบบนี้อย่างเพิ่งตกใจ เพราะว่าทั้งหมดนี้คือคำสั่งที่จำเป็นสำหรับการใช้งาน TWA โดยจะใช้ Activity ที่ชื่อว่า com.google.androidbrowserhelper.trusted.LauncherActivity
สำหรับเปิด PWA ของเรานั่นเอง
และเพื่อช่วยให้เราไม่ต้องเขียนโค้ด Kotlin/Java เอง LauncherActivity จึงรับค่าต่าง ๆ ผ่านทาง Metadata แทน ซึ่งจะเห็นได้จาก Metadata ที่อยู่ข้างในที่ชื่อว่า android.support.customtabs.trusted.DEFAULT_URL
ซึ่งเป็น Metadata สำหรับกำหนด URL ของเว็ปที่เราต้องการเปิดใน LauncherActivity นั่นเอง
สำหรับ <intent-filter>
ทั้ง 2 ตัวที่อยู่ข้างใน LauncherActivity เป็นตัวกำหนดว่าแอปจะรองรับการเรียกใช้งานจากระบบแอนดรอยด์ในรูปแบบไหนบ้าง
โดย Intent Filter ตัวแรกสุด (ที่กำหนด Main Action และ Launcher Category ไว้ข้างใน) เป็นการบอกให้ระบบแอนดรอยด์สร้างไอคอนของแอปไว้ที่ App Launcher ด้วย เพื่อให้ผู้ใช้สามารถกดที่ไอคอนของแอปเพื่อเข้าใช้งานได้

ส่วน Intent Filter ตัวถัดมา (ที่กำหนด View Action, Default Category และ Browsable Category ไว้ข้างใน) เป็นการบอกให้ระบบแอนดรอยด์รู้ว่าแอปตัวนี้รองรับ Deep Links ด้วยโดยอิงตาม <data>
ที่กำหนดไว้ เมื่อใดก็ตามที่ผู้ใช้เปิด URL ของเว็ปเรา ระบบแอนดรอยด์จะมีให้เลือกว่าจะให้เปิดด้วย Web Browser หรือเปิดแอปแอนดรอยด์ของเรา

กำหนด Asset Statement ของเว็ปไว้ใน Android Manifest
ขาดขั้นตอนนี้ไปไม่ได้แน่นอน เพราะว่าเราได้เตรียมกันไว้ในบทความก่อนหน้านี้
ในการกำหนด Asset Statement สำหรับเว็ปของเราจะต้องนำ JSON ที่เตรียมไว้ไปเก็บไว้ใน String Resource เสียก่อน ซึ่งจะอยู่ที่ res/values/strings.xml
ของโปรเจค

โดยให้เพิ่ม <string>
เข้าไปที่บรรทัดสุดท้ายของ <resources>
แบบนี้
String Resource ที่เก็บ Asset Statement ของเว็ปไว้ เราจะกำหนดชื่อว่า asset_statements
ซึ่งจะนำไปกำหนดไว้ใน Android Manifest ทีหลัง แต่สิ่งที่ควรระวังสำหรับการเก็บ JSON ไว้ใน String Resource ก็คืออักขระพิเศษอย่าง ”
ซึ่งจะต้องเปลี่ยนเป็น \”
แทน
String Resource คือพื้นที่สำหรับเก็บข้อความต่าง ๆ และข้อมูลจำพวก String ที่จะใช้งานภายในแอปแอนดรอยด์ ซึ่งมีจุดเด่นตรงที่สามารถทำให้แอปรองรับข้อความที่มีหลายภาษาได้ง่าย (แต่ไม่จำเป็นสำหรับ PWA เพราะการเปลี่ยนภาษาทำที่ฝั่งเว็ปทั้งหมด)
กลับมาที่ AndroidManifest.xml
ให้เพิ่ม Metadata ไว้ข้างใน <Application>
(ย้ำว่า Application) แบบนี้
Metadata สำหรับ Digital Asset Links จะใช้ชื่อว่า asset_statements โดยใช้ String Resource ที่ได้สร้างไว้ก่อนหน้านี้นั่นเอง
@string/asset_statements
คือวิธีอ้างอิง Resource ที่แอนดรอยด์ออกแบบไว้ โดยใช้@string
นำหน้าเพื่อบอกว่าเป็น String Resource โดยใช้ String จาก String Resource ที่ชื่อasset_statement
เนื่องจากการทำ Digital Asset Links เป็นการทำในระดับทั้ง Applicaition ไม่ใช่แค่บาง Activity ดังนั้น Metadata ตัวนี้จึงอยู่ใน <Application>
แทน ไม่ใช่ <Activity>
เพียงเท่านี้เว็ปของเราก็จะกลายเป็น Trusted Web ทำให้เวลาเปิดบน TWA จะทำการซ่อน Title Bar โดยอัตโนมัติ และกลายเป็นเว็ปที่เรียบเนียนเหมือนแอปแอนดรอยด์ไม่มีผิด

ซึ่งเป็นอภิสิทธิ์พิเศษที่ Chrome บนแอนดรอยด์ทำให้เฉพาะตอนที่เปิด Trusted Web เท่านั้น
ในที่สุดเว็ปของเราก็สามารถ
เพิ่มลูกเล่นให้กับ TWA ด้วย Metadata ตัวอื่น ๆ
ขั้นตอนในก่อนหน้านี้ทั้งหมดเป็นขั้นตอนสำคัญในการใช้งาน TWA ซึ่งไม่สามารถข้ามขั้นตอนใด ๆ ไปได้เลย
แต่นอกจากขั้นตอนเหล่านั้นแล้ว เรายังสามารถกำหนดค่าต่าง ๆ ให้กับ TWA เพิ่มได้อีกด้วย เพราะ LauncherActivity รองรับ Metadata เหล่านี้ที่จะกำหนดหรือไม่กำหนดก็ได้
STATUS_BAR_COLOR
: กำหนดสีของ Status Bar และ Title BarNAVIGATION_BAR_COLOR
: กำหนดสี Navigation BarSPLASH_IMAGE_DRAWABLE
: กำหนดภาพเพื่อใช้แสดงใน Splash ScreenSPLASH_SCREEN_BACKGROUND_COLOR
: กำหนดสีพื้นหลังของ Splash ScreenSPLASH_SCREEN_FADE_OUT_DURATION
: ระยะเวลาของ Fade Out Animation ของ Splash Screen (เพื่อเข้าสู่หน้าเว็ปของเราที่โหลดเสร็จแล้ว) โดยมีหน่วยเป็น Millisecond
จะเห็นว่าผมได้กำหนดค่าสีใน Metadata บางตัวเป็น @color/statusBarColor
, @color/navigationBarColor
และ @color/splashScreenBackgroundColor
ซึ่งเป็นการกำหนดด้วย Color Resource นั่นเอง โดยไฟล์สำหรับ Color Resource จะอยู่ใน res/values/colors.xml
ถ้าไม่อยากสร้าง Color Resource ก็สามารถกำหนดเป็นรหัสสีโดยตรงได้เหมือนกัน (เช่น #177780 เป็นต้น)
และสำหรับ @drawable/ic_splash_screen
ก็คือ Drawable Resource สำหรับเก็บรูปภาพไอคอนที่ใช้แสดงใน Splash Screen นั่นเอง รองรับได้ทั้ง JPG, PNG, WebP และ Vector Drawable ที่ Import จากไฟล์ SVG ได้ โดย Drawable Resource จะแยกเป็นไฟล์ของภาพแต่ละอันไว้ข้างใน res/drawable-<dpi>
Drawable Resource จะมีการแยกไฟล์รูปตาม DPI (เช่น
drawable-mdpi
,drawable-hdpi
หรือdrawable -xxxhdpi
เป็นต้น) เพื่อให้นักพัฒนาสามารถเตรียมรูปภาพสำหรับหน้าจอที่มีความละเอียดที่แตกต่างกันได้โดยนิยมแยก Drawable Resource ตาม DPI เฉพาะไฟล์ภาพ JPG, PNG และ WebP เท่านั้น ถ้าเป็น Vector Drawable สามารถเก็บไว้ใน
res/drawable
ได้เลย
อย่าลืมกำหนดภาพไอคอนของแอปแอนดรอยด์
ไฟล์ภาพที่ใช้เป็นภาพไอคอนของแอปจะกำหนดไว้ใน Android Manifest และเก็บอยู่ใน Mipmap Resource สามารถเปลี่ยนเป็นภาพอื่น ๆ ได้ตามใจชอบ
แต่เพื่อให้ภาพไอคอนของแอปสามารถแสดงได้อย่างสมบูรณ์แบบ อย่าใส่ไฟล์ภาพด้วยตัวเอง ให้ใช้ GUI ของ Android Studio ช่วยในการกำหนดภาพไอคอนของแอปดีกว่า
โดยให้คลิกขวาที่ res
แล้วเลือก New > Image Asset

จากนั้นจะมีหน้าต่างของ Image Asset แสดงขึ้นมาเพื่อให้เรากำหนดภาพไอคอนของแอป

ข้อดีของการใช้ Image Asset เพื่อกำหนดภาพไอคอนของแอปคือจะมั่นใจได้ 100% ว่าภาพไอคอนนั้นแสดงได้อย่างสมบูรณ์แบบบนอุปกรณ์แอนดรอยด์ทุกรุ่น อีกทั้งยังรองรับ Adaptive Icons ซึ่งเป็นลูกเล่นอย่างหนึ่งในภาพไอคอนของแอปบนแอนดรอยด์ และรวมไปถึงภาพไอคอนที่จะต้องใช้ตอนอัปโหลดแอปขึ้น Google Play อีกด้วย
Adaptive Icons จะกำหนดภาพไอคอน (Foreground) และภาพพื้นหลัง (Background) แยกกัน จึงเป็นที่มาว่าตอนกำหนดภาพไอคอนใน Image Asset จะต้องกำหนดทั้ง 2 อัน
เมื่อกำหนดเสร็จแล้วก็กด Next
ได้เลย

แล้วจะมาที่หน้ายืนยันการสร้างไฟล์ภาพไอคอนของแอป ซึ่งผู้อ่านสามารถกด Finish
ได้เลย
เพียงเท่านี้แอปของคุณก็จะเปลี่ยนไปใช้ภาพไอคอนตามที่กำหนดไว้แล้ว
เพิ่มเติม — การกำหนดภาพไอคอนของแอปจะกำหนดไว้ใน
<application>
ของ Android Manifest ด้วย Attribute ที่ชื่อว่าandroid:icon
และandroid:roundIcon
คุณได้แอปแอนดรอยด์ที่ทำงานด้วย PWA + TWA จำนวน 1 ea
จะเห็นว่าการใช้ TWA จะช่วยลดขั้นตอนต่าง ๆ ในการทำแอปได้เยอะมาก จนไม่ต้องเขียนโค้ด Kotlin/Java เลย มีแค่เพียงขั้นตอนการกำหนดค่าต่าง ๆ ให้กับ TWA ด้วย XML เท่านั้นเอง
ในที่สุดก็สามารถทำให้ PWA ของเราเปิดบนแอปแอนดรอยด์เพื่อทำเป็น Signed APK และอัปโหลดขึ้น Google Play ได้แล้ว~♪