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

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

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

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

แม้ว่าคุณจะระบุช่วงพักโฆษณาได้ทั้งใน Sender และ 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);

เพิ่มการดำเนินการที่กำหนดเอง

แอป Sender สามารถขยาย MediaIntentReceiver เพื่อจัดการการดำเนินการที่กำหนดเองหรือลบล้างลักษณะการทำงานได้ หากคุณได้ติดตั้งใช้งาน MediaIntentReceiver ของคุณเองแล้ว คุณต้องเพิ่ม MediaIntentReceiver ลงในไฟล์ Manifest และตั้งชื่อ MediaIntentReceiver ใน 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) {
    }
}

เพิ่มแชแนลที่กำหนดเอง

แอปของคุณต้องสร้างแชแนลที่กำหนดเองเพื่อให้แอป Sender สื่อสารกับแอป Receiver ได้ Sender สามารถใช้แชแนลที่กำหนดเองเพื่อส่งข้อความสตริงไปยัง Receiver ได้ แชแนลที่กำหนดเองแต่ละแชแนลจะกำหนดโดยเนมสเปซที่ไม่ซ้ำกันและต้องขึ้นต้นด้วยคำนำหน้า urn:x-cast: เช่น urn:x-cast:com.example.custom คุณสามารถมีแชแนลที่กำหนดเองหลายแชแนล โดยแต่ละแชแนลจะมีเนมสเปซที่ไม่ซ้ำกัน นอกจากนี้ แอป Receiver ยังสามารถ ส่งและรับข้อความ โดยใช้เนมสเปซเดียวกันได้ด้วย

แชแนลที่กำหนดเองจะติดตั้งใช้งานด้วย 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);
    }
}

เมื่อแอป Sender เชื่อมต่อกับแอป Receiver แล้ว คุณจะสร้างแชแนลที่กำหนดเองได้โดยใช้ 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);
}

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

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 ของสื่อ แต่แอป Sender อาจมีแหล่งที่มาอื่นสำหรับ URL

คลาส ImagePicker กำหนดวิธีการเลือกรูปภาพที่เหมาะสมจากรายการรูปภาพ ใน MediaMetadata โดยอิงตามการใช้รูปภาพ เช่น ภาพขนาดย่อของการแจ้งเตือน หรือพื้นหลังแบบเต็มหน้าจอ การติดตั้งใช้งาน ImagePicker เริ่มต้นจะเลือกรูปภาพแรกเสมอ หรือแสดงผลเป็น Null หากไม่มีรูปภาพใน MediaMetadata แอปของคุณสามารถสร้างคลาสย่อย ImagePicker และลบล้าง onPickImage(MediaMetadata, ImageHints) เมธอดเพื่อให้มีการติดตั้งใช้งานอื่น แล้วเลือกคลาสย่อยนั้น ด้วย setImagePicker เมธอดของ CastMediaOptions.Builder ImageHints จะให้คำแนะนำแก่ ImagePicker เกี่ยวกับประเภทและขนาดของรูปภาพที่จะเลือกเพื่อแสดงใน UI

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

การจัดการวงจรการทำงานของเซสชัน

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

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

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

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

สถานะไม่มีอุปกรณ์

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

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

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

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