ช่วงพักโฆษณา
Android Sender SDK รองรับช่วงพักโฆษณาและโฆษณาที่แสดงร่วมภายในสตรีมสื่อที่ระบุ
ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีการทำงานของช่วงพักโฆษณาได้ในภาพรวมของช่วงพักโฆษณาบนเว็บ
แม้ว่าคุณจะระบุช่วงพักได้ทั้งฝั่งผู้ส่งและผู้รับ แต่เราขอแนะนำให้ระบุช่วงพักโฆษณาในเว็บรีซีฟเวอร์และตัวรับสัญญาณ Android TV เพื่อให้ทำงานในแพลตฟอร์มต่างๆ ได้สอดคล้องกัน
ใน Android ให้ระบุช่วงพักโฆษณาในคำสั่งโหลดโดยใช้ AdBreakClipInfo
และ AdBreakInfo
ดังนี้
val breakClip1: AdBreakClipInfo = AdBreakClipInfo.Builder("bc0") .setTitle("Clip title") .setPosterUrl("https://www.some.url") .setDuration(60000) .setWhenSkippableInMs(5000) // Set this field so that the ad is skippable .build() val breakClip2: AdBreakClipInfo = … val breakClip3: AdBreakClipInfo = … val break1: AdBreakClipInfo = AdBreakInfo.Builder(/* playbackPositionInMs= */ 10000) .setId("b0") .setBreakClipIds({"bc0","bc1","bc2"}) … .build() val mediaInfo: MediaInfo = MediaInfo.Builder() … .setAdBreaks({break1}) .setAdBreakClips({breakClip1, breakClip2, breakClip3}) .build() val mediaLoadRequestData: MediaLoadRequestData = MediaInfo.Builder() … .setMediaInfo(mediaInfo) .build() remoteMediaClient.load(mediaLoadRequestData)
AdBreakClipInfo breakClip1 = new AdBreakClipInfo.Builder("bc0") .setTitle("Clip title") .setPosterUrl("https://www.some.url") .setDuration(60000) .setWhenSkippableInMs(5000) // Set this field so that the ad is skippable .build(); AdBreakClipInfo breakClip2 = … AdBreakClipInfo breakClip3 = … AdBreakInfo break1 = new AdBreakInfo.Builder(/* playbackPositionInMs= */ 10000) .setId("b0") .setBreakClipIds({"bc0","bc1","bc2"}) … .build(); MediaInfo mediaInfo = new MediaInfo.Builder() … .setAdBreaks({break1}) .setAdBreakClips({breakClip1, breakClip2, breakClip3}) .build(); MediaLoadRequestData mediaLoadRequestData = new MediaInfo.Builder() … .setMediaInfo(mediaInfo) .build(); remoteMediaClient.load(mediaLoadRequestData);
เพิ่มการกระทำที่กำหนดเอง
แอปของผู้ส่งสามารถขยาย MediaIntentReceiver
เพื่อจัดการการดำเนินการที่กำหนดเองหรือลบล้างลักษณะการทำงานของแอปนั้นได้ หากคุณใช้ MediaIntentReceiver
ของตัวเอง คุณต้องเพิ่มไฟล์ Manifest ลงในไฟล์ Manifest และตั้งชื่อไฟล์ใน CastMediaOptions
ด้วย ตัวอย่างนี้มีการดำเนินการที่กำหนดเองซึ่งลบล้างการสลับการเล่นสื่อระยะไกล การกดปุ่มสื่อ และการทำงานประเภทอื่นๆ
// In AndroidManifest.xml
<receiver android:name="com.example.MyMediaIntentReceiver" />
// In your OptionsProvider var mediaOptions = CastMediaOptions.Builder() .setMediaIntentReceiverClassName(MyMediaIntentReceiver::class.java.name) .build() // Implementation of MyMediaIntentReceiver internal class MyMediaIntentReceiver : MediaIntentReceiver() { override fun onReceiveActionTogglePlayback(currentSession: Session) { } override fun onReceiveActionMediaButton(currentSession: Session, intent: Intent) { } override fun onReceiveOtherAction(context: Context?, action: String, intent: Intent) { } }
// In your OptionsProvider CastMediaOptions mediaOptions = new CastMediaOptions.Builder() .setMediaIntentReceiverClassName(MyMediaIntentReceiver.class.getName()) .build(); // Implementation of MyMediaIntentReceiver class MyMediaIntentReceiver extends MediaIntentReceiver { @Override protected void onReceiveActionTogglePlayback(Session currentSession) { } @Override protected void onReceiveActionMediaButton(Session currentSession, Intent intent) { } @Override protected void onReceiveOtherAction(Context context, String action, Intent intent) { } }
เพิ่มแชแนลที่กำหนดเอง
เพื่อให้แอปของผู้ส่งสื่อสารกับแอปฝั่งผู้รับ แอปของคุณจะต้องสร้างแชแนลที่กำหนดเอง ผู้ส่งสามารถใช้แชแนลที่กำหนดเองเพื่อส่งข้อความ
สตริงไปยังผู้รับ แชแนลที่กำหนดเองแต่ละรายการจะกำหนดโดยเนมสเปซที่ไม่ซ้ำกัน และต้องขึ้นต้นด้วยคำนำหน้า urn:x-cast:
เช่น urn:x-cast:com.example.custom
สามารถมีแชแนลที่กำหนดเองหลายแชแนล
โดยแต่ละแชแนลมีเนมสเปซที่ไม่ซ้ำกัน แอปผู้รับยังสามารถส่งและรับข้อความโดยใช้เนมสเปซเดียวกันได้อีกด้วย
มีการใช้แชแนลที่กำหนดเองกับอินเทอร์เฟซ Cast.MessageReceivedCallback
ดังนี้
class HelloWorldChannel : MessageReceivedCallback { val namespace: String get() = "urn:x-cast:com.example.custom" override fun onMessageReceived(castDevice: CastDevice, namespace: String, message: String) { Log.d(TAG, "onMessageReceived: $message") } }
class HelloWorldChannel implements Cast.MessageReceivedCallback { public String getNamespace() { return "urn:x-cast:com.example.custom"; } @Override public void onMessageReceived(CastDevice castDevice, String namespace, String message) { Log.d(TAG, "onMessageReceived: " + message); } }
เมื่อแอปผู้ส่งเชื่อมต่อกับแอปฝั่งผู้รับแล้ว คุณจะสร้างแชแนลที่กำหนดเองได้โดยใช้เมธอด setMessageReceivedCallbacks
ดังนี้
try { mCastSession.setMessageReceivedCallbacks( mHelloWorldChannel.namespace, mHelloWorldChannel) } catch (e: IOException) { Log.e(TAG, "Exception while creating channel", e) }
try { mCastSession.setMessageReceivedCallbacks( mHelloWorldChannel.getNamespace(), mHelloWorldChannel); } catch (IOException e) { Log.e(TAG, "Exception while creating channel", e); }
เมื่อสร้างแชแนลที่กำหนดเองแล้ว ผู้ส่งสามารถใช้เมธอด sendMessage
เพื่อส่งข้อความสตริงไปยังผู้รับผ่านช่องทางนั้น
private fun sendMessage(message: String) { if (mHelloWorldChannel != null) { try { mCastSession.sendMessage(mHelloWorldChannel.namespace, message) .setResultCallback { status -> if (!status.isSuccess) { Log.e(TAG, "Sending message failed") } } } catch (e: Exception) { Log.e(TAG, "Exception while sending message", e) } } }
private void sendMessage(String message) { if (mHelloWorldChannel != null) { try { mCastSession.sendMessage(mHelloWorldChannel.getNamespace(), message) .setResultCallback( status -> { if (!status.isSuccess()) { Log.e(TAG, "Sending message failed"); } }); } catch (Exception e) { Log.e(TAG, "Exception while sending message", e); } } }
การรองรับการเล่นอัตโนมัติ
โปรดดูส่วน API การเล่นอัตโนมัติและการจัดคิว
ลบล้างการเลือกรูปภาพสําหรับวิดเจ็ต UX
คอมโพเนนต์ต่างๆ ของเฟรมเวิร์ก (ได้แก่ กล่องโต้ตอบ Cast, มินิคอนโทรลเลอร์ และ UIMediaController หากมีการกำหนดค่าไว้) จะแสดงอาร์ตเวิร์กสำหรับสื่อที่กำลังแคสต์ในปัจจุบัน โดยทั่วไปแล้ว URL ของอาร์ตเวิร์กจะรวมอยู่ใน MediaMetadata
สำหรับสื่อ แต่แอปของผู้ส่งอาจมีแหล่งที่มาสำรองสำหรับ URL ดังกล่าว
คลาส ImagePicker
กำหนดวิธีการเลือกรูปภาพที่เหมาะสมจากรายการรูปภาพใน MediaMetadata
โดยอิงตามการใช้รูปภาพ เช่น ภาพขนาดย่อการแจ้งเตือนหรือพื้นหลังแบบเต็มหน้าจอ การใช้งาน ImagePicker
เริ่มต้นจะเลือกอิมเมจแรกเสมอ หรือแสดงผลเป็น Null หากไม่มีอิมเมจใน MediaMetadata
แอปของคุณสามารถคลาสย่อย ImagePicker
และลบล้างเมธอด onPickImage(MediaMetadata, ImageHints)
เพื่อระบุการใช้งานทางเลือก จากนั้นเลือกคลาสย่อยนั้นด้วยเมธอด setImagePicker
แบบ CastMediaOptions.Builder
ImageHints
ให้คำแนะนำเกี่ยวกับImagePicker
เกี่ยวกับประเภทและขนาดของรูปภาพที่จะเลือกให้แสดงใน UI
การปรับแต่งกล่องโต้ตอบการแคสต์
SessionManager
เป็นศูนย์กลางสำหรับการจัดการวงจรเซสชัน SessionManager
จะฟัง
Android
MediaRouter
สถานะการเลือกเส้นทางเปลี่ยนไปเพื่อเริ่มต้นเซสชันต่อ และสิ้นสุด เมื่อเลือกเส้นทางแล้ว SessionManager
จะสร้างออบเจ็กต์ Session
และพยายามเริ่มต้นหรือกลับมาทำงานอีกครั้ง เมื่อยกเลิกการเลือกเส้นทางแล้ว SessionManager
จะสิ้นสุดเซสชันปัจจุบัน
ดังนั้นเพื่อให้ SessionManager
จัดการวงจรเซสชันได้อย่างถูกต้อง คุณต้องตรวจสอบว่า
- ในกล่องโต้ตอบตัวเลือกเส้นทาง
ให้เรียก
MediaRouter.selectRoute(MediaRouter.RouteInfo)
เมื่อผู้ใช้เลือกอุปกรณ์ - ในกล่องโต้ตอบตัวควบคุมเส้นทาง (ในสถานะที่เชื่อมต่อหรือสถานะการแคสต์) ให้เรียก
MediaRouter.unselect(int)
เมื่อผู้ใช้หยุดแคสต์
คุณอาจต้องดำเนินการเพิ่มเติมโดยขึ้นอยู่กับวิธีสร้างกล่องโต้ตอบการแคสต์
- หากคุณสร้างกล่องโต้ตอบแคสต์โดยใช้
MediaRouteChooserDialog
และMediaRouteControllerDialog
กล่องโต้ตอบเหล่านี้จะอัปเดตการเลือกเส้นทางในMediaRouter
โดยอัตโนมัติ คุณจึงไม่ต้องดำเนินการใดๆ - หากคุณตั้งค่าปุ่ม "แคสต์" โดยใช้
CastButtonFactory.setUpMediaRouteButton(Context, Menu, int)
หรือCastButtonFactory.setUpMediaRouteButton(Context, MediaRouteButton)
กล่องโต้ตอบจะสร้างขึ้นโดยใช้MediaRouteChooserDialog
และMediaRouteControllerDialog
ดังนั้นคุณไม่ต้องดำเนินการใดๆ เช่นกัน - สำหรับกรณีอื่นๆ คุณจะสร้างกล่องโต้ตอบการแคสต์ที่กำหนดเอง คุณจึงต้องทำตามวิธีการข้างต้นเพื่ออัปเดตสถานะการเลือกเส้นทางใน
MediaRouter
ขั้นตอนถัดไป
นี่จะสรุปฟีเจอร์ที่คุณสามารถเพิ่มในแอป Android Sender ได้ ตอนนี้คุณสร้างแอปผู้ส่งสำหรับแพลตฟอร์มอื่น (iOS หรือ Web) หรือสร้างแอป Web Receiver ได้แล้ว