Cast'i Android Uygulamanıza Entegre Edin

Bu geliştirici kılavuzunda, Google Cast desteğini Android cihazınıza nasıl ekleyeceğiniz açıklanmaktadır. Android Sender SDK'sı kullanan bir gönderen uygulaması.

Mobil cihaz veya dizüstü bilgisayar, oynatmayı kontrol eden gönderendir ve Google Cast cihazı, içeriği TV'de görüntüleyen Alıcıdır.

Gönderen çerçevesi, Cast sınıf kitaplığı ikili programını ve kaynaklar gönderilir. Gönderen uygulaması veya Cast uygulaması gönderen üzerinde de çalışan bir uygulama anlamına gelir. Web Alıcı uygulaması Cast uyumlu cihazda çalışan HTML uygulamasını belirtir.

Gönderen çerçevesi, göndereni bilgilendirmek için eşzamansız bir geri çağırma tasarımı kullanır ve Cast uygulaması hayatının çeşitli durumları arasında geçiş yapmak için kullanılan döngüsünü de takip eder.

Uygulama akışı

Aşağıdaki adımlarda, bir gönderen için tipik üst düzey yürütme akışı açıklanmaktadır Android uygulaması:

  • Cast çerçevesi otomatik olarak başlatılır MediaRouter Activity yaşam döngüsüne göre cihaz keşfi.
  • Kullanıcı Yayınla düğmesini tıkladığında çerçeve, Yayınla iletişim kutusu gösterilir.
  • Kullanıcı bir yayın cihazı seçtiğinde çerçeve, cihazın ilk birkaç adımını Yayın cihazındaki Web Alıcı uygulaması.
  • Çerçeve, web sitesinin kapsayıcı olmadığını doğrulamak için gönderen uygulamasında geri çağırmaları Alıcı uygulaması kullanıma sunuldu.
  • Bu çerçeve, gönderen ile web arasında bir iletişim kanalı oluşturur Alıcı uygulamalar.
  • Bu çerçeve, medya içeriklerini yüklemek ve kontrol etmek için iletişim kanalını kullanır. Web Alıcısı'nda oynatma.
  • Çerçeve, medya oynatma durumunu gönderen ve Web Alıcı: Kullanıcı, gönderen kullanıcı arayüzü işlemleri yaptığında çerçeve Web Alıcısı'na göndermek ve Web Alıcısı medya durumu güncellemeleri gönderdiğinde çerçeve, gönderen kullanıcı arayüzünün durumunu günceller.
  • Kullanıcı Yayın cihazı bağlantısını kesmek için Yayın düğmesini tıkladığında çerçeve, gönderen uygulamasının Web Alıcısı ile bağlantısını keser.

Google Cast'teki tüm sınıfların, yöntemlerin ve etkinliklerin kapsamlı listesi için Android SDK; Google Cast Sender API Reference for Android. Aşağıdaki bölümlerde, Android uygulamanıza Cast'i eklemeniz için uygulanacak adımlar ele alınmaktadır.

Android manifestini yapılandırma

Uygulamanızın AndroidManifest.xml dosyası için aşağıdaki kodu yapılandırmanız gerekiyor öğeleri oluşturun:

uses-sdk

Cast SDK'sının desteklediği minimum ve hedef Android API düzeylerini belirleyin. Şu anda minimum değer API düzeyi 23'tür, hedef ise API düzeyi 34.

<uses-sdk
        android:minSdkVersion="23"
        android:targetSdkVersion="34" />

android:theme

Uygulamanızın temasını minimum Android SDK sürümüne göre ayarlayın. Örneğin, kendi temanızı uygulamıyorsanız, Şu minimum Android SDK sürümü hedeflendiğinde Theme.AppCompat Lollipop'tan önce gelir.

<application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/Theme.AppCompat" >
       ...
</application>

Yayınlama Bağlamını Başlat

Çerçeve, tablodaki global bir tekil nesne (CastContext) içerir. tüm çerçevelerin etkileşimleri.

Uygulamanız OptionsProvider ilk kullanıma hazırlamak için gereken seçenekleri sağlayacak CastContext singleton. OptionsProvider, şunu sağlar: CastOptions seçenekleri içerir. En Bunlardan en önemlisi, algoritmik verileri filtrelemek için kullanılan en son sürümüne sahip olduğunu ve yayın oturumu başladığında Web Alıcı uygulamasını başladı.

Kotlin
class CastOptionsProvider : OptionsProvider {
    override fun getCastOptions(context: Context): CastOptions {
        return Builder()
            .setReceiverApplicationId(context.getString(R.string.app_id))
            .build()
    }

    override fun getAdditionalSessionProviders(context: Context): List<SessionProvider>? {
        return null
    }
}
Java
public class CastOptionsProvider implements OptionsProvider {
    @Override
    public CastOptions getCastOptions(Context context) {
        CastOptions castOptions = new CastOptions.Builder()
            .setReceiverApplicationId(context.getString(R.string.app_id))
            .build();
        return castOptions;
    }
    @Override
    public List<SessionProvider> getAdditionalSessionProviders(Context context) {
        return null;
    }
}

Uygulanan OptionsProvider öğesinin tam adını beyan etmeniz gerekir gönderen uygulamasının AndroidManifest.xml dosyasında meta veri alanı olarak:

<application>
    ...
    <meta-data
        android:name=
            "com.google.android.gms.cast.framework.OPTIONS_PROVIDER_CLASS_NAME"
        android:value="com.foo.CastOptionsProvider" />
</application>

CastContext.getSharedInstance() şu durumlarda CastContext geç başlatılır: çağrılır.

Kotlin
class MyActivity : FragmentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        val castContext = CastContext.getSharedInstance(this)
    }
}
Java
public class MyActivity extends FragmentActivity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        CastContext castContext = CastContext.getSharedInstance(this);
    }
}

Cast UX Widget'ları

Cast çerçevesi, Cast Tasarımı'na uygun widget'lar sağlar. Yapılacaklar listesi:

  • Tanıtım Yer Paylaşımı: Çerçeve, özel bir Görünüm sağlar, IntroductoryOverlay, kullanıcının Yayınla düğmesine dikkatini göstermesi için yeni bir e-posta alırsınız. Sender uygulaması, Metni ve başlığın konumunu özelleştirin metin.

  • Yayınla Düğmesi: Yayınla düğmesi, yayın cihazlarının kullanılabilirliğinden bağımsız olarak görünür. Kullanıcı Yayınla düğmesini ilk kez tıkladığında Yayınla iletişim kutusu görüntülenir cihazlar listelenir. Kullanıcı Yayınla düğmesini tıkladığında Cihaz bağlıyken, geçerli medya meta verilerini (örneğin, başlığı, kayıt stüdyosunun adı ve küçük resim) veya kullanıcının yayın cihazıyla bağlantıyı kesin. "Yayınla düğmesi" bazen "Yayınla simgesi" olarak değiştirebilirsiniz.

  • Mini Kumanda: Kullanıcı içerik yayınlarken geçerli sayfadan ayrıldığında içerik sayfasını veya genişletilmiş denetleyiciyi, gönderen uygulamasındaki başka bir ekrana kullanıcıya izin vermek için ekranın altında mini kumanda görüntülenir. yayınlanan medya meta verilerini görebilir ve oynatmayı kontrol edebilirsiniz.

  • Genişletilmiş Denetleyici: Kullanıcı içerik yayınlarken medya bildirimini tıklarsa kullanıyorsanız genişletilmiş kumanda devreye girer ve her ekranda medya meta verilerini oynatıyordur ve kontrol etmek için bazı düğmeler sağlar medya oynatmaya başladı.

  • Bildirim: Yalnızca Android'de sunulur. Kullanıcı içerik yayınlarken ve gönderen uygulamasını sağlarsanız şu anda yayınlanan içeriği gösteren bir medya bildirimi medya meta verileri ve oynatma denetimleri gibi.

  • Kilit Ekranı: Yalnızca Android'de sunulur. Kullanıcı içerik yayınlarken (veya cihazda) gezindiğinde zaman aşımına uğrarsa) kilit ekranında o anda yayınlanan medya meta verilerini ve oynatma kontrollerini gösterir.

Aşağıdaki kılavuzda, bu widget'ların en iyi şekilde yararlanabilirsiniz.

Yayınla Düğmesi Ekle

Android MediaRouter API'ler, ikincil cihazlarda medya görüntüleme ve oynatmayı etkinleştirmek için tasarlanmıştır. MediaRouter API kullanan Android uygulamaları, kullanıcıların, medya içeriğini oynatmak üzere bir medya yolu seçmelerine olanak tanımak için Yayın cihazı gibi ikincil bir cihaz.

Bu çerçeve, MediaRouteButton olarak Cast button çok kolay. Önce xml dosyasına bir menü seçeneği veya MediaRouteButton eklemelisiniz dosyanızı tanımlayan CastButtonFactory bunu çerçeveyle bağlayacağım.

// To add a Cast button, add the following snippet.
// menu.xml
<item
    android:id="@+id/media_route_menu_item"
    android:title="@string/media_route_menu_title"
    app:actionProviderClass="androidx.mediarouter.app.MediaRouteActionProvider"
    app:showAsAction="always" />
.
Kotlin
// Then override the onCreateOptionMenu() for each of your activities.
// MyActivity.kt
override fun onCreateOptionsMenu(menu: Menu): Boolean {
    super.onCreateOptionsMenu(menu)
    menuInflater.inflate(R.menu.main, menu)
    CastButtonFactory.setUpMediaRouteButton(
        applicationContext,
        menu,
        R.id.media_route_menu_item
    )
    return true
}
Java
// Then override the onCreateOptionMenu() for each of your activities.
// MyActivity.java
@Override public boolean onCreateOptionsMenu(Menu menu) {
    super.onCreateOptionsMenu(menu);
    getMenuInflater().inflate(R.menu.main, menu);
    CastButtonFactory.setUpMediaRouteButton(getApplicationContext(),
                                            menu,
                                            R.id.media_route_menu_item);
    return true;
}

Bu durumda, Activity cihazınız FragmentActivity buraya bir MediaRouteButton uygulayın.

// activity_layout.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:gravity="center_vertical"
   android:orientation="horizontal" >

   <androidx.mediarouter.app.MediaRouteButton
       android:id="@+id/media_route_button"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_weight="1"
       android:mediaRouteTypes="user"
       android:visibility="gone" />

</LinearLayout>
.
Kotlin
// MyActivity.kt
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_layout)

    mMediaRouteButton = findViewById<View>(R.id.media_route_button) as MediaRouteButton
    CastButtonFactory.setUpMediaRouteButton(applicationContext, mMediaRouteButton)

    mCastContext = CastContext.getSharedInstance(this)
}
Java
// MyActivity.java
@Override
protected void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.activity_layout);

   mMediaRouteButton = (MediaRouteButton) findViewById(R.id.media_route_button);
   CastButtonFactory.setUpMediaRouteButton(getApplicationContext(), mMediaRouteButton);

   mCastContext = CastContext.getSharedInstance(this);
}

Yayınla düğmesinin görünümünü bir tema kullanarak ayarlamak için bkz. Yayınla Düğmesini özelleştirin.

Cihaz bulmayı yapılandırın

Cihaz bulma tamamen CastContext. CastContext başlatılırken, gönderen uygulama Web Alıcısı'nı belirtir uygulama kimliği ve isteğe bağlı olarak ayara göre ad alanı filtrelemesi isteyebilir supportedNamespaces inç CastOptions CastContext, dahili olarak MediaRouter öğesine referans veriyor ve çalışmaya başlayacak aşağıdaki koşullar altında keşfetme sürecini destekler:

  • Cihaz keşif gecikmesini ve kullanıyorsanız keşif zaman zaman otomatik olarak Gönderen uygulaması ön plana geçer.
  • Yayınla iletişim kutusu açık.
  • Cast SDK'sı, Cast oturumunu kurtarmaya çalışıyor.

Yayınla iletişim kutusu kapatıldığında veya arka plana girer.

Kotlin
class CastOptionsProvider : OptionsProvider {
    companion object {
        const val CUSTOM_NAMESPACE = "urn:x-cast:custom_namespace"
    }

    override fun getCastOptions(appContext: Context): CastOptions {
        val supportedNamespaces: MutableList<String> = ArrayList()
        supportedNamespaces.add(CUSTOM_NAMESPACE)

        return CastOptions.Builder()
            .setReceiverApplicationId(context.getString(R.string.app_id))
            .setSupportedNamespaces(supportedNamespaces)
            .build()
    }

    override fun getAdditionalSessionProviders(context: Context): List<SessionProvider>? {
        return null
    }
}
Java
class CastOptionsProvider implements OptionsProvider {
    public static final String CUSTOM_NAMESPACE = "urn:x-cast:custom_namespace";

    @Override
    public CastOptions getCastOptions(Context appContext) {
        List<String> supportedNamespaces = new ArrayList<>();
        supportedNamespaces.add(CUSTOM_NAMESPACE);

        CastOptions castOptions = new CastOptions.Builder()
            .setReceiverApplicationId(context.getString(R.string.app_id))
            .setSupportedNamespaces(supportedNamespaces)
            .build();
        return castOptions;
    }

    @Override
    public List<SessionProvider> getAdditionalSessionProviders(Context context) {
        return null;
    }
}

Oturum yönetiminin işleyiş şekli

Cast SDK'sı, Cast oturumu, Bir cihaza bağlanma, Web'i başlatma (veya Web'e katılma) adımlarını birleştiren kuruluş Alıcı uygulama, bu uygulamaya bağlanma ve medya kontrol kanalını başlatma. Web Buyer'ı göster Uygulama yaşam döngüsü kılavuzu daha fazla bilgi edinmek için Yardım Merkezi'ni ziyaret edebilirsiniz.

Oturumlar sınıf tarafından yönetilir SessionManager, uygulamanızın CastContext.getSessionManager(). Farklı oturumlar sınıfın alt sınıflarıyla temsil edilir Session. Örneğin, CastSession Yayın cihazlarıyla ilgili oturumları temsil eder. Uygulamanız şu anda etkin Oturumu şunu kullanarak yayınla: SessionManager.getCurrentCastSession().

Uygulamanız SessionManagerListener oluşturma, askıya alma, devam ettirme ve gibi oturum etkinliklerini feshedilebilir. Çerçeve otomatik olarak oturum aktif durumdayken anormal/ani fesih.

Oturumlar, kullanıcı hareketlerine göre otomatik olarak oluşturulur ve kısaltılır iletişim kutusunu MediaRouter

Uygulamalar, Yayın başlatma hatalarını daha iyi anlamak için CastContext#getCastReasonCodeForCastStatusCode(int) oturum başlatma hatasını CastReasonCodes. Bazı oturum başlatma hatalarının (ör. CastReasonCodes#CAST_CANCELLED) mevcut olduğunu lütfen unutmayın Amaçlanan davranışlardır ve hata olarak günlüğe kaydedilmemelidir.

Oturumla ilgili olarak yapılan değişiklikleri bilmeniz gerekiyorsa SessionManagerListener. Bu örnekte bir Activity içinde CastSession.

Kotlin
class MyActivity : Activity() {
    private var mCastSession: CastSession? = null
    private lateinit var mCastContext: CastContext
    private lateinit var mSessionManager: SessionManager
    private val mSessionManagerListener: SessionManagerListener<CastSession> =
        SessionManagerListenerImpl()

    private inner class SessionManagerListenerImpl : SessionManagerListener<CastSession?> {
        override fun onSessionStarting(session: CastSession?) {}

        override fun onSessionStarted(session: CastSession?, sessionId: String) {
            invalidateOptionsMenu()
        }

        override fun onSessionStartFailed(session: CastSession?, error: Int) {
            val castReasonCode = mCastContext.getCastReasonCodeForCastStatusCode(error)
            // Handle error
        }

        override fun onSessionSuspended(session: CastSession?, reason Int) {}

        override fun onSessionResuming(session: CastSession?, sessionId: String) {}

        override fun onSessionResumed(session: CastSession?, wasSuspended: Boolean) {
            invalidateOptionsMenu()
        }

        override fun onSessionResumeFailed(session: CastSession?, error: Int) {}

        override fun onSessionEnding(session: CastSession?) {}

        override fun onSessionEnded(session: CastSession?, error: Int) {
            finish()
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        mCastContext = CastContext.getSharedInstance(this)
        mSessionManager = mCastContext.sessionManager
        mSessionManager.addSessionManagerListener(mSessionManagerListener, CastSession::class.java)
    }

    override fun onResume() {
        super.onResume()
        mCastSession = mSessionManager.currentCastSession
    }

    override fun onDestroy() {
        super.onDestroy()
        mSessionManager.removeSessionManagerListener(mSessionManagerListener, CastSession::class.java)
    }
}
Java
public class MyActivity extends Activity {
    private CastContext mCastContext;
    private CastSession mCastSession;
    private SessionManager mSessionManager;
    private SessionManagerListener<CastSession> mSessionManagerListener =
            new SessionManagerListenerImpl();

    private class SessionManagerListenerImpl implements SessionManagerListener<CastSession> {
        @Override
        public void onSessionStarting(CastSession session) {}
        @Override
        public void onSessionStarted(CastSession session, String sessionId) {
            invalidateOptionsMenu();
        }
        @Override
        public void onSessionStartFailed(CastSession session, int error) {
            int castReasonCode = mCastContext.getCastReasonCodeForCastStatusCode(error);
            // Handle error
        }
        @Override
        public void onSessionSuspended(CastSession session, int reason) {}
        @Override
        public void onSessionResuming(CastSession session, String sessionId) {}
        @Override
        public void onSessionResumed(CastSession session, boolean wasSuspended) {
            invalidateOptionsMenu();
        }
        @Override
        public void onSessionResumeFailed(CastSession session, int error) {}
        @Override
        public void onSessionEnding(CastSession session) {}
        @Override
        public void onSessionEnded(CastSession session, int error) {
            finish();
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mCastContext = CastContext.getSharedInstance(this);
        mSessionManager = mCastContext.getSessionManager();
        mSessionManager.addSessionManagerListener(mSessionManagerListener, CastSession.class);
    }

    @Override
    protected void onResume() {
        super.onResume();
        mCastSession = mSessionManager.getCurrentCastSession();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mSessionManager.removeSessionManagerListener(mSessionManagerListener, CastSession.class);
    }
}

Akış aktarma

Akış aktarımının temeli oturum durumunu korumaktır. Bu yöntemde kullanıcılar sesli komutları, Google Home'u kullanarak mevcut ses ve video akışlarını cihazlar arasında taşıyabilir uygulama veya akıllı ekranlar. Medya bir cihazda (kaynak) duruyor ve başka bir cihazda (kaynaktaki) devam ediyor hedef). En son donanım yazılımına sahip Cast cihazları bir akış aktarımı.

Akış aktarımı veya genişletme sırasında yeni hedef cihazı almak için bir kaydettirmek Cast.Listener her bir arama terimi için CastSession#addCastListener. Ardından şu numarayı arayın: CastSession#getCastDevice() onDeviceNameChanged geri araması sırasında.

Görüntüleyin Web Alıcısında akış aktarımı konulu videomuzu izleyin.

Otomatik yeniden bağlanma

Bu çerçeve, ReconnectionService Bu ayar, gönderen uygulaması tarafından yeniden bağlanmayı yönetmek için Örneğin:

  • Geçici kablosuz ağ kaybından kurtulma
  • Cihazı uyku modundan kurtar
  • Uygulamayı arka plana alma durumundan kurtar
  • Uygulama kilitlenirse kurtar

Bu hizmet varsayılan olarak etkindir ve şuradan devre dışı bırakılabilir: CastOptions.Builder.

Otomatik birleştirme yapılırsa bu hizmet otomatik olarak uygulamanızın manifest dosyasıyla birleştirilebilir gradle dosyanızda etkin.

Çerçeve, medya oturumu olduğunda hizmeti başlatır ve durdurur sona erecektir.

Medya Denetimi nasıl çalışır?

Cast çerçevesi, RemoteMediaPlayer Cast 2.x'teki sınıf lehine yeni bir sınıf RemoteMediaClient, Bu API, aynı işlevselliği daha kullanışlı bir dizi API'de sağlar ve GoogleApiClient'ı aktarmak zorunda kalmaktan kaçınır.

Uygulamanız CastSession medya ad alanını destekleyen bir Web Alıcı uygulamasına sahip olan RemoteMediaClient, çerçeve tarafından otomatik olarak oluşturulur; uygulamanız CastSession üzerinde getRemoteMediaClient() yöntemini çağırarak erişin kullanır.

Web Alıcısına istek gönderen tüm RemoteMediaClient yöntemleri bu isteği izlemek için kullanılabilecek bir PendingResult nesnesi döndürür.

RemoteMediaClient örneğinin şu kullanıcılar tarafından paylaşılması beklenir: uygulamanızın bazı dahili bileşenleri de dahil olmak üzere ve kullanıcı tanımlı değişkenleri kullanın. Örneğin, sürekli mini denetleyiciler ve bildirim hizmetini kullanın. Bu amaçla, bu örnek birden fazla RemoteMediaClient.Listener

Medya meta verilerini ayarla

İlgili içeriği oluşturmak için kullanılan MediaMetadata class, Yayınlamak istediğiniz medya öğesiyle ilgili bilgileri temsil eder. İlgili içeriği oluşturmak için kullanılan aşağıdaki örnek, bir filmin yeni MediaMetadata örneğini oluşturur ve başlık, alt başlık ve iki resim.

Kotlin
val movieMetadata = MediaMetadata(MediaMetadata.MEDIA_TYPE_MOVIE)

movieMetadata.putString(MediaMetadata.KEY_TITLE, mSelectedMedia.getTitle())
movieMetadata.putString(MediaMetadata.KEY_SUBTITLE, mSelectedMedia.getStudio())
movieMetadata.addImage(WebImage(Uri.parse(mSelectedMedia.getImage(0))))
movieMetadata.addImage(WebImage(Uri.parse(mSelectedMedia.getImage(1))))
Java
MediaMetadata movieMetadata = new MediaMetadata(MediaMetadata.MEDIA_TYPE_MOVIE);

movieMetadata.putString(MediaMetadata.KEY_TITLE, mSelectedMedia.getTitle());
movieMetadata.putString(MediaMetadata.KEY_SUBTITLE, mSelectedMedia.getStudio());
movieMetadata.addImage(new WebImage(Uri.parse(mSelectedMedia.getImage(0))));
movieMetadata.addImage(new WebImage(Uri.parse(mSelectedMedia.getImage(1))));

Görüntüleyin Resim Seçimi izin verilebilir.

Medya yükle

Uygulamanız, aşağıdaki kodda gösterildiği gibi bir medya öğesi yükleyebilir. İlk kullanım MediaInfo.Builder medyanın meta verileriyle karşılaştırarak MediaInfo kullanır. Şunu edinin: RemoteMediaClient geçerli CastSession öğesinden sonra MediaInfo öğesini RemoteMediaClient. Oynatmak, duraklatmak ve diğer işlemleri yapmak için RemoteMediaClient kullanın Web Alıcısı'nda çalışan bir medya oynatıcı uygulamasını kontrol edebilir.

Kotlin
val mediaInfo = MediaInfo.Builder(mSelectedMedia.getUrl())
    .setStreamType(MediaInfo.STREAM_TYPE_BUFFERED)
    .setContentType("videos/mp4")
    .setMetadata(movieMetadata)
    .setStreamDuration(mSelectedMedia.getDuration() * 1000)
    .build()
val remoteMediaClient = mCastSession.getRemoteMediaClient()
remoteMediaClient.load(MediaLoadRequestData.Builder().setMediaInfo(mediaInfo).build())
Java
MediaInfo mediaInfo = new MediaInfo.Builder(mSelectedMedia.getUrl())
        .setStreamType(MediaInfo.STREAM_TYPE_BUFFERED)
        .setContentType("videos/mp4")
        .setMetadata(movieMetadata)
        .setStreamDuration(mSelectedMedia.getDuration() * 1000)
        .build();
RemoteMediaClient remoteMediaClient = mCastSession.getRemoteMediaClient();
remoteMediaClient.load(new MediaLoadRequestData.Builder().setMediaInfo(mediaInfo).build());

Ayrıca, medya parçalarını kullanma.

4K video biçimi

Medyanızın hangi video biçimini gösterdiğini kontrol etmek için şunu kullanın: getVideoInfo() almak için MediaStatus'a gidip VideoInfo. Bu örnek, HDR TV biçiminin türünü ve ekran yüksekliğini içerir ve genişliği piksel cinsinden belirtmektedir. 4K biçiminin varyantları sabit değerlerle gösterilir HDR_TYPE_*.

Birden fazla cihaza uzaktan bildirim gönderme

Bir kullanıcı yayın yaparken aynı ağdaki diğer Android cihazlar oynatmayı kontrol etmelerine olanak tanımak için bir bildirim. Cihazı olan herkes bu tür bildirimleri aldığında, bu bildirimleri Ayarlar'dan söz konusu cihaz için devre dışı bırakabilirsiniz uygulaması > Google Cast > Uzaktan kumanda bildirimlerini göster. (Bildirimler, Ayarlar uygulamasına giden bir kısayol içerir.) Daha fazla bilgi için bkz. Uzaktan kumanda bildirimlerini yayınlayın.

Mini kumanda ekle

Cast Tasarımına göre Yapılacaklar listesi gönderen uygulaması, mini denetleyici geçerli içerik sayfasından ayrıldığında ve diğer bir bölümüdür. Mini kumanda, ekranda görünen bir hatırlatıcı sağlar. Geçerli Cast oturumunun kullanıcısına gönderilir. Mini kumandaya dokunduğunuzda kullanıcı Cast tam ekran genişletilmiş denetleyici görünümüne dönebilir.

Çerçeve, ekleyebileceğiniz özel bir MiniControllerFragment sunar. göstermek istediğiniz her etkinliğin düzen dosyasının en altına mini kumanda.

<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" />

Gönderen uygulamanız bir video veya ses canlı yayını oynatırken SDK, oynatma/duraklatma düğmesi yerine otomatik olarak bir oynat/durdur düğmesi görüntüler mini kumandada.

Bu özel görünümün başlığının ve alt başlığının metin görünümünü ayarlamak için ve düğmeleri seçmek için bkz. Mini Kumanda'yı özelleştirin.

Genişletilmiş denetleyici ekle

Google Cast Tasarım Kontrol Listesi, bir gönderen uygulamasının genişletilmiş bir denetleyici medya içeriği yayınlamada fayda var. Genişletilmiş denetleyici, için de geçerlidir.

Cast SDK'sı, genişletilmiş denetleyici için ExpandedControllerActivity. Bu, Yayınla düğmesi eklemek için alt sınıfa girmeniz gereken soyut bir sınıftır.

Öncelikle, genişletilmiş denetleyicinin sağlaması için yeni bir menü kaynak dosyası oluşturun Yayınla düğmesi:

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

ExpandedControllerActivity kapsamını genişleten yeni bir sınıf oluşturun.

Kotlin
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
    }
}
Java
public class ExpandedControlsActivity extends ExpandedControllerActivity {
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);
        getMenuInflater().inflate(R.menu.expanded_controller, menu);
        CastButtonFactory.setUpMediaRouteButton(this, menu, R.id.media_route_menu_item);
        return true;
    }
}

Şimdi yeni etkinliğinizi application etiketinin içindeki uygulama manifest'inde bildirin:

<application>
...
<activity
        android:name=".expandedcontrols.ExpandedControlsActivity"
        android:label="@string/app_name"
        android:launchMode="singleTask"
        android:theme="@style/Theme.CastVideosDark"
        android:screenOrientation="portrait"
        android:parentActivityName="com.google.sample.cast.refplayer.VideoBrowserActivity">
    <intent-filter>
        <action android:name="android.intent.action.MAIN"/>
    </intent-filter>
</activity>
...
</application>

CastOptionsProvider öğesini düzenleyip NotificationOptions ve CastMediaOptions kullanarak hedef aktiviteyi yeni etkinliğinize ayarlayın:

Kotlin
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()
}
Java
public CastOptions getCastOptions(Context context) {
    NotificationOptions notificationOptions = new NotificationOptions.Builder()
            .setTargetActivityClassName(ExpandedControlsActivity.class.getName())
            .build();
    CastMediaOptions mediaOptions = new CastMediaOptions.Builder()
            .setNotificationOptions(notificationOptions)
            .setExpandedControllerActivityClassName(ExpandedControlsActivity.class.getName())
            .build();

    return new CastOptions.Builder()
            .setReceiverApplicationId(context.getString(R.string.app_id))
            .setCastMediaOptions(mediaOptions)
            .build();
}

Aşağıdakileri görüntülemek için LocalPlayerActivity loadRemoteMedia yöntemini güncelleyin uzak medya yüklendiğinde yeni etkinlik:

Kotlin
private fun loadRemoteMedia(position: Int, autoPlay: Boolean) {
    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(mSelectedMedia)
            .setAutoplay(autoPlay)
            .setCurrentTime(position.toLong()).build()
    )
}
Java
private void loadRemoteMedia(int position, boolean autoPlay) {
    if (mCastSession == null) {
        return;
    }
    final RemoteMediaClient remoteMediaClient = mCastSession.getRemoteMediaClient();
    if (remoteMediaClient == null) {
        return;
    }
    remoteMediaClient.registerCallback(new RemoteMediaClient.Callback() {
        @Override
        public void onStatusUpdated() {
            Intent intent = new Intent(LocalPlayerActivity.this, ExpandedControlsActivity.class);
            startActivity(intent);
            remoteMediaClient.unregisterCallback(this);
        }
    });
    remoteMediaClient.load(new MediaLoadRequestData.Builder()
            .setMediaInfo(mSelectedMedia)
            .setAutoplay(autoPlay)
            .setCurrentTime(position).build());
}

Gönderen uygulamanız bir video veya ses canlı yayını oynatırken SDK, oynatma/duraklatma düğmesi yerine otomatik olarak bir oynat/durdur düğmesi görüntüler ekleyebilirsiniz.

Temaları kullanarak görünümü ayarlamak için, görüntülenecek düğmeleri seçin, ve özel düğmeler eklemek için Genişletilmiş Denetleyici'yi özelleştirin.

Ses düzeyi kontrolü

Çerçeve, gönderen uygulaması için ses düzeyini otomatik olarak yönetir. Çerçeve Gönderenin, gönderen ve Web Alıcı uygulamalarını otomatik olarak senkronize etmesi için, Kullanıcı arayüzü, her zaman Web Alıcısı tarafından belirtilen ses düzeyini bildirir.

Fiziksel düğme ses düzeyi kontrolü

Android'de, gönderen cihazın üzerindeki fiziksel düğmeler, varsayılan olarak Web Alıcısı'ndaki Yayın oturumunun ses düzeyi Jelly Bean veya daha yeni sürümler.

Jelly Bean'den önce fiziksel düğme ses düzeyi kontrolü

Şurada Web Alıcısı cihaz ses düzeyini kontrol etmek üzere fiziksel ses düzeyi tuşlarını kullanmak için: Jelly Bean'den daha eski Android cihazlar; gönderen uygulaması, dispatchKeyEvent ve telefon görüşmesi yapmak için CastContext.onDispatchVolumeKeyEventBeforeJellyBean():

Kotlin
class MyActivity : FragmentActivity() {
    override fun dispatchKeyEvent(event: KeyEvent): Boolean {
        return (CastContext.getSharedInstance(this)
            .onDispatchVolumeKeyEventBeforeJellyBean(event)
                || super.dispatchKeyEvent(event))
    }
}
Java
class MyActivity extends FragmentActivity {
    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
        return CastContext.getSharedInstance(this)
            .onDispatchVolumeKeyEventBeforeJellyBean(event)
            || super.dispatchKeyEvent(event);
    }
}

Bildirim ve kilit ekranına medya denetimleri ekleyin

Yalnızca Android'de, Google Cast Tasarımla İlgili Yapılacaklar Listesi bir gönderen uygulamasının medya kontrollerini de bildirim ve kilitte ekranı Bu durumda, gönderenin yayın yaptığı ancak gönderen uygulamasının odağı olmadığı durumlar olabilir. İlgili içeriği oluşturmak için kullanılan çerçeve, MediaNotificationService ve MediaIntentReceiver (gönderen uygulamasının bildirim ve kilit simgesinde medya denetimleri oluşturmasına yardımcı olur) tıklayın.

MediaNotificationService, gönderen yayın yaparken çalışır ve bir uyarı görüntüler küçük resmi ve geçerli yayınla ilgili bilgileri içeren bildirim bir oynatma/duraklat düğmesi ve bir durdurma düğmesi.

MediaIntentReceiver, şuradan gelen kullanıcı işlemlerini işleyen bir BroadcastReceiver: bildirim.

Uygulamanız, kilit ekranından bildirim ve medya kontrolünü yapılandırabilir. NotificationOptions. Uygulamanız bildirimde hangi düğmelerin gösterileceğini yapılandırabilir ve Kullanıcı bildirime dokunduğunda hangi Activity açılacaktır. Eğer eylemler doğrudan sağlanmazsa, varsayılan değerler, MediaIntentReceiver.ACTION_TOGGLE_PLAYBACK ve MediaIntentReceiver.ACTION_STOP_CASTING kullanılacak.

Kotlin
// Example showing 4 buttons: "rewind", "play/pause", "forward" and "stop casting".
val buttonActions: MutableList<String> = ArrayList()
buttonActions.add(MediaIntentReceiver.ACTION_REWIND)
buttonActions.add(MediaIntentReceiver.ACTION_TOGGLE_PLAYBACK)
buttonActions.add(MediaIntentReceiver.ACTION_FORWARD)
buttonActions.add(MediaIntentReceiver.ACTION_STOP_CASTING)

// Showing "play/pause" and "stop casting" in the compat view of the notification.
val compatButtonActionsIndices = intArrayOf(1, 3)

// Builds a notification with the above actions. Each tap on the "rewind" and "forward" buttons skips 30 seconds.
// Tapping on the notification opens an Activity with class VideoBrowserActivity.
val notificationOptions = NotificationOptions.Builder()
    .setActions(buttonActions, compatButtonActionsIndices)
    .setSkipStepMs(30 * DateUtils.SECOND_IN_MILLIS)
    .setTargetActivityClassName(VideoBrowserActivity::class.java.name)
    .build()
Java
// Example showing 4 buttons: "rewind", "play/pause", "forward" and "stop casting".
List<String> buttonActions = new ArrayList<>();
buttonActions.add(MediaIntentReceiver.ACTION_REWIND);
buttonActions.add(MediaIntentReceiver.ACTION_TOGGLE_PLAYBACK);
buttonActions.add(MediaIntentReceiver.ACTION_FORWARD);
buttonActions.add(MediaIntentReceiver.ACTION_STOP_CASTING);

// Showing "play/pause" and "stop casting" in the compat view of the notification.
int[] compatButtonActionsIndices = new int[]{1, 3};

// Builds a notification with the above actions. Each tap on the "rewind" and "forward" buttons skips 30 seconds.
// Tapping on the notification opens an Activity with class VideoBrowserActivity.
NotificationOptions notificationOptions = new NotificationOptions.Builder()
    .setActions(buttonActions, compatButtonActionsIndices)
    .setSkipStepMs(30 * DateUtils.SECOND_IN_MILLIS)
    .setTargetActivityClassName(VideoBrowserActivity.class.getName())
    .build();

Bildirim ve kilit ekranında medya denetimlerini gösterme özelliği şu kullanıcı tarafından etkinleştirildi: varsayılandır ve çağrı yaparak devre dışı bırakılabilir setNotificationOptions içinde boş değer olan CastMediaOptions.Builder. Şu anda bildirim etkinleştirildiği sürece kilit ekranı özelliği etkin durumdadır açıldı.

Kotlin
// ... continue with the NotificationOptions built above
val mediaOptions = CastMediaOptions.Builder()
    .setNotificationOptions(notificationOptions)
    .build()
val castOptions: CastOptions = Builder()
    .setReceiverApplicationId(context.getString(R.string.app_id))
    .setCastMediaOptions(mediaOptions)
    .build()
Java
// ... continue with the NotificationOptions built above
CastMediaOptions mediaOptions = new CastMediaOptions.Builder()
        .setNotificationOptions(notificationOptions)
        .build();
CastOptions castOptions = new CastOptions.Builder()
        .setReceiverApplicationId(context.getString(R.string.app_id))
        .setCastMediaOptions(mediaOptions)
        .build();

Gönderen uygulamanız bir video veya ses canlı yayını oynatırken SDK, oynatma/duraklatma düğmesi yerine otomatik olarak bir oynat/durdur düğmesi görüntüler kilit ekranı denetiminde değil.

Not: Lollipop öncesi cihazlarda kilit ekranı kontrollerini görüntülemek için RemoteMediaClient, sizin adınıza otomatik olarak ses odağı isteğinde bulunacak.

Hataları işleme

Gönderen uygulamalarının tüm hata geri çağırmalarıyla ilgilenmesi ve her aşaması için en iyi yanıtı verir. Uygulama, mesajı gönderebilir veya web ile olan bağlantıyı koparabilir. Web Alıcısı.