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

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

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

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

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

ใน 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

การปรับแต่งกล่องโต้ตอบแคสต์

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

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

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

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

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

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

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

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

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

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