Dodaj zaawansowane funkcje do swojej aplikacji na Androida

Przerwy na reklamy

Pakiet Android Sender SDK zapewnia obsługę przerw na reklamy i reklam towarzyszących w określonym strumieniu multimediów.

Przeczytaj omówienie przerw na reklamy w odbiorniku internetowym, aby dowiedzieć się więcej o tym, jak działają przerwy na reklamy.

Chociaż przerwy można określić zarówno u nadawcy, jak i u odbiorcy, zalecamy to jednak zrobić w odbiorniku internetowym i odbiorniku Android TV, aby zachować spójność działania na różnych platformach.

W przypadku Androida przerwy na reklamę określ w poleceniu wczytywania za pomocą właściwości 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);

Dodaj działania niestandardowe

Aplikacja nadawcy może dodać rozszerzenie MediaIntentReceiver do obsługi działań niestandardowych lub zastąpienia ich działania. Jeśli masz zaimplementowany własny plik MediaIntentReceiver, musisz dodać go do pliku manifestu i ustawić jego nazwę w elemencie CastMediaOptions. W tym przykładzie pokazujemy działania niestandardowe, które zastępują przełączanie zdalnego odtwarzania multimediów, naciśnięcie przycisku multimediów i inne działania.

// 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ą adresata, 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 się zaczynać od prefiksu urn:x-cast:, np. urn:x-cast:com.example.custom. Możesz mieć wiele kanałów niestandardowych, każdy z nich z unikalną przestrzenią nazw. Aplikacja odbierająca może też wysyłać i odbierać wiadomości, korzystając z tej samej przestrzeni nazw.

Kanał niestandardowy należy zaimplementować 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 nadawcy połączy się z aplikacją adresata, kanał niestandardowy można utworzyć 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 za pomocą metody sendMessage 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

Więcej informacji znajdziesz w sekcji Interfejsy API do automatycznego odtwarzania i kolejkowania.

Zastępowanie wyboru obrazów w widżetach UX

Różne komponenty platformy (na przykład okno Cast, minikontroler i kontroler UIMediaController, jeśli zostały skonfigurowane) będą wyświetlać grafikę aktualnie przesyłanych multimediów. Adresy URL grafiki ze zdjęciem są zwykle zawarte w elemencie MediaMetadata multimediów, ale aplikacja nadawcy może mieć alternatywne źródło tych adresów.

Klasa ImagePicker określa sposób wyboru odpowiedniego obrazu z listy obrazów w elemencie MediaMetadata na podstawie użycia obrazu, np. miniatury powiadomienia lub pełnego ekranu. Domyślna implementacja ImagePicker zawsze wybiera pierwszy obraz lub zwraca wartość null, jeśli w MediaMetadata nie ma obrazu. Aplikacja może podklasę ImagePicker i zastąpić metodę onPickImage(MediaMetadata, ImageHints), aby udostępnić alternatywną implementację, a następnie wybrać tę podklasę z metodą setImagePicker CastMediaOptions.Builder. ImageHints podaje w elemencie ImagePicker wskazówki dotyczące typu i rozmiaru obrazu, który ma być wyświetlany w interfejsie.

Dostosowywanie okien przesyłania

Zarządzanie cyklem życia sesji

SessionManager to główne miejsce do zarządzania cyklem życia sesji. SessionManager nasłuchuje Androida MediaRouter przekierowuje zmiany stanu wyboru, aby rozpoczynać, wznawiać i kończyć sesje. Gdy wybierzesz trasę, SessionManager utworzy obiekt Session i spróbuje ją uruchomić lub wznowić. Jeśli nie wybierzesz żadnej trasy, SessionManager zakończy bieżącą sesję.

Dlatego, aby mieć pewność, że usługa SessionManager prawidłowo zarządza cyklami życia sesji, sprawdź, czy:

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

Stan zero urządzeń

Jeśli tworzysz niestandardowe okna przesyłania, niestandardowe okno MediaRouteChooserDialog powinno obsługiwać żadne urządzenia. Okno powinno zawierać wskaźniki, które będą jasno informować użytkowników, że aplikacja wciąż próbuje znaleźć urządzenia i kiedy próba wykrywania nie jest już aktywna.

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

Dalsze kroki

To już wszystkie funkcje, które możesz dodać do aplikacji Android Sender. Możesz teraz utworzyć aplikację nadawcy na inną platformę (iOS lub Internet) albo aplikację Web Receiver.