อัพเดตข่าวสารอาชีพประจำปี กับงาน Android Bangkok Conference 2023
ปีนี้เป็นชาวบ้านหนึ่ง ไม่ใช่ speaker นั่งฟังเนื้อหาสาระต่าง ๆ เทรนในปีนี้ แน่น๊อนน Jetpaack Compose กำลังเริ่มมาแล้วแหละ
![](https://www.mikkipastel.com/content/images/2023/11/20231105_131808-1.webp)
งาน Android Bangkok Conference 2023 จัดขึ้นวันอาทิตย์ที่ 5 พฤศจิกายน ที่ SCB NEXT TECH
รายละเอียดงานจ้า
![](https://res.cloudinary.com/startup-grind/image/upload/c_fill,dpr_2.0,f_auto,g_center,h_1080,q_100,w_1080/v1/gcs/platform-data-goog/events/FB_Page_Profile.png)
อันนี้ session วันก่อนหน้า DevFest Bangkok 2023 สามารถอ่านที่บล็อกนี้เลย
![](https://www.mikkipastel.com/content/images/2023/11/20231104_124227--1-.jpg)
เพิ่มกำลังด้วยชาเขียวสักหน่อย สั่งจากแอพไปรับที่สาขา
![](https://www.mikkipastel.com/content/images/2023/11/image-148.png)
มาถึงปุ๊ป อ้าวว session แรกแล้วหรอ ม่ายยยยย
ปล. ตัวสไลด์ทั้งหมดเราเอามาจากโพสนี้น้า
.
Compose Modifiers Made Easy - Tipatai Puthanukunkit
มาถึงก็เริ่ม session ไปแล้ว แต่ตามทันอยู่น้า เพราะช่วงนี้ลองทำแอพ Jetpack Compose เล่นอยู่
![](https://www.mikkipastel.com/content/images/2023/11/image-149.png)
Order of Modifiers is important
order สำหรับ Jetpack Compose เป็นเรื่องสำคัญ มันทำงานจากบนลงล่าง
![](https://www.mikkipastel.com/content/images/2023/11/image-150.png)
เช่น อันนี้จะ set ให้เต็มความกว้างก่อน แล้วเท bacckground สีเขียวลงไป แล้วก็ทำ padding ให้รูปห่างจากขอบ 32dp
![](https://www.mikkipastel.com/content/images/2023/11/image-151.png)
หรืออันนี้ทำ paadding ก่อน ซึ่งถ้า padding ถูกกำหนดก่อน ก็เหมือน set margin บน xml แล้วแหละ
![](https://www.mikkipastel.com/content/images/2023/11/20231105_125510.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_125528.webp)
การทำ View ซ้อนกันเป็นเรื่องง่ายขึ้น และบางครั้งก็ง่ายกว่า xml ด้วย
![](https://www.mikkipastel.com/content/images/2023/11/image-153.png)
เลยทำให้มัน reuse ได้ เป็น extension function แล้วใส่ Modifier เป็นตัวแปรได้
![](https://www.mikkipastel.com/content/images/2023/11/20231105_125700.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_125719.webp)
insets padding สำหรับ Jetpack Compose มีให้เราจัดการตรงนี้ได้
![](https://www.mikkipastel.com/content/images/2023/11/image-155.png)
แล้วสามารถทำ blur ได้ด้วยนะ แบบไม่ต้องไปลง library เพิ่ม
![](https://www.mikkipastel.com/content/images/2023/11/image-156.png)
Clip
เป็นการตัดรูป เช่น ครอปเป็นวงกลมให้หน่อย clip(CircleShape)
![](https://www.mikkipastel.com/content/images/2023/11/image-157.png)
หรือจะสี่เหลี่ยมขอบมนก็ได้เช่นกัน โดยใช้ RoundedCornerShape
โดยจะ ใส่ parameter ตัวเดียว เช่น RoundedCornerShape(64.dp)
หรือจะใส่เป็นแบบเลือกขอบมนเฉพาะมุมก็ได้ RoundedCornerShape(topStart = 64.dp, bottomEnd = 64.dp)
![](https://www.mikkipastel.com/content/images/2023/11/image-158.png)
custom shape สามารถทำแบบแปลก ๆ ซึ่งอันนี้มีเป็น library แยกเนอะ
![](https://www.mikkipastel.com/content/images/2023/11/image-159.png)
Clickable
แล้วเราจะให้มันคลิกได้ยังไง ใช้ clickable
ใส่ใน Modifer ได้เลย มันจะทำ auto ripple ให้ ยํ้าอีกรอบนึง order สำคัญมาก ตอนคลิกเห็นเป็นสี่เหลี่ยม เพราะเราให้ clip เป็นวงกลมทีหลัง แก้โดยให้ clip(CircleShape)
ก่อน แล้วสั่ง clickable
ทีหลัง
![](https://www.mikkipastel.com/content/images/2023/11/image-160.png)
Scroll
ใช้สำหรับตัวที่ไม่มี list item เยอะจนเกินไป สามารถใช้ได้ทั้งแนวนอนและแนวตั้ง มี rememberScrollState()
ด้วย
![](https://www.mikkipastel.com/content/images/2023/11/20231105_130322.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_130335.webp)
Offset
เลื่อน UI โดยยึดจากจุดตั้งต้นไปเท่าไหร่ เอาไว้ทำพวก animation ซ้ายขวา
offset(x = 200.dp)
เลื่อนรูปไปด้านซ้าย 200dpoffset(x = (-200).dp)
เลื่อนรูปไปด้านขวา 200dpoffset(y = (-200).dp)
เลื่อนรูปขึ้นไป 200dpoffset(y = 100.dp)
เลื่อนรูปลงมา 100dp
![](https://www.mikkipastel.com/content/images/2023/11/image-161.png)
ตัวอย่างการนำไปใช้ในการทำ animation
![](https://www.mikkipastel.com/content/images/2023/11/image-162.png)
อันนี้แบบ video มีเคลื่อนที่ปกติ และหมุนไปด้วย
Semantics
sementics ทำเมื่อผู้บกพร่องทำด้านต่าง ๆ อย่างการใส่ contentDescription
บอกว่าสิ่งนี้คือรูปน้องทาโร่นะ
![](https://www.mikkipastel.com/content/images/2023/11/image-163.png)
สามารถนำไปใส่เป็น flag เพื่อระบุตอน test ได้ง่าย
![](https://www.mikkipastel.com/content/images/2023/11/image-164.png)
Scoped Modifier
สามารถใช้ได้ครบทุก composable แต่อันที่ใช้ได้มีบางอันเท่านั้น เช่น ใช้ weight กับ RowScope, align column เรียงแนวนอน
![](https://www.mikkipastel.com/content/images/2023/11/image-167.png)
ตัวอย่างการใช้ weight จะคล้าย ๆ ที่เรา set ที่ LinearLayout เลย
![](https://www.mikkipastel.com/content/images/2023/11/20231105_131018.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_131028.webp)
alignByBaseline()
ตรงบรรทัด
![](https://www.mikkipastel.com/content/images/2023/11/image-165.png)
Box Scope จะคล้าย ๆ FrameLayout
![](https://www.mikkipastel.com/content/images/2023/11/20231105_131239.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_131253.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_131342.webp)
เท color background ทับแมว ใช้ matchParentSize()
![](https://www.mikkipastel.com/content/images/2023/11/20231105_131355.webp)
Intrinsic
ปกติใช้ ContrainLayout ในการทำ view อะไรแบบนี้เนอะ
![](https://www.mikkipastel.com/content/images/2023/11/image-168.png)
สำหรับ Jetpack Compose ใช้ Intrinsic มาช่วย อันนี้คือก่อนหน้า
![](https://www.mikkipastel.com/content/images/2023/11/image-169.png)
ที่ไม่เป็นไปตามนั้นเพราะตัว View ไม่รู้ความสูง ดังนั้นจะต้องรู้ความสูงก่อน โดยใส่ height(IntrinsicSize.Min)
ลงไปที่ Modifier
![](https://www.mikkipastel.com/content/images/2023/11/image-170.png)
สรุปทั้งหมดใน session
![](https://www.mikkipastel.com/content/images/2023/11/image-171.png)
สไลด์ของ session แรกจ้า
Hidden powers of Compose Canvas - Fedor Erofeev
อันนี้ตอนเขายกตัวอย่างแต่ละ view อาจจะตามไม่ค่อยทัน คิดว่าอ่านสไลด์เขาด้วยน่าจะเข้าใจได้ง่ายกว่าที่เราสรุปนะ 555
จริง ๆ ก็มีหลาย ๆ Modifier ที่ใช้วาดนะ
![](https://www.mikkipastel.com/content/images/2023/11/image-172.png)
แล้วทางอื่น ๆ ล่ะ ความแตกต่างของแต่ละอัน ไม่ว่าจะเป็น
- DrawScope: สร้าง scope ในการสาดรูป มีการ provide ตัว stateless API เพื่อวาด shape และ path โดยไม่มีต้อง maintain state ของ Canvas
- Compose Canvas: เราสามารถวาดได้โดยตรงโดยใช้
drawIntoCanvas()
ในการควบคุมการวาดต่าง ๆ - Native Canvas: เราสามารถเข้าถึง Native Canvas ได้จาก Compose Canvas ในกรณีที่อยากทำให้ Canvas สมบูรณ์ขึ้น เช่น การเพิ่มเงา
![](https://www.mikkipastel.com/content/images/2023/11/image-229.png)
ทางที่ดีที่สุดคือใช้ DrawScope แล้วทำไมต้อง DrawScope เอาไว้วาดรูปร่างต่าง ๆ ได้ง่าย และมีประสิทธิภาพมากที่สุด และมีบาง function ที่เหมือนกับ Compose Canvas ด้วย
![](https://www.mikkipastel.com/content/images/2023/11/20231105_132131.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_132205.webp)
Animation in Compose
ใน session นี้กล่าวถึง animation 3 ชนิด คือ
- InfiniteTransition: วิ่งตลอด
- Animatable: วิ่งครั้งเดียวจบ
- InfiniteAnimationPolicy: วิ่งตาม frame time
![](https://www.mikkipastel.com/content/images/2023/11/20231105_132319.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_132434.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_132516.webp)
Moving Thing Round
พูดถึงการ transform กับ canvas ของเรา เช่น ทำ loading spinner
![](https://www.mikkipastel.com/content/images/2023/11/image-233.png)
วิธีการคร่าว ๆ คือ วาด 12 เส้น แล้วหามุม แล้ว alpha ของแต่ละอัน มาวาด และ rotate ให้มันเป็นวงกลมอ่ะ
![](https://www.mikkipastel.com/content/images/2023/11/20231105_132713.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_132732.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_132805.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_132836.webp)
Blending things together
พูดถึงการ blend ของ 2 สิ่งเข้าด้วยกัน เช่น การสร้าง pie chart เป็นการเอาสี่เหลี่ยมกับวงกลมมาซ้อนกัน แล้วก็แสดงแบบหมุน ๆ จนเต็มวง
![](https://www.mikkipastel.com/content/images/2023/11/image-279.png)
เริ่มจากสร้าง data class มาเก็บค่าสี และ size แล้วมาทำ animate วาดเส้น arc แล้วลากเส้นจนครบวง
![](https://www.mikkipastel.com/content/images/2023/11/20231105_133029.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_133143--2-.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_133219.webp)
ตัวอย่างอื่นที่ประยุกต์ใช้ได้
![](https://www.mikkipastel.com/content/images/2023/11/image-278.png)
Adding Colors
การระบายสี มีหลาย ๆ แบบ เช่น เทสีลงไปเลย หรือใช้ gradient ในแบบต่าง ๆ
![](https://www.mikkipastel.com/content/images/2023/11/image-280.png)
ตัวอย่าง คือการทำ flashing button มีการเล่น animation จากมุมทั้งหมด 360 องศา โดยใช้ LinearGradient และเป็นสี่เหลี่ยมมุมมน
![](https://www.mikkipastel.com/content/images/2023/11/image-281.png)
Applying effects
สร้าง DrawModifier ในการวาด content ที่เราต้องการ
![](https://www.mikkipastel.com/content/images/2023/11/image-282.png)
ในที่นี้คือทำตัว view นี้ และพื้นหลังเป็นรูปที่มีการเล่น gradient และซูมเข้าออก
วิธีการคร่าว ๆ คือ set gradient และ image scale ก่อน จากนั้นโหลดรูปที่ต้องการมาใส่ แล้วก็วาด content ด้านบนที่เป็นตั๋ว กับคำว่า travel แล้วเอารูปที่ทำมาซ้อนหลัง แล้วใส่ gradient
![](https://www.mikkipastel.com/content/images/2023/11/image-283.png)
Animation Paths
วาดเล่นให้เป็นดาว คือรูปดาวนี้เป็นไฟล์ svg สามารถเอามาใช้ในการวาด path ได้เลย
![](https://www.mikkipastel.com/content/images/2023/11/image-284.png)
Making texts look cool
อันน้ีว้าวหน่อย คือวาด text ด้วย Compose Canvas
![](https://www.mikkipastel.com/content/images/2023/11/image-285.png)
อันนี้เป็น text ที่มีเงา แล้วเลื่อนขึ้นลงไปมา การทำคร่าว ๆ คือ set animating offset ว่าเราขะให้ขึ้นลงเท่าไหร่ จากนั้น measuring text แล้วสั่งให้เล่นขึ้นลง แล้วเลื่อนเงาไป
![](https://www.mikkipastel.com/content/images/2023/11/image-286.png)
Drawing drawables
ใช้ Oainter class ในการวาดบน DrawScope ทำโดยการสร้าง animation แล้วใช้ VectorPainter ในการวาด drawable resource แล้ววาด icon อันนี้มาเพิ่ม
![](https://www.mikkipastel.com/content/images/2023/11/image-287.png)
Doing magic with shaders
พูดถึง shader เป็นคำสั่งในการ exexute ทุก ๆ pixel บน screen อันนี้เขียน script ภาษา C++ แล้วให้มัน generate time frame ออกมาอะไรงี้
![](https://www.mikkipastel.com/content/images/2023/11/20231105_134530.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_134550.webp)
code ตัวอย่างทั้งหมดใน session นี้
ส่วนอันน้ีสไลด์จ้า ค่อย ๆ อ่านสไลด์เอาเนอะ ทางเราสรุปแบบคร่าว ๆ
Premium Media Experiences on Android - Hassan Abid
![](https://www.mikkipastel.com/content/images/2023/11/image-214.png)
ก่อนอื่นเขาเปิดคลิปอันนี้ก่อนเลย
คนใช้มือถือทำอะไรบ้าง? ส่วนใหญ่ใช้ในการเสพสื่อต่าง ๆ และความบันเทิง เช่นฟังเพลง ดู YouTube และใช้ social network ต่าง ๆ การที่มีคน subscription พวก entertainment เยอะ ทำให้ตัว platform มีรายได้
premium devices มีความเกี่ยวข้องกับ 3 เรื่อง คือ
- Technology ที่ใหม่ล่าสุด ในส่วนของ processor, กล้อง, senser และหน้าจอ
- Longevity มีการใช้งานที่ยืนยาว โดยอัด RAM มาแบบเต็มที่ มี chip ที่ทำให้อายุการใช้งานเครื่องยาวนาน และ support การ update software แบบยาวนานด้วย
- Polish ใส่ hardware ที่ดีในการทำงานต่าง ๆ ของมือถือได้อย่าง smooth มากขึ้น เช่น เล่นเกมส์ที่กราฟฟิคดี ๆ ได้, AI/MLfeatures, สร้างและเล่น media ในคุณภาพที่สูงได้
ถ้าไม่ใช่ premium devices มีข้อจำกัดทาง hardware ทุกอย่าง ซึ่งบาง feature ก็ไม่ได้ support ทุก device ด้วย
Jetpack Media3
เป็น playback video และ audio ตัวนี้เป็น new ExoPlayer ด้วยล่ะ
Migration Guide
ExoPlayer2 → Media3 ดูตาม document นี้เลย
![](https://www.mikkipastel.com/content/images/2023/11/image-270.png)
![](https://developer.android.com/guide/topics/media/media3/overview.png)
Video Editing (Transformation API)
ตัว Transformation API อยู่ใน Media3 มี API ต่าง ๆ ให้ใช้ดังนี้
- Transcoding เช่นถ่ายจาก pixel ไปเปิดรูปบน Fold ให้มัน HD เหมือนเดิม
- HDR Video
- Video Editing ตัดต่อ video แหละ
Transcoding
การ Transcoding เป็นอะไรที่แพงมาก วิดีโอ HD 1 ชั่วโมง ใช้เงินไป 1.02 USD
![](https://www.mikkipastel.com/content/images/2023/11/image-271.png)
การใส่ Trancode ใส่อันนี้ไปในโค้ดแบบนี้ setVideoMimeType(MimeTypes.VIDEO_H264)
![](https://www.mikkipastel.com/content/images/2023/11/image-272.png)
Video Editing
การตัดต่อวิดีโอแหละว่ากันง่าย ๆ มีการหมุนคลิป, zoom-in and zoom out, trim video, OpenGL effect, Single Asset Edits ส่วน Multi Asset ติดตามกันต่อไป
แน่นอนว่าถ้าใครที่ลองเล่น FFmpeg ตามความเข้าใจของเราคือมันเป็น low-level library เนอะ ใส่ไปปุ๊ป ทำให้แอพเราบวมขึ้น 40-100 MB เลย
![](https://www.mikkipastel.com/content/images/2023/11/image-273.png)
ถ้าเราใช้ FFmpeg ในการหมุนคลิปมันทำยากเนอะ จำไม่ได้ว่าทำยังไง แต่สำหรับ Media3 เพียง implement ไปแบบนี้ ก็เป็นการหมุนคลิปแล้ว
![](https://www.mikkipastel.com/content/images/2023/11/image-274.png)
// Rotate a Video
Transformer.Builder(context)
.setVideoEffects(
listOf(
ScaleToFitTransformation.Builder()
.setRotationDegrees(90f)
.build()
)
)
.build()
หรือการ zoom-out ก็เช่นกัน
![](https://www.mikkipastel.com/content/images/2023/11/image-275.png)
MediaPipe
เช่น face filter บน TikTok
Demo
เชื่อมกับ Firebase ดึงเครื่องเทสจาก Firebase Test Lab ออกมาใช้ด้วยแหะ แต่ด้วยเหตุบางอย่าง เลยไม่ได้ใช้
![](https://www.mikkipastel.com/content/images/2023/11/image-276.png)
เขาเปิด sample app เพื่อนำวิดีโอมาใช้กับ Transformer APIs และ MediaPipe
![](https://www.mikkipastel.com/content/images/2023/11/image-277.png)
อันนี้เป็นคลิป
Studio Bot
เป็น feature ที่ยังไม่รองรับประเทศไทยซะที เราสามารถถาม code กับตัว bot ได้ แล้วเรา copy error ไปถามได้ด้วยน้า แล้วก็กด merge ตรงสาเหตุนั้นได้ คุณ speaker เลยเปิดเล่นเป็นบุญตาให้กับ developer ชาวไทย
![](https://www.mikkipastel.com/content/images/2023/11/20231105_143012.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_143048.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_143220.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_143245.webp)
Camera Previews
เห็น stat อันนี้ก็ไม่แน่ใจเลย ว่า 76 ล้านคน ใช้เวลากับกล้องในแต่ละครั้ง 45 นาทีอ่ะ
![](https://www.mikkipastel.com/content/images/2023/11/image-267.png)
- preview จริงเราบวม ดังนั้นทำให้ preview กับของจริงตรงกัน ด้วย stabilization mode
![](https://www.mikkipastel.com/content/images/2023/11/20231105_143536.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_143625.webp)
- ทำให้ feature กล้อง support ทุก screen
![](https://www.mikkipastel.com/content/images/2023/11/20231105_143713.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_143800.webp)
- Foldable ออกแบบให้ user สามารถ selfie ได้ดีขึ้น
- ใส่ camera extension ให้ go premium
![](https://www.mikkipastel.com/content/images/2023/11/image-268.png)
picture-in-picture เป็น UX ที่ดี สามารถเล่น media บน background ได้
ตอนนี้ media3 ยังไม่พร้อมใช้ใน Compose ให้ติดตามกันต่อไป
![](https://www.mikkipastel.com/content/images/2023/11/image-265.png)
อันนี้สไลด์ของ speaker ซึ่งเขาให้เรา scan ช่วงต้น session เลย
Recreate Portrait Watch Face on Wear OS - Ammar Lanui
อันนี้ฟังสนุกดี คือเป็นการทำ portrait watch face เอารูปไปใส่ในอุปกรณ์ Wear OS ได้รับแรงบันดาลใจจาก Apple Watch แล้วทำได้ไหม ต้องทำยังไงบ้าง ไปดูกัน
![](https://www.mikkipastel.com/content/images/2023/11/image-215.png)
speaker แนะนำตัว เขาเป็นผู้มีประสบการณ์ด้าน Wear OS มานานมาก ๆ
![](https://www.mikkipastel.com/content/images/2023/11/image-216.png)
ตัวแอพที่เขาทำ ชื่อว่า Willow สามารถส่งรูปจากโทรศัพท์ของเราเพื่อไปปรับแต่งตัว watch face ได้ มีการปรับพวก font ใน style ที่เราชอบ และนำรูปและ font จากภายนอกมาใช้ได้ด้วย
![](https://www.mikkipastel.com/content/images/2023/11/image-217.png)
ตัว portrait watch face ได้แรงบันดาลใจมาจาก Apple Watch ซึ่งตัวรูป portrait จะมี depth map จากตัว iPhone เอามาเล่น multilayer ได้ด้วย
ถ้าถ่ายรูปโหมดอื่นที่ไม่ใช่ portrait จะเล่นแบบนี้ไม่ได้นะ
![](https://www.mikkipastel.com/content/images/2023/11/image-218.png)
เมื่อลองมารวมร่างกัน พบว่ามี issue ในเรื่องความสวยงามมากมาย
![](https://www.mikkipastel.com/content/images/2023/11/20231105_145005.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_145146.webp)
ขั้นตอนการทำ
- Multilayered effect from Depth map: แยก layer ต่าง ๆ มี original image, text แสดงวันที่, text แสดงเวลา และส่วน portrait image ซึ่งอยู่บนสุด
![](https://www.mikkipastel.com/content/images/2023/11/image-220.png)
- Focused subject: เรา focus ส่วน portrait image
- Blur background: blur พื้นหลัง
- Options for Typography: เพิ่ม text แสดงเวลา และเรื่อง font
ทำไมถึงอยากทำสิ่งนี้บน Wear OS ล่ะ?
- มัน cool
- มันตอบโจทย์ปัญหาต่าง ๆ เกี่ยวกับรูปบน watch face
- ยังไม่มีคนทำสิ่งนี้บน Wear OS
- คนที่ไม่มี Apple Watch ก็อยากใช้สิ่งนี้
![](https://www.mikkipastel.com/content/images/2023/11/image-221.png)
Technical challenge
- อะไรคือ process ในการส่งรูปจากมือถือไปแสดงบน watch
- เราจะปรัย watch face ให้แสดงเวลา โดยแสดงอยู่ข้างหลัง object ที่เราสนใจ
- อะไรคือ step ในการเปลี่ยน font บน watch face
- เราจะ reposition text หรือ element อื่น ๆ ที่อยู่ใต้ portrait area ได้อย่างไร
![](https://www.mikkipastel.com/content/images/2023/11/image-222.png)
Watch Face Creation Tool
![](https://www.mikkipastel.com/content/images/2023/11/image-223.png)
Watch Face Format: ตัวนี้สามารถลากวางได้ โดยเอารูปจริง และตัว background มาใส่ได้
Watch Face Studio: เช่นของ Samsung มีให้ทำ face watch เองได้ เหมือนทำบน Photoshop สามารถ submit ไป Play Store ได้
![](https://www.mikkipastel.com/content/images/2023/11/20231105_145755.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_145958.webp)
แต่วิธีนี้มันเป็น static แล้วมัน recompile ไม่ได้
![](https://www.mikkipastel.com/content/images/2023/11/20231105_150125.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_150131.webp)
Native Kotlin: control program การทำงานต่าง ๆ ได้ เราสามารถเขียนอะไรก็ได้ เหมือนเราเป็นเทพเจ้าในการสร้างสิ่งนี้ขึ้นมา
![](https://www.mikkipastel.com/content/images/2023/11/20231105_150221.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_150235.webp)
แล้วระหว่างมือถือ และตัว watch จะคุยกันยังไง? คุยผ่าน Wear OS สิ ง่ายกว่า ในการใช้ API ในการคุยกัน
![](https://www.mikkipastel.com/content/images/2023/11/20231105_150342.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_150533.webp)
ในส่วนนี้สามารถศึกษา github sample code เพิ่มเติมได้เลย
ตอนนี้ตอบ technical challenge ได้หมดล่ะ
![](https://www.mikkipastel.com/content/images/2023/11/image-224.png)
แต่ยังเหลือ challenge อีกอย่างนึงคือ เราจะลบ background ออกยังไง?
![](https://www.mikkipastel.com/content/images/2023/11/image-225.png)
ไม่ใช้ machine learning เพราะกลัว bias ของ AI แล้วตัดผิด
ถ้าส่งไป online service ดีไหมนะ? มีการ upload phone และมีเรื่อง privacy แล้วก็ consent ต่าง ๆ มีการลบ data ออกจาก server ให้ด้วยไหม เก็บข้อมูลเป็นระยะเวลาเท่าไหร่ แล้วมีเรื่อง cost ต่าง ๆ ด้วย
![](https://www.mikkipastel.com/content/images/2023/11/20231105_151014.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_151027.webp)
สุดท้ายใช้ ML Kit ในการตัดพื้นหลัง และมัน run on device ทำให้หมดปัญหาต่าง ๆ process ต่าง ๆ จะอยู่บน on-device
![](https://www.mikkipastel.com/content/images/2023/11/image-226.png)
ใช้ selfie segmentation เป็น image subtraction แยก background กับคนออกจากกัน
![](https://www.mikkipastel.com/content/images/2023/11/20231105_151237.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_151324.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_151419.webp)
Demo
เป็นแอพที่เลือกรูปจากตัวแอพ แล้วก็สลับ layer ต่าง ๆ ได้ ประมาณนี้
![](https://www.mikkipastel.com/content/images/2023/11/20231105_151616.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_151708.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_152042.webp)
ตัวสไลด์ของ session นี้
อันนี้ตัว code ของแอพ Willow Watch Face ใช้ได้เฉพาะ Samsung Watch device เท่านั้น ใครสนใจมาตำได้ ยังเหลืออยู่
A to Z of Snapshot Testing - Aung Kyaw Paing
แว่บแรกในงานทุกคนเห็นอะไรจาก session นี้
เนื้อหา ❌
ราคา BTC, ETH, USDT ที่อยู่แถบด้านบนจอของ speaker ✅
![](https://www.mikkipastel.com/content/images/2023/11/image-228.png)
ก่อนอื่นเลย snapshot != UI Test แต่มันคือเป็นการ check ความถูกต้องว่ามันตรงกับ design ไหม
![](https://www.mikkipastel.com/content/images/2023/11/image-235.png)
เข้าใจว่าถ้าเราทำ Snapshot Test เยอะ ๆ จะทำให้เราทำ UI Test น้อยลงด้วย
![](https://www.mikkipastel.com/content/images/2023/11/image-236.png)
เช่น view Card Render เรา check ว่า
- text แสดงไหม
- icon แสดงไหม แสดงเป็นหน้าตาแบบนี้นะ
- icon แสดงด้านซ้าย text แสดงด้านขวา
- content padding 64 dp
- มี background กับ text แบบนี้นะ
![](https://www.mikkipastel.com/content/images/2023/11/image-237.png)
อันนี้ก็ test case เนาะ
![](https://www.mikkipastel.com/content/images/2023/11/image-238.png)
ข้อเสียของ UI Test คือ ไม่สามารถ test แบบ visual aspect ของแต่ละ comonent ได้, ช้า, มีการ set up ที่ซับซ้อน
![](https://www.mikkipastel.com/content/images/2023/11/image-239.png)
โดยตัว UI Test เน้นหา Interaction bugs เช่นการ scroll การกดปุ่มใด ๆ ส่วน Snapshot Test เน้นหา Visual bugs อย่างพวก style ต่าง ๆ ความห่าง ธีม
![](https://www.mikkipastel.com/content/images/2023/11/image-240.png)
Visual Bugs
แล้ว visual bug มีอะไรบ้าง? นอกจากการเปลี่ยนแปลงจากตัว library เองแล้วยังมีพวก style, padding, margin, สี, ธีมของตัวแอพ แล้วก็ layout edge case
![](https://www.mikkipastel.com/content/images/2023/11/20231105_152915-1.webp)
ก่อน test อย่าลืม check device กันก่อนนะ ไม่ว่า layout จะเป็น xml หรือ compose เองก็ตาม
![](https://www.mikkipastel.com/content/images/2023/11/20231105_153116-1.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_153143.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_153203.webp)
tool มันดี แต่การทำ manual มันน่าเบื่อ และยาก อีกทั้งทำให้ regression ไม่ได้
![](https://www.mikkipastel.com/content/images/2023/11/image-241.png)
Snapshot Testing
เราจะใช้ screenshot หรือ snapshot ที่มี reference ในการ compare ผลกัน
ขั้นตอนก็จะมี
![](https://www.mikkipastel.com/content/images/2023/11/image-242.png)
- Record: take snapshot เก็บไว้
- Verify: compare กับ snapshot ล่าสุดว่ามัน match กันไหม
ในส่วน record เมื่อเดฟทำการเปลี่ยน layout บางอย่าง และ record snapshot ใหม่ไปให้ ทำการเปิด PR เอา snapshot ไปเก็บไว้
ส่วนการ verify หลังจากเปิด PR ก็เข้า pipeline เพื่อเอาก้อน record มา check
![](https://www.mikkipastel.com/content/images/2023/11/20231105_153404.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_153504.webp)
Configuration Matters!
ผลอาจต่างกัน ตาม enironment ที่ set ไว้
![](https://www.mikkipastel.com/content/images/2023/11/image-243.png)
แล้วเราจะเริ่มยังไง?
- Screen level snapshot testing: ใช้ dependencies เยอะ มี state มากมาย มี component เยอะแยะ และยากในการ trace เมื่อมีการเปลี่ยนแปลง
![](https://www.mikkipastel.com/content/images/2023/11/20231105_153852-1.webp)
- Component level snapshot testing? เราควรหยิบตรงไหนมาเทสดี?
ไม่หยิบ app bar ที่ไม่เปลี่ยน กับพวก library component เพราะเขาน่าจะเทสมาแล้ว ให้หยิบ content มา test
![](https://www.mikkipastel.com/content/images/2023/11/20231105_154055.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_154111.webp)
Tooling
มีเยอะแยะมากมายเลย
![](https://www.mikkipastel.com/content/images/2023/11/image-246.png)
ในที่นี้พูดถึง Roborazzi เช่นเราอยาก test view นี้
![](https://www.mikkipastel.com/content/images/2023/11/image-249.png)
อ่าตัวโปรเจกต์ตัวอย่างใช้ Jetpack Compose ถ้าใช้ stateless composable จะแบ่ง UI Test และ Snapshot Test คือ UI Test เน้นพวก flow เช่นโหลดข้อมูลมาแสดง ส่วน Snapshot Test ดูว่ามัน render ถูกตำแหน่งไหม
![](https://www.mikkipastel.com/content/images/2023/11/image-250.png)
หน้าตา test case คร่าว ๆ
![](https://www.mikkipastel.com/content/images/2023/11/image-251.png)
เรา setting ผ่าน gradle ตามนี้เลย ตอน compare เราจะเห็นเป็นอันแดง ๆ เนอะ
![](https://www.mikkipastel.com/content/images/2023/11/20231105_154559.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_154630.webp)
./gradlew recordRoborazziDebug
./gradlew testDebugUnitTest -Proborazzi.test.record=true
./gradlew verifyRoborazziDebug
./gradlew testDebug UnitTest -Proborazzi.test.verify=true
./gradlew compareRoborazziDebug
./gradlew testDebugUnitTest -Proborazzi.test.compare=true
ตัว test case มีการ set rule ไว้ก่อน test
![](https://www.mikkipastel.com/content/images/2023/11/image-252.png)
มีการ set device ก่อนที่จะทำ test case ด้วย
![](https://www.mikkipastel.com/content/images/2023/11/20231105_154752.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_154905.webp)
สรุปเส้นทางในการทำ Snapshot Testing
- analyze อันที่เราจะ test ให้เริ่มจากอันเล็ก ๆ และ critical ก่อน
- scale up กับหลาย ๆ config
- integrate กับ workflow ของเรา
![](https://www.mikkipastel.com/content/images/2023/11/image-248.png)
Resources เพิ่มเติม เผื่อใครอยากอ่านเพิ่ม
![](https://www.mikkipastel.com/content/images/2023/11/image-247.png)
![](https://hashnode.com/utility/r?url=https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1628533930318%2FZNNQS3-A3.jpeg%3Fw%3D1200%26h%3D630%26fit%3Dcrop%26crop%3Dentropy%26auto%3Dcompress%2Cformat%26format%3Dwebp%26fm%3Dpng)
อันนี้สไลด์จ้า
Optimizing Compose App - Thaw Zin Toe (Pe Tut)
![](https://www.mikkipastel.com/content/images/2023/11/image-227.png)
session นี้มีอะไรบ้าง ไปดูกัน
![](https://www.mikkipastel.com/content/images/2023/11/image-234.png)
Use R8
ใช้ R8 mode ใน release mode
![](https://www.mikkipastel.com/content/images/2023/11/image-253.png)
สามารถ optimize โดบการลบของที่ไม่ใช้ทิ้ง ไม่ว่าจะเป็น class, function, field, resource แล้วก็ optimize โค้ด
Take advantages using Baseline Profile
การใช้ Baseline Profile ช่วย improve code execution speed 30% จากการ launch ครั้งแรก
![](https://www.mikkipastel.com/content/images/2023/11/image-254.png)
Understanding Compose Phases
ภาพคร่าว ๆ ว่าเราจะทำ composition อะไร ที่ layout ไหน และวาดยังไง
![](https://www.mikkipastel.com/content/images/2023/11/image-255.png)
composition ดูเป็น UI Test มองเป็น node
![](https://www.mikkipastel.com/content/images/2023/11/image-256.png)
layout เราจัดวาง view ยังไง
![](https://www.mikkipastel.com/content/images/2023/11/image-257.png)
drawing เราวาด content อะไร
![](https://www.mikkipastel.com/content/images/2023/11/image-258.png)
ในส่วน layout มีการวัด view ลูก ตัดสินใจ แล้ววาง view ลูก
![](https://www.mikkipastel.com/content/images/2023/11/image-259.png)
Compose Best Practices
- อย่าเอาไป
sortedWith
ก่อนขึ้น view ให้ใช้remember
แทน
![](https://www.mikkipastel.com/content/images/2023/11/20231105_160745.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_160818.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_160826.webp)
- Lazylist key ใช้ในการ define key แต่ละ item
![](https://www.mikkipastel.com/content/images/2023/11/20231105_160921.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_160956.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_161025.webp)
- devivedStateOf {} ใช้เพื่อ buffer ในการเปลี่ยนแปลง
![](https://www.mikkipastel.com/content/images/2023/11/20231105_161121.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_161201.webp)
- Procrastination: เช่นการ animate background compare ทุก ๆ frame มีการ reading state
![](https://www.mikkipastel.com/content/images/2023/11/20231105_161225.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_161303.webp)
- Reading state
![](https://www.mikkipastel.com/content/images/2023/11/image-263.png)
Diagnose & Find compose stability issues
- Compose Compiler Reports วิธีการ setup และ generate report
![](https://www.mikkipastel.com/content/images/2023/11/20231105_161421.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_161523.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_161541.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_161604.webp)
How to fix Stability issues ?
ทำความรู้จัก parameter แต่ละแบบ
![](https://www.mikkipastel.com/content/images/2023/11/image-264.png)
list, set, map ไม่ unstable ให้ใช้ immutable แทน
![](https://www.mikkipastel.com/content/images/2023/11/20231105_161925.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_161953.webp)
สรุปคร่าว ๆ
![](https://www.mikkipastel.com/content/images/2023/11/image-262.png)
contact ของ speaker
![](https://www.mikkipastel.com/content/images/2023/11/image-261.png)
อันนี้สไลด์
Page Object Model, The Automated Testing pattern on Android - Natcha Jintanasatien
![](https://www.mikkipastel.com/content/images/2023/11/image-176.png)
agenda ของ session นี้
![](https://www.mikkipastel.com/content/images/2023/11/image-177.png)
Automated Testing overview
Test Pyramid ทดสอบการทำงานของแอพ มี 3 ชั้น คือ
- Unit Test: test ส่วนที่เล็กที่สุด
- Integration Test
- E2E Test: test ว่าทั้งหมดทำงานได้ถูกต้องไหม
![](https://www.mikkipastel.com/content/images/2023/11/image-179.png)
session นี้ เทสบน Android device โดยใช้ AndroidJUnitRunner, context ต่าง ๆ ว่าจะทำอะไร ใช้แทน id แล้วก็ test case
ตัวอย่างการทำ E2E เช่นการเข้าหน้าแอพ login จากนั้นเข้าหน้าแรก และคลิกที่ profile นับเป็น 1 test case
จาก demo ใช้โค้ด 50 บรรทัดต่อ 1 test case ไม่มี pattern เขียนต่อไปเรื่อย ๆ จะเกิด duplicate code แล้วจะทำยังไงดี?
![](https://www.mikkipastel.com/content/images/2023/11/image-180.png)
What is the Page Object Model?
ทีมจะต้องมี pattern อ่านแล้วเข้าใจตรงกัน ในที่นี้คือ page object model เป็นการทำ E2E test
ส่วนประกอบคร่าว ๆ คือ ScreenPlay เอาไว้ทำ action ต่าง ๆ และ PageObject หา object ของ screenplay นั้น ๆ โดยทั้งสองเป็น module แยกเนอะ
![](https://www.mikkipastel.com/content/images/2023/11/image-181.png)
ตัวอย่าง UI แบ่งยังไงดี? เช่นหน้านี้เราจะ test การกด view ข้างบน ข้างในนั้นแบ่งเป็น object อยู่ใน PageObject ส่วนการคลิก item หรืออะไรใด ๆ มันคือ ScreenPlay ในที่นี้คือกดที่ object นึง
![](https://www.mikkipastel.com/content/images/2023/11/20231105_164050.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_164133.webp)
มาเขียน test กัน เช่นหน้า project file เข้าหน้าได้ถูกต้องไหม เช่น sign in → home → profile
![](https://www.mikkipastel.com/content/images/2023/11/image-182.png)
ในส่วนหน้า sign in มี ScreenPlay คือ การกรอก username การกรอก password และการกดปุ่มเนอะ และตัว PageObject นี้ก็มีที่กรอก username ที่กรอก password และปุ่ม sign in
![](https://www.mikkipastel.com/content/images/2023/11/image-183.png)
หน้า home เราสนใจการกดปุ่มเพื่อไปหน้า profile
![](https://www.mikkipastel.com/content/images/2023/11/image-184.png)
ส่วนหน้า profile นี้ก็มีหลากหลาย idea ในการทำ test case ในการตรวจสอบการแสดงผลด้วยนะ
![](https://www.mikkipastel.com/content/images/2023/11/image-185.png)
และนำทั้งหมดมาเรียงร้อยเป็น E2E Test
![](https://www.mikkipastel.com/content/images/2023/11/image-186.png)
แต่ถ้า journey ลูกค้าเปลี่ยนไปล่ะ? เช่น จำรหัสผ่านไม่ได้ (เออปัญหาระดับชาติจริง) อยากได้ 1-time password ทำให้ test case นั้น failed ตั้งแต่แรก ตัว test case เดิมเปลี่ยนตัวหน้า และเพิ่มเรื่อง verify code เข้าไป
![](https://www.mikkipastel.com/content/images/2023/11/20231105_164740.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_164813.webp)
Screen Play ทำตาม action ที่ตัวเองมี ตาม test case และจำเป็นต้องรู้จัก Page Object ด้วยการหาปุ่มให้เรา ทำให้รู้จัก Content Description ของ object นั้น ๆ ได้ถูกต้อง
![](https://www.mikkipastel.com/content/images/2023/11/image-187.png)
อันนี้สไลด์ของ session นี้
Building the automated Android UI testing in Continuous Integration at LINE MAN Wongnai - Somkiat Khitwongwattana
เมื่อเราเขียน test เป็นแล้ว ก็เอาไป run บน CI ต่อเล้ยย และการ test ไม่ควรผูกกับ framework
![](https://www.mikkipastel.com/content/images/2023/11/image-188.png)
ก่อนอื่น LINE MAN Wongnai ไม่ได้มีแอพแค่ LINE MAN และ Wongnai เท่านั้น ยังมีแอพสำหรับร้านค้า และสำหรับ rider แลพ driver อีกด้วย และบางส่วนเป็น Native Android และเป็น React Native
![](https://www.mikkipastel.com/content/images/2023/11/20231105_165308.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_165407.webp)
การทำ Android UI Testing บน CI เป็นเรื่องที่ท้าทายสำหรับ developer แต่มันจำเป็นต้องทำล่ะสิ เพื่อสามารถ scalability ได้ในอนาคต
![](https://www.mikkipastel.com/content/images/2023/11/image-190.png)
แล้วใครเป็นคนทำสิ่งนี้ล่ะ? Android Developer หรือ DevOps?
![](https://www.mikkipastel.com/content/images/2023/11/image-191.png)
สรุป Android Developer จะรับผิดชอบในการทำ CI และมีคนดูแล structure ต่าง ๆ อาจจะเป็นทีม DevOps หรือคนอื่น ๆ
ซึ่งก่อนหน้านี้มี process ตรงนี้มานานแล้ว มี CI run E2E ต่าง ๆ บนเครื่อง iMac ที่ที่นั่นเรียกกันว่า machine b มีหน้าที่ในการ execute และ run emulator เมื่อน้องตุยขึ้นมา จะต้อง remote เพื่อ restart เครื่องได้ แล้วให้มันทำงานต่อ และมีช่วงโควิด machine b ตายแบบต้องกดปุ่ม reset ต้องมีคนเสียสละไปที่ออฟฟิศเพื่อทำสิ่งนี้ให้
![](https://www.mikkipastel.com/content/images/2023/11/image-189.png)
มาดู stack กัน โค้ดของที่นี่อยู่ใน Gitlab และทำ integration test บางส่วน
![](https://www.mikkipastel.com/content/images/2023/11/image-192.png)
แล้วพวก Android device ล่ะ? ถ้าไม่พึ่งพาเจ้า machine b ที่ฟังดูแล้วทำงานหนักเอามาก ๆ ก็ต้องเป็น emulator ที่อยู่บน cloud
![](https://www.mikkipastel.com/content/images/2023/11/image-193.png)
Candidates
![](https://www.mikkipastel.com/content/images/2023/11/image-194.png)
Firebase Test Lab: ได้ทั้ง iOS และ Andriod device, สามารถเลือกเครื่องได้ ทั้งเครื่องจริง และ virtual device, มีการติดตั้ง Google Play service ให้กับเครื่อง Android
note: test report เก็บใน Google Cloud Storage เลยไม่เลือกใช้ และเรื่องราคาด้วยส่วนนึง
![](https://www.mikkipastel.com/content/images/2023/11/20231105_170121.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_170218.webp)
![](https://firebase.google.com/images/social.png)
Genymotion Device Image: เขาเป็น cloud solution อยู่แล้ว มี vistual device ให้ cloud service provider มีการ sent CPI ให้รันลื่นโดยไม่มี GPU ได้ ถ้าไม่มีการ์ดจอแยกมาให้ และจ่ายเงินเป็น subscription โดยทาง LMWN ใช้ spec แรก คือ t4g.medium
![](https://www.mikkipastel.com/content/images/2023/11/20231105_170317.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_170452.webp)
Smartphone Test Farm: เป็น farm device ของเรา เอาไป plug แล้วเอา pipeline เข้าไปได้ และเราเองก็ไม่อยากให้คนอื่นเข้าเครื่องที่เราใช้ เป็น open-source เข้าถึงได้ และจองคิวได้
![](https://www.mikkipastel.com/content/images/2023/11/image-195.png)
Criteria
- Configurability: สามารถ custom อะไรบางอย่างได้
- Maintainability: ถ้าคนในทีมลา หรือไม่อยู่ ก็สามารถรับช่วงต่อได้
- Stability: merge ของวันศุกร์แล้ว เจ้า CI ตุย พังแล้ว failed ได้ในเวลาไม่นาน
- Ease of use: ใช้งานได้ง่าย
- Custom Test Executor: สามารถ custom การ test ได้
- VPN: privacy VPN เพื่อความปลอดภัย
- Price: ราคาก็เรื่องสำคัญ
![](https://www.mikkipastel.com/content/images/2023/11/image-196.png)
Benchmark
Firebase Test Lab ไม่สามารถ Custom Test Executor ได้ ไหนจะเรื่อง VPN เลยถูกปัดตกไป
![](https://www.mikkipastel.com/content/images/2023/11/image-197.png)
ส่วน Smartphone Test Farm คือการทำ farm device แล้วทำการ run automate 1 ปีผ่านไป แบตบวม เปลี่ยนแบตก็ยากอีก ถ้าสมมุติเราทำ farm device แล้วมันระเบิดขึ้นมาล่ะ? ก็เลยเลือกใช้ virsual device มากกว่า
![](https://www.mikkipastel.com/content/images/2023/11/image-198.png)
และทั้งหมดเป็นเหตุผลที่ Genymotion Device Image ชนะจ้า
Job
และการทำงานใน process นี้ มี Build App → Run UI Test → Generate Test Report
![](https://www.mikkipastel.com/content/images/2023/11/image-199.png)
โดยเรา focus ไปที่ Run UI Test
![](https://www.mikkipastel.com/content/images/2023/11/image-200.png)
Gitlab Runner มีเครื่อง run ให้ start โดยการเปิด instance แล้วพอจบให้ทำลายทิ้ง
- Start Job → Create Instance: Terraform สร้าง instance บน cloud service ให้สร้าง image บน Genymotion บน EC2
![](https://www.mikkipastel.com/content/images/2023/11/image-201.png)
- Initialization: ใช้ Shell script ในการ connect ABD
- Test Execution: ตัว runner ทำการ install APK และทำ UI Test และบน Genymotion เก็บ test result และ device log ส่งกลับไปที่ Gitlab
![](https://www.mikkipastel.com/content/images/2023/11/image-202.png)
- End Job → Destory Instance: Terraform สั่งให้ทำลาย instance
แต่ตัว Gitlab คิดว่ามันพังไม่ได้ ดังนั้นไม่ควรทำงานเกิน 1 ชั่วโมง จึงมี cron job มาครอบ
![](https://www.mikkipastel.com/content/images/2023/11/image-203.png)
ใส่ instance แล้วเดี๋ยวตัว Terraform จะ check ว่าอันไหนยังรอดอยู่บ้าง และช่วยแจกจ่ายงาน
![](https://www.mikkipastel.com/content/images/2023/11/image-204.png)
subscript บน marketplace ได้ AMI ที่เขาสร้างมาให้บน system แล้วเอา id มาสร้าง instance เพื่อ run บน Android device
![](https://www.mikkipastel.com/content/images/2023/11/image-205.png)
แล้วบน Genymotion ต้องทำอะไรเพิ่มบ้างนะ? สิ่งที่มีในตอนนี้
![](https://www.mikkipastel.com/content/images/2023/11/image-206.png)
- ADB ถูกปิดโดย default
- ไม่มี Google Play service
- หน้าจอขนาดที่เราไม่ต้องการ
- ไม่มี WebView engine มาให้
- ภาษาอังกฤษเป็นภาษาหลัก
เราสามารถทำชุด setup เองตามใจชอบ ด้วย HTTP API เพื่อสั่งงานบางอย่างได้ โดยมันจะอยู่บน swagger ต้องเปิด emulator ก่อนถึงจะใช้งานได้
![](https://www.mikkipastel.com/content/images/2023/11/20231105_171804.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_171836.webp)
All setup operations
- [HTTP] Enable ADB connection: เปิด ADB มันจะอยู่บน swagger ต้องเปิด emulator ก่อนถึงจะใช้งานได้
![](https://www.mikkipastel.com/content/images/2023/11/image-208.png)
- [ADB] Connect device: ใช้
adb connect <ip_address>
ปกติ - [HTTP] Change screen resolution: ทำให้ resolution ตํ่า ๆ เพื่อให้ทำงานได้ไวขึ้น สนใจแค่ dp เท่านั้น คำนวณให้ได้ dp เท่าเดิม โดยใช้สูตร
dp * (dpi / 160) = px
![](https://www.mikkipastel.com/content/images/2023/11/20231105_171946.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_172109.webp)
![](https://developer.android.com/static/images/social/android-developers.png)
- [HTTP] Change device location: set location ที่เราต้องการ
![](https://www.mikkipastel.com/content/images/2023/11/image-209.png)
- [ADB] Change device language: เปลี่ยนภาษาเป็นภาษาไทย
![](https://www.mikkipastel.com/content/images/2023/11/image-210.png)
- [ADB] Install OpenGApps: ติดตั้ง OpenGApps แบบ unofficial เพื่อลงใน emulator ได้ ตัว version GPU package เอา Google Play service เลือก pico
![](https://www.mikkipastel.com/content/images/2023/11/20231105_172242.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_172331.webp)
![](https://opengapps.org/images/opengapps.png)
- [ADB] Install Google Maps and Chrome for Android: ใช้แค่ Google Maps กับ Chrome
![](https://www.mikkipastel.com/content/images/2023/11/Screenshot-2566-11-19-at-18.55.01.webp)
- [ADB] Reboot the device
![](https://www.mikkipastel.com/content/images/2023/11/image-211.png)
- [ADB] Reconnect the ADB after device rebooted
![](https://www.mikkipastel.com/content/images/2023/11/image-212.png)
- [ADB] Grant location permission for Google Maps: ให้ permission location เพราะมันกดเองไม่เป็น
![](https://www.mikkipastel.com/content/images/2023/11/image-213.png)
- [ADB] Allow Google's Location Service from Google Maps: สนใจ text (สามารถหาจาก resource id) กับ bounds ให้กดเปิด location service
![](https://www.mikkipastel.com/content/images/2023/11/20231105_172548.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_172616.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_172703.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_172758.webp)
หน้าตามันประมาณนี้
โดยการ setup operation ทั้งหมดพี่เอกเอามาจากไหน มาจาก ChatGPT นะ
1 job ทำ 10 อย่าง setup จนเสร็จใน 5 นาที ให้ทำ pre-config ให้เรียบร้อย ได้ custom AMI เหมือนเราสร้างตัว visual machine หรือ docker อะไรงี้ สร้าง image-as-a-code
![](https://www.mikkipastel.com/content/images/2023/11/20231105_172816.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_172905.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_172955.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_173019.webp)
Summary
- เปิด PR → แยก instance บน cloud, stable กว่าของเดิม, ใช้ได้หมดทุก platform
- แต่ละที่มี CI เป็นของตัวเอง เพราะแต่ละ project มีความแตกต่างกัน มองสิ่งที่อยู่ใน session เป็น idea ได้
- ในส่วน spawn ถ้าทีมไม่ได้เรียกอะไร ไม่ต้องเสียเงินในช่วงนั้น
- ส่วนนี้ทำงานกับทีม Site Reliability Engineer ใช้เวลาหลัก quarter กว่าจะเสร็จใน phase แรก include ไปเรื่อย ๆ เป็นปี ให้คำนึงถึง effort ด้วย
- POC ไม่ควรเปิด public IP มี AWS scan แล้วเตือนมาว่ามีคนแอบฝัง bot บนเครื่อง ดังนั้นเลยให้เข้าได้โดยการต่อ VPN เท่านั้น
![](https://www.mikkipastel.com/content/images/2023/11/20231105_173049.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_173348.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_173804.webp)
อันนี้สไลด์ ของ speakerdeck สามารถจิ้มดูแต่ละหน้าได้เลย
หลังจากงานก็รับประทานอาหารกันกับชาว Android Developer (ที่เราขอเนียนนับ iOS Developer ไปในนี้ 1 คน ฮี่ฮี้) ที่ร้านเคนชิน อิซากะยะ ที่สาขา MBK บอกเลยว่าทุลักทุเลสุด ๆ เริ่มตั้งแต่ไม่สามารถใช้ทางหน้าพาร์คพารากอนได้ เนื่องจากวันนั้นฝนตกหนักตั้งแต่ตอนเรามาแล้ว นํ้าเจิ่งนองสุด ๆ เลยต้องลงไปข้ามทางม้าลายด้านล่าง เพื่อไป siam center และ siam discovery ตามลำดับ บอกเลยว่าอาจจะมีพา speaker ชาวต่างชาติหลงไปบ้างนิด ๆ หน่อย ๆ จนในที่สุด ถึงร้านเรียบร้อย เย้ ๆ ก็รับประทานอาหาร พร้อมเม้ามอยกันทั้งภาษาไทยและภาษาอังกฤษกันไป
เอาจริงร้านเคนชินเนี่ย ร้านประจำชาวเดฟเลยนะ เอ๊ะอะมาร้านนี้กันตลอด แล้วแต่แถวนั้นจะมีสาขาอะไร 5555555 ทางเราได้ทานปลาซาบะดองย่าง signature ของทางร้าน 5555 ไก่ทอดที่กรอบนอก ฉํ่าใน ยากิโซบะเขาทำเข้มข้นมาก แต่หลัง ๆ แอบเลี่ยนไปนิดนึง
![](https://www.mikkipastel.com/content/images/2023/11/20231105_191419.webp)
![](https://www.mikkipastel.com/content/images/2023/11/20231105_191741.webp)
บล็อกนี้แน่นอนว่าช้ากว่ากำหนดเนอะ เนื่องจากก็มีเรื่องอื่น ๆ ที่ต้องทำ ไหนจะเหนื่อยจากงานแบบหมดพลัง ไหนจะเฝ้าบูธ Pudgy Thailand ที่งาน Blockchain Genesis 2023 ไหนจะซ้อม RoV เพื่อไปแข่งอีก แหะ ๆ
หวังว่าบล็อกนี้จะได้ประโยชน์กับชาว Android Developer ทุกคนน้า ปีนี้ยอมรับว่ากระแส Jetpack Compose มาแรงมาก ๆ จริง ๆ นึกถึงปีนั้นที่ป้าย Kotlin กันกระจายเลย 5555555
เอ้อปีนี้ได้เสื้อจากการซื้อบัตร มีให้เลือกเป็นสีดำ ที่มี logo Android 14 และเสื้อขาว ที่มีน้อง Android version มีขนด้วย พร้อม sticker เหมือนงาน DevFest Bangkok 2023 ด้วยล่ะ
ติดตามข่าวสารตามช่องทางต่าง ๆ และทุกช่องทางโดเนทกันไว้ที่นี่เลย แนะนำให้ใช้ tipme เน้อ ผ่าน promptpay ได้เต็มไม่หักจ้า
ติดตามข่าวสารแบบไว ๆ มาที่ Twitter เลย บางอย่างไม่มีในบล็อก และหน้าเพจนะ
สวัสดีจ้า ฝากเนื้อฝากตัวกับชาวทวิตเตอร์ด้วยน้าา
— Minseo | Stocker DAO (@mikkipastel) August 24, 2020