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
:
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)
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" />
// 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) { } }
// 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
:
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") } }
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
:
try { mCastSession.setMessageReceivedCallbacks( mHelloWorldChannel.namespace, mHelloWorldChannel) } catch (e: IOException) { Log.e(TAG, "Exception while creating channel", e) }
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:
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) } } }
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 oknie selektora trasy wywołaj
MediaRouter.selectRoute(MediaRouter.RouteInfo)
, gdy użytkownik wybierze urządzenie. - W oknie kontrolera trasy (w stanie połączenia lub stanie przesyłania) wywołaj
MediaRouter.unselect(int)
, gdy użytkownik przestanie przesyłać.
W zależności od sposobu tworzenia okien przesyłania może być konieczne wykonanie dodatkowych czynności:
- Jeśli okna przesyłania tworzysz przy użyciu
MediaRouteChooserDialog
iMediaRouteControllerDialog
, automatycznie aktualizują one wybór trasy wMediaRouter
, więc nie musisz nic robić. - Jeśli skonfigurujesz przycisk przesyłania za pomocą
CastButtonFactory.setUpMediaRouteButton(Context, Menu, int)
lubCastButtonFactory.setUpMediaRouteButton(Context, MediaRouteButton)
, okna dialogowe są tworzone za pomocą usługMediaRouteChooserDialog
iMediaRouteControllerDialog
, więc nie musisz nic robić. - W innych przypadkach będą tworzone niestandardowe okna przesyłania, więc musisz wykonać powyższe instrukcje, by zaktualizować stan wyboru trasy w
MediaRouter
.
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.