Menambahkan Fitur Lanjutan ke Aplikasi Android

Jeda Iklan

Android Sender SDK memberikan dukungan untuk jeda iklan dan iklan pengiring dalam streaming media tertentu.

Lihat Ringkasan Jeda Iklan Penerima Web untuk mengetahui informasi selengkapnya tentang cara kerja Jeda Iklan.

Meskipun jeda dapat ditentukan di pengirim dan penerima, sebaiknya jeda ditentukan di Penerima Web dan Penerima Android TV untuk mempertahankan perilaku yang konsisten di seluruh platform.

Di Android, tentukan jeda iklan dalam perintah pemuatan menggunakan AdBreakClipInfo dan 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);

Menambahkan tindakan kustom

Aplikasi pengirim dapat memperluas MediaIntentReceiver untuk menangani tindakan kustom atau mengganti perilakunya. Jika telah menerapkan MediaIntentReceiver sendiri, Anda harus menambahkannya ke manifes, dan juga menetapkan namanya di CastMediaOptions. Contoh ini menyediakan tindakan kustom yang menggantikan pemutaran media jarak jauh, menekan tombol media, dan jenis tindakan lainnya.

// 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) {
    }
}

Menambahkan saluran khusus

Agar aplikasi pengirim dapat berkomunikasi dengan aplikasi penerima, aplikasi Anda perlu membuat channel kustom. Pengirim dapat menggunakan saluran kustom untuk mengirim pesan string kepada penerima. Setiap saluran kustom ditentukan oleh namespace unik dan harus diawali dengan awalan urn:x-cast:, misalnya, urn:x-cast:com.example.custom. Anda dapat memiliki beberapa saluran kustom, yang masing-masing memiliki namespace unik. Aplikasi penerima juga dapat mengirim dan menerima pesan menggunakan namespace yang sama.

Saluran kustom diimplementasikan dengan antarmuka 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);
    }
}

Setelah aplikasi pengirim terhubung ke aplikasi penerima, channel kustom dapat dibuat menggunakan metode 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);
}

Setelah saluran kustom dibuat, pengirim dapat menggunakan metode sendMessage untuk mengirim pesan string ke penerima melalui saluran tersebut:

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);
        }
    }
}

Mendukung putar otomatis

Lihat bagian API Putar Otomatis & Pengantrean.

Mengganti pilihan gambar untuk widget UX

Berbagai komponen framework (yaitu dialog Cast, pengontrol mini, dan UIMediaController, jika dikonfigurasi demikian) akan menampilkan karya seni untuk media yang saat ini ditransmisikan. URL untuk karya seni gambar biasanya disertakan dalam MediaMetadata untuk media, tetapi aplikasi pengirim mungkin memiliki sumber alternatif untuk URL.

Class ImagePicker menentukan cara untuk memilih gambar yang sesuai dari daftar gambar dalam MediaMetadata, berdasarkan penggunaan gambar, misalnya, thumbnail notifikasi atau latar belakang layar penuh. Implementasi ImagePicker default selalu memilih gambar pertama, atau menampilkan null jika tidak ada gambar yang tersedia di MediaMetadata. Aplikasi Anda dapat membuat subclass ImagePicker dan mengganti metode onPickImage(MediaMetadata, ImageHints) untuk memberikan implementasi alternatif, lalu memilih subclass tersebut dengan metode setImagePicker dari CastMediaOptions.Builder. ImageHints memberikan petunjuk kepada ImagePicker tentang jenis dan ukuran gambar yang akan dipilih untuk ditampilkan di UI.

Menyesuaikan dialog Cast

Mengelola Siklus Proses Sesi

SessionManager adalah tempat pusat untuk mengelola siklus proses sesi. SessionManager memantau perubahan status pemilihan rute Android MediaRouter untuk memulai, melanjutkan, dan mengakhiri sesi. Saat rute dipilih, SessionManager akan membuat objek Session dan mencoba memulai atau melanjutkannya. Saat rute dibatalkan pilihannya, SessionManager akan mengakhiri sesi saat ini.

Oleh karena itu, untuk memastikan SessionManager mengelola siklus proses sesi dengan benar, Anda harus memastikan bahwa:

Bergantung pada cara Anda membuat dialog Cast, tindakan tambahan mungkin perlu dilakukan:

Status Tanpa Perangkat

Jika Anda membuat dialog Cast kustom, MediaRouteChooserDialog kustom Anda harus menangani kasus saat tidak ada perangkat yang ditemukan dengan benar. Dialog harus memiliki indikator yang memperjelas bagi pengguna Anda kapan aplikasi Anda masih mencoba menemukan perangkat dan kapan upaya penemuan tidak lagi aktif.

Jika Anda menggunakan MediaRouteChooserDialog default, status nol perangkat sudah ditangani.

Langkah berikutnya

Dengan demikian, fitur yang dapat Anda tambahkan ke aplikasi Pengirim Android Anda telah selesai dibahas. Sekarang Anda dapat membuat aplikasi pengirim untuk platform lain (iOS atau Web), atau membuat aplikasi Penerima Web.