Dodaj zaawansowane funkcje do swojej aplikacji na Androida

Przerwy na reklamę

Pakiet SDK nadawcy na Androida obsługuje przerwy na reklamę i reklamy towarzyszące w danym strumieniu multimediów.

Więcej informacji o tym, jak działają przerwy na reklamę, znajdziesz w artykule Omówienie przerw na reklamę w odbiorniku internetowym.

Przerwy można określać zarówno w aplikacji nadawcy, jak i odbiorcy, ale zalecamy, aby robić to w odbiorniku internetowym i odbiorniku Android TV, aby zachować spójne działanie na różnych platformach.

Na Androidzie określ przerwy na reklamę w poleceniu wczytania za pomocą AdBreakClipInfo i 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);

Dodawanie działań niestandardowych

Aplikacja nadawcy może rozszerzyć MediaIntentReceiver , aby obsługiwać działania niestandardowe lub zastępować jego działanie. Jeśli masz własną implementację MediaIntentReceiver, musisz dodać ją do pliku manifestu, a także ustawić jej nazwę w CastMediaOptions. Ten przykład zawiera działania niestandardowe, które zastępują przełączanie odtwarzania multimediów na urządzeniu zdalnym, naciśnięcie przycisku multimediów i inne typy działań.

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

Dodawanie kanału niestandardowego

Aby aplikacja nadawcy mogła komunikować się z aplikacją odbiorcy, musi utworzyć kanał niestandardowy. Nadawca może używać kanału niestandardowego do wysyłania wiadomości tekstowych do odbiorcy. Każdy kanał niestandardowy jest definiowany przez unikalną przestrzeń nazw i musi zaczynać się od prefiksu urn:x-cast:, np. urn:x-cast:com.example.custom. Możesz mieć wiele kanałów niestandardowych, z których każdy ma unikalną przestrzeń nazw. Aplikacja odbiorcy może też wysyłać i odbierać wiadomości przy użyciu tej samej przestrzeni nazw.

Kanał niestandardowy jest implementowany za pomocą Cast.MessageReceivedCallback interfejsu:

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

Gdy aplikacja nadawcy połączy się z aplikacją odbiorcy, kanał niestandardowy można utworzyć za pomocą setMessageReceivedCallbacks metody:

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

Po utworzeniu kanału niestandardowego nadawca może użyć metody sendMessage, aby wysyłać wiadomości tekstowe do odbiorcy za pomocą tego kanału:

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

Obsługa autoodtwarzania

Zapoznaj się z sekcją Interfejsy API autoodtwarzania i kolejkowania.

Zastępowanie wyboru obrazu w widżetach interfejsu

Różne komponenty platformy (mianowicie okno Cast, miniodtwarzacz i UIMediaController, jeśli jest skonfigurowany) będą wyświetlać grafikę aktualnie przesyłanych multimediów. Adresy URL grafiki są zwykle zawarte w MediaMetadata multimediów, ale aplikacja nadawcy może mieć alternatywne źródło adresów URL.

Klasa ImagePicker określa sposób wybierania odpowiedniego obrazu z listy obrazów w MediaMetadata, na podstawie użycia obrazu, np. miniatury powiadomienia lub tła na pełnym ekranie. Domyślna implementacja ImagePicker zawsze wybiera pierwszy obraz lub zwraca wartość null, jeśli w MediaMetadata nie ma obrazu. Twoja aplikacja może utworzyć podklasę ImagePicker i zastąpić metodę onPickImage(MediaMetadata, ImageHints) , aby zapewnić alternatywną implementację, a następnie wybrać tę podklasę za pomocą metody setImagePicker klasy CastMediaOptions.Builder. ImageHints zawiera wskazówki dla ImagePicker dotyczące typu i rozmiaru obrazu, który ma być wyświetlany w interfejsie.

Dostosowywanie okien Cast

Zarządzanie cyklem życia sesji

SessionManager to centralne miejsce do zarządzania cyklem życia sesji. SessionManager nasłuchuje zmian stanu wyboru trasy MediaRouter w Androidzie, aby rozpoczynać, wznawiać i kończyć sesje. Gdy trasa zostanie wybrana, SessionManager utworzy Session obiekt i spróbuje go uruchomić lub wznowić. Gdy trasa zostanie odznaczona, SessionManager zakończy bieżącą sesję.

Aby SessionManager prawidłowo zarządzał cyklami życia sesji, musisz:

W zależności od sposobu tworzenia okien Cast może być konieczne wykonanie dodatkowych działań:

Stan braku urządzeń

Jeśli tworzysz niestandardowe okna Cast, Twój niestandardowy MediaRouteChooserDialog powinien prawidłowo obsługiwać przypadek, w którym nie znaleziono żadnych urządzeń. Okno powinno zawierać wskaźniki informujące użytkowników, kiedy aplikacja nadal próbuje znaleźć urządzenia, a kiedy próba wykrycia nie jest już aktywna.

Jeśli używasz domyślnego MediaRouteChooserDialog, stan braku urządzeń jest już obsługiwany.

Dalsze kroki

To wszystkie funkcje, które możesz dodać do aplikacji nadawcy na Androida. Możesz teraz utworzyć aplikację nadawcy na inną platformę (iOS lub sieć) albo utworzyć aplikację odbiorcy internetowego.