Bir Android uygulamasını Cast uyumlu hale getirme

1. Genel bakış

Google Cast logosu

Bu codelab'de, Google Cast uyumlu bir cihazda içerik yayınlamak için mevcut bir Android video uygulamasını nasıl değiştireceğinizi öğreneceksiniz.

Google Cast nedir?

Google Cast, kullanıcıların bir mobil cihazdan TV'ye içerik yayınlamasına olanak tanır. Kullanıcılar daha sonra mobil cihazlarını TV'de medya oynatmak için uzaktan kumanda olarak kullanabilir.

Google Cast SDK'sı, uygulamanızı bir TV veya ses sistemini kontrol edecek şekilde genişletmenize olanak tanır. 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.

Neyi inşa edeceğiz?

Bu codelab'i tamamladığınızda videoları Google Cast uyumlu bir cihazda yayınlayabilecek bir Android video uygulamanız olacaktır.

Neler öğreneceksiniz?

  • Örnek bir video uygulamasına Google Cast SDK'sı 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 kumanda ekleme.
  • Medya bildirimleri ve kilit ekranı kontrolleri nasıl desteklenir?
  • Genişletilmiş kumanda nasıl eklenir?
  • Tanıtım amaçlı yer paylaşımı nasıl sağlanır?
  • Yayın widget'ları nasıl özelleştirilir?
  • Cast Connect ile entegrasyon

Gerekenler

  • En son Android SDK.
  • Android Studio 3.2 ve sonraki sürümleri
  • Android 4.1+ Jelly Bean (API düzeyi 16) yüklü bir mobil cihaz.
  • Mobil cihazınızı geliştirme bilgisayarınıza bağlamak için bir USB veri kablosu.
  • İnternet erişimi olan, Chromecast veya Android TV gibi bir Google Cast cihazı.
  • HDMI girişi olan bir TV veya monitör.
  • Cast Connect entegrasyonunu test etmek için Google TV Yüklü Chromecast gereklidir, ancak Codelab'in geri kalanı için isteğe bağlıdır. Destek kaydınız yoksa bu eğiticinin sonuna doğru olan Cast Connect Desteği Ekleme adımını atlayabilirsiniz.

Deneyim

  • Kotlin ve Android geliştirme konusunda önceden bilgi sahibi olmanız gerekir.
  • Ayrıca TV izleme konusunda da önceden bilgi sahibi olmanız gerekir :)

Bu eğiticiyi nasıl kullanacaksınız?

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

Android uygulamaları oluşturma deneyiminizi nasıl değerlendirirsiniz?

Acemi Orta Düzey Yeterli

TV izleme deneyiminizi nasıl değerlendirirsiniz?

Acemi Orta Düzey Yeterli

2. Örnek kodu alın

Örnek kodun tamamını bilgisayarınıza indirebilirsiniz...

indirilen zip dosyasını açın.

3. Örnek uygulamayı çalıştırma

pusula simgesi

Önce tamamlanmış örnek uygulamanın nasıl göründüğüne bakalım. Uygulama, temel bir video oynatıcıdır. Kullanıcı, listeden bir video seçebilir ve videoyu cihazda yerel olarak oynatabilir veya bir Google Cast cihazına yayınlayabilir.

Kod indirildikten sonra aşağıdaki talimatlarda, tamamlanmış örnek uygulamayı Android Studio'da nasıl açacağınız ve çalıştıracağınız açıklanmaktadır:

Karşılama ekranında Projeyi İçe Aktar'ı veya Dosya > Yeni > Projeyi İçe Aktar... menü seçeneklerini belirleyin.

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

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

Android cihazınızda USB üzerinden hata ayıklamayı etkinleştirin. Android 4.2 ve sonraki sürümlerde Geliştirici seçenekleri ekranı varsayılan olarak gizlidir. Telefonu görünür hale getirmek için Ayarlar > Telefon hakkında'ya gidip 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 hata ayıklaması'na dokunarak özelliği etkinleştirin.

Android cihazınızı fişe takın ve Android Studio'daki 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ını görürsünüz.

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

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

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

Genişletilmiş 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" uygulamasını çalıştıran Android telefon ve ekranın altında mini kumandanın göründüğü çizim

Videoyu alıcıda 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 Yayın oturumuyla ilgili bir bildirim görürsünüz.

Telefonunuzu kilitlediğinizde, kilidini açtığınızda medya oynatmayı kontrol etmek veya yayınlamayı durdurmak için kilit ekranında bir bildirim görürsünüz.

Video uygulamasına dönün ve Google Cast cihazında yayını durdurmak için Yayınla düğmesini tıklayın.

Sık sorulan sorular

4. Başlangıç projesini hazırlama

"Video Yayınla" uygulamasını çalıştıran bir Android telefonu gösteren görsel

İndirdiğiniz başlangıç uygulamasına Google Cast desteği eklememiz gerekiyor. Bu codelab'de kullanacağımız bazı Google Cast terminolojisini aşağıda bulabilirsiniz:

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

Artık Android Studio'yu kullanarak başlangıç projesinin temelini oluşturmaya hazırsınız:

  1. Örnek kod indirmenizden klasör simgesiapp-start dizinini seçin (hoş geldiniz ekranında Projeyi İçe Aktar'ı veya Dosya > Yeni > Projeyi İçe Aktar... menü seçeneğini seçin).
  2. Android Studio "Projeyi Gradle ile Senkronize Et" düğmesi Sync Project with Gradle Files (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 bir video seçerek ayrıntılarını görebilir veya videoyu mobil cihazlarında yerel olarak oynatabilir.

Uygulama iki ana etkinlikten oluşuyor: VideoBrowserActivity ve LocalPlayerActivity. Google Cast işlevselliğinin entegre edilmesi için Etkinlikler, AppCompatActivity veya üst öğesinden FragmentActivity öğesini devralmalıdır. Bu sınırlama, MediaRouteButton öğesini (MediaRouter destek kitaplığında sağlanır) MediaRouteActionProvider olarak eklememiz gerekeceğinden ve bu işlem yalnızca etkinliğin yukarıda belirtilen sınıflardan devraldığı durumlarda işe yarayacaktır. 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. Videoların listesi ve ilişkili meta verileri, JSON dosyası olarak uzak bir sunucuda barındırılır. AsyncTaskLoader (VideoItemLoader) bu JSON'u getirir ve MediaItem nesnelerinin listesini oluşturmak için işler.

MediaItem nesnesi, bir videoyu ve onunla ilişkili meta verileri (ör. başlığı, açıklaması, akışın URL'si, destekleyici resimlerin URL'si ve varsa ilişkili Metin Parçaları) modeller. MediaItem nesnesi etkinlikler arasında aktarılır. Bu nedenle MediaItem, nesneyi Bundle (veya tersi) için yardımcı program yöntemlerine sahiptir.

Yükleyici MediaItems listesini oluşturduğunda, bu listeyi VideoListAdapter'a iletir. Daha sonra, bu liste VideoBrowserFragment içinde MediaItems listesini sunar. Kullanıcıya, her videonun kısa bir açıklamasını içeren video küçük resimlerinden oluşan bir liste sunulur. Bir öğe seçildiğinde, karşılık gelen MediaItem bir Bundle öğesine dönüştürülür ve LocalPlayerActivity öğesine iletilir.

LocalPlayerActivity

Bu etkinlik, belirli bir video hakkındaki meta verileri görüntüler ve kullanıcının mobil cihazda videoyu yerel olarak oynatmasına olanak tanır.

Etkinlikte bir VideoView, bazı medya denetimleri ve seçilen videonun açıklamasının gösterildiği bir metin alanı bulunur. Oynatıcı ekranın üst kısmını kaplar ve videonun ayrıntılı açıklaması için yer bırakır. Kullanıcı videoları oynatabilir/duraklatabilir veya yerel olarak oynatılmasını arayabilir.

Bağımlılıklar

AppCompatActivity kullandığımız için AppCompat destek kitaplığına ihtiyacımız var. Video listesini yönetmek ve listedeki görselleri 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 Yayınla düğmesinin göründüğü görsel

Cast uyumlu bir uygulamanın, etkinliklerinin her birinde Yayın düğmesi görüntülenir. Yayınla 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çildiğinde ilgili yayın cihazında oynatma başlatılır veya devam ettirilir. Yayınlama oturumu sırasında istediği zaman kullanıcı Yayınla düğmesini tıklayabilir ve uygulamanızın Yayın cihazına yayınlanmasını durdurabilir. Kullanıcı, uygulamanızdaki herhangi bir etkinlik sırasında Google Cast Tasarım Kontrol Listesi'nde açıklandığı gibi yayın cihazına bağlanabilmeli veya yayın 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"
}

Proje derlemelerinin hatasız olduğunu onaylamak için projeyi senkronize edin.

Başlatma

Cast çerçevesi, tüm Cast etkileşimlerini koordine eden genel bir tekil nesneye (CastContext) sahiptir.

CastContext teklisini başlatmak için gereken CastOptions kaynağını sağlamak amacıyla OptionsProvider arayüzünü uygulamanız gerekir. En önemli seçenek, yayın cihazının 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.

Cast uyumlu kendi uygulamanızı geliştirdiğinizde, Cast geliştiricisi olarak kaydolmanız ve ardından uygulamanız için bir uygulama kimliği almanız gerekir. Bu codelab için örnek bir uygulama kimliği kullanacağız.

Aşağıdaki yeni CastOptionsProvider.kt dosyasını projenin com.google.sample.cast.refplayer paketine 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 uygulama AndroidManifest.xml dosyasının "application" etiketi içinde OptionsProvider öğesini tanımlayın:

<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ç bir şekilde 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)
}

Aynı başlatma mantığını LocalPlayerActivity öğesine ekleyin.

Yayınla düğmesi

CastContext başlatıldığına göre kullanıcının yayın cihazı seçebilmesi 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 ilgili menü öğesini menünüze 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 öğesini 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
}

LocalPlayerActivity öğesinde onCreateOptionsMenu öğesini benzer bir ş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 keşfi CastContext tarafından otomatik olarak yönetilir. Yayın cihazınızı seçin. Yayın cihazına örnek alıcı uygulaması yüklenir. Göz atma etkinliği ile yerel oynatıcı etkinliği arasında gezinebilirsiniz. Yayın düğmesinin durumu senkronize edilir.

Medya oynatma desteği almadığımızdan henüz yayın cihazında video oynatamıyorsunuz. Bağlantıyı kesmek için Yayınla düğmesini tıklayın.

6. Video içeriği yayınlanıyor

&quot;Video Yayınla&quot; uygulamasını çalıştıran bir Android telefonu gösteren görsel

Örnek uygulamanın kapsamını, videoları bir Cast cihazında uzaktan oynatacak şekilde genişleteceğiz. Bunun için Cast çerçevesi tarafından oluşturulan çeşitli etkinlikleri dinlememiz gerekir.

Medya yayınlanıyor

Genel olarak, bir yayın cihazında medya oynatmak isterseniz aşağıdakileri yapmanız gerekir:

  1. Medya öğesini modelleyen bir MediaInfo nesnesi oluşturun.
  2. Yayın cihazına bağlanıp 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 bağlı olarak alıcıya oynatma komutları gönderin.

Önceki bölümde yer alan 2. Adım'ı zaten yapmıştık. 3. adımı Cast çerçevesiyle yapmak kolaydır. 1. adım bir nesnenin başka bir nesneyle eşlenmesi anlamına gelir; MediaInfo, Cast çerçevesinin anladığı bir şey, MediaItem ise uygulamamızın bir medya öğesine yönelik kapsülüdür. Bir MediaItem öğesini kolayca bir MediaInfo ile eşleyebiliriz.

Örnek uygulama LocalPlayerActivity, şu enum'u kullanarak yerel ve uzaktan oynatma arasında zaten ayrım yapmaktadır:

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. Uygulamanızın medya oynatıcısının, iki oynatma konumunu benzer bir şekilde fark etmesi için değiştirilmesi gerektiğini anlamak önemlidir.

Şu anda yerel oynatıcı, Yayınlama durumları 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 göre 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 işlem devam ederken yayını durdurursak yerel oynatmaya geçiş yapmamız gerekir. Bunu halletmek için Cast çerçevesi tarafından oluşturulan çeşitli etkinlikleri dinlememiz gerekir.

Yayın oturumu yönetimi

Yayın çerçevesi için Cast oturumu; cihaza bağlanma, başlatma (veya katılma), alıcı uygulamaya bağlanma ve uygunsa bir medya kontrol kanalını başlatma adımlarını birleştirir. Medya kontrol kanalı, Yayın çerçevesinin alıcı medya oynatıcıdan mesaj gönderip alma yöntemidir.

Yayın oturumu, kullanıcı Yayınla düğmesinden bir cihaz seçtiğinde otomatik olarak başlatılır ve kullanıcı bağlantısı kesildiğinde otomatik olarak durdurulur. Ağ sorunları nedeniyle alıcı oturumuna yeniden bağlanma da otomatik olarak Cast SDK'sı tarafından gerçekleştirilir.

LocalPlayerActivity içine 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, Cast cihazına bağlandığımızda veya cihaz bağlantısı kesildiğinde bilgi almak isteriz. Böylece yerel oynatıcıya veya yerel oynatıcıdan geçiş yapabiliriz. Bağlantının yalnızca uygulamanızın mobil cihazınızda çalışan örneği nedeniyle kesintiye uğrayabileceğini değil, aynı zamanda uygulamanızın farklı bir mobil cihazda çalışan (ya da başka bir) uygulamanızın başka bir örneği nedeniyle de kesintiye uğrayabileceğini unutmayın.

Şu anda etkin olan oturuma SessionManager.getCurrentSession() adresinden erişilebilir. Oturumlar, kullanıcıların Yayınlama iletişim kutularıyla olan etkileşimlerine yanıt olarak otomatik olarak oluşturulur ve azaltılı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'sında RemoteMediaClient, alıcıdaki uzaktan medya oynatmayı yönetmek için kullanabileceğiniz 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 aşağıdaki yöntemleri LocalPlayerActivity öğesine 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 de uzaktan oynatmayı desteklemek üzere Yayın 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, 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. Yayın cihazınıza bağlanın ve bir videoyu oynatmaya başlayın. Videonun alıcıda oynatıldığını görüyor olmanız gerekir.

7. Mini kumanda

Yayın Tasarımı Kontrol Listesi, tüm Cast uygulamalarında kullanıcı geçerli içerik sayfasından ayrıldığında görünen bir mini denetleyici olmasını gerektirir. Mini kumanda, geçerli Yayın oturumu için anında erişim ve görünür bir hatırlatıcı sağlar.

Android telefonun alt kısmındaki Cast Videolar uygulamasındaki mini oynatıcı görseli

Cast SDK'sı, mini kumandayı göstermek istediğiniz etkinliklerin uygulama düzen dosyasına eklenebilecek özel bir görünüm (MiniControllerFragment) sağlar.

res/layout/player_activity.xml ve res/layout/video_browser.xml kodunun altına aşağıdaki parça tanımını 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 kısmında mini kumandanın belirdiğini 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 gezinirseniz mini kumandanın 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, gönderen uygulamanın bir bildirim ve kilit ekranındaki medya denetimlerini uygulamasını gerektirir.

Bildirimler alanındaki medya denetimlerini gösteren bir Android telefon görseli

Cast SDK'sı, gönderen uygulamanın bildirim ve kilit ekranı için medya kontrolleri oluşturmasına yardımcı olmak üzere bir MediaNotificationService sağlar. Hizmet, gradle tarafından otomatik olarak uygulamanızın manifest dosyasıyla birleştirilir.

MediaNotificationService, gönderen yayın sırasında arka planda çalışır ve geçerli yayın öğesine ilişkin küçük resim ve meta veriler, bir oynat/duraklat düğmesi ve bir durdurma düğmesi içeren bir bildirim gösterir.

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

CastOptionsProvider öğesini düzenleyin ve getCastOptions uygulamasını bu kodla eşleşecek şekilde değiştirin:

import com.google.android.gms.cast.framework.media.CastMediaOptions
import com.google.android.gms.cast.framework.media.NotificationOptions

override fun getCastOptions(context: Context): CastOptions {
   val notificationOptions = NotificationOptions.Builder()
            .setTargetActivityClassName(VideoBrowserActivity::class.java.name)
            .build()
    val mediaOptions = CastMediaOptions.Builder()
            .setNotificationOptions(notificationOptions)
            .build()
   return CastOptions.Builder()
                .setReceiverApplicationId(context.getString(R.string.app_id))
                .setCastMediaOptions(mediaOptions)
                .build()
}

Uygulamayı mobil cihazınızda çalıştırmak için Android Studio&#39;nun Çalıştır düğmesi (sağı gösteren yeşil bir üçgen)Çalıştır düğmesini tıklayın. Video yayınlayın ve örnek uygulamadan ayrılın. Alıcıda gösterilmekte olan video için bildirim gösterilir. Mobil cihazınızı kilitlediğinizde, kilit ekranında Yayın cihazında medya oynatmaya ilişkin kontroller gösterilecektir.

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

9. Tanıtım yer paylaşımı

Google Cast tasarımıyla ilgili yapılacaklar listesi, bir gönderen uygulamanın, gönderen uygulamasının artık yayınlamayı desteklediğini ve Google Cast'i kullanmaya yeni başlayan kullanıcılara da yardımcı olduğunu bildirmek için mevcut kullanıcılara Yayın düğmesini tanıtmasını gerektirir.

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

Cast SDK'sı, kullanıcılara ilk gösterildiğinde Yayın düğmesini vurgulamak için kullanılabilen özel bir görünüm (IntroductoryOverlay) sağlar. VideoBrowserActivity için şu kodu 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 CastStateListener ekleyip onCreate yöntemini değiştirerek bir yayın cihazı kullanılabilir olduğunda showIntroductoryOverlay yöntemini çağırın ve onResume ile onPause yöntemlerini aşağıdakilerle eşleşecek şekilde geçersiz kılın:

import com.google.android.gms.cast.framework.CastState
import com.google.android.gms.cast.framework.CastStateListener

private var mCastStateListener: CastStateListener? = null

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.video_browser)
    setupActionBar()
    mCastStateListener = object : CastStateListener {
            override fun onCastStateChanged(newState: Int) {
                if (newState != CastState.NO_DEVICES_AVAILABLE) {
                    showIntroductoryOverlay()
                }
            }
        }
    mCastContext = CastContext.getSharedInstance(this)
}

override fun onResume() {
    super.onResume()
    mCastContext?.addCastStateListener(mCastStateListener!!)
}

override fun onPause() {
    super.onPause()
    mCastContext?.removeCastStateListener(mCastStateListener!!)
}

Uygulama verilerini temizleyin veya uygulamayı cihazınızdan kaldırın. Ardından, uygulamayı mobil cihazınızda çalıştırmak için Android Studio&#39;nun Çalıştır düğmesi (sağı gösteren yeşil bir üçgen)Çalıştır düğmesini tıklayın. Tanıtım amaçlı yer paylaşımını görürsünüz (yer paylaşımı görünmüyorsa uygulama verilerini temizleyin).

10. Genişletilmiş kumanda

Google Cast tasarım listesi, gönderen uygulamanın, yayınlanmakta olan 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ş kumandanın yer aldığı bir Android telefonda oynatılan videonun resmi

Cast SDK'sı, genişletilmiş kumanda için ExpandedControllerActivity adlı bir widget sağlar. Bu, Yayınla düğmesi eklemek için alt sınıfa getirmeniz gereken soyut bir sınıftır.

Öncelikle, genişletilmiş denetleyicinin Yayın 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. Ardından com.google.sample.cast.refplayer.expandedcontrols paketinde ExpandedControlsActivity.kt adlı yeni bir dosya oluşturun.

package com.google.sample.cast.refplayer.expandedcontrols

import android.view.Menu
import com.google.android.gms.cast.framework.media.widget.ExpandedControllerActivity
import com.google.sample.cast.refplayer.R
import com.google.android.gms.cast.framework.CastButtonFactory

class ExpandedControlsActivity : ExpandedControllerActivity() {
    override fun onCreateOptionsMenu(menu: Menu): Boolean {
        super.onCreateOptionsMenu(menu)
        menuInflater.inflate(R.menu.expanded_controller, menu)
        CastButtonFactory.setUpMediaRouteButton(this, menu, R.id.media_route_menu_item)
        return true
    }
}

Şimdi AndroidManifest.xml öğesinin içinde, OPTIONS_PROVIDER_CLASS_NAME öğesinin üzerindeki application etiketinin içinde 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 değerine ayarlamak için NotificationOptions ve CastMediaOptions değerlerini değiştirin:

import com.google.sample.cast.refplayer.expandedcontrols.ExpandedControlsActivity

override fun getCastOptions(context: Context): CastOptions {
    val notificationOptions = NotificationOptions.Builder()
            .setTargetActivityClassName(ExpandedControlsActivity::class.java.name)
            .build()
    val mediaOptions = CastMediaOptions.Builder()
            .setNotificationOptions(notificationOptions)
            .setExpandedControllerActivityClassName(ExpandedControlsActivity::class.java.name)
            .build()
    return CastOptions.Builder()
            .setReceiverApplicationId(context.getString(R.string.app_id))
            .setCastMediaOptions(mediaOptions)
            .build()
}

Uzak medya yüklendiğinde ExpandedControlsActivity öğesini görüntülemek için LocalPlayerActivity loadRemoteMedia yöntemini güncelleyin:

import com.google.sample.cast.refplayer.expandedcontrols.ExpandedControlsActivity

private fun loadRemoteMedia(position: Int, autoPlay: Boolean) {
    if (mCastSession == null) {
        return
    }
    val remoteMediaClient = mCastSession!!.remoteMediaClient ?: return
    remoteMediaClient.registerCallback(object : RemoteMediaClient.Callback() {
        override fun onStatusUpdated() {
            val intent = Intent(this@LocalPlayerActivity, ExpandedControlsActivity::class.java)
            startActivity(intent)
            remoteMediaClient.unregisterCallback(this)
        }
    })
    remoteMediaClient.load(MediaLoadRequestData.Builder()
                .setMediaInfo(buildMediaInfo())
                .setAutoplay(autoPlay)
                .setCurrentTime(position.toLong()).build())
}

Uygulamayı mobil cihazınızda çalıştırmak ve video yayınlamak için Android Studio&#39;nun Çalıştır düğmesi (sağı gösteren yeşil bir üçgen)Çalıştır düğmesini tıklayın. Genişletilmiş denetleyici gösterilir. Video listesine geri dönün. Mini kumandayı tıkladığınızda genişletilmiş kumanda tekrar yüklenir. Bildirimi görmek için uygulamanın dışına gidin. Genişletilmiş kumandayı 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ü aracılığıyla 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'i uygulamak için play-services-cast-framework, 19.0.0 veya daha yüksek olmalıdır.

LaunchOptions

Android Alıcı olarak da bilinen Android TV uygulamasını başlatmak için LaunchOptions nesnesinde setAndroidReceiverCompatible işaretini true olarak ayarlamamız gerekir. Bu LaunchOptions nesnesi, alıcının nasıl başlatılacağını belirler ve CastOptionsProvider sınıfı tarafından döndürülen CastOptions öğesine iletilir. Yukarıda bahsedilen işaretin false değerine ayarlanması, Cast Developer Console'da tanımlanan Uygulama Kimliği için web alıcısı başlatır.

CastOptionsProvider.kt dosyasında getCastOptions yöntemine aşağıdaki kodu 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 Ayarla

Gönderen tarafında, oturuma kimlerin katıldığını temsil etmesi için CredentialsData değerini belirtebilirsiniz. credentials, ATV uygulamanız tarafından anlaşılabildiği sürece kullanıcı tanımlı bir dizedir. CredentialsData, Android TV uygulamanıza yalnızca başlatma veya katılma sırasında aktarılır. Bağlıyken tekrar ayarlarsanız Android TV uygulamanıza aktarılmaz.

Başlatma Kimlik Bilgilerinin ayarlanması için CredentialsData ürününün tanımlanması ve LaunchOptions nesnesine geçirilmesi gerekir. Aşağıdaki kodu CastOptionsProvider.kt dosyanızdaki getCastOptions yöntemine 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 Belirleme

Web Alıcısı ve Android TV uygulamanız credentials ürününü farklı şekilde ele alıyorsa her biri için ayrı bir credentials tanımlamanız gerekebilir. Bu işlemi yapmak için LocalPlayerActivity.kt dosyanıza 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 hangi kimlik bilgilerinin kullanılacağını otomatik olarak işliyor.

Cast Connect'i test etme

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

  1. Android TV cihazınızın IP adresini bulun. Bu özellik genellikle Ayarlar > Ağ ve İnternet > (Cihazınızın bağlı olduğu ağ adı) altından bulunur. Sağ tarafta, ayrıntıları ve cihazınızın ağdaki IP'sini gösterir.
  2. Cihazınıza terminali kullanarak ADB aracılığıyla bağlanmak için IP adresini kullanın:
$ adb connect <device_ip_address>:5555
  1. Terminal pencerenizden, bu codelab'in başında indirdiğiniz codelab örneklerinin üst düzey klasörüne gidin. Örneğin:
$ cd Desktop/android_codelab_src
  1. Aşağı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 adıyla bir uygulamayı görebilmeniz gerekir.
  2. Android Studio projenize dönün ve gönderen uygulamasını fiziksel mobil cihazınıza yükleyip çalıştırmak için Çalıştır düğmesini tıklayın. Sağ üst köşedeki yayınlama simgesini tıklayın ve mevcut seçenekler arasından Android TV cihazınızı seçin. Artık Android TV cihazınızda Android TV uygulamasını görüyor olmanız gerekir. Video oynattığınızda video oynatmayı Android TV uzaktan kumandanızı kullanarak kontrol edebilirsiniz.

12. Yayın widget'larını özelleştirme

Renkleri ayarlayarak, düğmelerin stilini, metni ve küçük resim görünümünü ayarlayarak ve görüntülenecek düğme türlerini seçerek Yayın widget'larını özelleştirebilirsiniz.

res/values/styles_castvideo.xml öğelerini güncelle

<style name="Theme.CastVideosTheme" parent="Theme.AppCompat.Light.NoActionBar">
    ...
    <item name="mediaRouteTheme">@style/CustomMediaRouterTheme</item>
    <item name="castIntroOverlayStyle">@style/CustomCastIntroOverlay</item>
    <item name="castMiniControllerStyle">@style/CustomCastMiniController</item>
    <item name="castExpandedControllerStyle">@style/CustomCastExpandedController</item>
    <item name="castExpandedControllerToolbarStyle">
        @style/ThemeOverlay.AppCompat.ActionBar
    </item>
    ...
</style>

Aşağıdaki özel temaları beyan edin:

<!-- 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'sı widget'larını kullanarak bir video uygulamasını Cast için nasıl etkinleştireceğinizi biliyorsunuz.

Daha ayrıntılı bilgi için Android Gönderen geliştirici kılavuzuna bakın.