Bir Android uygulamasını Cast uyumlu hale getirme

1. Genel Bakış

Google Cast logosu

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?

Yalnızca okuma Okuyun ve alıştırmaları tamamlayın

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

Acemi Orta Yeterli

TV izleme deneyiminizi nasıl değerlendirirsiniz?

Acemi Orta Yeterli

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

bir çift pusula simgesi

Ö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 klasör simgesiapp-done dizinini seçip Tamam'ı tıklayın.

Dosya > Android Studio "Projeyi Gradle ile Senkronize Et" düğme 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 Android Studio'nun Çalıştır düğmesi, sağı gösteren yeşil bir üçgenÇ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. "Video Yayınla" özelliğini çalıştıran Android telefonun görseli ekranın altında görünen mini kumandanın yer aldığı uygulama

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

"Video Yayınla" özelliğini çalıştıran Android telefonun görseli uygulama

İ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:

  1. Örnek kod indirme işleminizden klasör simgesiapp-start dizinini seçin (Karşılama 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üğme 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 Çalıştır düğmesi, sağı gösteren yeşil bir üçgenÇ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 Video uygulamasının çalıştığı bir Android telefonun üst kısmının görseli; ekranın sağ üst köşesinde görünen Yayınla düğmesi

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 Android Studio&#39;nun Çalıştır düğmesi, sağı gösteren yeşil bir üçgenÇ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

&quot;Video Yayınla&quot; özelliğini çalıştıran Android telefonun görseli uygulama

Ö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:

  1. 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 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 Android Studio&#39;nun Çalıştır düğmesi, sağı gösteren yeşil bir üçgenÇ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.

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 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 Android Studio&#39;nun Çalıştır düğmesi, sağı gösteren yeşil bir üçgenÇ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.

Bildirimler alanındaki medya kontrollerini gösteren Android telefon resmi

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 Android Studio&#39;nun Çalıştır düğmesi, sağı gösteren yeşil bir üçgenÇ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.

Kilit ekranında medya denetimlerini gösteren bir Android telefon resmi

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.

Video Yayınla Android uygulamasındaki Yayınla düğmesinin etrafındaki Yayın yer paylaşımını tanıtım amaçlı gösteren görsel

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 Android Studio&#39;nun Çalıştır düğmesi, sağı gösteren yeşil bir üçgenÇ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.

Genişletilmiş kumanda ile Android telefonda oynatılan bir video görseli

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 Android Studio&#39;nun Çalıştır düğmesi, sağı gösteren yeşil bir üçgenÇ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ı

  1. 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.
  2. 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
  1. 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
  1. 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
  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 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.