Build Variants Android

Jedsada Tiwongvorakul
20Scoops CNX
Published in
3 min readFeb 8, 2017

เมื่อลูกค้า หรือคนภายในทีมต้องการที่จะทดสอบแอปพลิเคชัน ที่ต่าง Environment กันภายในเครื่องเดียว น้องๆ ทำให้พี่หน่อยสิ !!

https://goo.gl/UQOhsN

เมื่อเจ้าของบล็อคเจอปัญหากับการ Build Application ให้กับคนภายในทีม หรือลูกค้าที่ต้องการจะเทส State ที่แตกต่างกันภายในเครื่องเดียว สิ่งที่น่ากลัวต่อจิตใจคือถ้าเกิดมี 10 คน และ App ก็มี 10 State ที่แตกต่างกันล่ะ ชีวิตยากละครับ วิธีทำแบบเดิมๆ คือ uninstall แล้วทำการ install App ตัวใหม่ให้วันๆ หนึ่งไม่ต้องทำอะไรแล้วครับ นั่ง Build อย่างเดียวไปเลย

เรามาแก้ไขปัญหานี้ไปพร้อมๆ กันเลยดีกว่าครับ

ไป Config ที่ไฟล์ build.gradle ของ module app ของเราเลยครับ โดยให้เพิ่ม Tag ที่ชื่อว่า productFlavors เข้าไปดังนี้

แค่นี้ก็เป็นอันเสร็จสิ้นกระบวนการ เรียบร้อยแล้วครับ

จากตัวอย่างจะเห็นว่าเจ้าของบล็อคได้ทำการ Config ไว้ สาม state คือ dev, staging และ production โดย ที่จะมี feild ที่ชื่อว่า applicationId ที่แตกต่างกันออกไป เพราะมันคือ package name ของ app นั่นเอง ละครับ โดยเจ้าของบล็อคตั้งไว้ว่าให้ applicationId มี . ต่อท้าย package name เดิมแล้วตามด้วย ชื่อของ state นั่นๆ แทนยกเว้นตัว production ที่จะไม่ทำอะไร และเรายังสามารถตั้งค่าตัวแปร ที่แต่ละ state ใช้ไม่เหมือนกันได้อีกด้วย จะเห็นได้จาก Feild ในตัวอย่างเจ้าของบล็อคได้กำหนด ตัวแปรที่ชื่อว่า SERVER โดยกำหนด domain ที่แตกต่างกันเพื่อใช้ในการเรียก API ของแต่ละ sever ได้เลยนะครับ โดยปกติใน class ที่เรียกใช้ Retrofit หรือ Library อื่นๆ จากเดิมที่เจ้าของบล็อคทำ คือจะประกาศตัวแปรเพื่อเก็บ domain ของ server ไว้ก็เปลี่ยนมากเรียกใช้ แบบนี้แทน

BuildConfig.SEVER

แค่นี้เจ้าของบล็อคก็สามารถแก้ไขปัญหาข้างต้นได้แล้ว แถมยังกำหนดค่าตัวแปรที่ใช้ในแต่ละ State ได้อีกด้วย เช่น domain ของ server และ api_key ของ service ต่างๆ ที่เราจะนำมาใช้ได้โดยไม่ต้องมา เปลี่ยนทุกครั้งที่จะ Build หรือ ต้องมานั่ง if else อีกแล้ว

วิธีการ Build App ก็ไปให้ไปเลือก Enviroment ที่เราได้ทำการตั้งไว้ ที่ Tab menu Build Variants ของ Android Studio ตามนี้เลยครับ

เลือกเสร็จก็กด รอสักพักให้เวลามัน build แปปนึ่งนะครับ แล้วค่อยกด Run นะครับจะเห็นได้ว่าเราสามารถ Build ได้หลากหลายมากยิ่งขึ้น จากเดิม Default ของมันจะมีแค่ Debug กับ Release เท่านัน เมื่อเจ้าของบล็อคได้ทำการลง App ทั้งสามตัวแล้วผลที่ได้คือ แยกไม่ออกว่าตัวไหนเป็น state อะไรเพราะชื่อ หรือ icon แมร่งเหมือนไปกันหมดเลย

ถ้ากรณีที่เราอยากเปลี่ยนชื่อ หรือรูป icon ของ app ให้เป็นไปตาม state ก็ให้เพิ่ม Folder เข้าไปใน src ของ module app โดยต้องมีชื่อตาม state ที่ท่านได้ประกาศไว้ใน productFlavors เท่านันนะครับ เช่น

เจ้าของบล็อคขอเพิ่มแค่ dev และ staging เท่านันนะครับส่วน production ปล่อยให้มันไปใช้ res ในโฟเดอร์ main แทน และ folder res ที่เราพึ่งเพิ่มเข้ามานั่นสามารถเพิ่มอะไรก็ได้นะครับที่เกี่ยวกับ Resources ไม่ว่าจะเป็น file string.xml, mipmap หรือ drawable เป็นต้น โดยเจ้าของบล็อคขอยกตัวอย่างเพียงแค่ไฟล์ string.xml ก่อนนะครับส่วนที่เหลือให้ไปใช้ของ main แทน โดยให้เพิ่มตัวแปรที่ชื่อว่า app_name เพื่อจะตั้งชื่อให้กับ app ใน state dev ตามนี้เลยครับ

<resources>
<string name="app_name">AppExample_Dev</string>
</resources>

State อื่นๆก็ทำเหมือนกันนะครับเมื่อกด Run เสร็จ ผลที่ได้ก็คือ ชื่อ Application ได้เปลี่ยนไปตามที่เราได้กำหนดไว้เรียบร้อย

https://goo.gl/fDGmXq

แต่ก็ยังมีปัญหาให้หนักใจอยู่ดีนะครับ คือก็ต้องมานั่ง Build เองอยู่ดี ง่ะ แล้วจะทำยังไงดีล่ะ คำตอบคือหา Tool เข้ามาทำระบบของเราเป็น Automation เลยสิครับ เช่น Jenkins , Fastlane และเครื่องมือที่ทำ CI ต่างๆ หรือจะทำผ่าน Terminal บนเครื่องเลยก็ได้นะครับ แล้วค่อยเอาอัพขึ้น google drive หรือจะเป็นที่เก็บไฟล์ของบริษัทก็ได้นะครับ แล้วบอกให้มันพ่น ไฟล์ APK ทุก Variants ออกมาให้หมดโดยขอเป็นแบบ Debug ก่อนนะครับ ด้วยคำสั่ง gradle ดังนี้

$gradlew assembleDebug

เพราะในส่วน Release ต้องไปกำหนด path key store โอ้ย ปวดหัว !! เลยคิดว่ายังดีกว่าเนาะเด๋วยาว และถ้าใครที่ยังไม่รู้จักคำสั่ง gradlew ใน command line ผมแนะนำให้อ่าน บทความของ พี่ somkiat ด่วนเลยนะครับ

สรุป การทำ Build Variants ช่วยลดเวลาชีวิตของเจ้าของบล็อคลงไปมากเลย เพราะแทนที่เจ้าของบล็อคจะต้องมานั่ง Build ทุกๆ state และการทำในแต่ละครั้งก็ต้องมานั่งแปรตัวแปรไปมาแถมยังเอาไว้ Monitor App ในทุกๆ Environment ได้ในเครื่องเดียวได้ทุกคน Happy แต่ก็ยังมีเรื่องที่ทำให้วัยรุ่นหัวร้อนอยู่ก็คือ ปัญหาเรื่องการ Build นั่นแหละครับ เพราะถ้าทำระบบให้เป็น Automation (CI) หรืออาจจะ Manual เองนั่นก็ต้องทำ Test ด้วยนะครับ ถ้าหากไม่เขียนเทสก็จะลดเวลาแค่การส่ง APK แต่ไม่ได้แก้ปัญหาเรื่อง code ที่เราเขียนมันจะทำงานได้อย่างถูกต้องทุกครั้งที่ส่งให้ทีมหรือผู้ใช้ เพราะฉะนั้นเราต้องทำให้มั่นใจว่าทุกครั้งที่ จะส่งของถึงมือลูกค้า นั่นของมันต้องใช้งานได้ ไม่ใช่เปิดมา Surprise ชุดใหญ่เลยนะครับ

--

--