วันอาทิตย์ที่ 25 มีนาคม พ.ศ. 2561

ทำแอปสตรีมมิ่งของตัวเองกันเถอะ ep 2 : streaming ไฟล์จาก firebase storage และเล่นด้วย Exoplayer

หลังจากที่ทำหน้าแอปหน้าแรกที่แสดง list แบบ mock-up กันไปแล้ว
ต่อไปจะลองแสดงผลชื่อไฟล์เพลงจาก firebase storage กัน ก่อนที่จะฟังเพลงแบบสตรีมมิ่ง

ตอนแรกว่าจะปล่อยอีกสองตอน พอทำไปทำมา ตอนนี้น่าจะเป็นตอนสุดท้ายของซีรีส์นี้หล่ะ
เอาจริงๆบล็อกอนนี้เขียนนานมากกกกกกกก เพราะ ExoPlayer เอาจริงๆถ้าเริ่มต้นทำใหม่มันไม่ง่ายเลย
ดังนั้นบทความในนี้จึงไม่สมบูรณ์ แต่ไม่ต้องกังวลไปนะ เดี๋ยวบอกตอนท้าย

มาให้แอปเราเชื่อมต่อกับ Firebase Storage กันเถอะ

ในที่นี้เราแค่ streaming file ไม่ได้ download เข้ามาในเครื่องนะ แต่ข้อจำกัดคือ เราต้องรู้ชื่อไฟล์ก่อน ถึงจะดึงมาได้

เราเลยมาลองแบบย่อๆแล้วกันเนอะ เพราะเน้นที่ตัว Exoplayer มากกว่า ขอแค่การันตีว่า มันดึงไฟล์มาสำเร็จและฟังได้ น่าจะพอแล้ว ณ ตอนนี้

ก่อนอื่น อัพไฟล์เพลงเราเข้า Firebase Storage ก่อนนะ แบบนี้


จากนั้นไปเพิ่มที่ build.gradle ของ module app ซึ่งในนี้ไม่ใช่ version ล่าสุดนะ

compile 'com.google.firebase:firebase-storage:11.4.2'

พออัญเชิญมาเรียบร้อยก็ sync gradle ซะ

เรารับชื่อไฟล์จากหน้าแรกของแอป และเริ่มเล่นเพลงอีกหน้านึง

ใน Firebase Storage นั้น จะมี url 2 ชนิด ได้แก่
1. Storage Location : gs://<project_name>.appspot.com/<file>
2. Download Url : https://firebasestorage.googleapis.com/v0/b/<project_name>.appspot.com/o/<file>?alt=media&token=<token> ตัว token นั้น Firebase จะ generate ให้

เราจะเห็นตอนกดไปดู detail ของแต่ละไฟล์ และเราใช้ download url ในการดึงไฟล์เข้ามา
เราเคยลองเขียนโค้ดเรียก url มักจะได้ Storage url มาตลอดเลย และเราสามารถเปิดไฟล์ได้คนเดียว ส่วน download url สามารถใช้ได้หมดเลย เช่น เราเคยอัพไฟล์รูปขึ้นหน้า portfolio website โดยแปะ url ตัวนี้ไป

สรุปจากการทดลอง โค้ดเราจะเป็นดังนี้



เราจะเรียกหาแต่ละชั้นของไฟล์เราก่อน จากนั้นใช้คำสั่ง getDownloadUrl().addOnSuccessListener() เพื่อ get download url ออกมา
ref : https://stackoverflow.com/questions/37374868/firebase-getdownloadurl

เมื่อเรา debug ดู พบว่า เรียกถูก path และ token มีการเปลี่ยนแปลงตลอดเวลาเลย แต่ตัวแอป crash เนื่องจากตัว Exoplayer ของเราเล่นไม่ได้นี่แหละ เข้าใจว่าไม่ใช่ format ที่รองรับนะ


ปัญหาที่เกิดขึ้น มี 2 อย่าง คือ โค้ด Exoplayer ที่ก็อปมา เปิดลิ้งค์ไฟล์เสียงไม่ได้ แล้ว file path เป็น null ระหว่างกดที่ item ไปยัง player ตัว player สร้างไวกว่าได้ url มาซะอีก

คิดว่าถ้าลองเขียน cloud function สักตัว เพื่อทำ realtime database ในการดึงว่ามีกี่ไฟล์ใน storage ก็น่าจะดีไม่น้อย ซึ่งมีคนใจดีเขียนบล็อกในการสร้าง API โดยอัพไฟล์ไปใน Firebase Storage แล้วไปแปะที่ Realtime Database จากนั้นใช้ cloud function สร้าง API ขึ้นมา แล้ว make sure โดยการเรียกใน postman โอ้เย้ ได้แล้ววววว ขอบพระคุณรัวๆเจ้าค่ะ


มาทำความรู้จักกันกับ Exoplayer ก่อน



มันคือ player ตัวใหม่ที่ใช้ใน Android จากทาง Google ซึ่งเขาเคลมว่ามันเสถียรกว่าตัวเดิมที่มีอยู่ (หมายถึงเจ้า MediaPlayer นั่นแล) ซึ่งเปิดตัวตอน Google I/O 2017 ที่ผ่านมาเลยนะนี่

Reference

ExoPlayer เป็น open source ของ media playback สำหรับ Android ไม่ใช่ Android Framework นะจ๊ะ
ตัวนี้จะช่วยเขียนโค้ดได้ minimal และ flexible มากขึ้นในการสร้างหน้าตาของ media player เหมาะกับการใช้งานแบบ streaming หรือมีการเข้ารหัสข้อมูล รองรับ Android 4.1 หรือ api version 16 ขึ้นไป สามารถ support file ได้เกือบทั้งหมดเลย มีแค่น้อยอันที่ไม่ได้ แต่ไม่ต้องกังวล เพราะส่วนใหญ่ก็รองรับอยู่แล้ว

เช่น แอปเราเปิดวิดีโอเอ็มวีของสินค้า และเราไม่อยากให้ใครสามารถดูดไปได้ ก็จะใช้การ streaming ในการนำวิดีโอมาเปิดในแอป และป้องกันไม่ให้ใครไปดูดวิดีโอมา จึงมีการเข้ารหัสไว้ ถ้าดูดมาได้ก็จะเป็นอะไรสักอย่างที่เข้ารหัสไว้ ประมาณนี้

การใช้งานที่เราเห็นทั่วไป ก็คือ YouTube และ Google Play Movies ในมือถือของเรานั่นเอง

เราลองทำตาม codelab ไปเล่นๆ ตาม https://github.com/googlecodelabs/exoplayer-intro.git
พอให้รู้จักกันคร่าวๆ

ก่อนอื่นทำพิธีการอัญเชิญเข้ามาก่อน

จุดแรก build.gradle ของโปรเจก ใส่ใน repository ใส่ได้สองท่า

ท่าแรก ท่ามาตรฐาน
maven { url "https://maven.google.com" }

ท่าที่สอง ท่าสายย่อ
google()

จุดที่สอง build.gradle ของ module เพิ่มใน dependency

// standard (require)
compile 'com.google.android.exoplayer:exoplayer:2.5.4'
// core function (require)
compile 'com.google.android.exoplayer:exoplayer-core:r2.5.4'
// DASH content
compile 'com.google.android.exoplayer:exoplayer-dash:r2.5.4'
// UI component
compile 'com.google.android.exoplayer:exoplayer-ui:r2.5.4'

แต่เดี๋ยวนี้แอดตัวเดียวเหอะ ตาม version ล่าสุดเลย

// standard (require)
compile 'com.google.android.exoplayer:exoplayer:2.7.1'

อธิบายการทำงานกันแบบคร่าวๆ

เราสร้าง layout หน้าแรกเพื่อแสดงเพลงทั้งหมดที่มี แล้วเวลากดเข้าไปก็จะเล่นเพลงนั้น

ตัว Exoplayer นอกจากจะเล่นไฟล์เดี่ยวๆแบบในตัวอย่างนี้แล้ว สามารถเล่น playlist ได้ด้วย และ repeat เพลงหรือ playlist ได้ด้วยนะ ดังนั้นเราต้องมาเปลี่ยนโค้ดและหน้าตาของมันนิดหน่อย เพื่อให้สามารถเล่นได้ตาม feature ที่เขามีอยู่ ลุยกันเลยจ้าาา

ก่อนอื่นมาดูหน้าตา player ของแอปในท้องตลาดกันเลย มีของ Spotify Fungjai และ JOOX


ตำแหน่งของปุ่มจะวางไว้ในแนวทางเดียวกัน เราก็ต้องเอาที่ user สะดวกนั่นแหละ

ถ้าส่วนแอปฟังเพลงแบบ niche ไปเลย ก็เรื่องของเขา 555 เช่น Nightwave plaza แอปฟังเพลง waporwave ยาวๆไป concept นี่น่าจะ windows 98 อะไรเทือกนี้แน่นอนนน


ดังนั้นเราจะสร้างปุ่มใหม่แบบนี้


และหน้าตา layout จะเป็นดังนี้


เราเองก็แก้อะไรมากมาย ทั้งโปรเจกเลย เช่น เรียกไฟล์จาก API ที่สร้างจาก cloud function ดังนั้นไปโฟกัสส่วน player ว่าแต่ละปุ่มเขียนยังไงก็แล้วกันเนอะ

สาเหตุที่เรียกใช้ API เพราะมันสะดวกดี ในแง่ของการดึงข้อมูลมาโชว์ ไม่ต้องมีปัญหาเนอะ

เราเล่าคร่าวๆว่าแต่ละปุ่มทำอะไรเนอะ

Play ปุ่มเล่น ตั้ง logic ที่ชื่อว่า songplay เป็น false ซะ จากนั้นก็จะให้เล่นเพลงเมื่อกดปุ่ม และเปลี่ยนปุ่มเป็น pause ด้วย โดยคำสั่งที่ใช้ในการเล่นเพลง เราสร้างเป็น function เพราะใช้หลายที่


Repeat เป็นตัวที่วนซํ้า มาตอน ExoPlayer version 2.5 ทำได้ทั้งไฟล์เดียวและ playlist จะมีโหมดแบบนี้

- No Repeat : โหมดปกติ ปิดแม่มเลย
player.setRepeatMode(Player.REPEAT_MODE_OFF);

- Repeat one : เล่นเพลงเดียวซํ้าไปซํ้ามา
player.setRepeatMode(Player.REPEAT_MODE_ONE);

- Repeat All : เล่นวนทั้ง playlist ถ้าเพลงสุดท้ายแล้ว ก็วกกลับมาเล่นเพลงแรกเอง คือต้องมี playlist ใน player ก่อนนะ
player.setRepeatMode(Player.REPEAT_MODE_ALL);

โดยเราสร้างปุ่มขึ้นมาเอง เมื่อกดจะเปลี่ยนโหมดตามด้านบน รูปก็เปลี่ยนไปด้วย แบบนี้


ตัวปุ่มจะใช้แบบสำเร็จ หรือทำปุ่มเองก็ได้แบบเราก็ได้ โดยเปลี่ยนรูปปุ่มตามที่กด 
ซึ่งรายละเอียดเพิ่มเติมอ่านได้ที่นี่
https://medium.com/google-exoplayer/repeat-modes-in-exoplayer-19dd85f036d3

Prev/Next จริงๆมันควรจะผูกกับ playlist แต่เราไม่ได้สร้าง playlist ไว้เลย เลยใช้ logic ในกากดปุ่มแทน ถ้าเพลงถูกเล่นอยู่ ก็ให้เล่นเพลงต่อไปได้เลย

จริงๆลองทำเองยังก็ยากแหละ เพราะปุ่มพวกนี้ อิงจาก playlist ที่มีนั่นเอง

สรุป ตัวอย่างที่เห็นไม่ใช่ตัวอย่างการทำ ExoPlayer ที่ถูกต้อง อ้าววววว อ้าวเลยหล่ะสิ
อ่านแล้วมันดูยากๆเนอะ

แล้วอะไรคือตัวอย่างที่ถูกต้องหล่ะ

มาพบวิธีที่ถูกต้องในงาน Android Bangkok 2018 ในวันที่ 31 มีนาคมนี้ ซึ่งเราจะมาพูดถึง ExoPlayer ตั้งแต่พื้นฐาน จนสร้างแอปได้ และเสริมส่วน advance เข้าไป ให้เข้าใจมากขึ้น

เข้าไปจับจองบัตรและดูตารางเวลาของแต่ละ session กันได้ที่ https://android.wi.th/bangkok/


เจอกันงาน Android Bangkok 2018 นะคะ <3

ป้ายกำกับ:

0 ความคิดเห็น:

แสดงความคิดเห็น

สมัครสมาชิก ส่งความคิดเห็น [Atom]

<< หน้าแรก