Dodaj zaawansowane funkcje do swojej aplikacji na Androida

Przerwy na reklamę

Pakiet Android Sender SDK 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 Web Receiver.

Przerwy można określać zarówno w aplikacji wysyłającej, jak i odbierającej, ale zalecamy, aby robić to w Web Receiver i Android TV Receiver, aby zachować spójne działanie na różnych platformach.

W Androidzie przerwy na reklamę określ 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 wysyłająca 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 zdalnego odtwarzania multimediów, 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 wysyłająca mogła komunikować się z aplikacją odbierającą, musi utworzyć kanał niestandardowy. Aplikacja wysyłająca może używać kanału niestandardowego do wysyłania wiadomości tekstowych do aplikacji odbierającej. 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 odbierająca 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 wysyłająca połączy się z aplikacją odbierającą, kanał niestandardowy może zostać utworzony 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 aplikacja wysyłająca może używać metody sendMessage do wysyłania wiadomości tekstowych do aplikacji odbierającej 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 dodawania do kolejki.

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 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 użycia obrazu, np. miniatury powiadomienia lub tła pełnoekranowego. 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ł cyklem ż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 Android Sender. Możesz teraz utworzyć aplikację wysyłającą na inną platformę (iOS lub sieć) albo utworzyć aplikację Web Receiver.