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:
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);
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" />
// 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ą 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:
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 wysyłająca połączy się z aplikacją odbierającą, kanał niestandardowy może
zostać utworzony za pomocą
setMessageReceivedCallbacks
metody:
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 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:
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
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 oknie wyboru trasy
wywołać
MediaRouter.selectRoute(MediaRouter.RouteInfo)gdy użytkownik wybierze urządzenie. - W oknie kontrolera trasy (w stanie połączenialub
przesyłania),
wywołać
MediaRouter.unselect(int)gdy użytkownik przestanie przesyłać.
W zależności od sposobu tworzenia okien Cast może być konieczne wykonanie dodatkowych działań:
- Jeśli tworzysz okna Cast za pomocą
MediaRouteChooserDialogiMediaRouteControllerDialog, te okna automatycznie zaktualizują wybór trasy wMediaRouterautomatycznie, więc nie musisz nic robić. - Jeśli skonfigurujesz przycisk Cast za pomocą
CastButtonFactory.setUpMediaRouteButton(Context, Menu, int)lubCastButtonFactory.setUpMediaRouteButton(Context, MediaRouteButton), okna zostaną utworzone za pomocąMediaRouteChooserDialogiMediaRouteControllerDialog, więc też nie musisz nic robić. - W innych przypadkach będziesz tworzyć niestandardowe okna Cast, więc musisz postępować zgodnie z powyższymi instrukcjami, aby zaktualizować stan wyboru trasy w
MediaRouter.
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.