Dodaj zaawansowane funkcje do swojej aplikacji na Androida

Przerwy na reklamę

Pakiet Android Sender SDK obsługuje przerwy na reklamy i reklamy towarzyszące w ramach danego strumienia multimediów.

Więcej informacji o działaniu przerw na reklamy znajdziesz w artykule Przerwy na reklamy w odbiorniku internetowym – omówienie.

Przerwy można określać zarówno na nadajniku, jak i odbiorniku, ale zalecamy określanie ich na odbiorniku internetowymodbiorniku Androida TV, aby zachować spójne działanie na różnych platformach.

Na Androidzie określ przerwy na reklamę w poleceniu wczytywania za pomocą tych parametrów:AdBreakClipInfoAdBreakInfo

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 wysyłająca może rozszerzać MediaIntentReceiver, aby obsługiwać działania niestandardowe lub zastępować jej działanie. Jeśli masz własną MediaIntentReceiver, musisz dodać ją do pliku manifestu i ustawić jej nazwę w CastMediaOptions. Ten przykład zawiera niestandardowe działania, które zastępują przełączanie zdalnego odtwarzania multimediów, naciśnięcie przycisku multimediów i inne rodzaje 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 wysyłająca mogła komunikować się z aplikacją odbierającą, musi utworzyć kanał niestandardowy. Nadawca może używać niestandardowego kanału do wysyłania wiadomości tekstowych do odbiorcy. Każdy kanał niestandardowy jest określany 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 w tej samej przestrzeni nazw.

Kanał niestandardowy jest implementowany za pomocą interfejsu 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);
    }
}

Gdy aplikacja wysyłająca jest połączona z aplikacją odbierającą, można utworzyć kanał niestandardowy za pomocą metody 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);
}

Po utworzeniu kanału niestandardowego nadawca może użyć metody sendMessage do wysyłania wiadomości tekstowych do odbiorcy za pośrednictwem 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 Autoodtwarzanie i kolejkowanie.

Zastępowanie wyboru obrazu w przypadku widżetów UX

Różne komponenty platformy (mianowicie okno przesyłania, minikontroler i UIMediaController, jeśli jest skonfigurowany) będą wyświetlać grafikę aktualnie przesyłanych multimediów. Adresy URL grafiki są zwykle zawarte w elemencie MediaMetadata dla multimediów, ale aplikacja wysyłająca 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 zastosowania 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 żadnego obrazu. Aplikacja może utworzyć podklasę ImagePicker i zastąpić metodę onPickImage(MediaMetadata, ImageHints) w celu udostępnienia alternatywnej implementacji, 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ć wybrany do wyświetlenia w interfejsie.

Dostosowywanie okien przesyłania

Zarządzanie cyklem życia sesji

SessionManager to centralne miejsce zarządzania cyklem życia sesji. SessionManager nasłuchuje zmian stanu wyboru trasy w Androidzie MediaRouter w celu rozpoczynania, wznawiania i kończenia sesji. Gdy wybierzesz trasę, SessionManager utworzy obiekt Session i spróbuje go uruchomić lub wznowić. Gdy trasa zostanie odznaczona,SessionManager zakończy bieżącą sesję.

Aby mieć pewność, że SessionManager prawidłowo zarządza cyklami życia sesji, musisz zadbać o to, aby:

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

Stan braku urządzeń

Jeśli tworzysz niestandardowe okna przesyłania, Twój niestandardowy element MediaRouteChooserDialog powinien prawidłowo obsługiwać sytuację, w której nie znaleziono żadnych urządzeń. W oknie dialogowym powinny być widoczne 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 już wszystkie funkcje, które możesz dodać do aplikacji nadawcy na Androida. Teraz możesz utworzyć aplikację nadawcy na inną platformę (iOS lub sieć) albo utworzyć aplikację odbiorcy internetowego.