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önderen üzerinde çalışma zamanında mevcut olana işaret eder. Gönderen uygulaması veya Yayın uygulaması, gönderende de çalışan bir uygulamayı ifade eder. 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.
  • Çerçeve, web alıcısında medya oynatmayı yüklemek ve kontrol etmek için iletişim kanalını kullanır.
  • Ç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ında, Cast SDK'sı için aşağıdaki öğeleri yapılandırmanız gerekir:

uses-sdk

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

<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 Lollipop öncesi bir minimum Android SDK sürümünü hedeflerken Theme.AppCompat'ün bir varyantını kullanmanız gerekir.

<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, CastContext tekil nesneyi başlatmak için gereken seçenekleri sağlamak amacıyla OptionsProvider arayüzünü uygulamalıdır. 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;
    }
}

Gönderen uygulamanın AndroidManifest.xml dosyasında, uygulanan OptionsProvider'nin tam nitelikli adını bir meta veri alanı olarak beyan etmeniz gerekir:

<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, bulunan cihazların listeleneceği bir Yayınla iletişim kutusu gösterilir. 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ın düğmesi" bazen "Yayın simgesi" olarak da adlandırılır.

  • 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. Öncelikle, xml dosyasına menünüzü tanımlayan bir menü öğesi veya MediaRouteButton eklemeniz ve bunu çerçeveye bağlamak için CastButtonFactory kullanmanız gerekir.

// 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ınlama iletişim kutusu açık.
  • Cast SDK'sı bir 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 Alıcısını 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(). Tekil oturumlar, Session sınıfının alt sınıflarıyla temsil edilir. Ö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, oturum etkinken anormal/ani bir sonlandırmadan otomatik olarak devam etmeyi dener.

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

Uygulamalar, Cast başlatma hatalarını daha iyi anlamak için oturum başlatma hatasını CastReasonCodes olarak dönüştürmek üzere CastContext#getCastReasonCodeForCastStatusCode(int) kullanabilir. 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, onDeviceNameChanged geri arama sırasında CastSession#getCastDevice()'ı arayın.

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 kurtarma
  • Uygulamayı arka plana aldıktan sonra kurtarma
  • Uygulama kilitlenirse kurtar

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

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 örneğidir.

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, uygulamanızın birden fazla bölümü ve çerçevenin bazı dahili bileşenleri (ör. kalıcı mini denetleyiciler ve bildirim hizmeti) tarafından paylaşılabileceği beklenir. Bu amaçla, bu örnek birden fazla RemoteMediaClient.Listener

Medya meta verilerini ayarlama

İ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. Öncelikle, bir MediaInfo örneği oluşturmak için medya meta verileriyle MediaInfo.Builder kullanın. Ş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());

Medya parçalarını kullanma bölümüne de göz atın.

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, mini denetleyiciyi göstermek istediğiniz her etkinliğin düzen dosyasının alt kısmına ekleyebileceğiniz özel bir görünüm (MiniControllerFragment) sağlar.

<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 sınıfı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;
    }
}

Ardından, yeni etkinliğinizi uygulama manifest dosyasında application etiketi içinde beyan edin:

<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, hangi düğmelerin gösterileceğini seçmek ve özel düğmeler eklemek için Genişletilmiş Denetleyiciyi Özelleştirme başlıklı makaleyi inceleyin.

Ses düzeyi kontrolü

Çerçeve, gönderen uygulamasının ses düzeyini otomatik olarak yönetir. Çerçeve, gönderen kullanıcı arayüzünün her zaman web alıcısı tarafından belirtilen ses düzeyini bildirmesi için gönderen ve web alıcısı uygulamalarını otomatik olarak senkronize eder.

Fiziksel düğme ses düzeyi kontrolü

Android'de, Jelly Bean veya sonraki sürümleri kullanan tüm cihazlarda varsayılan olarak web alıcısındaki Cast oturumunun ses seviyesini değiştirmek için gönderen cihazdaki fiziksel düğmeler kullanılabilir.

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. Gönderen uygulamanın bildirimde ve kilit ekranında medya kontrolleri oluşturmasına yardımcı olmak için çerçeve MediaNotificationService ve MediaIntentReceiver sağlar.

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. İşlemler açıkça sağlanmazsa varsayılan değerler (MediaIntentReceiver.ACTION_TOGGLE_PLAYBACK ve MediaIntentReceiver.ACTION_STOP_CASTING) kullanılır.

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ından medya denetimlerinin gösterilmesi varsayılan olarak etkindir ve CastMediaOptions.Builder parametresinde null değeriyle setNotificationOptions çağrılarak devre dışı bırakılabilir. Ş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 video veya sesli canlı yayın oynatırken SDK, bildirim kontrolünde oynatma/duraklatma düğmesi yerine otomatik olarak oynatma/durdurma düğmesi gösterir ancak kilit ekranı kontrolünde bu düğmeyi göstermez.

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