Bir Android uygulamasını Cast uyumlu hale getirme

1. Genel Bakış

Google Cast logosu

Bu kod laboratuvarında, mevcut bir Android video uygulamasını Google Cast uyumlu bir cihazda içerik yayınlayacak şekilde nasıl değiştireceğinizi öğreneceksiniz.

Google Cast nedir?

Google Cast, kullanıcıların mobil cihazdan TV'ye içerik yayınlamasına olanak tanır. Kullanıcılar, mobil cihazlarını TV'de medya oynatmak için 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 Listesi, Cast kullanıcı deneyimini desteklenen tüm platformlarda basit ve tahmin edilebilir hale getirmek için sağlanmıştır.

Ne oluşturacağız?

Bu kod laboratuvarını tamamladığınızda, Google Cast özellikli bir cihazda video yayınlayabilecek bir Android video uygulamasına sahip olursunuz.

Neler öğreneceksiniz?

  • Google Cast SDK'sını örnek bir video uygulamasına ekleme.
  • Google Cast cihazı seçmek için Cast düğmesini ekleme.
  • Bir Cast cihazına bağlanma ve medya alıcısını başlatma.
  • Video yayınlama
  • Uygulamanıza Cast mini kontrol cihazı ekleme.
  • Medya bildirimleri ve kilit ekranı kontrolleri nasıl desteklenir?
  • Genişletilmiş denetleyici ekleme.
  • Tanıtım yer paylaşımı nasıl sağlanır?
  • Yayın widget'larını özelleştirme
  • 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 ve sonraki sürümleri (API düzeyi 16) çalıştıran bir mobil cihaz.
  • Mobil cihazınızı geliştirme bilgisayarınıza bağlamak için USB veri kablosu.
  • İnternet erişimi yapılandırılmış bir Chromecast veya Android TV gibi 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 hakkında bilgi sahibi olmanız gerekir.
  • Ayrıca TV izleme konusunda bilgi sahibi olmanız gerekir.

Bu eğiticiden nasıl yararlanacaksınız?

Sadece okumayı Okuyun ve alıştırmaları tamamlayın

Android uygulamaları geliştirme deneyiminizi nasıl değerlendirirsiniz?

Acemi Orta Uzman

TV izleme deneyiminizi nasıl değerlendirirsiniz?

Acemi Orta Seviye Uzman

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

bir çift pusula simgesi

Ö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 ve ardından videoyu cihazda yerel olarak oynatabilir veya bir Google Cast cihazına 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:

Hoş geldiniz ekranında Proje İçe Aktar'ı veya Dosya > Yeni > Proje İçe Aktar... menü seçeneklerini belirleyin.

Örnek kod klasöründen klasör simgesiapp-done dizinini seçip Tamam'ı tıklayın.

Dosya > Android Studio "Projeyi Gradle ile senkronize et" düğmesi Projeyi Gradle Dosyalarıyla Senkronize Et'i tıklayın.

Android cihazınızda USB hata ayıklama özelliğini etkinleştirin. Android 4.2 ve sonraki sürümlerde Geliştirici seçenekleri ekranı varsayılan olarak gizlidir. Görüntülemek için Ayarlar > Telefon hakkında'ya gidin ve Derleme numarası'na yedi kez dokunun. Önceki ekrana dönün, Sistem > Gelişmiş'e gidin ve alt tarafa yakın bir yerde Geliştirici seçenekleri'ne dokunun, ardından USB üzerinden hata ayıklama'ya dokunarak bu özelliği açın.

Android cihazınızı prize takın ve Android Studio'da Android Studio'nun sağa bakan yeşil üçgen Çalıştır düğmesiÇalıştır düğmesini tıklayın. Birkaç saniye sonra Videoları Yayınla adlı video uygulaması gösterilir.

Video uygulamasındaki Cast düğmesini tıklayın ve Google Cast cihazınızı seçin.

Bir video seçin ve oynat düğmesini tıklayın.

Video, Google Cast cihazınızda oynatılmaya başlar.

Genişletilmiş kontrol cihazı gösterilir. Oynatmayı kontrol etmek için oynatma/duraklatma düğmesini kullanabilirsiniz.

Video listesine geri dönün.

Ekranın alt kısmında mini bir kontrol cihazı görünür. Ekranın alt kısmında mini kontrol cihazının göründüğü "Videoları Yayınla" uygulamasını çalıştıran bir Android telefonun resmi

Alıcıdaki videoyu duraklatmak için mini kumandadaki duraklat düğmesini tıklayın. Videoyu tekrar oynatmaya devam etmek için mini kontrol cihazındaki oynatma düğmesini tıklayın.

Mobil cihazın ana sayfa düğmesini tıklayın. Bildirimleri aşağı çekin. Artık Cast oturumuyla ilgili bir bildirim göreceksiniz.

Telefonunuzu kilitleyin ve kilidini açtığınızda kilit ekranında medya oynatmayı kontrol etme veya yayınlamayı durdurma bildirimini 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

"Video Yayınla" uygulamasını çalıştıran Android telefonun görseli

İndirdiğiniz başlangıç uygulamasına Google Cast desteği eklememiz gerekiyor. Bu codelab'de kullanacağımız bazı Google Cast terimleri şunlardır:

  • Mobil cihazda veya dizüstü bilgisayarda bir gönderen uygulaması çalışır,
  • Google Cast cihazında bir alıcı uygulaması çalışır.

Artık Android Studio'yu kullanarak başlangıç projesinin üzerine uygulama geliştirmeye hazırsınız:

  1. İndirdiğiniz örnek koddaki klasör simgesiapp-start dizinini seçin (hoş geldiniz ekranında Projeyi İçe Aktar'ı veya Dosya > Yeni > Projeyi İçe Aktar... menü seçeneğini belirleyin).
  2. Android Studio "Projeyi Gradle ile senkronize et" düğmesi Projeyi Gradle Dosyalarıyla Senkronize Et düğmesini tıklayın.
  3. Uygulamayı çalıştırmak ve kullanıcı arayüzünü keşfetmek için Android Studio'nun sağa bakan yeşil üçgen Çalıştır düğmesiÇ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çerir. Bu liste bir ArrayAdapter (VideoListAdapter) ile desteklenir. Videoların listesi ve ilişkili meta verileri, uzak bir sunucuda JSON dosyası olarak barındırılır. AsyncTaskLoader (VideoItemLoader), bu JSON'u getirir ve MediaItem nesnelerinin listesini oluşturmak için işler.

MediaItem nesnesi, bir videoyu ve videoyla ilişkili meta verileri (ör. başlığı, açıklaması, yayının URL'si, destekleyici resimlerin URL'si ve varsa altyazılar için ilişkili metin parçaları) modeller. MediaItem nesnesi etkinlikler arasında iletildiğinden MediaItem, kendisini Bundle'e ve bunun tersine dönüştürmek için yardımcı yöntemlere 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, ilgili MediaItem bir Bundle'a dönüştürülür ve LocalPlayerActivity'ye iletilir.

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ı kaplar ve videonun ayrıntılı açıklamasına 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

Video Cast uygulamasının çalıştığı bir Android telefonun üst kısmının resmi; ekranın sağ üst köşesinde Yayınla düğmesi görünüyor

Cast uyumlu bir uygulama, etkinliklerinin her birinde Cast düğmesini gösterir. Yayınla düğmesini tıkladığınızda kullanıcının seçebileceği Cast cihazlarının listesi gösterilir. 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. Kullanıcı, Cast oturumu sırasında dilediğinde Cast düğmesini tıklayarak uygulamanızı Cast cihazına yayınlamayı durdurabilir. Kullanıcı, Google Cast Tasarım Kontrol Listesi'nde açıklandığı gibi, uygulamanızdaki herhangi bir etkinlikteyken Cast cihazına bağlanabilmeli veya Cast cihazıyla bağlantısını kesebilmelidir.

Bağımlılıklar

Uygulamanın 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"
}

Projenin hatasız derlendiğini doğrulamak 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 tekil nesnesi için gerekli CastOptions değerini sağlamak üzere OptionsProvider arayüzünü uygulamanız gerekir. En önemli seçenek, Cast cihazı keşif sonuçlarını filtrelemek ve bir Cast oturumu başlatıldığında alıcı uygulamasını başlatmak için kullanılan alıcı uygulama kimliğidir.

Kendi Cast özellikli 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 kod laboratuvarında ö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
    }
}

Ardından, AndroidManifest.xml uygulamasının "application" etiketinde OptionsProvider öğesini beyan edin:

<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 yavaşça 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 Cast cihazı seçmesine izin vermek için Cast düğmesini eklememiz gerekir. Yayınla düğmesi, MediaRouter destek kitaplığındaki MediaRouteButton tarafından uygulanır. Etkinliğinize ekleyebileceğiniz tüm işlem simgelerinde (ActionBar veya Toolbar kullanılarak) olduğu gibi, önce ilgili menü öğesini menünüze eklemeniz gerekir.

res/menu/browse.xml dosyasını düzenleyin ve menüye 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"/>

MediaRouteButton öğesini Cast çerçevesine bağlamak için CastButtonFactory kullanarak VideoBrowserActivity öğesinin 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 Android Studio&#39;nun sağa bakan yeşil üçgen Çalıştır düğmesiÇ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 özelliği CastContext tarafından otomatik olarak yönetilir. Cast cihazınızı seçtiğinizde örnek alıcı uygulaması Cast cihazına yüklenir. Göz atma etkinliği ile yerel oynatıcı etkinliği arasında gezinebilirsiniz. Bu sırada Yayınla düğmesi durumu senkronize edilir.

Medya oynatma için henüz destek sağlamadığımızdan Cast cihazda henüz video oynatamazsınız. Bağlantıyı kesmek için Yayınla düğmesini tıklayın.

6. Video içeriğini yayınlama

&quot;Video Yayınla&quot; uygulamasını çalıştıran bir Android telefonun resmi

Örnek uygulamayı, Cast cihazlarda da videoları uzaktan oynatacak şekilde genişleteceğiz. Bunu yapmak için Cast çerçevesi tarafından oluşturulan çeşitli etkinlikleri dinlememiz gerekiyor.

Medya yayınlama

Bir Cast cihazda medya oynatmak için genel olarak şunları yapmanız gerekir:

  1. Bir medya öğesini modelleyen bir MediaInfo nesnesi oluşturun.
  2. Yayın cihazına bağlanın ve alıcı uygulamanızı başlatın.
  3. MediaInfo nesnesini alıcınıza yükleyin ve içeriği oynatın.
  4. Medya durumunu izleyin.
  5. Kullanıcı etkileşimlerine göre oynatma komutlarını alıcıya gönderme.

2. adımı önceki bölümde tamamlamıştık. 3. adımı Cast çerçevesiyle kolayca yapabilirsiniz. 1. adım, bir nesnenin diğeriyle eşlenmesini ifade eder; MediaInfo, Cast çerçevesinin anladığı bir şeydir ve MediaItem, uygulamamızın bir medya öğesi için sarmalayıcısıdır; MediaItem'yi MediaInfo ile kolayca 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, örnek oynatıcı mantığının tümünün tam olarak nasıl çalıştığını anlamanız gerekmez. İ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.

Yerel oynatıcı, henüz Yayınlama durumları hakkında hiçbir şey bilmediği için şu anda her zaman yerel oynatma durumundadır. Kullanıcı arayüzünü, Cast çerçevesinde gerçekleşen durum geçişlerine göre güncellememiz gerekiyor. Örneğin, yayınlamaya başlarsak yerel oynatmayı durdurmamız ve bazı kontrolleri devre dışı bırakmamız gerekir. Benzer şekilde, bu etkinlikteyken yayınlamayı durdurursak yerel oynatmaya geçmemiz gerekir. Bunu yapabilmek için Cast çerçevesi tarafından oluşturulan çeşitli etkinlikleri dinlememiz gerekir.

Yayın oturumu yönetimi

Cast çerçevesi için Cast oturumu, bir cihaza bağlanma, başlatma (veya katılma), alıcı uygulamasına bağlanma ve uygun durumlarda bir medya kontrol kanalını başlatma adımlarını birleştirir. Medya kontrol kanalı, Cast çerçevesinin alıcı medya oynatıcıya mesaj gönderip almasını sağlar.

Kullanıcı Yayınla düğmesinden bir cihaz seçtiğinde Yayınlama oturumu otomatik olarak başlatılır ve kullanıcı bağlantıyı kestikten sonra 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 alanına bir 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çiş yapabilmemiz için Cast cihazına bağlandığımızda veya Cast cihazıyla bağlantımız kesildiğinde bilgilendirilmek isteriz. 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() olarak erişilebilir. Oturumlar, kullanıcıların Cast iletişim kutularıyla etkileşimlerine yanıt olarak otomatik olarak oluşturulur ve kapatılır.

Oturum dinleyicimizi kaydetmemiz ve etkinlikte kullanacağımız bazı değişkenleri başlatmamız gerekir. 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 bir 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 öğesine 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()
    }
}

Artık uzaktan oynatmayı desteklemek için Cast oturumu mantığını kullanmak üzere 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))
    ...
}

Ardından, mobil cihazınızda uygulamayı çalıştırmak için Android Studio&#39;nun sağa bakan yeşil üçgen Çalıştır düğmesiÇ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 oynattığınızdan emin olun.

7. Mini kontrol cihazı

Cast Tasarım Kontrol Listesi, tüm Cast uygulamalarının kullanıcı mevcut içerik sayfasından ayrıldığında görünen bir mini kontrol cihazı sağlamasını zorunlu kılar. Mini kontrol cihazı, anında erişim sağlar ve mevcut Cast oturumu için görünür bir hatırlatıcı sunar.

Android telefonun alt kısmında bulunan ve Videolar Yayınla uygulamasındaki mini oynatıcıyı gösteren görsel

Cast SDK'sı, mini denetleyiciyi 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'un 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 Android Studio&#39;nun sağa bakan yeşil üçgen Çalıştır düğmesiÇalıştır düğmesini tıklayın. Alıcıda oynatma başladığında her etkinliğin alt kısmında mini kontrol cihazını görürsünüz. 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 kontrol cihazının durumu, alıcı medya oynatma durumuyla senkronize kalır.

8. Bildirim ve kilit ekranı

Google Cast tasarımı yapılacaklar listesi, gönderen uygulamasının bildirim ve kilit ekranından medya denetimleri uygulaması gerektiğini belirtir.

Bildirimler alanında medya denetimlerini gösteren bir Android telefonun resmi

Cast SDK'sı, gönderen uygulamanın bildirim ve kilit ekranı için medya kontrolleri oluşturmasına yardımcı olan 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 geçerli yayın öğesi, oynatma/duraklatma ve durdurma düğmeleri ile birlikte küçük resim ve meta veriler içeren bir bildirim gösterir.

Bildirim ve kilit ekranı denetimleri, CastContext başlatılırken CastOptions ile etkinleştirilebilir. Bildirim ve kilit ekranı için medya denetimleri varsayılan olarak açıktır. Bildirim açık olduğu sürece kilit ekranı özelliği de açıktır.

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 Android Studio&#39;nun sağa bakan yeşil üçgen Çalıştır düğmesiÇalıştır düğmesini tıklayın. Bir videoyu yayınlayıp örnek uygulamadan çıkın. Alıcının şu anda oynatmakta olduğu videoyla ilgili bir bildirim gösterilir. Mobil cihazınızı kilitleyin. Kilit ekranında artık Cast cihazındaki medya oynatma denetimleri gösterilir.

Kilit ekranındaki medya denetimlerini gösteren bir Android telefonun resmi

9. Tanıtım amaçlı yer paylaşımı

Google Cast tasarımı yapılacaklar listesi, gönderen uygulamasının mevcut kullanıcılara Cast düğmesini tanıtmasını gerektirir. Böylece gönderen uygulamasının artık yayınlamayı desteklediğini ve Google Cast'te yeni olan kullanıcılara yardımcı olduğunu bildirebilir.

Android uygulamasında Video Yayınla düğmesinin etrafındaki ilk yayın içi yer paylaşımını gösteren görsel

Cast SDK'sı, kullanıcılara ilk kez gösterildiğinde Cast 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 bir CastStateListener ekleyin ve onCreate yöntemini değiştirerek Cast cihazı mevcut olduğunda showIntroductoryOverlay yöntemini çağırın. Ardından onResume ve onPause yöntemlerini aşağıdakiyle eşleşecek şekilde geçersiz kılı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 Android Studio&#39;nun sağa bakan yeşil üçgen Çalıştır düğmesiÇalıştır düğmesini tıklayın. Giriş yer paylaşımını görürsünüz (yer paylaşımı görünmüyorsa uygulama verilerini temizleyin).

10. Genişletilmiş kontrol cihazı

Google Cast tasarımı yapılacaklar listesi, gönderen uygulamasının, aktarılan medya için genişletilmiş denetleyici sağlamasını gerektirir. Genişletilmiş kumanda, mini kumandanın tam ekran sürümüdür.

Android telefonda oynatılan bir videonun üzerine genişletilmiş denetleyicinin yerleştirildiği görsel

Cast SDK'sı, genişletilmiş denetleyici için ExpandedControllerActivity adlı bir widget sağlar. Bu, yayınlama düğmesi eklemek için alt sınıf oluşturmanız gereken soyut bir sınıftır.

Öncelikle, genişletilmiş denetleyicinin Yayınla düğmesini sağlaması için expanded_controller.xml adlı yeni bir menü kaynağı 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 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'ın üzerindeki application etiketinde AndroidManifest.xml içinde ExpandedControlsActivity'ü 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>

Hedef etkinliği ExpandedControlsActivity olarak ayarlamak için CastOptionsProvider'ü düzenleyin ve 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ırmak ve video yayınlamak için Android Studio&#39;nun sağa bakan yeşil üçgen Çalıştır düğmesiÇalıştır düğmesini tıklayın. Genişletilmiş denetleyiciyi görürsünüz. 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 ekleme

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 alıcı olarak görev yaptığında Cast altyapısının üzerine kuruludur.

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 TV uygulaması (Android alıcı olarak da bilinir) başlatmak için LaunchOptions nesnesinde setAndroidReceiverCompatible işaretini 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 nesnesine iletilir. Yukarıda belirtilen işareti false olarak ayarlamak, Cast Developer Console'da tanımlanan uygulama kimliği için web alıcısını başlatı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()

Lansman Kimlik Bilgilerini Ayarlama

Gönderen tarafında, oturuma kimin katıldığını belirtmek için CredentialsData değerini kullanabilirsiniz. credentials, ATV uygulamanız tarafından anlaşıldığı sürece kullanıcı tarafından tanımlanabilen bir dizedir. CredentialsData yalnızca Android TV uygulamanıza başlatma veya katılma sırasında iletilir. Bağlantınız açıkken tekrar ayarlarsanız bu ayar 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'yi farklı şekilde ele alıyorsa her biri için ayrı credentials tanımlamanız gerekebilir. Bu sorunu gidermek 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ınladığı alıcı uygulamaya bağlı olarak SDK, mevcut oturum için hangi kimlik bilgilerinin kullanılacağını otomatik olarak yönetir.

Cast Connect'i test etme

Android TV APK'sını Google TV Yüklü Chromecast'e yükleme adımları

  1. Android TV cihazınızın IP adresini bulun. Genellikle Ayarlar > Ağ ve İnternet > (Cihazınızın bağlı olduğu ağ adı) bölümünde bulunur. Sağ tarafta, ayrıntılar ve cihazınızın ağdaki IP adresi gösterilir.
  2. Terminali kullanarak cihazınıza ADB üzerinden bağlanmak için cihazınızın IP adresini kullanın:
$ adb connect <device_ip_address>:5555
  1. Terminal pencerenizde, bu codelab'in başında indirdiğiniz codelab örneklerinin üst düzey klasörüne gidin. Örneğin:
$ cd Desktop/android_codelab_src
  1. Aşağıdakileri uygulayarak bu klasördeki .apk dosyasını Android TV'nize yükleyin:
$ adb -s <device_ip_address>:5555 install android-tv-app.apk
  1. Artık Android TV cihazınızdaki Uygulamalarınız menüsünde Video Yayınla adlı uygulamayı görebilirsiniz.
  2. 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öşedeki yayınla simgesini tıklayın ve mevcut seçenekler arasından Android TV cihazınızı seçin. Artık Android TV cihazınızda Android TV uygulamasının başlatıldığını göreceksiniz. Bir video oynattığınızda Android TV uzaktan kumandanızı kullanarak video oynatmayı kontrol edebilirsiniz.

12. Yayınlama widget'larını özelleştirin

Renkleri ayarlayarak, düğmelere, metne ve küçük resim görünümüne stil uygulayarak ve gösterilecek düğme türlerini seçerek Yayın widget'larını özelleştirebilirsiniz.

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ın Cast'i nasıl etkinleştireceğinizi biliyorsunuz.

Daha fazla bilgi için Android Gönderen geliştirici kılavuzunu inceleyin.