1. Genel Bakış
Bu codelab'de, Google Cast uyumlu cihazlarda içerik yayınlamak için mevcut bir Android video uygulamasını nasıl değiştireceğiniz açıklanmaktadır.
Google Cast nedir?
Google Cast, kullanıcıların mobil cihazdan TV'ye içerik yayınlamasına olanak tanır. Böylece kullanıcılar, TV'de medya oynatmak için mobil cihazlarını uzaktan kumanda olarak kullanabilir.
Google Cast SDK'sı, uygulamanızın kapsamını genişleterek bir TV'yi veya ses sistemini kontrol etmenizi sağlar. Cast SDK'sı, 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ğlanmıştır.
Ne oluşturacağız?
Bu codelab'i tamamladığınızda, Google Cast uyumlu bir cihazda video yayınlayabilecek bir Android video uygulamanız olacak.
Neler öğreneceksiniz?
- Google Cast SDK'sı örnek bir video uygulamasına nasıl eklenir?
- Google Cast cihazı seçmek için yayın düğmesi nasıl eklenir?
- Yayın cihazına bağlanıp medya alıcısı nasıl başlatılır?
- Video nasıl yayınlanır?
- Uygulamanıza Cast mini kumandası nasıl eklenir?
- Medya bildirimleri ve kilit ekranı denetimleri nasıl desteklenir?
- Genişletilmiş kumanda ekleme
- Tanıtım yer paylaşımı nasıl sağlanır?
- Cast widget'ları nasıl özelleştirilir?
- Cast Connect ile entegrasyon
İhtiyacınız olanlar
- En son Android SDK.
- Android Studio 3.2 sürümü veya daha yeni bir sürüm
- Android 4.1 veya sonraki bir Jelly Bean (API düzeyi 16) sürümüne sahip bir mobil cihaz.
- Mobil cihazınızı geliştirme bilgisayarınıza bağlamak için bir USB veri kablosu.
- Chromecast veya Android TV gibi internet erişimi olan bir Google Cast cihazı.
- HDMI girişli bir TV veya monitör.
- Cast Connect entegrasyonunu test etmek için Google TV'li Chromecast gereklidir, ancak Codelab'in geri kalanı için isteğe bağlıdır. AdSense hesabınız yoksa bu eğiticinin sonuna doğru, Cast Connect Desteği Ekle adımını atlayabilirsiniz.
Deneyim
- Kotlin ve Android geliştirme için önceden bilgi sahibi olmanız gerekir.
- TV izleme konusunda önceden bilgiye de sahip olmanız gerekir :)
Bu eğiticiden nasıl yararlanacaksınız?
Android uygulamaları geliştirme 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ın paketini açın.
3. Örnek uygulamayı çalıştırma
Öncelikle tamamlanan ö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 ve daha sonra videoyu cihazda yerel olarak oynatabilir veya bir Google Cast cihazında yayınlayabilir.
Kod indirildikten sonra aşağıdaki talimatlarda, tamamlanmış örnek uygulamanın Android Studio'da nasıl açılacağı ve çalıştırılacağı açıklanmaktadır:
Karşılama ekranında Projeyi İçe Aktar'ı veya Dosya > Yeni > Projeyi İçe Aktar... menü seçenekleri.
Örnek kod klasöründen app-done
dizinini seçip Tamam'ı tıklayın.
Dosya > Projeyi Gradle Dosyaları ile senkronize edin.
Android cihazınızda USB üzerinden 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'yı tıklayın ve Derleme numarası'na yedi kez dokunun. Önceki ekrana dönün, Sistem > Gelişmiş'e gidin ve alt taraftaki Geliştirici seçenekleri'ne dokunun, ardından USB'de hata ayıklama'ya dokunarak bu özelliği açın.
Android cihazınızı fişe takın ve Android Studio'da Çalıştır düğmesini tıklayın. Birkaç saniye sonra Video Yayınla adlı video uygulaması görünecektir.
Video uygulamasında Yayınla 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 cihazınızda oynatılmaya başlar.
Genişletilmiş kumanda gösterilir. Oynatmayı kontrol etmek için oynat/duraklat düğmesini kullanabilirsiniz.
Video listesine geri dönün.
Ekranın alt kısmında artık bir mini kumanda görünüyor.
Alıcıdaki videoyu duraklatmak için mini kumandadaki duraklat düğmesini tıklayın. Videoyu tekrar oynatmaya devam etmek için mini kumandadaki oynat düğmesini tıklayın.
Mobil cihazın ana sayfa düğmesini tıklayın. Bildirimleri aşağı çektiğinizde artık yayınlama oturumuyla ilgili bir bildirim göreceksiniz.
Telefonunuzu kilitler ve kilidini açtığınızda, kilit ekranında medya oynatmayı kontrol etmek veya yayınlamayı durdurmak için bir bildirim görürsünüz.
Video uygulamasına dönün ve Google Cast cihazında yayını durdurmak için Yayın 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 codelab'de kullanacağımız Google Cast terminolojilerinden bazılarını aşağıda bulabilirsiniz:
- Mobil cihazda veya dizüstü bilgisayarda çalışan gönderen uygulaması,
- Google Cast cihazında çalışan bir alıcı uygulaması.
Artık Android Studio'yu kullanarak başlangıç projesinin üzerine geliştirme yapmaya hazırsınız:
- Örnek kod indirme işleminizden
app-start
dizinini 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 atabileceği bir liste sağlar. Kullanıcılar, ayrıntılarını görmek için bir video seçebilir veya videoyu mobil cihazda yerel olarak oynatabilir.
Uygulama iki ana etkinlikten oluşur: VideoBrowserActivity
ve LocalPlayerActivity
. Google Cast işlevini entegre etmek için Etkinliklerin, AppCompatActivity
veya üst öğesi FragmentActivity
öğesinden devralınması gerekir. Bu sınırlama, MediaRouteButton
öğesini (MediaRouter destek kitaplığında sağlanan) MediaRouteActionProvider
olarak eklememiz gerekeceğinden dolayı mevcuttur. Bu işlem yalnızca etkinliğin yukarıda belirtilen sınıflardan devralınması durumunda işe yarar. MediaRouter destek kitaplığı, gerekli sınıfları sağlayan AppCompat destek kitaplığına bağlıdır.
VideoBrowserActivity
Bu etkinlik bir Fragment
(VideoBrowserFragment
) içeriyor. Bu liste ArrayAdapter
(VideoListAdapter
) ile desteklenmektedir. Video listesi ve bunlarla ilişkili meta veriler, uzak sunucuda JSON dosyası olarak barındırılır. AsyncTaskLoader
(VideoItemLoader
), bu JSON'u getirir ve MediaItem
nesne içeren bir liste oluşturmak için işler.
MediaItem
nesnesi, bir video ve video ile ilişkili meta verileri (ör. başlığı, açıklaması, akışın URL'si, destekleyici resimlerin URL'si) ve varsa ilişkili Metin Parçalarını (altyazılar için) modeller. MediaItem
nesnesi etkinlikler arasında aktarılır. Bu nedenle MediaItem
, Bundle
nesnesine (veya tam tersi) dönüştürmek için yardımcı program yöntemlerine sahiptir.
Yükleyici, MediaItems
listesini oluşturduğunda, bu listeyi VideoListAdapter
öğesine iletir ve daha sonra, VideoBrowserFragment
içinde MediaItems
listesini sunar. Kullanıcıya, her videonun kısa açıklamalarının yer aldığı bir video küçük resimleri listesi sunulur. Bir öğe seçildiğinde, karşılık gelen MediaItem
Bundle
öğesine dönüştürülür ve LocalPlayerActivity
'a aktarılır.
LocalPlayerActivity
Bu etkinlik, belirli bir videoyla ilgili meta verileri gösterir ve kullanıcının videoyu mobil cihazda yerel olarak oynatmasına olanak tanır.
Etkinlik; bir VideoView
, bazı medya kontrolleri ve seçilen videonun açıklamasını gösteren bir metin alanı barındırır. Oynatıcı ekranın üst kısmını örterek alttaki videonun ayrıntılı açıklaması için yer bırakır. Kullanıcı, yerel olarak oynatılan videoları oynatabilir/duraklatabilir veya yerini sarabilir.
Bağımlılıklar
AppCompatActivity
kullandığımızdan AppCompat destek kitaplığına ihtiyacımız var. Video listesini yönetmek ve listedeki görüntüleri eşzamansız olarak almak için Volley kitaplığını kullanıyoruz.
Sık sorulan sorular
5. Yayınla düğmesi ekleniyor
Cast uyumlu bir uygulama, etkinliklerinin her birinde Yayınla düğmesini görüntüler. Yayın düğmesi tıklandığında, kullanıcının seçebileceği Yayın cihazlarının listesi görüntülenir. Kullanıcı içeriği gönderen cihazda yerel olarak oynatıyorsa bir yayın cihazı seçtiğinde oynatma işlemi o yayın cihazında başlar veya devam ettirilir. Yayın oturumu sırasında herhangi bir zamanda, kullanıcı Yayın düğmesini tıklayabilir ve uygulamanızı Yayın cihazına yayınlamayı durdurabilir. Kullanıcı, uygulamanızın herhangi bir etkinliğinde Google Cast Tasarım Kontrol Listesi'nde açıklandığı gibi Cast cihazına bağlanabilmeli veya cihazın bağlantısını kesebilmelidir.
Bağımlılıklar
Uygulama build.gradle dosyasını gerekli kitaplık bağımlılıklarını içerecek şekilde 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"
}
Derlemeleri hatasız olarak onaylamak için projeyi senkronize edin.
Başlatma
Cast çerçevesi, tüm Cast etkileşimlerini koordine eden CastContext
adlı global bir tekil nesneye sahiptir.
CastContext
single'ını başlatmak için gereken CastOptions
kaynağını sağlamak üzere OptionsProvider
arayüzünü uygulamanız gerekir. En önemli seçenek, yayın cihazı keşif sonuçlarını filtrelemek ve bir yayın oturumu başlatıldığında alıcı uygulamayı 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 edinmeniz gerekir. Bu codelab için ö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 OptionsProvider
öğesini "application
" içinde tanımlayın uygulama AndroidManifest.xml
dosyasının etiketi:
<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
için de aynı başlatma mantığını ekleyin.
Yayınla düğmesi
CastContext
başlatıldığına göre kullanıcının bir Yayın cihazı seçmesine izin vermek için Yayınla düğmesini eklememiz gerekir. Yayınla düğmesi, MediaRouter destek kitaplığındaki MediaRouteButton
tarafından uygulanır. Etkinliğinize ekleyebileceğiniz herhangi bir işlem simgesi gibi (ActionBar
veya Toolbar
kullanarak) önce menünüze ilgili menü öğesini eklemeniz gerekir.
res/menu/browse.xml
dosyasını düzenleyin ve menüde, ayarlar öğesinin önüne 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"/>
MediaRouteButton
cihazını Cast çerçevesine bağlamak için CastButtonFactory
kullanarak VideoBrowserActivity
onCreateOptionsMenu()
yöntemini geçersiz kılı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
öğesini 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ınla düğmesi görürsünüz. Bu düğmeyi tıkladığınızda yerel ağınızdaki Yayın cihazları listelenir. Cihaz bulma, CastContext
tarafından otomatik olarak yönetilir. Yayın cihazınızı seçtiğinizde örnek alıcı uygulaması yayın cihazınıza yüklenir. Göz atma etkinliği ile yerel oynatıcı etkinliği arasında gezinebilirsiniz ve Yayınla düğmesinin durumu senkronize edilir.
Medya oynatma için herhangi bir destek kaydetmediğimizden henüz Cast cihazında video oynatamazsınız. Bağlantıyı kesmek için Yayınla düğmesini tıklayın.
6. Video içeriği yayınlama
Örnek uygulamanın kapsamını, Cast cihazında uzaktan video oynatacak şekilde genişleteceğiz. Bunu yapmak için Cast çerçevesi tarafından oluşturulan çeşitli etkinlikleri dinlememiz gerekiyor.
Medya yayınlanıyor
Genel olarak, bir yayın cihazında medya oynatmak isterseniz şunları yapmanız gerekir:
- Medya öğesini modelleyen bir
MediaInfo
nesnesi oluşturun. - Yayın cihazına bağlanın ve alıcı uygulamanızı başlatın.
MediaInfo
nesnesini alıcınıza yükleyin ve içeriği oynatın.- Medya durumunu izleyin.
- Kullanıcı etkileşimlerine göre alıcıya oynatma komutları gönderin.
Önceki bölümde yer alan 2. Adım'ı uyguladık. 3. Adım, Cast çerçevesiyle kolayca yapılabilir. 1. Adım, bir nesnenin başka bir nesneyle eşlenmesi anlamına gelir; MediaInfo
, Cast çerçevesinin anladığı bir şeydir; MediaItem
ise uygulamamızın bir medya öğesini kapsamasıdır; bir MediaItem
öğesini kolayca MediaInfo
ile eşleyebiliriz.
Örnek uygulama LocalPlayerActivity
zaten şu sıralamayı kullanarak yerel oynatma ile 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 oynatıcı mantığının tam olarak nasıl çalıştığını anlamanız önemli değildir. İki oynatma konumunu benzer şekilde tanımak için uygulamanızın medya oynatıcısının değiştirilmesi gerektiğini anlamanız önemlidir.
Şu anda yerel oynatıcı, Yayınlama durumu hakkında henüz hiçbir şey bilmediğinden her zaman yerel oynatma durumundadır. Kullanıcı arayüzünü, Cast çerçevesinde gerçekleşen durum geçişlerine dayalı olarak güncellememiz gerekir. Örneğin, yayınlamaya başlarsak yerel oynatmayı durdurmamız ve bazı kontrolleri devre dışı bırakmamız gerekir. Benzer şekilde, bu etkinlik sırasında yayını durdurursak yerel oynatmaya geçmemiz gerekir. Bunun için Cast çerçevesi tarafından oluşturulan çeşitli etkinlikleri dinlememiz gerekir.
Yayın oturumu yönetimi
Cast çerçevesi için bir Cast oturumu; cihaza bağlanma, cihazı başlatma (veya katılma), alıcı uygulamaya bağlanma ve uygun durumlarda medya kontrol kanalını başlatma adımlarını birleştirir. Medya kontrol kanalı, Cast çerçevesinin alıcı medya oynatıcıdan mesaj gönderip alma şeklidir.
Kullanıcı, Yayın düğmesinden cihaz seçtiğinde yayın oturumu otomatik olarak başlatılır ve kullanıcının bağlantısı kesildiğinde otomatik olarak durdurulur. Ağ sorunları nedeniyle alıcı oturumuna yeniden bağlanma işlemi de Cast SDK'sı tarafından otomatik olarak gerçekleştirilir.
LocalPlayerActivity
öğesine 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, yayın cihazıyla bağlantı kurulduğunda veya cihaz bağlantısı kesildiğinde bildirim almak istiyoruz. Böylece yerel oynatıcıya geçebilir veya ondan ayrılabiliriz. Bağlantının yalnızca uygulamanızın mobil cihazınızda çalışmasından kaynaklanabileceğini, aynı zamanda uygulamanızın (veya başka bir uygulamanın farklı bir mobil cihazda) çalışmasından kaynaklanabileceğini de unutmayın.
Şu anda etkin olan oturuma SessionManager.getCurrentSession()
hesabıyla erişilebilir. Oturumlar, kullanıcıların Cast iletişim kutularıyla kurduğu etkileşimlere göre otomatik olarak oluşturulur ve bölünür.
Oturum işleyicimizi 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'da 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 RemoteMediaClient
örneği oluşturulur. CastSession
örneğinde getRemoteMediaClient()
yöntemi çağrılarak erişilebilir. Şu anda seçili olan videoyu alıcıya yüklemek için LocalPlayerActivity
ürününe 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 üzere Google Cast oturumu mantığını kullanmak için mevcut çeşitli yöntemleri 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 mobil cihazınızda uygulamayı çalıştırmak için Çalıştır düğmesini tıklayın. Yayın cihazınıza bağlanıp video oynatmaya başlayın. Videonun alıcıda oynatıldığını göreceksiniz.
7. Mini kumanda
Cast Tasarımı Kontrol Listesi, tüm Cast uygulamalarında, kullanıcı mevcut içerik sayfasından ayrıldığında görünen bir mini kumanda sağlamalıdır. Mini kumanda, anında erişim sağlar ve mevcut yayın oturumu için görünür bir hatırlatıcı içerir.
Cast SDK'sı, mini kumandayı göstermek istediğiniz etkinliklerin uygulama düzeni dosyasına eklenebilecek ö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 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 altında mini kumandayı görürsünüz. Mini kumandayı kullanarak uzaktan oynatmayı kontrol edebilirsiniz. Göz atma etkinliği ile yerel oynatıcı etkinliği arasında geçiş yaparsanız mini kumanda durumu, alıcının medya oynatma durumuyla senkronize olmalıdır.
8. Bildirim ve kilit ekranı
Google Cast tasarımıyla ilgili yapılacaklar listesi, bir gönderen uygulamasının bildirim ve kilit ekranından medya denetimlerini uygulamasını gerektirir.
Cast SDK'sı, gönderen uygulamasının bildirim ve kilit ekranı için medya denetimleri oluşturmasına yardımcı olan bir MediaNotificationService
sağlar. Hizmet, gradle ile otomatik olarak uygulamanızın manifestiyle birleştirilir.
MediaNotificationService
, gönderen yayın yaparken arka planda çalışır ve mevcut yayın öğesiyle ilgili küçük resim ve meta veriler, oynat/duraklat düğmesi ve durdurma düğmesi içeren bir bildirim gösterir.
Bildirim ve kilit ekranı denetimleri, CastContext
başlatılırken CastOptions
ile etkinleştirilebilir. Bildirim ve kilit ekranı ile ilgili medya denetimleri varsayılan olarak etkindir. Bildirim etkin olduğu sürece kilit ekranı özelliği de etkindir.
CastOptionsProvider
öğesini düzenleyin ve getCastOptions
uygulamasını şu 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 ayrılın. Alıcıda oynatılan videoyla ilgili bir bildirim olmalıdır. Mobil cihazınızı kilitlediğinizde kilit ekranında Yayın cihazında medya oynatma kontrolleri gösterilir.
9. Tanıtım yer paylaşımı
Google Cast tasarım yapılacaklar listesi, bir gönderen uygulamasının mevcut kullanıcılara yayın düğmesini tanıtmasını gerektirir. Bu şekilde kullanıcılar, söz konusu uygulamanın artık yayınlamayı desteklediğini ve Google Cast'i yeni kullanmaya başlayan kullanıcılara yardımcı olur.
Cast SDK'sı, kullanıcılara ilk kez gösterildiğinde Yayınla düğmesini vurgulamak için kullanılabilecek özel bir IntroductoryOverlay
görünümü sağlar. Şu kodu VideoBrowserActivity
alanı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 bir CastStateListener
ekleyin ve onCreate
yöntemini değiştirerek onResume
ve onPause
yöntemlerini aşağıdakilerle 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ş denetleyici
Google Cast tasarım kontrol listesi, bir gönderen uygulamasının yayınlanan medya için genişletilmiş denetleyici sağlamasını gerektirir. Genişletilmiş kumanda, mini kumandanın tam ekran sürümüdür.
Cast SDK'sı, genişletilmiş denetleyici için ExpandedControllerActivity
adlı bir widget sağlar. Bu, Yayınla düğmesi eklemek için alt sınıfa girmeniz gereken soyut bir sınıftır.
İlk olarak genişletilmiş denetleyicinin Yayınla düğmesini sağlaması için 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 expandedcontrols
paketi oluşturun. Sonra, com.google.sample.cast.refplayer.expandedcontrols
paketinde ExpandedControlsActivity.kt
adında 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
öğesinin üzerindeki application
etiketinin içindeki AndroidManifest.xml
içindeki 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
değerlerini 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örüntülemek 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ırıp video yayınlamak için Çalıştır düğmesini tıklayın. Genişletilmiş denetleyici göreceksiniz. Video listesine geri dönün. Mini kumandayı tıkladığınızda genişletilmiş kumanda tekrar yüklenir. Bildirimi görmek için uygulamadan ayrılın. Genişletilmiş denetleyiciyi yüklemek için bildirim resmini tıklayın.
11. Cast Connect desteği ekleyin
Cast Connect kitaplığı, mevcut gönderen uygulamalarının Cast protokolü üzerinden 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ını temel alır.
Bağımlılıklar
Not: Cast Connect'in uygulanması için play-services-cast-framework
değerinin 19.0.0
veya daha yüksek olması gerekir.
LaunchOptions
Android Alıcı olarak da bilinen Android TV uygulamasını başlatmak için LaunchOptions
nesnesinde setAndroidReceiverCompatible
işaretini doğru değerine ayarlamamız gerekir. Bu LaunchOptions
nesnesi, alıcının nasıl başlatılacağını ve CastOptionsProvider
sınıfı tarafından döndürülen CastOptions
öğesine iletileceğini belirtir. Yukarıda belirtilen işaret false
olarak ayarlanırsa Cast Developer Console'da tanımlanan uygulama kimliği için web alıcı 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 Ayarlayın
Gönderen tarafında, oturuma kimlerin katılabileceğini belirtmek için CredentialsData
belirtebilirsiniz. credentials
, ATV uygulamanız anabildiği sürece kullanıcı tarafından tanımlanabilecek bir dizedir. CredentialsData
, Android TV uygulamanıza yalnızca başlatma veya katılma sırasında aktarılır. İnternete bağlıyken tekrar ayarlarsanız Android TV uygulamanıza aktarılmaz.
Başlatma Kimlik Bilgilerini ayarlamak için CredentialsData
öğesinin tanımlanması ve LaunchOptions
nesnesine iletilmesi gerekir. 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'te Kimlik Bilgilerini Ayarlama
Web Alıcı uygulamanız ve Android TV uygulamanız credentials
öğesini farklı şekilde kullanıyorsa her biri için ayrı credentials
tanımlamanız gerekebilir. Bu sorunu gidermek için LocalPlayerActivity.kt
dosyanızda 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 artık geçerli oturum için kullanılacak kimlik bilgilerinin otomatik olarak işlenmesini sağlar.
Cast Connect test ediliyor
Android TV APK'sını Google TV Yüklü Chromecast'e yükleme adımları
- Android TV cihazınızın IP adresini bulun. Bu işlev genellikle Ayarlar > Ağ ve İnternet > (Cihazınızın bağlı olduğu ağ adı). Sağ tarafta ayrıntılar ve cihazınızın ağdaki IP'si gösterilir.
- Cihazınıza ADB üzerinden bağlanmak için terminali kullanarak cihazınızın IP adresini kullanın:
$ adb connect <device_ip_address>:5555
- Terminal pencerenizden, bu codelab'in başında indirdiğiniz codelab örneklerinin bulunduğu üst düzey klasöre gidin. Örneğin:
$ cd Desktop/android_codelab_src
- Aşağıdaki komutu çalıştırarak bu klasördeki .apk dosyasını Android TV'nize yükleyin:
$ adb -s <device_ip_address>:5555 install android-tv-app.apk
- Artık Android TV cihazınızdaki Uygulamalarınız menüsünde Video Yayınla adlı uygulamayı görebilirsiniz.
- Android Studio projenize dönün ve uygulamayı yüklemek için Çalıştır düğmesini tıklayın ve gönderen uygulamasını fiziksel mobil cihazınızda çalıştırabilirsiniz. Sağ üst köşedeki yayınlama simgesini tıklayıp mevcut seçenekler arasından Android TV cihazınızı seçin. Şimdi Android TV uygulamasının Android TV cihazınızda başlatıldığını görüyor olmanız ve video oynattığınızda, video oynatmayı Android TV uzaktan kumandanızı kullanarak kontrol edebileceksiniz.
12. Yayınlama widget'larını özelleştirin
Yayınlama widget'larını özelleştirmek için renkleri ayarlayabilir, düğmelerin, metinlerin ve küçük resim görünümünün şekillendirilmesini sağlayabilir ve görüntülenecek düğme türlerini seçebilirsiniz.
res/values/styles_castvideo.xml
öğelerini güncelle
<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ı tanımlayın:
<!-- 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ını nasıl yayınlayabileceğinizi biliyorsunuz.
Daha ayrıntılı bilgi için Android Sender geliştirici kılavuzuna bakın.