Bu sayfa, kod snippet'lerini ve bu veriler için kullanılabilecek özelliklerin açıklamalarını içerir TV Alıcısı uygulamasını özelleştirmenize olanak tanır.
Kitaplıkları yapılandırma
Cast Connect API'lerinin Android TV uygulamanızda kullanılabilmesi için:
-
Uygulama modülü dizininizde
build.gradle
dosyasını açın. -
google()
öğesinin listelenenrepositories
içinde bulunduğunu doğrulayın.repositories { google() }
-
Uygulamanızın hedef cihaz türüne bağlı olarak en yeni sürümleri ekleyin
kitaplığını bağımlılarınıza nasıl ekleyeceksiniz?
-
Android Alıcı uygulaması için:
dependencies { implementation 'com.google.android.gms:play-services-cast-tv:21.1.0' implementation 'com.google.android.gms:play-services-cast:21.5.0' }
. -
Android Sender uygulaması için:
dependencies { implementation 'com.google.android.gms:play-services-cast:21.1.0' implementation 'com.google.android.gms:play-services-cast-framework:21.5.0' }
.
-
Android Alıcı uygulaması için:
-
Değişiklikleri kaydedin ve
Sync Project with Gradle Files
düğmesini tıklayın tıklayın.
-
Podfile
uygulamanızıngoogle-cast-sdk
4.8.3 sürümünü hedeflediğinden emin olun veya üzeri -
iOS 14 veya sonraki sürümleri hedefleyin. Sürüm Notları'na bakın.
inceleyebilirsiniz.
platform: ios, '14' def target_pods pod 'google-cast-sdk', '~>4.8.3' end
- Chromium tarayıcı M87 veya sonraki sürümünü gerektirir.
-
Web Sender API kitaplığını projenize ekleme
<script src="//www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1"></script>
.
AndroidX gereksinimi
Google Play Hizmetleri'nin yeni sürümleri, bir uygulamanın kullanılabilmesi için güncellenmiş olmasını gerektirir
androidx
ad alanında yer alır. Talimatlar için
AndroidX'e taşınıyor.
Android TV uygulaması ile ilgili ön koşullar
Android TV uygulamanızda Cast Connect'in desteklenmesi için uygulama oluşturmanız ve destek etkinliklerini görebilirsiniz. Medya oturumunuz tarafından sağlanan veriler videonun oynatmaya devam etmesi için medya durumunuz. Medya oturumunuz Cast Connect kitaplığı tarafından da kullanılır bir gönderenden belirli mesajları (ör. duraklatma) aldığını belirtmek için kullanılır.
Medya oturumu ve medya oturumunu başlatma hakkında daha fazla bilgi için bkz. bir medya oturumu rehberiyle çalışın.
Medya oturumu yaşam döngüsü
Uygulamanız oynatma başladığında bir medya oturumu oluşturmalı ve oynatma başladığında bunu yayınlamalıdır artık kontrol edilemez. Örneğin, uygulamanız bir video uygulamasıysa Kullanıcı, oynatma etkinliğinden çıktığında oturumu serbest bırakmalı "geri"yi seçmek kullanarak veya uygulamayı arka planda kullanarak gerçekleştirebilirsiniz. Eğer uygulamanız bir müzik uygulamasıysa, artık hiçbir müzik çalmadığında bunu yayınlamanız gerekir medya
Oturum durumu güncelleniyor
Medya oturumunuzdaki veriler, projenizin durumuna göre güncel tutulmalıdır. oynatıcıya gitmiş olur. Örneğin, oynatma duraklatıldığında oynatma işlemini güncellemeniz gerekir. ve desteklenen işlemleri görebilirsiniz. Aşağıdaki tablolarda, satın alma işlemi için siz sorumlusunuz.
MediaMetadataCompat
Meta Veri Alanı | Açıklama |
---|---|
METADATA_KEY_TITLE (gerekli) | Medya başlığı. |
METADATA_KEY_DISPLAY_SUBTITLE | Alt başlık. |
METADATA_KEY_DISPLAY_ICON_URI | Simge URL'si. |
METADATA_KEY_DURATION (gerekli) | Medya süresi. |
METADATA_KEY_MEDIA_URI | Content ID. |
METADATA_KEY_ARTIST | Sanatçı. |
METADATA_KEY_ALBUM | Albüm. |
PlaybackStateCompat
Gerekli Yöntem | Açıklama |
---|---|
setActions() | Desteklenen medya komutlarını ayarlar. |
setState() | Oynatma durumunu ve geçerli konumu ayarlayın. |
MediaSessionCompat
Gerekli Yöntem | Açıklama |
---|---|
setRepeatMode() | Tekrarlama modunu ayarlar. |
setShuffleMode() | Karıştırma modunu ayarlar. |
setMetadata() | Medya meta verilerini ayarlar. |
setPlaybackState() | Oynatma durumunu ayarlar. |
private fun updateMediaSession() { val metadata = MediaMetadataCompat.Builder() .putString(MediaMetadataCompat.METADATA_KEY_TITLE, "title") .putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_SUBTITLE, "subtitle") .putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON_URI, mMovie.getCardImageUrl()) .build() val playbackState = PlaybackStateCompat.Builder() .setState( PlaybackStateCompat.STATE_PLAYING, player.getPosition(), player.getPlaybackSpeed(), System.currentTimeMillis() ) .build() mediaSession.setMetadata(metadata) mediaSession.setPlaybackState(playbackState) }
private void updateMediaSession() { MediaMetadataCompat metadata = new MediaMetadataCompat.Builder() .putString(MediaMetadataCompat.METADATA_KEY_TITLE, "title") .putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_SUBTITLE, "subtitle") .putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON_URI,mMovie.getCardImageUrl()) .build(); PlaybackStateCompat playbackState = new PlaybackStateCompat.Builder() .setState( PlaybackStateCompat.STATE_PLAYING, player.getPosition(), player.getPlaybackSpeed(), System.currentTimeMillis()) .build(); mediaSession.setMetadata(metadata); mediaSession.setPlaybackState(playbackState); }
Aktarım kontrolünü işleme
Uygulamanızda medya oturumu aktarım kontrolü geri çağırması uygulanmalıdır. İlgili içeriği oluşturmak için kullanılan Aşağıdaki tabloda, işlemeleri gereken aktarım denetimi işlemleri gösterilmektedir:
MediaSessionCompat.Callback
İşlemler | Açıklama |
---|---|
onPlay() | Devam ettir |
onPause() | Duraklat |
onSeekTo() | Bir konuma sar |
onStop() | Geçerli medyayı durdur |
class MyMediaSessionCallback : MediaSessionCompat.Callback() { override fun onPause() { // Pause the player and update the play state. ... } override fun onPlay() { // Resume the player and update the play state. ... } override fun onSeekTo (long pos) { // Seek and update the play state. ... } ... } mediaSession.setCallback( MyMediaSessionCallback() );
public MyMediaSessionCallback extends MediaSessionCompat.Callback { public void onPause() { // Pause the player and update the play state. ... } public void onPlay() { // Resume the player and update the play state. ... } public void onSeekTo (long pos) { // Seek and update the play state. ... } ... } mediaSession.setCallback(new MyMediaSessionCallback());
Cast desteğini yapılandırma
Gönderen uygulama tarafından başlatma isteği gönderildiğinde amaç oluşturulur.
ile başlar. Bunun işlenmesinden uygulamanız sorumludur
ve bunun bir örneğini oluşturmak,
CastReceiverContext
nesne olarak tanımlar. CastReceiverContext
nesnesi gerekiyor
TV uygulaması çalışırken Cast ile etkileşimde bulunun. Bu nesne, TV'nizin
uygulamasının bağlı gönderenlerden gelen Cast medya mesajlarını kabul etmesi gerekir.
Android TV kurulumu
Başlatma amacı filtresi ekleme
Lansmanı gerçekleştirmek istediğiniz etkinliğe yeni bir intent filtresi ekleyin. Intent'i tıklayın:
<activity android:name="com.example.activity">
<intent-filter>
<action android:name="com.google.android.gms.cast.tv.action.LAUNCH" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
Alıcı seçenekleri sağlayıcısını belirtin
Şunu uygulamanız gerekiyor:
ReceiverOptionsProvider
sağlamak için
CastReceiverOptions
:
class MyReceiverOptionsProvider : ReceiverOptionsProvider { override fun getOptions(context: Context?): CastReceiverOptions { return CastReceiverOptions.Builder(context) .setStatusText("My App") .build() } }
public class MyReceiverOptionsProvider implements ReceiverOptionsProvider { @Override public CastReceiverOptions getOptions(Context context) { return new CastReceiverOptions.Builder(context) .setStatusText("My App") .build(); } }
Ardından, AndroidManifest
sayfanızda seçenek sağlayıcıyı belirtin:
<meta-data
android:name="com.google.android.gms.cast.tv.RECEIVER_OPTIONS_PROVIDER_CLASS_NAME"
android:value="com.example.mysimpleatvapplication.MyReceiverOptionsProvider" />
ReceiverOptionsProvider
, aşağıdaki durumlarda CastReceiverOptions
için kullanılır:
CastReceiverContext
başlatıldı.
Yayın alıcı bağlamı
İlk kullanıma hazırla
CastReceiverContext
Uygulamanız oluşturulduğunda:
override fun onCreate() { CastReceiverContext.initInstance(this) ... }
@Override public void onCreate() { CastReceiverContext.initInstance(this); ... }
Uygulamanız ön plana geçtiğinde CastReceiverContext
modunu başlatın:
CastReceiverContext.getInstance().start()
CastReceiverContext.getInstance().start();
Telefonla arama
stop()
uygulamasında
CastReceiverContext
pek çok destekleyici olmayan video uygulamaları veya uygulamalar için arka plana çıktıktan sonra
arka planda oynatma:
// Player has stopped. CastReceiverContext.getInstance().stop()
// Player has stopped. CastReceiverContext.getInstance().stop();
Ayrıca, uygulamanız arka planda oynatmayı destekliyorsa stop()
numaralı telefonu arayın.
arka planda oynatma durduğunda CastReceiverContext
adlı cihazda.
androidx.lifecycle
aramaları yönetmek için kitaplık
CastReceiverContext.start()
ve
CastReceiverContext.stop()
özellikle de yerel uygulamanızın birden fazla etkinliği varsa. Bu, ırkı önler
farklı etkinliklerden start()
ve stop()
aradığınızda çeşitli koşullar.
// Create a LifecycleObserver class. class MyLifecycleObserver : DefaultLifecycleObserver { override fun onStart(owner: LifecycleOwner) { // App prepares to enter foreground. CastReceiverContext.getInstance().start() } override fun onStop(owner: LifecycleOwner) { // App has moved to the background or has terminated. CastReceiverContext.getInstance().stop() } } // Add the observer when your application is being created. class MyApplication : Application() { fun onCreate() { super.onCreate() // Initialize CastReceiverContext. CastReceiverContext.initInstance(this /* android.content.Context */) // Register LifecycleObserver ProcessLifecycleOwner.get().lifecycle.addObserver( MyLifecycleObserver()) } }
// Create a LifecycleObserver class. public class MyLifecycleObserver implements DefaultLifecycleObserver { @Override public void onStart(LifecycleOwner owner) { // App prepares to enter foreground. CastReceiverContext.getInstance().start(); } @Override public void onStop(LifecycleOwner owner) { // App has moved to the background or has terminated. CastReceiverContext.getInstance().stop(); } } // Add the observer when your application is being created. public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); // Initialize CastReceiverContext. CastReceiverContext.initInstance(this /* android.content.Context */); // Register LifecycleObserver ProcessLifecycleOwner.get().getLifecycle().addObserver( new MyLifecycleObserver()); } }
// In AndroidManifest.xml set MyApplication as the application class
<application
...
android:name=".MyApplication">
MediaSession'ı MediaManager'a Bağlama
Bir
MediaSession
mevcut MediaSession
jetonunu da
CastReceiverContext
böylece komutları nereye göndereceğini ve medya oynatma durumunu alabileceğini bilir:
val mediaManager: MediaManager = receiverContext.getMediaManager() mediaManager.setSessionCompatToken(currentMediaSession.getSessionToken())
MediaManager mediaManager = receiverContext.getMediaManager(); mediaManager.setSessionCompatToken(currentMediaSession.getSessionToken());
Etkin olmayan oynatma nedeniyle MediaSession
cihazınızı serbest bıraktığınızda bir
boş jeton açık
MediaManager
:
myPlayer.stop() mediaSession.release() mediaManager.setSessionCompatToken(null)
myPlayer.stop(); mediaSession.release(); mediaManager.setSessionCompatToken(null);
Uygulamanız arka plandayken medya oynatmayı destekliyorsa
arama
CastReceiverContext.stop()
arka plana gönderildiğinde çağrıyı yalnızca uygulamanız arka plana
arka planda ve artık medya oynatmıyor. Örneğin:
class MyLifecycleObserver : DefaultLifecycleObserver { ... // App has moved to the background. override fun onPause(owner: LifecycleOwner) { mIsBackground = true myStopCastReceiverContextIfNeeded() } } // Stop playback on the player. private fun myStopPlayback() { myPlayer.stop() myStopCastReceiverContextIfNeeded() } // Stop the CastReceiverContext when both the player has // stopped and the app has moved to the background. private fun myStopCastReceiverContextIfNeeded() { if (mIsBackground && myPlayer.isStopped()) { CastReceiverContext.getInstance().stop() } }
public class MyLifecycleObserver implements DefaultLifecycleObserver { ... // App has moved to the background. @Override public void onPause(LifecycleOwner owner) { mIsBackground = true; myStopCastReceiverContextIfNeeded(); } } // Stop playback on the player. private void myStopPlayback() { myPlayer.stop(); myStopCastReceiverContextIfNeeded(); } // Stop the CastReceiverContext when both the player has // stopped and the app has moved to the background. private void myStopCastReceiverContextIfNeeded() { if (mIsBackground && myPlayer.isStopped()) { CastReceiverContext.getInstance().stop(); } }
Exoplayer'ı Cast Connect ile kullanma
Şunu kullanıyorsanız:
Exoplayer
kullanıyorsanız,
MediaSessionConnector
oturumun ve tüm ilgili bilgilerin (ör.
oynatma durumunu kontrol edebilirsiniz.
MediaSessionConnector.MediaButtonEventHandler
,
setMediaButtonEventHandler(MediaButtonEventHandler)
Bunlar aksi takdirde
MediaSessionCompat.Callback
varsayılan olarak.
Entegrasyon için
MediaSessionConnector
Uygulamanızda, aşağıdaki bilgileri oyuncu etkinliği sınıfınıza veya bulunduğunuz herhangi bir yere ekleyin
medya oturumunuzu yönetin:
class PlayerActivity : Activity() { private var mMediaSession: MediaSessionCompat? = null private var mMediaSessionConnector: MediaSessionConnector? = null private var mMediaManager: MediaManager? = null override fun onCreate(savedInstanceState: Bundle?) { ... mMediaSession = MediaSessionCompat(this, LOG_TAG) mMediaSessionConnector = MediaSessionConnector(mMediaSession!!) ... } override fun onStart() { ... mMediaManager = receiverContext.getMediaManager() mMediaManager!!.setSessionCompatToken(currentMediaSession.getSessionToken()) mMediaSessionConnector!!.setPlayer(mExoPlayer) mMediaSessionConnector!!.setMediaMetadataProvider(mMediaMetadataProvider) mMediaSession!!.isActive = true ... } override fun onStop() { ... mMediaSessionConnector!!.setPlayer(null) mMediaSession!!.release() mMediaManager!!.setSessionCompatToken(null) ... } }
public class PlayerActivity extends Activity { private MediaSessionCompat mMediaSession; private MediaSessionConnector mMediaSessionConnector; private MediaManager mMediaManager; @Override protected void onCreate(Bundle savedInstanceState) { ... mMediaSession = new MediaSessionCompat(this, LOG_TAG); mMediaSessionConnector = new MediaSessionConnector(mMediaSession); ... } @Override protected void onStart() { ... mMediaManager = receiverContext.getMediaManager(); mMediaManager.setSessionCompatToken(currentMediaSession.getSessionToken()); mMediaSessionConnector.setPlayer(mExoPlayer); mMediaSessionConnector.setMediaMetadataProvider(mMediaMetadataProvider); mMediaSession.setActive(true); ... } @Override protected void onStop() { ... mMediaSessionConnector.setPlayer(null); mMediaSession.release(); mMediaManager.setSessionCompatToken(null); ... } }
Gönderen uygulamasının kurulumu
Cast Connect desteğini etkinleştir
Gönderen uygulamanızı Cast Connect desteğiyle güncelledikten sonra beyan için
ne kadar hazır olduğunu
belirleyerek
androidReceiverCompatible
bayrak açık
LaunchOptions
"doğru" olarak ayarlayın.
play-services-cast-framework
sürümü gerektirir
19.0.0
veya üzeri.
androidReceiverCompatible
işareti şurada ayarlandı:
LaunchOptions
(CastOptions
'nın bir parçasıdır):
class CastOptionsProvider : OptionsProvider { override fun getCastOptions(context: Context?): CastOptions { val launchOptions: LaunchOptions = Builder() .setAndroidReceiverCompatible(true) .build() return CastOptions.Builder() .setLaunchOptions(launchOptions) ... .build() } }
public class CastOptionsProvider implements OptionsProvider { @Override public CastOptions getCastOptions(Context context) { LaunchOptions launchOptions = new LaunchOptions.Builder() .setAndroidReceiverCompatible(true) .build(); return new CastOptions.Builder() .setLaunchOptions(launchOptions) ... .build(); } }
google-cast-sdk
v4.4.8
veya
daha yüksek.
androidReceiverCompatible
işareti şurada ayarlandı:
GCKLaunchOptions
GCKCastOptions
):
let options = GCKCastOptions(discoveryCriteria: GCKDiscoveryCriteria(applicationID: kReceiverAppID)) ... let launchOptions = GCKLaunchOptions() launchOptions.androidReceiverCompatible = true options.launchOptions = launchOptions GCKCastContext.setSharedInstanceWith(options).
Chromium tarayıcı sürümü gerekir
M87
veya üzeri.
const context = cast.framework.CastContext.getInstance(); const castOptions = new cast.framework.CastOptions(); castOptions.receiverApplicationId = kReceiverAppID; castOptions.androidReceiverCompatible = true; context.setOptions(castOptions);
Cast Developer Console kurulumu
Android TV uygulamasını yapılandırma
Android TV uygulamanızın paket adını şuraya ekleyin: Google Play Geliştirici Konsolu'nu yayınlama kullanarak bunu Cast Uygulaması Kimliğinizle ilişkilendirin.
Geliştirici cihazlarını kaydedin
Kullanacağınız Android TV cihazının seri numarasını kaydedin ve Arkadaş Bitkiler Projesi’nde Cast Developer Console.
Kayıt olmadan Cast Connect yalnızca Güvenlik nedeniyle Google Play Store.
Yayın için yayın veya Android TV cihazı kaydettirme hakkında daha fazla bilgi için kayıt sayfasına bakın.
Medya yükleniyor
Android TV uygulamanızda derin bağlantı desteğini zaten uyguladıysanız Android TV manifestinizde benzer bir tanımınız olmalıdır:
<activity android:name="com.example.activity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="https"/>
<data android:host="www.example.com"/>
<data android:pathPattern=".*"/>
</intent-filter>
</activity>
Gönderendeki varlığa göre yükle
Gönderenlerde, medyadaki entity
değerini ayarlayarak derin bağlantıyı iletebilirsiniz.
yükleme isteği hakkındaki bilgiler:
val mediaToLoad = MediaInfo.Builder("some-id") .setEntity("https://example.com/watch/some-id") ... .build() val loadRequest = MediaLoadRequestData.Builder() .setMediaInfo(mediaToLoad) .setCredentials("user-credentials") ... .build() remoteMediaClient.load(loadRequest)
MediaInfo mediaToLoad = new MediaInfo.Builder("some-id") .setEntity("https://example.com/watch/some-id") ... .build(); MediaLoadRequestData loadRequest = new MediaLoadRequestData.Builder() .setMediaInfo(mediaToLoad) .setCredentials("user-credentials") ... .build(); remoteMediaClient.load(loadRequest);
let mediaInfoBuilder = GCKMediaInformationBuilder(entity: "https://example.com/watch/some-id") ... mediaInformation = mediaInfoBuilder.build() let mediaLoadRequestDataBuilder = GCKMediaLoadRequestDataBuilder() mediaLoadRequestDataBuilder.mediaInformation = mediaInformation mediaLoadRequestDataBuilder.credentials = "user-credentials" ... let mediaLoadRequestData = mediaLoadRequestDataBuilder.build() remoteMediaClient?.loadMedia(with: mediaLoadRequestData)
Chromium tarayıcı sürümü gerekir
M87
veya üzeri.
let mediaInfo = new chrome.cast.media.MediaInfo('some-id"', 'video/mp4'); mediaInfo.entity = 'https://example.com/watch/some-id'; ... let request = new chrome.cast.media.LoadRequest(mediaInfo); request.credentials = 'user-credentials'; ... cast.framework.CastContext.getInstance().getCurrentSession().loadMedia(request);
Yükleme komutu, derin bağlantınız ve paket adıyla birlikte bir intent aracılığıyla gönderilir geliştirici konsolunda tanımladığınız bir adla kontrol edin.
Gönderende ATV kimlik bilgileri ayarlanıyor
Web Receiver uygulamanız ve Android TV uygulamanız farklı olabilir.
derin bağlantılar ve credentials
(örneğin, kimlik doğrulama ile
iki platformda farklı şekilde). Bu sorunu gidermek için
Android TV için entity
ve credentials
:
val mediaToLoad = MediaInfo.Builder("some-id") .setEntity("https://example.com/watch/some-id") .setAtvEntity("myscheme://example.com/atv/some-id") ... .build() val loadRequest = MediaLoadRequestData.Builder() .setMediaInfo(mediaToLoad) .setCredentials("user-credentials") .setAtvCredentials("atv-user-credentials") ... .build() remoteMediaClient.load(loadRequest)
MediaInfo mediaToLoad = new MediaInfo.Builder("some-id") .setEntity("https://example.com/watch/some-id") .setAtvEntity("myscheme://example.com/atv/some-id") ... .build(); MediaLoadRequestData loadRequest = new MediaLoadRequestData.Builder() .setMediaInfo(mediaToLoad) .setCredentials("user-credentials") .setAtvCredentials("atv-user-credentials") ... .build(); remoteMediaClient.load(loadRequest);
let mediaInfoBuilder = GCKMediaInformationBuilder(entity: "https://example.com/watch/some-id") mediaInfoBuilder.atvEntity = "myscheme://example.com/atv/some-id" ... mediaInformation = mediaInfoBuilder.build() let mediaLoadRequestDataBuilder = GCKMediaLoadRequestDataBuilder() mediaLoadRequestDataBuilder.mediaInformation = mediaInformation mediaLoadRequestDataBuilder.credentials = "user-credentials" mediaLoadRequestDataBuilder.atvCredentials = "atv-user-credentials" ... let mediaLoadRequestData = mediaLoadRequestDataBuilder.build() remoteMediaClient?.loadMedia(with: mediaLoadRequestData)
Chromium tarayıcı sürümü gerekir
M87
veya üzeri.
let mediaInfo = new chrome.cast.media.MediaInfo('some-id"', 'video/mp4'); mediaInfo.entity = 'https://example.com/watch/some-id'; mediaInfo.atvEntity = 'myscheme://example.com/atv/some-id'; ... let request = new chrome.cast.media.LoadRequest(mediaInfo); request.credentials = 'user-credentials'; request.atvCredentials = 'atv-user-credentials'; ... cast.framework.CastContext.getInstance().getCurrentSession().loadMedia(request);
Web Receiver uygulaması başlatıldığında entity
ve credentials
kullanır.
yükleme isteği. Ancak Android TV uygulamanız başlatılırsa SDK,
atvEntity
ve atvCredentials
ile entity
ve credentials
(belirtilmişse).
Content ID veya MediaQueueData ile yükleme
entity
veya atvEntity
kullanmıyorsanız ve Content ID ya da
Medya Bilgilerinizdeki içeriğin URL'si veya daha ayrıntılı Medya Yüklemesini kullanın
"İstek Verileri"ni kullanıyorsanız aşağıdaki önceden tanımlanmış intent filtresini
Android TV uygulamanız:
<activity android:name="com.example.activity">
<intent-filter>
<action android:name="com.google.android.gms.cast.tv.action.LOAD"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
Gönderen tarafında, varlığa göre yüklemeye benzer şekilde,
içerik bilgilerinizi içeren bir yükleme isteği oluşturabilir ve load()
numaralı telefonu arayabilir.
val mediaToLoad = MediaInfo.Builder("some-id").build() val loadRequest = MediaLoadRequestData.Builder() .setMediaInfo(mediaToLoad) .setCredentials("user-credentials") ... .build() remoteMediaClient.load(loadRequest)
MediaInfo mediaToLoad = new MediaInfo.Builder("some-id").build(); MediaLoadRequestData loadRequest = new MediaLoadRequestData.Builder() .setMediaInfo(mediaToLoad) .setCredentials("user-credentials") ... .build(); remoteMediaClient.load(loadRequest);
let mediaInfoBuilder = GCKMediaInformationBuilder(contentId: "some-id") ... mediaInformation = mediaInfoBuilder.build() let mediaLoadRequestDataBuilder = GCKMediaLoadRequestDataBuilder() mediaLoadRequestDataBuilder.mediaInformation = mediaInformation mediaLoadRequestDataBuilder.credentials = "user-credentials" ... let mediaLoadRequestData = mediaLoadRequestDataBuilder.build() remoteMediaClient?.loadMedia(with: mediaLoadRequestData)
Chromium tarayıcı sürümü gerekir
M87
veya üzeri.
let mediaInfo = new chrome.cast.media.MediaInfo('some-id"', 'video/mp4'); ... let request = new chrome.cast.media.LoadRequest(mediaInfo); ... cast.framework.CastContext.getInstance().getCurrentSession().loadMedia(request);
Yükleme isteklerini işleme
Etkinliğinizde, bu yükleme isteklerini işlemek için intent'leri işlemeniz gerekir geri aramalarınızda şunları yapabilirsiniz:
class MyActivity : Activity() { override fun onStart() { super.onStart() val mediaManager = CastReceiverContext.getInstance().getMediaManager() // Pass the intent to the SDK. You can also do this in onCreate(). if (mediaManager.onNewIntent(intent)) { // If the SDK recognizes the intent, you should early return. return } // If the SDK doesn't recognize the intent, you can handle the intent with // your own logic. ... } // For some cases, a new load intent triggers onNewIntent() instead of // onStart(). override fun onNewIntent(intent: Intent) { val mediaManager = CastReceiverContext.getInstance().getMediaManager() // Pass the intent to the SDK. You can also do this in onCreate(). if (mediaManager.onNewIntent(intent)) { // If the SDK recognizes the intent, you should early return. return } // If the SDK doesn't recognize the intent, you can handle the intent with // your own logic. ... } }
public class MyActivity extends Activity { @Override protected void onStart() { super.onStart(); MediaManager mediaManager = CastReceiverContext.getInstance().getMediaManager(); // Pass the intent to the SDK. You can also do this in onCreate(). if (mediaManager.onNewIntent(getIntent())) { // If the SDK recognizes the intent, you should early return. return; } // If the SDK doesn't recognize the intent, you can handle the intent with // your own logic. ... } // For some cases, a new load intent triggers onNewIntent() instead of // onStart(). @Override protected void onNewIntent(Intent intent) { MediaManager mediaManager = CastReceiverContext.getInstance().getMediaManager(); // Pass the intent to the SDK. You can also do this in onCreate(). if (mediaManager.onNewIntent(intent)) { // If the SDK recognizes the intent, you should early return. return; } // If the SDK doesn't recognize the intent, you can handle the intent with // your own logic. ... } }
MediaManager
ise
amacın yükleme amacı olduğunu algıladığında
MediaLoadRequestData
ve çağırmak için
MediaLoadCommandCallback.onLoad()
.
Yükleme isteğini işlemek için bu yöntemi geçersiz kılmanız gerekir. Geri çağırma,
şu tarihten önce kaydedilmiş olmalıdır:
MediaManager.onNewIntent()
adı verilir (bir Etkinlik veya Uygulamada onCreate()
olması önerilir
yöntemini) kullanın.
class MyActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val mediaManager = CastReceiverContext.getInstance().getMediaManager() mediaManager.setMediaLoadCommandCallback(MyMediaLoadCommandCallback()) } } class MyMediaLoadCommandCallback : MediaLoadCommandCallback() { override fun onLoad( senderId: String?, loadRequestData: MediaLoadRequestData ): Task{ return Tasks.call { // Resolve the entity into your data structure and load media. val mediaInfo = loadRequestData.getMediaInfo() if (!checkMediaInfoSupported(mediaInfo)) { // Throw MediaException to indicate load failure. throw MediaException( MediaError.Builder() .setDetailedErrorCode(DetailedErrorCode.LOAD_FAILED) .setReason(MediaError.ERROR_REASON_INVALID_REQUEST) .build() ) } myFillMediaInfo(MediaInfoWriter(mediaInfo)) myPlayerLoad(mediaInfo.getContentUrl()) // Update media metadata and state (this clears all previous status // overrides). castReceiverContext.getMediaManager() .setDataFromLoad(loadRequestData) ... castReceiverContext.getMediaManager().broadcastMediaStatus() // Return the resolved MediaLoadRequestData to indicate load success. return loadRequestData } } private fun myPlayerLoad(contentURL: String) { myPlayer.load(contentURL) // Update the MediaSession state. val playbackState: PlaybackStateCompat = Builder() .setState( player.getState(), player.getPosition(), System.currentTimeMillis() ) ... .build() mediaSession.setPlaybackState(playbackState) }
public class MyActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); MediaManager mediaManager = CastReceiverContext.getInstance().getMediaManager(); mediaManager.setMediaLoadCommandCallback(new MyMediaLoadCommandCallback()); } } public class MyMediaLoadCommandCallback extends MediaLoadCommandCallback { @Override public TaskonLoad(String senderId, MediaLoadRequestData loadRequestData) { return Tasks.call(() -> { // Resolve the entity into your data structure and load media. MediaInfo mediaInfo = loadRequestData.getMediaInfo(); if (!checkMediaInfoSupported(mediaInfo)) { // Throw MediaException to indicate load failure. throw new MediaException( new MediaError.Builder() .setDetailedErrorCode(DetailedErrorCode.LOAD_FAILED) .setReason(MediaError.ERROR_REASON_INVALID_REQUEST) .build()); } myFillMediaInfo(new MediaInfoWriter(mediaInfo)); myPlayerLoad(mediaInfo.getContentUrl()); // Update media metadata and state (this clears all previous status // overrides). castReceiverContext.getMediaManager() .setDataFromLoad(loadRequestData); ... castReceiverContext.getMediaManager().broadcastMediaStatus(); // Return the resolved MediaLoadRequestData to indicate load success. return loadRequestData; }); } private void myPlayerLoad(String contentURL) { myPlayer.load(contentURL); // Update the MediaSession state. PlaybackStateCompat playbackState = new PlaybackStateCompat.Builder() .setState( player.getState(), player.getPosition(), System.currentTimeMillis()) ... .build(); mediaSession.setPlaybackState(playbackState); }
Yükleme amacını işlemek için amacı veri yapılarına ayrıştırabilirsiniz.
tanımladığımız
(MediaLoadRequestData
)
(yükleme istekleri için).
Medya komutlarını destekleme
Temel oynatma kontrolü desteği
Temel entegrasyon komutları, medyayla uyumlu olan komutları içerir kabul edilir. Bu komutlar medya oturumu geri çağırmaları aracılığıyla bildirilir. Şunları yapmanız gerekir: bunu desteklemek için bir medya oturumuna geri çağırma kaydedin (bunu yapıyor zaten).
private class MyMediaSessionCallback : MediaSessionCompat.Callback() { override fun onPause() { // Pause the player and update the play state. myPlayer.pause() } override fun onPlay() { // Resume the player and update the play state. myPlayer.play() } override fun onSeekTo(pos: Long) { // Seek and update the play state. myPlayer.seekTo(pos) } ... } mediaSession.setCallback(MyMediaSessionCallback())
private class MyMediaSessionCallback extends MediaSessionCompat.Callback { @Override public void onPause() { // Pause the player and update the play state. myPlayer.pause(); } @Override public void onPlay() { // Resume the player and update the play state. myPlayer.play(); } @Override public void onSeekTo(long pos) { // Seek and update the play state. myPlayer.seekTo(pos); } ... } mediaSession.setCallback(new MyMediaSessionCallback());
Yayın kontrolü komutlarını destekleme
Şurada kullanılamayan bazı Yayınlama komutları var:
MediaSession
örneğin:
skipAd()
veya
setActiveMediaTracks()
.
Ayrıca, yayın sırası
MediaSession
sırası ile tam olarak uyumlu değil.
class MyMediaCommandCallback : MediaCommandCallback() { override fun onSkipAd(requestData: RequestData?): Task{ // Skip your ad ... return Tasks.forResult(null) } } val mediaManager = CastReceiverContext.getInstance().getMediaManager() mediaManager.setMediaCommandCallback(MyMediaCommandCallback())
public class MyMediaCommandCallback extends MediaCommandCallback { @Override public TaskonSkipAd(RequestData requestData) { // Skip your ad ... return Tasks.forResult(null); } } MediaManager mediaManager = CastReceiverContext.getInstance().getMediaManager(); mediaManager.setMediaCommandCallback(new MyMediaCommandCallback());
Desteklenen medya komutlarını belirtme
Yayın alıcınızda olduğu gibi, Android TV uygulamanız hangi komutları belirtmelidir?
desteklenir. Böylece, gönderenler belirli kullanıcı arayüzü denetimlerini etkinleştirebilir veya devre dışı bırakabilir. Örneğin,
komut satırının
MediaSession
komut satırındaki
PlaybackStateCompat
.
Ek komutlar
MediaStatusModifier
.
// Set media session supported commands val playbackState: PlaybackStateCompat = PlaybackStateCompat.Builder() .setActions(PlaybackStateCompat.ACTION_PLAY or PlaybackStateCompat.ACTION_PAUSE) .setState(PlaybackStateCompat.STATE_PLAYING) .build() mediaSession.setPlaybackState(playbackState) // Set additional commands in MediaStatusModifier val mediaManager = CastReceiverContext.getInstance().getMediaManager() mediaManager.getMediaStatusModifier() .setMediaCommandSupported(MediaStatus.COMMAND_QUEUE_NEXT)
// Set media session supported commands PlaybackStateCompat playbackState = new PlaybackStateCompat.Builder() .setActions(PlaybackStateCompat.ACTION_PLAY | PlaybackStateCompat.ACTION_PAUSE) .setState(PlaybackStateCompat.STATE_PLAYING) .build(); mediaSession.setPlaybackState(playbackState); // Set additional commands in MediaStatusModifier MediaManager mediaManager = CastReceiverContext.getInstance().getMediaManager(); mediaManager.getMediaStatusModifier() .setMediaCommandSupported(MediaStatus.COMMAND_QUEUE_NEXT);
Desteklenmeyen düğmeleri gizle
Android TV uygulamanız yalnızca temel medya kontrolünü destekliyorsa, ancak Web Alıcınız uygulamanız daha gelişmiş denetimleri destekliyorsa gönderen uygulamanızın doğru çalıştığından emin olun. Örneğin, Android TV'niz uygulamanız, Web Alıcı uygulamanız destekliyorsa oynatma hızını değiştirmeyi desteklemiyorsa desteklenen işlemleri her platformda doğru şekilde ayarlamalı gönderen uygulamanız kullanıcı arayüzünü düzgün şekilde oluşturur.
MediaStatus değiştiriliyor
Parça, reklam, canlı yayın ve sıraya alma gibi gelişmiş özellikleri desteklemek için
TV uygulamasının,
MediaSession
.
Google tarafından sağlanan
MediaStatusModifier
bir kurs hazırladık. MediaStatusModifier
her zaman
Ayarladığınız MediaSession
CastReceiverContext
.
Oluşturmak ve yayınlamak için
MediaStatus
:
val mediaManager: MediaManager = castReceiverContext.getMediaManager() val statusModifier: MediaStatusModifier = mediaManager.getMediaStatusModifier() statusModifier .setLiveSeekableRange(seekableRange) .setAdBreakStatus(adBreakStatus) .setCustomData(customData) mediaManager.broadcastMediaStatus()
MediaManager mediaManager = castReceiverContext.getMediaManager(); MediaStatusModifier statusModifier = mediaManager.getMediaStatusModifier(); statusModifier .setLiveSeekableRange(seekableRange) .setAdBreakStatus(adBreakStatus) .setCustomData(customData); mediaManager.broadcastMediaStatus();
İstemci kitaplığımız MediaSession
adlı sağlayıcıdan temel MediaStatus
, sizin
Android TV uygulaması,
MediaStatus
değiştiricisi.
Bazı durumlar ve meta veriler hem MediaSession
içinde hem de içinde ayarlanabilir.
MediaStatusModifier
. Bunları kesinlikle yalnızca
MediaSession
. Yine de
MediaSession
: Değiştiricideki durum her zaman olduğu için bu işlem önerilmez
MediaSession
tarafından sağlanan değerlere göre daha yüksek önceliğe sahip.
Göndermeden önce MediaStatus'a müdahale etme
Web Buyer SDK'sı ile aynı şekilde. Web Buyer SDK'sı ile aynı şekilde,
bir iletişim planı (ör.
MediaStatusInterceptor
iş akışını
MediaStatus
-
gönderilir. Bir
MediaStatusWriter
MediaStatus
öğesini göndermeden önce manipüle edin.
mediaManager.setMediaStatusInterceptor(object : MediaStatusInterceptor { override fun intercept(mediaStatusWriter: MediaStatusWriter) { // Perform customization. mediaStatusWriter.setCustomData(JSONObject("{data: \"my Hello\"}")) } })
mediaManager.setMediaStatusInterceptor(new MediaStatusInterceptor() { @Override public void intercept(MediaStatusWriter mediaStatusWriter) { // Perform customization. mediaStatusWriter.setCustomData(new JSONObject("{data: \"my Hello\"}")); } });
Kullanıcı kimlik bilgilerini işleme
Android TV uygulamanız yalnızca belirli kullanıcıların uygulamayı başlatmasına veya katılmasına izin veriyor olabilir kabul edilir. Örneğin, gönderenin yalnızca aşağıdaki durumlarda başlatılmasına veya katılmasına izin verin:
- Gönderen uygulama, ATV uygulamasıyla aynı hesaba ve profile giriş yapar.
- Gönderen uygulama, ATV uygulamasıyla aynı hesaba ancak farklı profile giriş yapmış.
Uygulamanız birden fazla veya anonim kullanıcıyı işleyebiliyorsa, kullanıcısının ATV oturumuna katılmasını sağlayın. Kullanıcı kimlik bilgisi sağlarsa ATV uygulamanız kullanıcı verilerinin sorunsuz bir şekilde iyi bir şekilde izlenmesini sağlar.
Gönderen uygulamanız Android TV uygulamanızı başlattığında veya uygulamanıza katıldığında gönderen uygulamanız oturuma kimlerin katıldığını temsil eden kimlik bilgilerini sağlamalıdır.
Gönderen, Android TV uygulamanızı başlatıp ona katılmadan önce aşağıdakileri belirtebilirsiniz: ve gönderen kimlik bilgilerine izin verilip verilmediğini görmek için denetleyiciyi başlatın. Değilse Cast Connect SDK, Web Alıcınızı başlatmaya geri döner.
Gönderen uygulama başlatma kimlik bilgileri ile ilgili veriler
Gönderen tarafında, alan adının kimin tarafından temsil edildiğini CredentialsData
belirtebilirsiniz.
oturuma katılıyorsunuz.
credentials
, ATV'niz bağlı olduğu sürece kullanıcı tarafından tanımlanabilecek bir dizedir.
anlayabilir. credentialsType
,
CredentialsData
özel bir değerden geliyor veya özel bir değer olabilir. Varsayılan olarak,
verinin gönderildiği platforma göre de ayarlayabilirsiniz.
CredentialsData
, Android TV uygulamanıza yalnızca lansman sırasında aktarılır.
katılma zamanı. İnternete bağlıyken tekrar ayarlarsanız bu ayar
Android TV uygulamanız. Gönderen kişi bağlıyken profili değiştirirse
veya telefonla arama yapabilir
SessionManager.endCurrentCastSession(boolean stopCasting)
yeni profilin oturumla uyumlu olmadığını düşünüyorsanız yeni profil oluşturabilirsiniz.
İlgili içeriği oluşturmak için kullanılan
CredentialsData
her gönderen için şu komut kullanılır:
getSenders
uygulamasında
CastReceiverContext
SenderInfo
almak için
getCastLaunchRequest()
almak için
CastLaunchRequest
,
ve ardından
getCredentialsData()
play-services-cast-framework
sürümü gerektirir
19.0.0
veya üzeri.
CastContext.getSharedInstance().setLaunchCredentialsData( CredentialsData.Builder() .setCredentials("{\"userId\": \"abc\"}") .build() )
CastContext.getSharedInstance().setLaunchCredentialsData( new CredentialsData.Builder() .setCredentials("{\"userId\": \"abc\"}") .build());
google-cast-sdk
v4.8.3
veya
daha yüksek.
Seçenekler ayarlandıktan sonra herhangi bir zamanda çağrılabilir:
GCKCastContext.setSharedInstanceWith(options)
GCKCastContext.sharedInstance().setLaunch( GCKCredentialsData(credentials: "{\"userId\": \"abc\"}").
Chromium tarayıcı sürümü gerekir
M87
veya üzeri.
Seçenekler ayarlandıktan sonra herhangi bir zamanda çağrılabilir:
cast.framework.CastContext.getInstance().setOptions(options);
let credentialsData = new chrome.cast.CredentialsData("{\"userId\": \"abc\"}"); cast.framework.CastContext.getInstance().setLaunchCredentialsData(credentialsData);
ATV lansman isteği denetleyiciyi uygulama
İlgili içeriği oluşturmak için kullanılan
CredentialsData
Bir gönderen başlatmaya veya katılmaya çalıştığında Android TV uygulamanıza aktarılır. Şunları yapabilirsiniz:
bir
LaunchRequestChecker
.
seçeneğini tıklayın.
Bir istek reddedilirse başlatılması yerine Web Alıcısı yüklenir. yerel olarak ATV uygulamasına ekleyebileceksiniz. ATV'niz şu anda Kullanıcı başlatma veya katılma isteğinde bulunan kullanıcıya işlem yapacaktır. Örnek olarak farklı bir Kullanıcı ATV uygulamasına istekte olduğundan daha fazla giriş yapmıştır ve uygulamanız, veya giriş yapmış bir kullanıcı olmaması gibi ATV uygulaması.
Bir isteğe izin verilirse ATV uygulaması başlatılır. Bunu özelleştirebilirsiniz
kullanıcı aşağıdaki işlemleri gerçekleştirdiğinde uygulamanızın yükleme isteği göndermeyi destekleyip desteklemediğine bağlı olarak
ATV uygulamasına giriş yapmamıştır veya kullanıcı uyuşmazlığı varsa. Bu davranış,
LaunchRequestChecker
içinde tamamen özelleştirilebilir.
Şunu uygulayan bir sınıf oluşturun:
CastReceiverOptions.LaunchRequestChecker
arayüz:
class MyLaunchRequestChecker : LaunchRequestChecker { override fun checkLaunchRequestSupported(launchRequest: CastLaunchRequest): Task{ return Tasks.call { myCheckLaunchRequest( launchRequest ) } } } private fun myCheckLaunchRequest(launchRequest: CastLaunchRequest): Boolean { val credentialsData = launchRequest.getCredentialsData() ?: return false // or true if you allow anonymous users to join. // The request comes from a mobile device, e.g. checking user match. return if (credentialsData.credentialsType == CredentialsData.CREDENTIALS_TYPE_ANDROID) { myCheckMobileCredentialsAllowed(credentialsData.getCredentials()) } else false // Unrecognized credentials type. }
public class MyLaunchRequestChecker implements CastReceiverOptions.LaunchRequestChecker { @Override public TaskcheckLaunchRequestSupported(CastLaunchRequest launchRequest) { return Tasks.call(() -> myCheckLaunchRequest(launchRequest)); } } private boolean myCheckLaunchRequest(CastLaunchRequest launchRequest) { CredentialsData credentialsData = launchRequest.getCredentialsData(); if (credentialsData == null) { return false; // or true if you allow anonymous users to join. } // The request comes from a mobile device, e.g. checking user match. if (credentialsData.getCredentialsType().equals(CredentialsData.CREDENTIALS_TYPE_ANDROID)) { return myCheckMobileCredentialsAllowed(credentialsData.getCredentials()); } // Unrecognized credentials type. return false; }
Ardından,
ReceiverOptionsProvider
:
class MyReceiverOptionsProvider : ReceiverOptionsProvider { override fun getOptions(context: Context?): CastReceiverOptions { return CastReceiverOptions.Builder(context) ... .setLaunchRequestChecker(MyLaunchRequestChecker()) .build() } }
public class MyReceiverOptionsProvider implements ReceiverOptionsProvider { @Override public CastReceiverOptions getOptions(Context context) { return new CastReceiverOptions.Builder(context) ... .setLaunchRequestChecker(new MyLaunchRequestChecker()) .build(); } }
Şuradaki true
çözümleniyor:
LaunchRequestChecker
ATV uygulamasını, false
ise Web Alıcı uygulamanızı başlatır.
ve gönderiliyor Özel Mesajlar Alma
Cast protokolü, gönderenler ve diğer kanallar arasında özel dize mesajları göndermenize olanak tanır.
alıcı başvurunuz. Gönderebilmek için bir ad alanı (kanal) kaydetmeniz gerekir.
başlatma işleminden önce
CastReceiverContext
.
Android TV - Özel Ad Alanı Belirtin
Desteklenen ad alanlarınızı
CastReceiverOptions
kurulum sırasında:
class MyReceiverOptionsProvider : ReceiverOptionsProvider { override fun getOptions(context: Context?): CastReceiverOptions { return CastReceiverOptions.Builder(context) .setCustomNamespaces( Arrays.asList("urn:x-cast:com.example.cast.mynamespace") ) .build() } }
public class MyReceiverOptionsProvider implements ReceiverOptionsProvider { @Override public CastReceiverOptions getOptions(Context context) { return new CastReceiverOptions.Builder(context) .setCustomNamespaces( Arrays.asList("urn:x-cast:com.example.cast.mynamespace")) .build(); } }
Android TV - Mesajlar Gönderiliyor
// If senderId is null, then the message is broadcasted to all senders. CastReceiverContext.getInstance().sendMessage( "urn:x-cast:com.example.cast.mynamespace", senderId, customString)
// If senderId is null, then the message is broadcasted to all senders. CastReceiverContext.getInstance().sendMessage( "urn:x-cast:com.example.cast.mynamespace", senderId, customString);
Android TV: Özel Ad Alanı Mesajları Alma
class MyCustomMessageListener : MessageReceivedListener { override fun onMessageReceived( namespace: String, senderId: String?, message: String ) { ... } } CastReceiverContext.getInstance().setMessageReceivedListener( "urn:x-cast:com.example.cast.mynamespace", new MyCustomMessageListener());
class MyCustomMessageListener implements CastReceiverContext.MessageReceivedListener { @Override public void onMessageReceived( String namespace, String senderId, String message) { ... } } CastReceiverContext.getInstance().setMessageReceivedListener( "urn:x-cast:com.example.cast.mynamespace", new MyCustomMessageListener());