Ten przewodnik dla programistów zawiera informacje o tym, jak dodać obsługę Google Cast na urządzeniach z Androidem. aplikacji nadawcy, używając pakietu Android Sender SDK.
Urządzenie mobilne lub laptop jest nadawcą, który steruje odtwarzaniem. Urządzenie Google Cast to odbiornik, który wyświetla treści na telewizorze.
Platforma nadawcy odnosi się do pliku binarnego biblioteki klas Cast zasoby dostępne w czasie działania u nadawcy. aplikację nadawcy lub aplikację Cast. odnosi się do aplikacji również uruchomionej u nadawcy. aplikacji Web Receiver odnosi się do aplikacji HTML działającej na urządzeniu obsługującym Cast.
Platforma nadawcy korzysta z asynchronicznego projektu wywołania zwrotnego do informowania nadawcy możesz w niej używać zdarzeń i przełączać się między różnymi stanami aplikacji Cast. cyklu.
Przepływ aplikacji
Poniższe kroki opisują typowy proces wysyłania wysokiego poziomu u nadawcy Aplikacja na Androida:
- Platforma Cast uruchamia się automatycznie
MediaRouter
wykrywanie urządzeń na podstawie cyklu życiaActivity
. - Gdy użytkownik kliknie przycisk Cast, platforma wyświetla moduł Cast z listą wykrytych urządzeń przesyłających.
- Gdy użytkownik wybierze urządzenie przesyłające, platforma próbuje uruchomić aplikacja Web Receiver na urządzeniu przesyłającym.
- Platforma wywołuje wywołania zwrotne w aplikacji nadawcy, aby potwierdzić, że internet Aplikacja odbiornika została uruchomiona.
- Platforma tworzy kanał komunikacji między nadawcą a internetem Aplikacje odbiorników.
- Platforma używa kanału komunikacyjnego do wczytywania mediów i sterowania nimi na odbiorniku internetowym.
- Platforma synchronizuje stan odtwarzania multimediów między nadawcą i Odbiornik internetowy: gdy użytkownik wykonuje działania w interfejsie nadawcy, platforma przekazuje żądania sterowania multimediami do odbiornika internetowego, wysyła aktualizacje stanu multimediów, platforma aktualizuje stan interfejsu użytkownika nadawcy.
- Gdy użytkownik kliknie przycisk Cast, by odłączyć urządzenie przesyłające, platforma odłączy aplikację wysyłającą od odbiornika internetowego.
Pełną listę wszystkich klas, metod i zdarzeń w Google Cast SDK dla Androida: zobacz materiały referencyjne na temat interfejsu Google Cast Sender API na urządzeniu z Androidem. W sekcjach poniżej znajdziesz instrukcje dodawania przesyłania do aplikacji na Androida.
Konfigurowanie pliku manifestu na Androida
Plik AndroidManifest.xml Twojej aplikacji wymaga skonfigurowania tych elementów elementy pakietu Cast SDK:
uses-sdk
Ustaw minimalne i docelowe poziomy interfejsu Android API obsługiwane przez pakiet Cast SDK. Obecnie minimalnym poziomem interfejsu API jest 23, a docelowym poziomem Poziom API 34.
<uses-sdk
android:minSdkVersion="23"
android:targetSdkVersion="34" />
android:theme
Ustaw motyw aplikacji na podstawie minimalnej wersji pakietu SDK na Androida. Na przykład, jeśli
nie implementujesz własnego motywu, użyj odmiany
Theme.AppCompat
w przypadku kierowania na wersję pakietu Android SDK na minimalną wersję
przed Lollipop.
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/Theme.AppCompat" >
...
</application>
Inicjowanie kontekstu przesyłania
Platforma ma globalny obiekt typu singleton o nazwie CastContext
, który udostępnia współrzędne
do wszystkich interakcji
w ramach platformy.
Aplikacja musi implementować
OptionsProvider
interfejsu dostarcza opcji potrzebnych do zainicjowania
CastContext
singleton. OptionsProvider
udostępnia instancję
CastOptions
.
który zawiera opcje wpływające na działanie platformy. Najbardziej
ważnym z nich jest identyfikator aplikacji odbiornika internetowego, który służy do filtrowania
w wynikach wykrywania i uruchamiać aplikację Web Receiver po rozpoczęciu sesji przesyłania.
rozpoczęto.
class CastOptionsProvider : OptionsProvider { override fun getCastOptions(context: Context): CastOptions { return Builder() .setReceiverApplicationId(context.getString(R.string.app_id)) .build() } override fun getAdditionalSessionProviders(context: Context): List<SessionProvider>? { return null } }
public class CastOptionsProvider implements OptionsProvider { @Override public CastOptions getCastOptions(Context context) { CastOptions castOptions = new CastOptions.Builder() .setReceiverApplicationId(context.getString(R.string.app_id)) .build(); return castOptions; } @Override public List<SessionProvider> getAdditionalSessionProviders(Context context) { return null; } }
Musisz zadeklarować pełną nazwę wdrożonego tagu OptionsProvider
jako pole metadanych w pliku AndroidManifest.xml aplikacji nadawcy:
<application>
...
<meta-data
android:name=
"com.google.android.gms.cast.framework.OPTIONS_PROVIDER_CLASS_NAME"
android:value="com.foo.CastOptionsProvider" />
</application>
Gdy funkcja CastContext.getSharedInstance()
jest inicjowana leniwie, funkcja CastContext
.
class MyActivity : FragmentActivity() { override fun onCreate(savedInstanceState: Bundle?) { val castContext = CastContext.getSharedInstance(this) } }
public class MyActivity extends FragmentActivity { @Override public void onCreate(Bundle savedInstanceState) { CastContext castContext = CastContext.getSharedInstance(this); } }
Widżety przesyłania
Platforma Cast udostępnia widżety zgodne z technologią Cast. Lista kontrolna:
Nakładka wprowadzająca: Platforma udostępnia widok niestandardowy,
IntroductoryOverlay
, wyświetlany użytkownikowi, by zwrócić uwagę na przycisk Cast. przy pierwszym użyciu odbiornika. Aplikacja Sender może dostosujesz tekst i pozycję tytułu. tekst.Przycisk przesyłania: Przycisk Cast jest widoczny niezależnie od dostępności urządzeń przesyłających. Gdy użytkownik po raz pierwszy kliknie przycisk Cast, pojawi się okno przesyłania. który zawiera listę wykrytych urządzeń. Gdy użytkownik kliknie przycisk Cast gdy jest podłączone, wyświetlane są bieżące metadane multimediów (np. tytułu, nazwy studia nagraniowego i obrazu miniatury) lub zezwala użytkownikowi , aby odłączyć urządzenie przesyłające. Przycisk „Przesyłaj” jest czasami określane jako „ikonę przesyłania”.
Minikontroler: Gdy użytkownik przesyła treści i opuszcza bieżące strony treści lub rozszerzenia kontrolera na inny ekran w aplikacji nadawcy, na dole ekranu wyświetlany jest minikontroler, aby użytkownik mógł przeglądać metadane aktualnie przesyłanych multimediów i sterować odtwarzaniem.
Rozszerzony kontroler: Gdy użytkownik przesyła treści, po kliknięciu powiadomienia o multimediach lub mini kontroler, pojawi się rozwinięty kontroler, który wyświetla odtwarzane metadane multimediów i udostępnienie kilku przycisków do sterowania, do odtwarzania multimediów.
Powiadomienie: Tylko na Androidzie. Gdy użytkownik przesyła treści i opuszcza aplikację nadawcy, wyświetla się powiadomienie o multimediach, które pokazuje aktualnie przesyłane treści metadanych multimediów i elementach sterujących odtwarzaniem.
Ekran blokady: Tylko na Androidzie. Gdy użytkownik przesyła treści i się porusza (lub gdy urządzenie limit czasu) na ekranie blokady, pojawia się element sterujący ekranu blokady multimediów, pokazuje metadane aktualnie przesyłanych multimediów i elementy sterujące odtwarzaniem.
W tym przewodniku znajdziesz opis tego, jak dodać te widżety do do aplikacji.
Dodaj przycisk Cast
Android
MediaRouter
Interfejsy API umożliwiają wyświetlanie i odtwarzanie multimediów na urządzeniach dodatkowych.
Aplikacje na Androida, które używają interfejsu API MediaRouter
, powinny zawierać przycisk Cast
interfejsu, aby umożliwić użytkownikom wybór trasy multimediów
z urządzenia dodatkowego, np. urządzenia przesyłającego.
Struktura ta umożliwia dodanie
MediaRouteButton
jako
Cast button
bardzo łatwe. Najpierw dodaj pozycję menu lub pole MediaRouteButton
w pliku XML
definiujący menu oraz
CastButtonFactory
.
w ramach konstrukcji.
// To add a Cast button, add the following snippet.
// menu.xml
<item
android:id="@+id/media_route_menu_item"
android:title="@string/media_route_menu_title"
app:actionProviderClass="androidx.mediarouter.app.MediaRouteActionProvider"
app:showAsAction="always" />
// Then override the onCreateOptionMenu() for each of your activities. // MyActivity.kt override fun onCreateOptionsMenu(menu: Menu): Boolean { super.onCreateOptionsMenu(menu) menuInflater.inflate(R.menu.main, menu) CastButtonFactory.setUpMediaRouteButton( applicationContext, menu, R.id.media_route_menu_item ) return true }
// Then override the onCreateOptionMenu() for each of your activities. // MyActivity.java @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); getMenuInflater().inflate(R.menu.main, menu); CastButtonFactory.setUpMediaRouteButton(getApplicationContext(), menu, R.id.media_route_menu_item); return true; }
Jeśli następnie element Activity
dziedziczy z elementu
FragmentActivity
,
możesz dodać
MediaRouteButton
do układu strony.
// activity_layout.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal" >
<androidx.mediarouter.app.MediaRouteButton
android:id="@+id/media_route_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:mediaRouteTypes="user"
android:visibility="gone" />
</LinearLayout>
// MyActivity.kt override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_layout) mMediaRouteButton = findViewById<View>(R.id.media_route_button) as MediaRouteButton CastButtonFactory.setUpMediaRouteButton(applicationContext, mMediaRouteButton) mCastContext = CastContext.getSharedInstance(this) }
// MyActivity.java @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_layout); mMediaRouteButton = (MediaRouteButton) findViewById(R.id.media_route_button); CastButtonFactory.setUpMediaRouteButton(getApplicationContext(), mMediaRouteButton); mCastContext = CastContext.getSharedInstance(this); }
Jeśli chcesz zmienić wygląd przycisku przesyłania, używając motywu, zobacz Dostosuj przycisk Cast
Skonfiguruj wykrywanie urządzeń
Wykrywaniem urządzeń zarządza w pełni
CastContext
Podczas inicjowania CastContext aplikacja nadawcy określa odbiornika internetowego
Identyfikator aplikacji i opcjonalnie może zażądać filtrowania przestrzeni nazw według ustawienia
supportedNamespaces
in
CastOptions
CastContext
zawiera wewnętrznie odwołanie do MediaRouter
i rozpocznie się
procesu wykrywania w następujących warunkach:
- Jest oparty na algorytmie zaprojektowanym z myślą o równowadze czasu oczekiwania w wykrywaniu urządzeń wykorzystanie baterii, wykrywanie będzie od czasu do czasu automatycznie uruchamiane, gdy aplikacja nadawcy działa na pierwszym planie.
- Okno Cast jest otwarte.
- Pakiet Cast SDK próbuje przywrócić sesję przesyłania.
Proces wykrywania zostanie zatrzymany po zamknięciu okna przesyłania lub aplikacja nadawcy przechodzi w tle.
class CastOptionsProvider : OptionsProvider { companion object { const val CUSTOM_NAMESPACE = "urn:x-cast:custom_namespace" } override fun getCastOptions(appContext: Context): CastOptions { val supportedNamespaces: MutableList<String> = ArrayList() supportedNamespaces.add(CUSTOM_NAMESPACE) return CastOptions.Builder() .setReceiverApplicationId(context.getString(R.string.app_id)) .setSupportedNamespaces(supportedNamespaces) .build() } override fun getAdditionalSessionProviders(context: Context): List<SessionProvider>? { return null } }
class CastOptionsProvider implements OptionsProvider { public static final String CUSTOM_NAMESPACE = "urn:x-cast:custom_namespace"; @Override public CastOptions getCastOptions(Context appContext) { List<String> supportedNamespaces = new ArrayList<>(); supportedNamespaces.add(CUSTOM_NAMESPACE); CastOptions castOptions = new CastOptions.Builder() .setReceiverApplicationId(context.getString(R.string.app_id)) .setSupportedNamespaces(supportedNamespaces) .build(); return castOptions; } @Override public List<SessionProvider> getAdditionalSessionProviders(Context context) { return null; } }
Jak działa zarządzanie sesjami
SDK Cast wprowadza pojęcie sesji przesyłania: instytucja łącząca etapy łączenia się z urządzeniem, uruchamiania (lub łączenia) z internetem Aplikacja odbiornika, łączenie się z nią i inicjowanie kanału sterowania multimediami. Zobacz odbiornik internetowy Przewodnik po cyklu życia zgłoszenia , by dowiedzieć się więcej o sesjach przesyłania i cyklu życia odbiornika internetowego.
Sesjami zarządza zajęcia
SessionManager
,
aplikacji, do których aplikacja ma dostęp
CastContext.getSessionManager()
Poszczególne sesje są reprezentowane przez podklasy klasy
Session
Przykład:
CastSession
reprezentuje sesje z urządzeniami przesyłającymi. Aplikacja może uzyskać dostęp do obecnie aktywnych
Sesja przesyłania przez
SessionManager.getCurrentCastSession()
Aplikacja może używać
SessionManagerListener
do monitorowania zdarzeń w sesji, takich jak utworzenie, zawieszenie, wznowienie
aplikacji. Platforma automatycznie próbuje wznowić od
nieprawidłowe lub nagłe zakończenie sesji, gdy była aktywna.
Sesje są tworzone i usuwane automatycznie w odpowiedzi na gesty użytkownika.
z okna MediaRouter
.
Aby lepiej zrozumieć błędy rozpoczynania przesyłania, aplikacje mogą używać
CastContext#getCastReasonCodeForCastStatusCode(int)
do konwertowania błędu rozpoczęcia sesji na
CastReasonCodes
Zwróć uwagę na błędy podczas uruchamiania sesji (np. CastReasonCodes#CAST_CANCELLED
)
są zamierzone i nie powinny być rejestrowane jako błąd.
Jeśli chcesz otrzymywać informacje o zmianach stanu w sesji, możesz zaimplementować
SessionManagerListener
. W tym przykładzie słyszymy o dostępności
CastSession
w: Activity
.
class MyActivity : Activity() { private var mCastSession: CastSession? = null private lateinit var mCastContext: CastContext private lateinit var mSessionManager: SessionManager private val mSessionManagerListener: SessionManagerListener<CastSession> = SessionManagerListenerImpl() private inner class SessionManagerListenerImpl : SessionManagerListener<CastSession?> { override fun onSessionStarting(session: CastSession?) {} override fun onSessionStarted(session: CastSession?, sessionId: String) { invalidateOptionsMenu() } override fun onSessionStartFailed(session: CastSession?, error: Int) { val castReasonCode = mCastContext.getCastReasonCodeForCastStatusCode(error) // Handle error } override fun onSessionSuspended(session: CastSession?, reason Int) {} override fun onSessionResuming(session: CastSession?, sessionId: String) {} override fun onSessionResumed(session: CastSession?, wasSuspended: Boolean) { invalidateOptionsMenu() } override fun onSessionResumeFailed(session: CastSession?, error: Int) {} override fun onSessionEnding(session: CastSession?) {} override fun onSessionEnded(session: CastSession?, error: Int) { finish() } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) mCastContext = CastContext.getSharedInstance(this) mSessionManager = mCastContext.sessionManager mSessionManager.addSessionManagerListener(mSessionManagerListener, CastSession::class.java) } override fun onResume() { super.onResume() mCastSession = mSessionManager.currentCastSession } override fun onDestroy() { super.onDestroy() mSessionManager.removeSessionManagerListener(mSessionManagerListener, CastSession::class.java) } }
public class MyActivity extends Activity { private CastContext mCastContext; private CastSession mCastSession; private SessionManager mSessionManager; private SessionManagerListener<CastSession> mSessionManagerListener = new SessionManagerListenerImpl(); private class SessionManagerListenerImpl implements SessionManagerListener<CastSession> { @Override public void onSessionStarting(CastSession session) {} @Override public void onSessionStarted(CastSession session, String sessionId) { invalidateOptionsMenu(); } @Override public void onSessionStartFailed(CastSession session, int error) { int castReasonCode = mCastContext.getCastReasonCodeForCastStatusCode(error); // Handle error } @Override public void onSessionSuspended(CastSession session, int reason) {} @Override public void onSessionResuming(CastSession session, String sessionId) {} @Override public void onSessionResumed(CastSession session, boolean wasSuspended) { invalidateOptionsMenu(); } @Override public void onSessionResumeFailed(CastSession session, int error) {} @Override public void onSessionEnding(CastSession session) {} @Override public void onSessionEnded(CastSession session, int error) { finish(); } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mCastContext = CastContext.getSharedInstance(this); mSessionManager = mCastContext.getSessionManager(); mSessionManager.addSessionManagerListener(mSessionManagerListener, CastSession.class); } @Override protected void onResume() { super.onResume(); mCastSession = mSessionManager.getCurrentCastSession(); } @Override protected void onDestroy() { super.onDestroy(); mSessionManager.removeSessionManagerListener(mSessionManagerListener, CastSession.class); } }
Przenoszenie strumienia
Zachowywanie stanu sesji jest podstawą transferu, gdzie użytkownicy mogą przenosić istniejące strumienie audio i wideo między urządzeniami, używając poleceń głosowych. Google Home Aplikacja lub inteligentne ekrany. Multimedia przestaje się odtwarzać na jednym urządzeniu (źródle) i kontynuuje na innym ( miejsce docelowe). Każde urządzenie przesyłające z najnowszą wersją oprogramowania może służyć jako źródło lub miejsce docelowe w przesyłanie strumienia.
Aby pobrać nowe urządzenie docelowe podczas przenoszenia lub rozszerzania transmisji:
zarejestruj
Cast.Listener
za pomocą
CastSession#addCastListener
Następnie zadzwoń
CastSession#getCastDevice()
podczas wywołania zwrotnego onDeviceNameChanged
.
Zobacz Przesyłanie strumienia w internetowym odbiorniku .
Automatyczne ponowne łączenie
Platforma ta zapewnia
ReconnectionService
który może zostać włączony przez aplikację nadawcy, aby obsługiwał ponowne połączenia w wielu subtelnych
etui narożne, takie jak:
- Odzyskanie połączenia po tymczasowej utracie sieci Wi-Fi
- Wypoczynek po uśpieniu urządzenia
- Przywracanie aplikacji w tle
- Przywracanie systemu w przypadku awarii aplikacji
Ta usługa jest domyślnie włączona, ale można ją wyłączyć w
CastOptions.Builder
Ta usługa może zostać automatycznie scalona z plikiem manifestu aplikacji w przypadku automatycznego scalania jest włączona w pliku Gradle.
Platforma uruchamia usługę w momencie wystąpienia sesji multimediów i ją zatrzymuje po zakończeniu sesji multimediów.
Jak działa Sterowanie multimediami
Platforma Cast wycofuje
RemoteMediaPlayer
klasy z Cast 2.x na nową klasę
RemoteMediaClient
,
który ma te same funkcje w zestawie wygodniejszych interfejsów API;
pozwala uniknąć konieczności przekazywania klienta GoogleApiClient.
Gdy aplikacja tworzy
CastSession
z aplikacją odbiornika internetowego, która obsługuje przestrzeń nazw multimediów,
Wartość RemoteMediaClient
zostanie automatycznie utworzona przez platformę. aplikacja może
aby uzyskać do niego dostęp, wywołaj metodę getRemoteMediaClient()
na: CastSession
instancji.
Wszystkie metody RemoteMediaClient
, które wysyłają żądania do odbiornika internetowego
zwraca obiekt PendingResult, który można wykorzystać do śledzenia danego żądania.
Oczekiwana jest sytuacja, w której instancja RemoteMediaClient
może być współdzielona przez
elementów aplikacji, a także niektórych wewnętrznych komponentów
takich jak stałe minikontrolery,
korzystać z usługi powiadomień.
Z tego względu ta instancja obsługuje rejestrację wielu instancji
RemoteMediaClient.Listener
Ustawianie metadanych multimediów
MediaMetadata
reprezentuje informacje o elemencie multimedialnym, który chcesz przesyłać.
W poniższym przykładzie tworzy się nową instancję MediaMetadata filmu i ustawia
tytuł, podtytuł i 2 obrazy.
val movieMetadata = MediaMetadata(MediaMetadata.MEDIA_TYPE_MOVIE) movieMetadata.putString(MediaMetadata.KEY_TITLE, mSelectedMedia.getTitle()) movieMetadata.putString(MediaMetadata.KEY_SUBTITLE, mSelectedMedia.getStudio()) movieMetadata.addImage(WebImage(Uri.parse(mSelectedMedia.getImage(0)))) movieMetadata.addImage(WebImage(Uri.parse(mSelectedMedia.getImage(1))))
MediaMetadata movieMetadata = new MediaMetadata(MediaMetadata.MEDIA_TYPE_MOVIE); movieMetadata.putString(MediaMetadata.KEY_TITLE, mSelectedMedia.getTitle()); movieMetadata.putString(MediaMetadata.KEY_SUBTITLE, mSelectedMedia.getStudio()); movieMetadata.addImage(new WebImage(Uri.parse(mSelectedMedia.getImage(0)))); movieMetadata.addImage(new WebImage(Uri.parse(mSelectedMedia.getImage(1))));
Zobacz Wybór obrazu na temat używania obrazów z metadanymi multimediów.
Wczytaj multimedia
Aplikacja może wczytać element multimedialny, jak pokazano w tym kodzie. Pierwsze użycie
MediaInfo.Builder
z metadanymi multimediów,
MediaInfo
instancji. Pobierz
RemoteMediaClient
z bieżącego CastSession
, a następnie wczytaj do niego MediaInfo
RemoteMediaClient
Używaj RemoteMediaClient
do odtwarzania, wstrzymywania itp.
sterować aplikacją odtwarzacza multimedialnego działającą na odbiorniku internetowym.
val mediaInfo = MediaInfo.Builder(mSelectedMedia.getUrl()) .setStreamType(MediaInfo.STREAM_TYPE_BUFFERED) .setContentType("videos/mp4") .setMetadata(movieMetadata) .setStreamDuration(mSelectedMedia.getDuration() * 1000) .build() val remoteMediaClient = mCastSession.getRemoteMediaClient() remoteMediaClient.load(MediaLoadRequestData.Builder().setMediaInfo(mediaInfo).build())
MediaInfo mediaInfo = new MediaInfo.Builder(mSelectedMedia.getUrl()) .setStreamType(MediaInfo.STREAM_TYPE_BUFFERED) .setContentType("videos/mp4") .setMetadata(movieMetadata) .setStreamDuration(mSelectedMedia.getDuration() * 1000) .build(); RemoteMediaClient remoteMediaClient = mCastSession.getRemoteMediaClient(); remoteMediaClient.load(new MediaLoadRequestData.Builder().setMediaInfo(mediaInfo).build());
Zobacz też sekcję na temat za pomocą ścieżek multimedialnych.
Format filmu 4K
Aby sprawdzić format wideo, użyj opcji
getVideoInfo()
w MediaStatus, aby uzyskać bieżącą instancję
VideoInfo
Ta instancja zawiera typ formatu telewizora HDR i wysokość wyświetlacza
i szerokość w pikselach. Warianty formatu 4K są oznaczone stałymi wartościami
HDR_TYPE_*
Zdalne sterowanie powiadomieniami na wiele urządzeń
Gdy użytkownik przesyła treści, inne urządzenia z Androidem w tej samej sieci otrzymują powiadomienie, aby umożliwić im sterowanie odtwarzaniem. Każda osoba, dla którego urządzenia otrzymujące takie powiadomienia, mogą je wyłączyć na tym urządzeniu w Ustawieniach w Google > Google Cast > Pokazuj powiadomienia pilota. (Powiadomienia zawierają skrót do aplikacji Ustawienia). Więcej informacji znajdziesz tutaj: Przesyłanie powiadomień z pilota
Dodaj minikontroler
Zgodnie z projektem obsady Lista kontrolna, aplikacja nadawcy powinna zapewniać trwałą kontrolę nazywaną minimalna kontroler który powinien pojawiać się, gdy użytkownik opuści bieżącą stronę z zawartością i w innej części aplikacji nadawcy. Minikontroler wyświetla widoczne przypomnienie użytkownikowi bieżącej sesji przesyłania. Po dotknięciu minikontrolera użytkownik może wrócić do rozszerzonego widoku kontrolera przesyłającego na pełny ekran.
Platforma udostępnia niestandardowy widok MiniControllerFragment, który można dodać na dole pliku układu każdej aktywności, w której chcesz pokazać minikontroler.
<fragment
android:id="@+id/castMiniController"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:visibility="gone"
class="com.google.android.gms.cast.framework.media.widget.MiniControllerFragment" />
Gdy aplikacja nadawcy odtwarza transmisję na żywo wideo lub audio, pakiet SDK automatycznie wyświetla przycisk odtwarzania/zatrzymania w miejscu przycisku odtwarzania/wstrzymania. na minikontrolerze.
Aby ustawić wygląd tytułu i podtytułu tego widoku niestandardowego: oraz o wyborze przycisków, zobacz Dostosuj minikontroler.
Dodaj rozszerzony kontroler
Lista kontrolna projektu Google Cast wymaga, by aplikacja wysyłająca udostępniała rozwinięte kontroler w przypadku multimediów objętych przesyłaniem. Rozwinięty kontroler to pełnoekranowa wersja na minikontroler.
Pakiet Cast SDK udostępnia widżet dla rozszerzonego kontrolera o nazwie
ExpandedControllerActivity
To jest klasa abstrakcyjna, którą musisz umieścić w podklasie, aby dodać przycisk Cast.
Najpierw utwórz nowy plik zasobów menu, który będzie udostępniany rozwiniętym kontrolerom. Przycisk Cast:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/media_route_menu_item"
android:title="@string/media_route_menu_title"
app:actionProviderClass="androidx.mediarouter.app.MediaRouteActionProvider"
app:showAsAction="always"/>
</menu>
Utwórz nowe zajęcia z rozszerzeniem ExpandedControllerActivity
.
class ExpandedControlsActivity : ExpandedControllerActivity() { override fun onCreateOptionsMenu(menu: Menu): Boolean { super.onCreateOptionsMenu(menu) menuInflater.inflate(R.menu.expanded_controller, menu) CastButtonFactory.setUpMediaRouteButton(this, menu, R.id.media_route_menu_item) return true } }
public class ExpandedControlsActivity extends ExpandedControllerActivity { @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); getMenuInflater().inflate(R.menu.expanded_controller, menu); CastButtonFactory.setUpMediaRouteButton(this, menu, R.id.media_route_menu_item); return true; } }
Teraz zadeklaruj nową aktywność w pliku manifestu aplikacji w tagu application
:
<application>
...
<activity
android:name=".expandedcontrols.ExpandedControlsActivity"
android:label="@string/app_name"
android:launchMode="singleTask"
android:theme="@style/Theme.CastVideosDark"
android:screenOrientation="portrait"
android:parentActivityName="com.google.sample.cast.refplayer.VideoBrowserActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
</intent-filter>
</activity>
...
</application>
Edytuj CastOptionsProvider
oraz zmień NotificationOptions
i
CastMediaOptions
, aby ustawić nową aktywność jako docelową aktywność:
override fun getCastOptions(context: Context): CastOptions? { val notificationOptions = NotificationOptions.Builder() .setTargetActivityClassName(ExpandedControlsActivity::class.java.name) .build() val mediaOptions = CastMediaOptions.Builder() .setNotificationOptions(notificationOptions) .setExpandedControllerActivityClassName(ExpandedControlsActivity::class.java.name) .build() return CastOptions.Builder() .setReceiverApplicationId(context.getString(R.string.app_id)) .setCastMediaOptions(mediaOptions) .build() }
public CastOptions getCastOptions(Context context) { NotificationOptions notificationOptions = new NotificationOptions.Builder() .setTargetActivityClassName(ExpandedControlsActivity.class.getName()) .build(); CastMediaOptions mediaOptions = new CastMediaOptions.Builder() .setNotificationOptions(notificationOptions) .setExpandedControllerActivityClassName(ExpandedControlsActivity.class.getName()) .build(); return new CastOptions.Builder() .setReceiverApplicationId(context.getString(R.string.app_id)) .setCastMediaOptions(mediaOptions) .build(); }
Zaktualizuj metodę LocalPlayerActivity
loadRemoteMedia
, aby wyświetlać
nowe działanie po załadowaniu zdalnych multimediów:
private fun loadRemoteMedia(position: Int, autoPlay: Boolean) { val remoteMediaClient = mCastSession?.remoteMediaClient ?: return remoteMediaClient.registerCallback(object : RemoteMediaClient.Callback() { override fun onStatusUpdated() { val intent = Intent(this@LocalPlayerActivity, ExpandedControlsActivity::class.java) startActivity(intent) remoteMediaClient.unregisterCallback(this) } }) remoteMediaClient.load( MediaLoadRequestData.Builder() .setMediaInfo(mSelectedMedia) .setAutoplay(autoPlay) .setCurrentTime(position.toLong()).build() ) }
private void loadRemoteMedia(int position, boolean autoPlay) { if (mCastSession == null) { return; } final RemoteMediaClient remoteMediaClient = mCastSession.getRemoteMediaClient(); if (remoteMediaClient == null) { return; } remoteMediaClient.registerCallback(new RemoteMediaClient.Callback() { @Override public void onStatusUpdated() { Intent intent = new Intent(LocalPlayerActivity.this, ExpandedControlsActivity.class); startActivity(intent); remoteMediaClient.unregisterCallback(this); } }); remoteMediaClient.load(new MediaLoadRequestData.Builder() .setMediaInfo(mSelectedMedia) .setAutoplay(autoPlay) .setCurrentTime(position).build()); }
Gdy aplikacja nadawcy odtwarza transmisję na żywo wideo lub audio, pakiet SDK automatycznie wyświetla przycisk odtwarzania/zatrzymania w miejscu przycisku odtwarzania/wstrzymania. w rozwiniętym kontrolerze.
Aby ustawić wygląd za pomocą motywów, wybierz przyciski, które mają być wyświetlane. i dodawanie przycisków niestandardowych, zobacz Dostosuj rozwinięty kontroler.
Sterowanie głośnością
Platforma automatycznie zarządza woluminem aplikacji nadawcy. Struktura automatycznie synchronizuje aplikacje nadawcy i adresata, Interfejs użytkownika zawsze zgłasza wolumin określony przez odbiornik internetowy.
Regulacja głośności za pomocą przycisku fizycznego
W Androidzie za pomocą fizycznych przycisków na urządzeniu nadawcy można zmienić sesji przesyłania na odbiorniku internetowym domyślnie na każdym urządzeniu Jelly Bean lub nowsza.
Sterowanie głośnością za pomocą przycisku fizycznego przed Jelly Bean
Aby sterować głośnością odbiornika internetowego za pomocą fizycznych przycisków głośności
Urządzenia z Androidem starsze niż Jelly Bean – aplikacja nadawcy powinna zastąpić
dispatchKeyEvent
w swoich działaniach i zadzwonić
CastContext.onDispatchVolumeKeyEventBeforeJellyBean()
:
class MyActivity : FragmentActivity() { override fun dispatchKeyEvent(event: KeyEvent): Boolean { return (CastContext.getSharedInstance(this) .onDispatchVolumeKeyEventBeforeJellyBean(event) || super.dispatchKeyEvent(event)) } }
class MyActivity extends FragmentActivity { @Override public boolean dispatchKeyEvent(KeyEvent event) { return CastContext.getSharedInstance(this) .onDispatchVolumeKeyEventBeforeJellyBean(event) || super.dispatchKeyEvent(event); } }
Dodaj opcje sterowania multimediami do powiadomień i ekranu blokady
Tylko na urządzeniach z Androidem lista kontrolna projektowania w Google Cast wymaga aplikacji nadawcy do
wdrożyć opcje sterowania multimediami
i w zamku
ekranu,
gdy nadawca przesyła treści, ale aplikacja nadawcy nie jest zaznaczona.
platforma zapewnia
MediaNotificationService
oraz
MediaIntentReceiver
aby pomóc aplikacji nadawcy tworzyć opcje sterowania multimediami w powiadomieniu i w blokadzie
ekranu.
MediaNotificationService
działa, gdy nadawca przesyła treści, i wyświetla komunikat
powiadomienie z miniaturą obrazu i informacjami o aktualnie przesyłaniu
element, przycisk odtwarzania/wstrzymywania i przycisk zatrzymania.
MediaIntentReceiver
to BroadcastReceiver
, który obsługuje działania użytkowników z:
powiadomienie.
Aplikacja może konfigurować powiadomienia i sterowanie multimediami na ekranie blokady
NotificationOptions
Aplikacja może skonfigurować, które przyciski sterowania mają być wyświetlane w powiadomieniach.
które Activity
ma się otworzyć, gdy użytkownik kliknie powiadomienie. Działania „If”
nie są jawnie podane wartości domyślne,
MediaIntentReceiver.ACTION_TOGGLE_PLAYBACK
i
Użyjemy formatu MediaIntentReceiver.ACTION_STOP_CASTING
.
// Example showing 4 buttons: "rewind", "play/pause", "forward" and "stop casting". val buttonActions: MutableList<String> = ArrayList() buttonActions.add(MediaIntentReceiver.ACTION_REWIND) buttonActions.add(MediaIntentReceiver.ACTION_TOGGLE_PLAYBACK) buttonActions.add(MediaIntentReceiver.ACTION_FORWARD) buttonActions.add(MediaIntentReceiver.ACTION_STOP_CASTING) // Showing "play/pause" and "stop casting" in the compat view of the notification. val compatButtonActionsIndices = intArrayOf(1, 3) // Builds a notification with the above actions. Each tap on the "rewind" and "forward" buttons skips 30 seconds. // Tapping on the notification opens an Activity with class VideoBrowserActivity. val notificationOptions = NotificationOptions.Builder() .setActions(buttonActions, compatButtonActionsIndices) .setSkipStepMs(30 * DateUtils.SECOND_IN_MILLIS) .setTargetActivityClassName(VideoBrowserActivity::class.java.name) .build()
// Example showing 4 buttons: "rewind", "play/pause", "forward" and "stop casting". List<String> buttonActions = new ArrayList<>(); buttonActions.add(MediaIntentReceiver.ACTION_REWIND); buttonActions.add(MediaIntentReceiver.ACTION_TOGGLE_PLAYBACK); buttonActions.add(MediaIntentReceiver.ACTION_FORWARD); buttonActions.add(MediaIntentReceiver.ACTION_STOP_CASTING); // Showing "play/pause" and "stop casting" in the compat view of the notification. int[] compatButtonActionsIndices = new int[]{1, 3}; // Builds a notification with the above actions. Each tap on the "rewind" and "forward" buttons skips 30 seconds. // Tapping on the notification opens an Activity with class VideoBrowserActivity. NotificationOptions notificationOptions = new NotificationOptions.Builder() .setActions(buttonActions, compatButtonActionsIndices) .setSkipStepMs(30 * DateUtils.SECOND_IN_MILLIS) .setTargetActivityClassName(VideoBrowserActivity.class.getName()) .build();
Pokazywanie opcji sterowania multimediami z powiadomień i ekranu blokady jest włączone przez
i można je wyłączyć, łącząc się
setNotificationOptions
z wartością null
CastMediaOptions.Builder
Funkcja ekranu blokady jest obecnie włączona, dopóki masz powiadomienie
włączony.
// ... continue with the NotificationOptions built above val mediaOptions = CastMediaOptions.Builder() .setNotificationOptions(notificationOptions) .build() val castOptions: CastOptions = Builder() .setReceiverApplicationId(context.getString(R.string.app_id)) .setCastMediaOptions(mediaOptions) .build()
// ... continue with the NotificationOptions built above CastMediaOptions mediaOptions = new CastMediaOptions.Builder() .setNotificationOptions(notificationOptions) .build(); CastOptions castOptions = new CastOptions.Builder() .setReceiverApplicationId(context.getString(R.string.app_id)) .setCastMediaOptions(mediaOptions) .build();
Gdy aplikacja nadawcy odtwarza transmisję na żywo wideo lub audio, pakiet SDK automatycznie wyświetla przycisk odtwarzania/zatrzymania w miejscu przycisku odtwarzania/wstrzymania. na elemencie sterującym powiadomieniami, ale nie na ekranie blokady.
Uwaga: aby wyświetlić opcje ekranu blokady na urządzeniach z systemem starszym niż Lollipop,
RemoteMediaClient
będzie automatycznie prosić o fokus w Twoim imieniu.
Obsługa błędów
Aplikacje nadawcy muszą obsługiwać wszystkie błędne wywołania zwrotne i podejmować decyzje, najlepszą odpowiedź na każdy etap cyklu życia Cast. Aplikacja może wyświetlać może wyświetlić użytkownikowi komunikat o błędzie lub może on unieważnić połączenie Odbiornik internetowy.