เพิ่มฟีเจอร์ขั้นสูงในแอป Android

ช่วงพักโฆษณา

Android Sender SDK รองรับช่วงพักโฆษณาและโฆษณาที่แสดงร่วมภายในสตรีมสื่อที่กำหนด

ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีการทำงานของช่วงพักโฆษณาได้ที่ภาพรวมช่วงพักโฆษณาของ Web Receiver

แม้ว่าจะระบุช่วงพักได้ทั้งในอุปกรณ์ที่ส่งและอุปกรณ์รับ แต่เราขอแนะนำให้ระบุช่วงพักใน Web Receiver และ Android TV Receiver เพื่อให้ลักษณะการทำงานสอดคล้องกันในทุกแพลตฟอร์ม

ใน Android ให้ระบุช่วงพักโฆษณาในคำสั่งโหลดโดยใช้ AdBreakClipInfo และ AdBreakInfo ดังนี้

Kotlin
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)
Java
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 และตั้งชื่อใน CastMediaOptions ด้วย ตัวอย่างนี้แสดงการดำเนินการที่กำหนดเองซึ่ง ลบล้างการสลับการเล่นสื่อจากระยะไกล การกดปุ่มสื่อ และการดำเนินการประเภทอื่นๆ

// In AndroidManifest.xml
<receiver android:name="com.example.MyMediaIntentReceiver" />
Kotlin
// 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) {
    }
}
Java
// 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

Kotlin
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")
    }
}
Java
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

Kotlin
try {
    mCastSession.setMessageReceivedCallbacks(
        mHelloWorldChannel.namespace,
        mHelloWorldChannel)
} catch (e: IOException) {
    Log.e(TAG, "Exception while creating channel", e)
}
Java
try {
    mCastSession.setMessageReceivedCallbacks(
            mHelloWorldChannel.getNamespace(),
            mHelloWorldChannel);
} catch (IOException e) {
    Log.e(TAG, "Exception while creating channel", e);
}

เมื่อสร้างแชแนลที่กำหนดเองแล้ว ผู้ส่งจะใช้เมธอด sendMessage เพื่อส่งข้อความสตริงไปยังผู้รับผ่านแชแนลนั้นได้

Kotlin
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)
        }
    }
}
Java
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

การปรับแต่งกล่องโต้ตอบของ Cast

การจัดการวงจรเซสชัน

SessionManager เป็นศูนย์กลางสำหรับการจัดการวงจรเซสชัน SessionManager จะรับฟัง ใน Android MediaRouter การเปลี่ยนแปลงสถานะการเลือกเส้นทางเพื่อเริ่ม หยุดชั่วคราว และสิ้นสุดเซสชัน เมื่อเลือกเส้นทางแล้ว SessionManager จะสร้างออบเจ็กต์ Session และพยายามเริ่มหรือดำเนินการต่อ เมื่อยกเลิกการเลือกเส้นทาง SessionManager จะสิ้นสุดเซสชันปัจจุบัน

ดังนั้น เพื่อให้ SessionManager จัดการวงจรช่วงเวลาที่ใช้งานได้อย่างถูกต้อง คุณต้องตรวจสอบว่า

คุณอาจต้องดำเนินการเพิ่มเติมต่อไปนี้ ทั้งนี้ขึ้นอยู่กับวิธีสร้างกล่องโต้ตอบการแคสต์

  • หากคุณสร้างกล่องโต้ตอบ Cast โดยใช้ MediaRouteChooserDialog และ MediaRouteControllerDialog กล่องโต้ตอบเหล่านี้จะอัปเดตการเลือกเส้นทางใน MediaRouter โดยอัตโนมัติ จึงไม่ต้องดำเนินการใดๆ
  • หากคุณตั้งค่าปุ่มแคสต์โดยใช้ CastButtonFactory.setUpMediaRouteButton(Context, Menu, int) หรือ CastButtonFactory.setUpMediaRouteButton(Context, MediaRouteButton) กล่องโต้ตอบจะสร้างขึ้นโดยใช้ MediaRouteChooserDialog และ MediaRouteControllerDialog ดังนั้นคุณจึงไม่ต้องทำอะไร
  • สำหรับกรณีอื่นๆ คุณจะต้องสร้างกล่องโต้ตอบการแคสต์ที่กำหนดเอง ดังนั้นคุณต้อง ทำตามวิธีการข้างต้นเพื่ออัปเดตสถานะการเลือกเส้นทางใน MediaRouter

สถานะอุปกรณ์เป็นศูนย์

หากสร้างกล่องโต้ตอบ Cast ที่กำหนดเอง MediaRouteChooserDialog ควรจัดการกรณีที่ไม่มีอุปกรณ์ ที่พบอย่างถูกต้อง กล่องโต้ตอบควรมีตัวบ่งชี้ที่ทำให้ผู้ใช้ทราบอย่างชัดเจนเมื่อแอปของคุณยังคงพยายามค้นหาอุปกรณ์ และเมื่อการพยายามค้นหาไม่ได้ใช้งานอีกต่อไป

หากคุณใช้ MediaRouteChooserDialog เริ่มต้น ระบบจะจัดการสถานะอุปกรณ์เป็น 0 อยู่แล้ว

ขั้นตอนถัดไป

ตอนนี้คุณได้ทราบฟีเจอร์ที่เพิ่มลงในแอปตัวส่ง Android ได้แล้ว คุณสามารถสร้างแอปตัวส่งสำหรับแพลตฟอร์มอื่น (iOS หรือ Web) หรือ สร้างแอปตัวรับสัญญาณบนเว็บ