1. Genel Bakış

Bu codelab'de, mevcut bir Android video uygulamasını Google Cast uyumlu bir cihazda içerik yayınlayacak şekilde nasıl değiştireceğiniz açıklanmaktadır.
Google Cast nedir?
Google Cast, kullanıcıların mobil cihazdaki içerikleri TV'ye yayınlamasına olanak tanır. Kullanıcılar daha sonra mobil cihazlarını TV'de medya oynatma için uzaktan kumanda olarak kullanabilir.
Google Cast SDK, uygulamanızı genişleterek TV'yi veya ses sistemini kontrol etmenizi sağlar. Cast SDK, Google Cast Tasarım Kontrol Listesi'ne göre gerekli kullanıcı arayüzü bileşenlerini eklemenize olanak tanır.
Google Cast Tasarım Kontrol Listesi, desteklenen tüm platformlarda Cast kullanıcı deneyimini basit ve tahmin edilebilir hale getirmek için sağlanır.
Ne geliştireceğiz?
Bu codelab'i tamamladığınızda, videoları Google Cast uyumlu bir cihaza yayınlayabilen bir Android video uygulamanız olacak.
Neler öğreneceksiniz?
- Google Cast SDK'sını örnek bir video uygulamasına ekleme
- Google Cast cihazı seçmek için Yayınla düğmesini ekleme
- Yayın cihazına bağlanma ve medya alıcısını başlatma
- Video yayınlama
- Uygulamanıza Cast mini denetleyici ekleme
- Medya bildirimleri ve kilit ekranı kontrolleri nasıl desteklenir?
- Genişletilmiş denetleyici ekleme
- Tanıtım amaçlı yer paylaşımı nasıl sağlanır?
- Cast widget'larını özelleştirme
- Cast Connect ile entegrasyon
İhtiyacınız olanlar
- En yeni Android SDK.
- Android Studio 3.2 veya sonraki sürümler
- Android 4.1+ Jelly Bean (API düzeyi 16) yüklü bir mobil cihaz.
- Mobil cihazınızı geliştirme yaptığınız bilgisayara bağlamak için USB veri kablosu.
- İnternet erişimiyle yapılandırılmış bir Chromecast veya Android TV gibi Google Cast yayın cihazı.
- HDMI girişi olan bir TV veya monitör.
- Cast Connect entegrasyonunu test etmek için Google TV Yüklü bir Chromecast gereklidir ancak codelab'in geri kalanı için isteğe bağlıdır. Yoksa bu eğitimin sonuna doğru Cast Connect desteği ekleme adımını atlayabilirsiniz.
Deneyim
- Daha önce Kotlin ve Android geliştirme konusunda bilgi sahibi olmanız gerekir.
- Ayrıca TV izleme konusunda önceden bilgi sahibi olmanız gerekir :)
Bu eğitimi nasıl kullanacaksınız?
Android uygulamaları oluşturma deneyiminizi nasıl değerlendirirsiniz?
TV izleme deneyiminizi nasıl değerlendirirsiniz?
2. Örnek kodu alın
Tüm örnek kodları bilgisayarınıza indirebilirsiniz...
ve indirilen ZIP dosyasını açın.
3. Örnek uygulamayı çalıştırma

Öncelikle, tamamlanmış örnek uygulamanın nasıl göründüğüne bakalım. Uygulama, temel bir video oynatıcıdır. Kullanıcı listeden bir video seçebilir, ardından videoyu cihazda yerel olarak oynatabilir veya Google Cast yayın cihazına yayınlayabilir.
Kod indirildikten sonra, aşağıdaki talimatlarda tamamlanmış örnek uygulamanın Android Studio'da nasıl açılıp çalıştırılacağı açıklanmaktadır:
Karşılama ekranında Projeyi İçe Aktar'ı veya Dosya > Yeni > Projeyi İçe Aktar... menü seçeneklerini belirleyin.
Örnek kod klasöründen 
app-done dizinini seçip Tamam'ı tıklayın.
File >
Sync Project with Gradle Files'ı (Dosya >
Projeyi Gradle Dosyalarıyla Senkronize Et) tıklayın.
Android cihazınızda USB hata ayıklamayı etkinleştirin. Android 4.2 ve sonraki sürümlerde Geliştirici seçenekleri ekranı varsayılan olarak gizlidir. Görünür hale getirmek için Ayarlar > Telefon hakkında'ya gidip Derleme numarası'na yedi kez dokunun. Önceki ekrana dönün, Sistem > Gelişmiş'e gidin ve alt kısımdaki Geliştirici seçenekleri'ne dokunun, ardından USB üzerinden hata ayıklama'ya dokunarak bu seçeneği etkinleştirin.
Android cihazınızı takın ve Android Studio'da
Çalıştır düğmesini tıklayın. Birkaç saniye sonra Cast Videos adlı video uygulamasının göründüğünü görürsünüz.
Video uygulamasında yayın düğmesini tıklayın ve Google Cast cihazınızı seçin.
Bir video seçip oynat düğmesini tıklayın.
Video, Google Cast yayın cihazınızda oynatılmaya başlar.
Genişletilmiş kumanda görüntülenir. Oynatmayı kontrol etmek için oynatma/duraklatma düğmesini kullanabilirsiniz.
Video listesine geri dönün.
Ekranın alt kısmında artık mini bir kontrol cihazı görünüyor. 
Alıcıdaki videoyu duraklatmak için mini denetleyicideki duraklatma düğmesini tıklayın. Videoyu tekrar oynatmaya devam etmek için mini kontrol panelindeki oynatma düğmesini tıklayın.
Mobil cihazın ana sayfa düğmesini tıklayın. Bildirimleri aşağı çektiğinizde Cast oturumuyla ilgili bir bildirim görürsünüz.
Telefonunuzu kilitleyin. Kilidi açtığınızda, medya oynatmayı kontrol etmek veya yayını durdurmak için kilit ekranında bir bildirim görürsünüz.
Video uygulamasına dönün ve Google Cast cihazında yayını durdurmak için Yayınla düğmesini tıklayın.
Sık sorulan sorular
4. Başlangıç projesini hazırlama

İndirdiğiniz başlangıç uygulamasına Google Cast desteği eklememiz gerekiyor. Bu kod laboratuvarında kullanacağımız bazı Google Cast terimleri şunlardır:
- Bir gönderen uygulaması mobil cihazda veya dizüstü bilgisayarda çalışıyorsa,
- Google Cast cihazında bir alıcı uygulaması çalışıyor olmalıdır.
Artık Android Studio'yu kullanarak başlangıç projesinin üzerine geliştirme yapmaya hazırsınız:
- Örnek kod indirme işleminizden

app-startdizinini seçin (Karşılama ekranında Projeyi İçe Aktar'ı veya Dosya > Yeni > Projeyi İçe Aktar... menü seçeneğini belirleyin).
Projeyi Gradle dosyalarıyla senkronize et düğmesini tıklayın.- Uygulamayı çalıştırmak ve kullanıcı arayüzünü keşfetmek için
Çalıştır düğmesini tıklayın.
Uygulama tasarımı
Uygulama, uzak bir web sunucusundan video listesi getirir ve kullanıcının göz atması için bir liste sağlar. Kullanıcılar, ayrıntıları görmek veya videoyu mobil cihazda yerel olarak oynatmak için bir video seçebilir.
Uygulama iki ana etkinlikten oluşur: VideoBrowserActivity ve LocalPlayerActivity. Google Cast işlevini entegre etmek için Etkinlikler, AppCompatActivity veya üst öğesi olan FragmentActivity öğesinden devralınmalıdır. Bu sınırlama, MediaRouteButton (MediaRouter destek kitaplığında sağlanır) MediaRouteActionProvider olarak eklememiz gerektiğinden vardır ve bu yalnızca etkinlik yukarıda belirtilen sınıflardan devralınıyorsa çalışır. MediaRouter destek kitaplığı, gerekli sınıfları sağlayan AppCompat destek kitaplığına bağlıdır.
VideoBrowserActivity
Bu etkinlikte bir Fragment (VideoBrowserFragment) bulunur. Bu liste, bir ArrayAdapter (VideoListAdapter) tarafından desteklenir. Videoların listesi ve ilişkili meta verileri, uzak bir sunucuda JSON dosyası olarak barındırılır. Bir AsyncTaskLoader (VideoItemLoader), bu JSON'u getirir ve MediaItem nesnelerinin listesini oluşturmak için işler.
MediaItem nesnesi, bir videoyu ve ilişkili meta verilerini (ör. başlığı, açıklaması, yayın URL'si, destekleyici resimlerin URL'si ve varsa ilişkili metin parçaları (altyazılar için)) modeller. MediaItem nesnesi etkinlikler arasında iletilir. Bu nedenle, MediaItem nesnesini Bundle nesnesine ve tam tersi şekilde dönüştürmek için yardımcı yöntemleri vardır.
Yükleyici, MediaItems listesini oluşturduğunda bu listeyi VideoListAdapter öğesine iletir. Bu öğe de MediaItems listesini VideoBrowserFragment içinde sunar. Kullanıcıya, her videonun kısa bir açıklamasının yer aldığı video küçük resimlerinin listesi gösterilir. Bir öğe seçildiğinde ilgili MediaItem, Bundle öğesine dönüştürülür ve LocalPlayerActivity öğesine iletilir.
LocalPlayerActivity
Bu etkinlik, belirli bir videonun meta verilerini gösterir ve kullanıcının videoyu mobil cihazda yerel olarak oynatmasına olanak tanır.
Etkinlikte VideoView, bazı medya kontrolleri ve seçilen videonun açıklamasını göstermek için bir metin alanı bulunur. Oynatıcı, ekranın üst kısmını kaplar ve altta videonun ayrıntılı açıklaması için yer bırakır. Kullanıcı, videoların yerel olarak oynatılmasını başlatabilir/duraklatabilir veya ileri/geri sarabilir.
Bağımlılıklar
AppCompatActivity kullandığımız için AppCompat destek kitaplığına ihtiyacımız var. Video listesini yönetmek ve listedeki resimleri eşzamansız olarak almak için Volley kitaplığını kullanıyoruz.
Sık sorulan sorular
5. Yayın düğmesini ekleme

Cast uyumlu bir uygulama, etkinliklerinin her birinde yayın düğmesini gösterir. Yayınla düğmesini tıkladığınızda, kullanıcının seçebileceği yayın cihazlarının listesi gösterilir. Kullanıcı, gönderen cihazda yerel olarak içerik oynatıyorsa bir yayın cihazı seçildiğinde bu yayın cihazında oynatma başlatılır veya devam ettirilir. Yayın oturumu sırasında kullanıcı istediği zaman Yayınla düğmesini tıklayarak uygulamanızın yayın cihazına yayınlanmasını durdurabilir. Kullanıcı, Google Cast Tasarım Kontrol Listesi'nde açıklandığı gibi, uygulamanızdaki herhangi bir etkinlik sırasında yayın cihazına bağlanabilmeli veya bağlantısını kesebilmelidir.
Bağımlılıklar
Gerekli kitaplık bağımlılıklarını eklemek için uygulamanın build.gradle dosyasını güncelleyin:
dependencies {
implementation 'androidx.appcompat:appcompat:1.5.0'
implementation 'androidx.mediarouter:mediarouter:1.3.1'
implementation 'androidx.recyclerview:recyclerview:1.2.1'
implementation 'com.google.android.gms:play-services-cast-framework:21.1.0'
implementation 'com.android.volley:volley:1.2.1'
implementation "androidx.core:core-ktx:1.8.0"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
}
Projenin hatasız oluşturulduğunu onaylamak için projeyi senkronize edin.
Başlatma
Cast çerçevesinde, tüm Cast etkileşimlerini koordine eden genel tekil nesne CastContext bulunur.
CastContext tekilini başlatmak için gereken CastOptions değerini sağlamak üzere OptionsProvider arayüzünü uygulamanız gerekir. En önemli seçenek, yayın cihazı bulma sonuçlarını filtrelemek ve yayın oturumu başlatıldığında alıcı uygulamasını başlatmak için kullanılan alıcı uygulama kimliğidir.
Kendi Cast uyumlu uygulamanızı geliştirirken Cast geliştiricisi olarak kaydolmanız ve ardından uygulamanız için bir uygulama kimliği almanız gerekir. Bu codelab'de örnek bir uygulama kimliği kullanacağız.
Projenin com.google.sample.cast.refplayer paketine aşağıdaki yeni CastOptionsProvider.kt dosyasını ekleyin:
package com.google.sample.cast.refplayer
import android.content.Context
import com.google.android.gms.cast.framework.OptionsProvider
import com.google.android.gms.cast.framework.CastOptions
import com.google.android.gms.cast.framework.SessionProvider
class CastOptionsProvider : OptionsProvider {
override fun getCastOptions(context: Context): CastOptions {
return CastOptions.Builder()
.setReceiverApplicationId(context.getString(R.string.app_id))
.build()
}
override fun getAdditionalSessionProviders(context: Context): List<SessionProvider>? {
return null
}
}
Şimdi uygulama AndroidManifest.xml dosyasının "application" etiketinde OptionsProvider öğesini tanımlayın:
<meta-data
android:name="com.google.android.gms.cast.framework.OPTIONS_PROVIDER_CLASS_NAME"
android:value="com.google.sample.cast.refplayer.CastOptionsProvider" />
VideoBrowserActivity onCreate yönteminde CastContext öğesini geç başlatın:
import com.google.android.gms.cast.framework.CastContext
private var mCastContext: CastContext? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.video_browser)
setupActionBar()
mCastContext = CastContext.getSharedInstance(this)
}
LocalPlayerActivity öğesine aynı ilk kullanıma hazırlama mantığını ekleyin.
Yayınla düğmesi
CastContext başlatıldığına göre, kullanıcının yayın cihazı seçmesine izin vermek için Yayınla düğmesini eklememiz gerekiyor. Yayınla düğmesi, MediaRouter destek kitaplığındaki MediaRouteButton tarafından uygulanır. Etkinliğinize ekleyebileceğiniz diğer işlem simgeleri (ActionBar veya Toolbar kullanılarak) gibi, önce menünüze ilgili menü öğesini eklemeniz gerekir.
res/menu/browse.xml dosyasını düzenleyin ve menüdeki ayarlar öğesinden önce MediaRouteActionProvider öğesini ekleyin:
<item
android:id="@+id/media_route_menu_item"
android:title="@string/media_route_menu_title"
app:actionProviderClass="androidx.mediarouter.app.MediaRouteActionProvider"
app:showAsAction="always"/>
onCreateOptionsMenu() yöntemini geçersiz kılmak için VideoBrowserActivity, MediaRouteButton öğesini Cast çerçevesine bağlamak üzere CastButtonFactory öğesini kullanın:
import com.google.android.gms.cast.framework.CastButtonFactory
private var mediaRouteMenuItem: MenuItem? = null
override fun onCreateOptionsMenu(menu: Menu): Boolean {
super.onCreateOptionsMenu(menu)
menuInflater.inflate(R.menu.browse, menu)
mediaRouteMenuItem = CastButtonFactory.setUpMediaRouteButton(getApplicationContext(), menu,
R.id.media_route_menu_item)
return true
}
onCreateOptionsMenu değerini LocalPlayerActivity içinde benzer şekilde geçersiz kılın.
Uygulamayı mobil cihazınızda çalıştırmak için
Çalıştır düğmesini tıklayın. Uygulamanın işlem çubuğunda bir yayın düğmesi görürsünüz. Bu düğmeyi tıkladığınızda yerel ağınızdaki yayın cihazları listelenir. Cihaz keşfi, CastContext tarafından otomatik olarak yönetilir. Yayın cihazınızı seçtiğinizde örnek alıcı uygulaması, yayın cihazına yüklenir. Göz atma etkinliği ile yerel oynatıcı etkinliği arasında geçiş yapabilirsiniz. Yayın düğmesinin durumu senkronize edilir.
Medya oynatma için henüz destek eklemediğimizden Cast cihazında videoları oynatamazsınız. Bağlantıyı kesmek için Yayınla düğmesini tıklayın.
6. Video içeriğini yayınlama

Örnek uygulamayı, videoları Cast cihazda uzaktan oynatacak şekilde genişleteceğiz. Bunu yapmak için Cast çerçevesi tarafından oluşturulan çeşitli etkinlikleri dinlememiz gerekir.
Medya yayınlama
Üst düzeyde, bir yayın cihazında medya oynatmak istiyorsanız şunları yapmanız gerekir:
- Bir medya öğesini modelleyen bir
MediaInfonesnesi oluşturun. - Yayın cihazına bağlanın ve alıcı uygulamanızı başlatın.
MediaInfonesnesini alıcınıza yükleyin ve içeriği oynatın.- Medya durumunu takip edin.
- Kullanıcı etkileşimlerine göre alıcıya oynatma komutları gönderme.
Önceki bölümde 2. adımı tamamlamıştık. 3. adım, Cast çerçevesiyle kolayca gerçekleştirilebilir. 1. adım, bir nesneyi başka bir nesneyle eşlemeye karşılık gelir. MediaInfo, Cast çerçevesinin anladığı bir şeydir ve MediaItem, uygulamamızın bir medya öğesi için kapsülüdür. MediaItem öğesini MediaInfo öğesiyle kolayca eşleyebiliriz.
LocalPlayerActivity örnek uygulaması, bu enum'u kullanarak yerel ve uzaktan oynatma arasında ayrım yapıyor:
private var mLocation: PlaybackLocation? = null
enum class PlaybackLocation {
LOCAL, REMOTE
}
enum class PlaybackState {
PLAYING, PAUSED, BUFFERING, IDLE
}
Bu codelab'de tüm örnek oyuncu mantığının tam olarak nasıl çalıştığını anlamanız önemli değildir. Uygulamanızın medya oynatıcısının, iki oynatma konumunu benzer şekilde algılayacak şekilde değiştirilmesi gerektiğini anlamanız önemlidir.
Şu anda yerel oynatıcı, yayınlama durumları hakkında henüz bir bilgiye sahip olmadığı için her zaman yerel oynatma durumundadır. Cast çerçevesinde gerçekleşen durum geçişlerine göre kullanıcı arayüzünü güncellememiz gerekiyor. Örneğin, yayınlamaya başladığımızda yerel oynatmayı durdurmamız ve bazı kontrolleri devre dışı bırakmamız gerekir. Benzer şekilde, bu aktivite sırasında yayınlamayı durdurursak yerel oynatmaya geçmemiz gerekir. Bunu işlemek için Cast çerçevesi tarafından oluşturulan çeşitli etkinlikleri dinlememiz gerekir.
Yayınlama oturumu yönetimi
Cast çerçevesinde, Cast oturumu bir cihaza bağlanma, başlatma (veya katılma), alıcı uygulamasına bağlanma ve uygunsa medya kontrol kanalı başlatma adımlarını birleştirir. Medya kontrol kanalı, Cast çerçevesinin alıcı medya oynatıcıdan mesaj gönderip aldığı yerdir.
Kullanıcı, Yayınla düğmesinden bir cihaz seçtiğinde yayın oturumu otomatik olarak başlatılır ve bağlantıyı kestiğinde otomatik olarak durdurulur. Ağ sorunları nedeniyle alıcı oturumuna yeniden bağlanma işlemi de Cast SDK tarafından otomatik olarak gerçekleştirilir.
LocalPlayerActivity alanına SessionManagerListener ekleyelim:
import com.google.android.gms.cast.framework.CastSession
import com.google.android.gms.cast.framework.SessionManagerListener
...
private var mSessionManagerListener: SessionManagerListener<CastSession>? = null
private var mCastSession: CastSession? = null
...
private fun setupCastListener() {
mSessionManagerListener = object : SessionManagerListener<CastSession> {
override fun onSessionEnded(session: CastSession, error: Int) {
onApplicationDisconnected()
}
override fun onSessionResumed(session: CastSession, wasSuspended: Boolean) {
onApplicationConnected(session)
}
override fun onSessionResumeFailed(session: CastSession, error: Int) {
onApplicationDisconnected()
}
override fun onSessionStarted(session: CastSession, sessionId: String) {
onApplicationConnected(session)
}
override fun onSessionStartFailed(session: CastSession, error: Int) {
onApplicationDisconnected()
}
override fun onSessionStarting(session: CastSession) {}
override fun onSessionEnding(session: CastSession) {}
override fun onSessionResuming(session: CastSession, sessionId: String) {}
override fun onSessionSuspended(session: CastSession, reason: Int) {}
private fun onApplicationConnected(castSession: CastSession) {
mCastSession = castSession
if (null != mSelectedMedia) {
if (mPlaybackState == PlaybackState.PLAYING) {
mVideoView!!.pause()
loadRemoteMedia(mSeekbar!!.progress, true)
return
} else {
mPlaybackState = PlaybackState.IDLE
updatePlaybackLocation(PlaybackLocation.REMOTE)
}
}
updatePlayButton(mPlaybackState)
invalidateOptionsMenu()
}
private fun onApplicationDisconnected() {
updatePlaybackLocation(PlaybackLocation.LOCAL)
mPlaybackState = PlaybackState.IDLE
mLocation = PlaybackLocation.LOCAL
updatePlayButton(mPlaybackState)
invalidateOptionsMenu()
}
}
}
LocalPlayerActivity etkinliğinde, yerel oynatıcıya geçebilmek veya yerel oynatıcıdan çıkabilmek için yayın cihazına bağlandığımızda ya da bağlantımız kesildiğinde bilgilendirilmek isteriz. Bağlantının yalnızca mobil cihazınızda çalışan uygulama örneğiniz tarafından değil, farklı bir mobil cihazda çalışan başka bir uygulama örneğiniz (veya başka bir uygulama) tarafından da kesintiye uğrayabileceğini unutmayın.
Şu anda etkin olan oturuma SessionManager.getCurrentSession() olarak erişilebilir. Oturumlar, kullanıcıların Cast iletişim kutularıyla etkileşimlerine yanıt olarak otomatik şekilde oluşturulur ve sonlandırılır.
Oturum dinleyicimizi kaydetmemiz ve etkinlikte kullanacağımız bazı değişkenleri başlatmamız gerekiyor. LocalPlayerActivity onCreate yöntemini şu şekilde değiştirin:
import com.google.android.gms.cast.framework.CastContext
...
private var mCastContext: CastContext? = null
...
override fun onCreate(savedInstanceState: Bundle?) {
...
mCastContext = CastContext.getSharedInstance(this)
mCastSession = mCastContext!!.sessionManager.currentCastSession
setupCastListener()
...
loadViews()
...
val bundle = intent.extras
if (bundle != null) {
....
if (shouldStartPlayback) {
....
} else {
if (mCastSession != null && mCastSession!!.isConnected()) {
updatePlaybackLocation(PlaybackLocation.REMOTE)
} else {
updatePlaybackLocation(PlaybackLocation.LOCAL)
}
mPlaybackState = PlaybackState.IDLE
updatePlayButton(mPlaybackState)
}
}
...
}
Medya yükleniyor
Cast SDK'sında RemoteMediaClient, alıcıda uzaktan medya oynatmayı yönetmek için bir dizi kullanışlı API sağlar. Medya oynatmayı destekleyen bir CastSession için SDK tarafından otomatik olarak bir RemoteMediaClient örneği oluşturulur. CastSession örneğinde getRemoteMediaClient() yöntemi çağrılarak erişilebilir. Şu anda alıcıda seçili olan videoyu yüklemek için LocalPlayerActivity'ya aşağıdaki yöntemleri ekleyin:
import com.google.android.gms.cast.framework.media.RemoteMediaClient
import com.google.android.gms.cast.MediaInfo
import com.google.android.gms.cast.MediaLoadOptions
import com.google.android.gms.cast.MediaMetadata
import com.google.android.gms.common.images.WebImage
import com.google.android.gms.cast.MediaLoadRequestData
private fun loadRemoteMedia(position: Int, autoPlay: Boolean) {
if (mCastSession == null) {
return
}
val remoteMediaClient = mCastSession!!.remoteMediaClient ?: return
remoteMediaClient.load( MediaLoadRequestData.Builder()
.setMediaInfo(buildMediaInfo())
.setAutoplay(autoPlay)
.setCurrentTime(position.toLong()).build())
}
private fun buildMediaInfo(): MediaInfo? {
val movieMetadata = MediaMetadata(MediaMetadata.MEDIA_TYPE_MOVIE)
mSelectedMedia?.studio?.let { movieMetadata.putString(MediaMetadata.KEY_SUBTITLE, it) }
mSelectedMedia?.title?.let { movieMetadata.putString(MediaMetadata.KEY_TITLE, it) }
movieMetadata.addImage(WebImage(Uri.parse(mSelectedMedia!!.getImage(0))))
movieMetadata.addImage(WebImage(Uri.parse(mSelectedMedia!!.getImage(1))))
return mSelectedMedia!!.url?.let {
MediaInfo.Builder(it)
.setStreamType(MediaInfo.STREAM_TYPE_BUFFERED)
.setContentType("videos/mp4")
.setMetadata(movieMetadata)
.setStreamDuration((mSelectedMedia!!.duration * 1000).toLong())
.build()
}
}
Şimdi, uzaktan oynatmayı desteklemek için mevcut çeşitli yöntemleri Cast oturumu mantığını kullanacak şekilde güncelleyin:
private fun play(position: Int) {
startControllersTimer()
when (mLocation) {
PlaybackLocation.LOCAL -> {
mVideoView!!.seekTo(position)
mVideoView!!.start()
}
PlaybackLocation.REMOTE -> {
mPlaybackState = PlaybackState.BUFFERING
updatePlayButton(mPlaybackState)
//seek to a new position within the current media item's new position
//which is in milliseconds from the beginning of the stream
mCastSession!!.remoteMediaClient?.seek(position.toLong())
}
else -> {}
}
restartTrickplayTimer()
}
private fun togglePlayback() {
...
PlaybackState.IDLE -> when (mLocation) {
...
PlaybackLocation.REMOTE -> {
if (mCastSession != null && mCastSession!!.isConnected) {
loadRemoteMedia(mSeekbar!!.progress, true)
}
}
else -> {}
}
...
}
override fun onPause() {
...
mCastContext!!.sessionManager.removeSessionManagerListener(
mSessionManagerListener!!, CastSession::class.java)
}
override fun onResume() {
Log.d(TAG, "onResume() was called")
mCastContext!!.sessionManager.addSessionManagerListener(
mSessionManagerListener!!, CastSession::class.java)
if (mCastSession != null && mCastSession!!.isConnected) {
updatePlaybackLocation(PlaybackLocation.REMOTE)
} else {
updatePlaybackLocation(PlaybackLocation.LOCAL)
}
super.onResume()
}
updatePlayButton yöntemi için isConnected değişkeninin değerini değiştirin:
private fun updatePlayButton(state: PlaybackState?) {
...
val isConnected = (mCastSession != null
&& (mCastSession!!.isConnected || mCastSession!!.isConnecting))
...
}
Şimdi, uygulamayı mobil cihazınızda çalıştırmak için
Çalıştır düğmesini tıklayın. Yayın cihazınıza bağlanın ve bir video oynatmaya başlayın. Videoyu alıcıda oynarken görmeniz gerekir.
7. Mini kumanda
Cast Tasarım Kontrol Listesi, kullanıcının mevcut içerik sayfasından ayrılması durumunda tüm Cast uygulamalarının mini denetleyici sağlamasını zorunlu kılar. Mini denetleyici, mevcut Cast oturumuna anında erişim ve görünür bir hatırlatıcı sağlar.

Cast SDK, mini denetleyiciyi göstermek istediğiniz etkinliklerin uygulama düzeni dosyasına eklenebilen özel bir görünüm (MiniControllerFragment) sağlar.
Aşağıdaki parça tanımını hem res/layout/player_activity.xml hem de res/layout/video_browser.xml öğesinin en altına ekleyin:
<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"/>
Uygulamayı çalıştırmak ve video yayınlamak için
Çalıştır düğmesini tıklayın. Alıcıda oynatma başladığında her etkinliğin en altında mini kumanda görünür. Mini denetleyiciyi kullanarak uzaktan oynatmayı kontrol edebilirsiniz. Göz atma etkinliği ile yerel oynatıcı etkinliği arasında geçiş yaparsanız mini denetleyici durumu, alıcıdaki medya oynatma durumuyla senkronize kalmalıdır.
8. Bildirim ve kilit ekranı
Google Cast tasarım kontrol listesi, gönderen uygulamasının bildirim ve kilit ekranından medya kontrollerini uygulaması gerektiğini belirtir.

Cast SDK, gönderen uygulamanın bildirim ve kilit ekranı için medya kontrolleri oluşturmasına yardımcı olacak bir MediaNotificationService sağlar. Hizmet, Gradle tarafından uygulamanızın manifest dosyasıyla otomatik olarak birleştirilir.
Gönderen içerik yayınlarken MediaNotificationService arka planda çalışır ve mevcut yayın öğesiyle ilgili küçük resim ve meta veriler içeren bir bildirim, oynatma/duraklatma düğmesi ve durdurma düğmesi gösterir.
CastContext başlatılırken CastOptions ile bildirim ve kilit ekranı kontrolleri etkinleştirilebilir. Bildirim ve kilit ekranı için medya kontrolleri varsayılan olarak etkindir. Bildirimler etkin olduğu sürece kilit ekranı özelliği de etkindir.
CastOptionsProvider öğesini düzenleyin ve getCastOptions uygulamasını bu kodla eşleşecek şekilde değiştirin:
import com.google.android.gms.cast.framework.media.CastMediaOptions
import com.google.android.gms.cast.framework.media.NotificationOptions
override fun getCastOptions(context: Context): CastOptions {
val notificationOptions = NotificationOptions.Builder()
.setTargetActivityClassName(VideoBrowserActivity::class.java.name)
.build()
val mediaOptions = CastMediaOptions.Builder()
.setNotificationOptions(notificationOptions)
.build()
return CastOptions.Builder()
.setReceiverApplicationId(context.getString(R.string.app_id))
.setCastMediaOptions(mediaOptions)
.build()
}
Uygulamayı mobil cihazınızda çalıştırmak için
Çalıştır düğmesini tıklayın. Bir video yayınlayın ve örnek uygulamadan uzaklaşın. Alıcıda oynatılan video için bir bildirim gösterilmelidir. Mobil cihazınızı kilitlediğinizde kilit ekranında, yayın cihazında medya oynatma kontrolleri gösterilir.

9. Tanıtım amaçlı yer paylaşımı
Google Cast tasarım kontrol listesi, gönderen uygulamasının mevcut kullanıcılara yayın düğmesini tanıtmasını gerektirir. Bu sayede kullanıcılar, gönderen uygulamasının artık Cast'i desteklediğini öğrenir ve Google Cast'i yeni kullanmaya başlayan kullanıcılara yardımcı olunur.

Cast SDK, kullanıcılara ilk kez gösterildiğinde yayın düğmesini vurgulamak için kullanılabilecek özel bir görünüm (IntroductoryOverlay) sağlar. Aşağıdaki kodu VideoBrowserActivity dosyasına ekleyin:
import com.google.android.gms.cast.framework.IntroductoryOverlay
import android.os.Looper
private var mIntroductoryOverlay: IntroductoryOverlay? = null
private fun showIntroductoryOverlay() {
mIntroductoryOverlay?.remove()
if (mediaRouteMenuItem?.isVisible == true) {
Looper.myLooper().run {
mIntroductoryOverlay = com.google.android.gms.cast.framework.IntroductoryOverlay.Builder(
this@VideoBrowserActivity, mediaRouteMenuItem!!)
.setTitleText("Introducing Cast")
.setSingleTime()
.setOnOverlayDismissedListener(
object : IntroductoryOverlay.OnOverlayDismissedListener {
override fun onOverlayDismissed() {
mIntroductoryOverlay = null
}
})
.build()
mIntroductoryOverlay!!.show()
}
}
}
Şimdi CastStateListener ekleyin ve onCreate yöntemini değiştirip onResume ve onPause yöntemlerini aşağıdakiyle eşleşecek şekilde geçersiz kılarak bir yayın cihazı kullanılabilir olduğunda showIntroductoryOverlay yöntemini çağırın:
import com.google.android.gms.cast.framework.CastState
import com.google.android.gms.cast.framework.CastStateListener
private var mCastStateListener: CastStateListener? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.video_browser)
setupActionBar()
mCastStateListener = object : CastStateListener {
override fun onCastStateChanged(newState: Int) {
if (newState != CastState.NO_DEVICES_AVAILABLE) {
showIntroductoryOverlay()
}
}
}
mCastContext = CastContext.getSharedInstance(this)
}
override fun onResume() {
super.onResume()
mCastContext?.addCastStateListener(mCastStateListener!!)
}
override fun onPause() {
super.onPause()
mCastContext?.removeCastStateListener(mCastStateListener!!)
}
Uygulama verilerini temizleyin veya uygulamayı cihazınızdan kaldırın. Ardından, uygulamayı mobil cihazınızda çalıştırmak için
Çalıştır düğmesini tıklayın. Tanıtım yer paylaşımını görmeniz gerekir (yer paylaşımı gösterilmezse uygulama verilerini temizleyin).
10. Genişletilmiş kontrol cihazı
Google Cast tasarım kontrol listesi, gönderen uygulamanın yayınlanan medya için genişletilmiş denetleyici sağlamasını zorunlu kılar. Genişletilmiş denetleyici, mini denetleyicinin tam ekran sürümüdür.

Cast SDK, genişletilmiş denetleyici için ExpandedControllerActivity adlı bir widget sağlar. Bu, Yayın düğmesi eklemek için alt sınıf oluşturmanız gereken bir soyut sınıftır.
İlk olarak, Cast düğmesini sağlamak için genişletilmiş denetleyiciye yönelik expanded_controller.xml adlı yeni bir menü kaynak dosyası oluşturun:
<?xml version="1.0" encoding="utf-8"?>
<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>
com.google.sample.cast.refplayer paketinde yeni bir paket expandedcontrols oluşturun. Ardından, com.google.sample.cast.refplayer.expandedcontrols paketinde ExpandedControlsActivity.kt adlı yeni bir dosya oluşturun.
package com.google.sample.cast.refplayer.expandedcontrols
import android.view.Menu
import com.google.android.gms.cast.framework.media.widget.ExpandedControllerActivity
import com.google.sample.cast.refplayer.R
import com.google.android.gms.cast.framework.CastButtonFactory
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
}
}
Şimdi OPTIONS_PROVIDER_CLASS_NAME etiketinin üzerindeki application etiketi içindeki AndroidManifest.xml öğesinde ExpandedControlsActivity öğesini tanımlayın:
<application>
...
<activity
android:name="com.google.sample.cast.refplayer.expandedcontrols.ExpandedControlsActivity"
android:label="@string/app_name"
android:launchMode="singleTask"
android:theme="@style/Theme.CastVideosDark"
android:screenOrientation="portrait"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
</intent-filter>
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.google.sample.cast.refplayer.VideoBrowserActivity"/>
</activity>
...
</application>
CastOptionsProvider öğesini düzenleyin ve hedef etkinliği ExpandedControlsActivity olarak ayarlamak için NotificationOptions ile CastMediaOptions öğesini değiştirin:
import com.google.sample.cast.refplayer.expandedcontrols.ExpandedControlsActivity
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()
}
Uzak medya yüklendiğinde ExpandedControlsActivity öğesini göstermek için LocalPlayerActivity loadRemoteMedia yöntemini güncelleyin:
import com.google.sample.cast.refplayer.expandedcontrols.ExpandedControlsActivity
private fun loadRemoteMedia(position: Int, autoPlay: Boolean) {
if (mCastSession == null) {
return
}
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(buildMediaInfo())
.setAutoplay(autoPlay)
.setCurrentTime(position.toLong()).build())
}
Uygulamayı mobil cihazınızda çalıştırmak ve video yayınlamak için
Çalıştır düğmesini tıklayın. Genişletilmiş denetleyiciyi görürsünüz. Video listesine geri dönün. Mini denetleyiciyi tıkladığınızda genişletilmiş denetleyici tekrar yüklenir. Bildirimi görmek için uygulamadan çıkın. Genişletilmiş denetleyiciyi yüklemek için bildirim resmini tıklayın.
11. Cast Connect desteği ekleme
Cast Connect kitaplığı, mevcut gönderen uygulamalarının Cast protokolü aracılığıyla Android TV uygulamalarıyla iletişim kurmasına olanak tanır. Cast Connect, Android TV uygulamanızın alıcı görevi gördüğü Cast altyapısı üzerine kuruludur.
Bağımlılıklar
Not: Cast Connect'i uygulamak için play-services-cast-framework sürümünün 19.0.0 veya daha yeni olması gerekir.
LaunchOptions
Android alıcı olarak da bilinen Android TV uygulamasını başlatmak için setAndroidReceiverCompatible işaretini LaunchOptions nesnesinde doğru olarak ayarlamamız gerekir. Bu LaunchOptions nesnesi, alıcının nasıl başlatılacağını belirler ve CastOptionsProvider sınıfı tarafından döndürülen CastOptions öğesine iletilir. Yukarıda belirtilen işareti false olarak ayarladığınızda, Cast Developer Console'da tanımlanan uygulama kimliği için web alıcısı başlatılır.
CastOptionsProvider.kt dosyasında getCastOptions yöntemine aşağıdakileri ekleyin:
import com.google.android.gms.cast.LaunchOptions
...
val launchOptions = LaunchOptions.Builder()
.setAndroidReceiverCompatible(true)
.build()
return new CastOptions.Builder()
.setLaunchOptions(launchOptions)
...
.build()
Başlatma Kimlik Bilgilerini Ayarlama
Gönderen tarafında, oturuma kimin katıldığını belirtmek için CredentialsData değerini belirtebilirsiniz. credentials, ATV uygulamanızın anlayabileceği sürece kullanıcı tarafından tanımlanabilen bir dizedir. CredentialsData yalnızca başlatma veya katılma sırasında Android TV uygulamanıza iletilir. Bağlıyken tekrar ayarlarsanız Android TV uygulamanıza aktarılmaz.
Başlatma kimlik bilgilerini ayarlamak için CredentialsData tanımlanmalı ve LaunchOptions nesnesine iletilmelidir. CastOptionsProvider.kt dosyanızdaki getCastOptions yöntemine aşağıdaki kodu ekleyin:
import com.google.android.gms.cast.CredentialsData
...
val credentialsData = CredentialsData.Builder()
.setCredentials("{\"userId\": \"abc\"}")
.build()
val launchOptions = LaunchOptions.Builder()
...
.setCredentialsData(credentialsData)
.build()
LoadRequest üzerinde kimlik bilgileri ayarlama
Web alıcı uygulamanız ve Android TV uygulamanız credentials farklı şekilde işliyorsa her biri için ayrı credentials tanımlamanız gerekebilir. Bunu düzeltmek için LocalPlayerActivity.kt dosyanızdaki loadRemoteMedia işlevinin altına aşağıdaki kodu ekleyin:
remoteMediaClient.load(MediaLoadRequestData.Builder()
...
.setCredentials("user-credentials")
.setAtvCredentials("atv-user-credentials")
.build())
Göndereninizin yayın yaptığı alıcı uygulamaya bağlı olarak SDK, mevcut oturum için hangi kimlik bilgilerinin kullanılacağını otomatik olarak işleyecektir.
Cast Connect'i test etme
Android TV APK'sını Google TV Yüklü Chromecast'e yükleme adımları
- Android TV cihazınızın IP adresini bulun. Genellikle Ayarlar > Ağ ve İnternet > (Cihazınızın bağlı olduğu ağın adı) bölümünde bulunur. Sağ tarafta ayrıntılar ve cihazınızın ağdaki IP'si gösterilir.
- Terminali kullanarak ADB üzerinden cihazınıza bağlanmak için cihazınızın IP adresini kullanın:
$ adb connect <device_ip_address>:5555
- Terminal pencerenizde, bu codelab'in başında indirdiğiniz codelab örneklerinin bulunduğu üst düzey klasöre gidin. Örneğin:
$ cd Desktop/android_codelab_src
- Bu klasördeki .apk dosyasını aşağıdaki komutu çalıştırarak Android TV'nize yükleyin:
$ adb -s <device_ip_address>:5555 install android-tv-app.apk
- Android TV cihazınızdaki Uygulamalarınız menüsünde Video Yayınla adlı bir uygulama görmeniz gerekir.
- Android Studio projenize dönün ve gönderen uygulamasını fiziksel mobil cihazınıza yükleyip çalıştırmak için Çalıştır düğmesini tıklayın. Sağ üst köşede yayın simgesini tıklayın ve mevcut seçenekler arasından Android TV cihazınızı seçin. Android TV uygulamasının Android TV cihazınızda başlatıldığını görmelisiniz. Bir video oynattığınızda ise Android TV kumandanızı kullanarak video oynatmayı kontrol edebilirsiniz.
12. Cast widget'larını özelleştirme
Renkleri ayarlayarak, düğmeleri, metni ve küçük resim görünümünü şekillendirerek ve gösterilecek düğme türlerini seçerek Cast widget'larını özelleştirebilirsiniz.
res/values/styles_castvideo.xml adresini güncelleyin
<style name="Theme.CastVideosTheme" parent="Theme.AppCompat.Light.NoActionBar">
...
<item name="mediaRouteTheme">@style/CustomMediaRouterTheme</item>
<item name="castIntroOverlayStyle">@style/CustomCastIntroOverlay</item>
<item name="castMiniControllerStyle">@style/CustomCastMiniController</item>
<item name="castExpandedControllerStyle">@style/CustomCastExpandedController</item>
<item name="castExpandedControllerToolbarStyle">
@style/ThemeOverlay.AppCompat.ActionBar
</item>
...
</style>
Aşağıdaki özel temaları bildirin:
<!-- Customize Cast Button -->
<style name="CustomMediaRouterTheme" parent="Theme.MediaRouter">
<item name="mediaRouteButtonStyle">@style/CustomMediaRouteButtonStyle</item>
</style>
<style name="CustomMediaRouteButtonStyle" parent="Widget.MediaRouter.Light.MediaRouteButton">
<item name="mediaRouteButtonTint">#EEFF41</item>
</style>
<!-- Customize Introductory Overlay -->
<style name="CustomCastIntroOverlay" parent="CastIntroOverlay">
<item name="castButtonTextAppearance">@style/TextAppearance.CustomCastIntroOverlay.Button</item>
<item name="castTitleTextAppearance">@style/TextAppearance.CustomCastIntroOverlay.Title</item>
</style>
<style name="TextAppearance.CustomCastIntroOverlay.Button" parent="android:style/TextAppearance">
<item name="android:textColor">#FFFFFF</item>
</style>
<style name="TextAppearance.CustomCastIntroOverlay.Title" parent="android:style/TextAppearance.Large">
<item name="android:textColor">#FFFFFF</item>
</style>
<!-- Customize Mini Controller -->
<style name="CustomCastMiniController" parent="CastMiniController">
<item name="castShowImageThumbnail">true</item>
<item name="castTitleTextAppearance">@style/TextAppearance.AppCompat.Subhead</item>
<item name="castSubtitleTextAppearance">@style/TextAppearance.AppCompat.Caption</item>
<item name="castBackground">@color/accent</item>
<item name="castProgressBarColor">@color/orange</item>
</style>
<!-- Customize Expanded Controller -->
<style name="CustomCastExpandedController" parent="CastExpandedController">
<item name="castButtonColor">#FFFFFF</item>
<item name="castPlayButtonDrawable">@drawable/cast_ic_expanded_controller_play</item>
<item name="castPauseButtonDrawable">@drawable/cast_ic_expanded_controller_pause</item>
<item name="castStopButtonDrawable">@drawable/cast_ic_expanded_controller_stop</item>
</style>
13. Tebrikler
Artık Android'de Cast SDK widget'larını kullanarak bir video uygulamasında Cast'i nasıl etkinleştireceğinizi biliyorsunuz.
Daha fazla bilgi için Android Gönderen geliştirici kılavuzuna bakın.