MediaRouteProvider'a genel bakış

Android medya yönlendiricisi çerçevesi, üreticilerin MediaRouteProvider adı verilen standart bir arayüz aracılığıyla cihazlarında oynatmayı etkinleştirmelerini sağlar. Rota sağlayıcı, alıcı cihazda medya oynatmak için ortak bir arayüz tanımlar. Bu sayede, medya yönlendirmelerini destekleyen herhangi bir Android uygulamasından ekipmanınızda medya oynatabilirsiniz.

Bu kılavuzda, alıcı cihaz için medya yönlendirmesi sağlayıcısının nasıl oluşturulacağı ve bu sağlayıcının Android'de çalışan diğer medya oynatma uygulamalarının kullanımına nasıl sunulacağı anlatılmaktadır. Bu API'yi kullanmak için MediaRouteProvider, MediaRouteProviderDescriptor ve RouteController anahtar sınıfları hakkında bilgi sahibi olmanız gerekir.

Genel bakış

Android medya yönlendiricisi çerçevesi, medya uygulaması geliştiricilerinin ve medya oynatma cihazı üreticilerinin ortak bir API ve ortak bir kullanıcı arayüzü üzerinden bağlantı kurmasını sağlar. Bir MediaRouter arayüzü uygulayan uygulama geliştiriciler daha sonra çerçeveye bağlanabilir ve medya yönlendiricisi çerçevesine katılan cihazlarda içerik oynatabilir. Medya oynatma cihazının üreticileri, diğer uygulamaların alıcı cihazlara bağlanmasına ve medyaları oynatmasına izin veren bir MediaRouteProvider yayınlayarak bu çerçeveye katılabilir. Şekil 1'de bir uygulamanın medya yönlendiricisi çerçevesi üzerinden bir alıcı cihaza nasıl bağlandığı gösterilmektedir.

Şekil 1. Medya yönlendirme sağlayıcısı sınıflarının, bir medya uygulamasından alıcı cihaza nasıl iletişim sağladığına genel bakış.

Alıcı cihazınız için bir medya rotası sağlayıcı oluşturduğunuzda, sağlayıcı aşağıdaki amaçlara hizmet eder:

  • Diğer uygulamaların keşfedebilmesi ve oynatma özelliklerini kullanabilmesi için alıcı cihazın özelliklerini açıklayıp yayınlayın.
  • Alıcı cihazın programlama arayüzünü ve iletişim aktarım mekanizmalarını paketleyerek cihazı medya yönlendiricisi çerçevesiyle uyumlu hale getirin.

Rota sağlayıcılarının dağılımı

Medya rotası sağlayıcısı, bir Android uygulamasının parçası olarak dağıtılır. Rota sağlayıcınız, MediaRouteProviderService hizmetinin kapsamını genişleterek veya MediaRouteProvider uygulamanızı kendi hizmetinize dahil ederek ve medya rotası sağlayıcı için intent filtresi bildirerek diğer uygulamaların kullanımına sunulabilir. Bu adımlar, diğer uygulamaların medya yönlendirmenizi keşfetmesine ve kullanmasına olanak tanır.

Not: Medya yönlendirme sağlayıcısını içeren uygulama, rota sağlayıcıya bir MediaRouter arayüzü de içerebilir, ancak bu gerekli değildir.

MediaRouter destek kitaplığı

Medya yönlendirici API'leri AndroidX MediaRouter kitaplığında tanımlanmıştır. Bu kitaplığı uygulama geliştirme projenize eklemeniz gerekir. Projenize destek kitaplıkları ekleme hakkında daha fazla bilgi edinmek için Destek Kitaplığı Kurulumu sayfasını inceleyin.

Dikkat: Medya yönlendiricisi çerçevesinin AndroidX uygulamasını kullandığınızdan emin olun. Eski android.media paketini kullanmayın.

Sağlayıcı Hizmeti oluşturma

Medya yönlendiricisi çerçevesi, diğer uygulamaların rotanızı kullanmasına izin vermek için medya rotası sağlayıcınızı keşfedebilmeli ve ona bağlanabilmelidir. Medya yönlendiricisi çerçevesi bunu yapmak için medya yönlendirme sağlayıcısı intent işlemi tanımlayan uygulamaları arar. Başka bir uygulama sağlayıcınıza bağlanmak istediğinde çerçevenin onu çağırabilmesi ve ona bağlanabilmesi gerekir. Böylece sağlayıcınız bir Service içine alınmalıdır.

Aşağıdaki örnek kod, bir manifest içindeki medya rotası sağlayıcı hizmetinin beyanını ve medya yönlendiricisi çerçevesi tarafından keşfedilip kullanılmasına izin veren intent filtresini göstermektedir:

<service android:name=".provider.SampleMediaRouteProviderService"
    android:label="@string/sample_media_route_provider_service"
    android:process=":mrp">
    <intent-filter>
        <action android:name="android.media.MediaRouteProviderService" />
    </intent-filter>
</service>

Bu manifest örneği gerçek medya rotası sağlayıcı sınıflarını sarmalayan bir hizmeti tanımlar. Android medya yönlendiricisi çerçevesi, medya yönlendirmesi sağlayıcıları için hizmet sarmalayıcı olarak kullanılmak üzere MediaRouteProviderService sınıfını sağlar. Aşağıdaki örnek kod, bu sarmalayıcı sınıfının nasıl kullanılacağını gösterir:

Kotlin

class SampleMediaRouteProviderService : MediaRouteProviderService() {

    override fun onCreateMediaRouteProvider(): MediaRouteProvider {
        return SampleMediaRouteProvider(this)
    }
}

Java

public class SampleMediaRouteProviderService extends MediaRouteProviderService {

    @Override
    public MediaRouteProvider onCreateMediaRouteProvider() {
        return new SampleMediaRouteProvider(this);
    }
}

Rota Özelliklerini Belirtme

Medya yönlendirici çerçevesine bağlanan uygulamalar, uygulamanızın manifest beyanları aracılığıyla medya rotanızı keşfedebilir ancak sağladığınız medya rotalarının özelliklerini de bilmelidir. Medya rotaları farklı türlerde olabilir ve farklı özelliklere sahip olabilir. Diğer uygulamaların, rotanızla uyumlu olup olmadıklarını belirlemek için bu ayrıntıları keşfedebilmesi gerekir.

Medya yönlendiricisi çerçevesi, medya rotanızın özelliklerini IntentFilter nesneleri, MediaRouteDescriptor nesneleri ve MediaRouteProviderDescriptor aracılığıyla tanımlayıp yayınlamanıza olanak tanır. Bu bölümde, diğer uygulamalar için medya yönlendirmenizin ayrıntılarını yayınlamak amacıyla bu sınıfları nasıl kullanacağınız açıklanmaktadır.

Rota kategorileri

Medya yönlendirme sağlayıcınızın programatik açıklamasının bir parçası olarak, sağlayıcınızın uzaktan oynatmayı mı, ikincil çıkışı mı yoksa ikisini birden mi desteklediğini belirtmeniz gerekir. Bunlar, medya yönlendiricisi çerçevesi tarafından sağlanan rota kategorileridir:

  • CATEGORY_LIVE_AUDIO — Kablosuz özellikli müzik sistemi gibi ikincil bir çıkış cihazına ses çıkışı.
  • CATEGORY_LIVE_VIDEO — Kablosuz Ekran cihazları gibi ikincil bir çıkış cihazına video çıkışı.
  • CATEGORY_REMOTE_PLAYBACK: Video veya ses içeriklerini Chromecast cihazlar gibi medya alma, kod çözme ve oynatma işlemlerini gerçekleştiren ayrı bir cihazda oynatın.

Bu ayarları medya rotanızın açıklamasına eklemek için IntentFilter nesnesine eklersiniz. Daha sonra bu nesneleri MediaRouteDescriptor nesnesine eklersiniz:

Kotlin

class SampleMediaRouteProvider(context: Context) : MediaRouteProvider(context) {

    companion object {
        private val CONTROL_FILTERS_BASIC: ArrayList<IntentFilter> = IntentFilter().run {
            addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)
            arrayListOf(this)
        }
    }
}

Java

public final class SampleMediaRouteProvider extends MediaRouteProvider {
    private static final ArrayList<IntentFilter> CONTROL_FILTERS_BASIC;
    static {
        IntentFilter videoPlayback = new IntentFilter();
        videoPlayback.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);
        CONTROL_FILTERS_BASIC = new ArrayList<IntentFilter>();
        CONTROL_FILTERS_BASIC.add(videoPlayback);
    }
}

CATEGORY_REMOTE_PLAYBACK amacını belirtirseniz medya yönlendirme sağlayıcınız tarafından desteklenen medya türlerini ve oynatma kontrollerini de tanımlamanız gerekir. Sonraki bölümde, cihazınız için bu ayarları nasıl belirteceğiniz açıklanmaktadır.

Medya türleri ve protokoller

Uzaktan oynatma cihazının medya yönlendirmesi sağlayıcısı, desteklediği medya türlerini ve aktarım protokollerini belirtmelidir. Bu ayarları, söz konusu nesnenin IntentFilter sınıfını ve addDataScheme() ile addDataType() yöntemlerini kullanarak belirtirsiniz. Aşağıdaki kod snippet'inde http, https ve Gerçek Zamanlı Akış Protokolü (RTSP) kullanarak uzaktan video oynatmayı desteklemek üzere nasıl niyet filtresi tanımlanacağı gösterilmektedir:

Kotlin

class SampleMediaRouteProvider(context: Context) : MediaRouteProvider(context) {

    companion object {

        private fun IntentFilter.addDataTypeUnchecked(type: String) {
            try {
                addDataType(type)
            } catch (ex: IntentFilter.MalformedMimeTypeException) {
                throw RuntimeException(ex)
            }
        }

        private val CONTROL_FILTERS_BASIC: ArrayList<IntentFilter> = IntentFilter().run {
            addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)
            addAction(MediaControlIntent.ACTION_PLAY)
            addDataScheme("http")
            addDataScheme("https")
            addDataScheme("rtsp")
            addDataTypeUnchecked("video/*")
            arrayListOf(this)
        }
    }
    ...
}

Java

public final class SampleMediaRouteProvider extends MediaRouteProvider {

    private static final ArrayList<IntentFilter> CONTROL_FILTERS_BASIC;

    static {
        IntentFilter videoPlayback = new IntentFilter();
        videoPlayback.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);
        videoPlayback.addAction(MediaControlIntent.ACTION_PLAY);
        videoPlayback.addDataScheme("http");
        videoPlayback.addDataScheme("https");
        videoPlayback.addDataScheme("rtsp");
        addDataTypeUnchecked(videoPlayback, "video/*");
        CONTROL_FILTERS_BASIC = new ArrayList<IntentFilter>();
        CONTROL_FILTERS_BASIC.add(videoPlayback);
    }
    ...

    private static void addDataTypeUnchecked(IntentFilter filter, String type) {
        try {
            filter.addDataType(type);
        } catch (MalformedMimeTypeException ex) {
            throw new RuntimeException(ex);
        }
    }
}

Oynatma denetimleri

Uzaktan oynatma sunan medya yönlendirmesi sağlayıcısı, desteklediği medya denetimi türlerini belirtmelidir. Medya yollarının sağlayabileceği genel denetim türleri şunlardır:

  • Oynatma, duraklatma, geri sarma ve ileri sarma gibi oynatma kontrolleri.
  • Sıra özellikleri: Gönderen uygulamanın, alıcı cihaz tarafından korunan bir oynatma listesine öğe ekleyip kaldırmasına olanak tanır.
  • Alıcı cihazın, istekte bulunan uygulamaya bir oturum kimliği sağlamasını ve ardından sonraki her oynatma kontrolü isteğinde bu kimliği kontrol etmesini sağlayarak uygulamaların gönderilmesinin birbirlerine müdahale etmesini engelleyen oturum özellikleri.

Aşağıdaki kod örneğinde, temel medya rotası oynatma kontrollerini desteklemek için intent filtresinin nasıl oluşturulacağı gösterilmektedir:

Kotlin

class SampleMediaRouteProvider(context: Context) : MediaRouteProvider(context) {

    companion object {
        ...
        private val CONTROL_FILTERS_BASIC: ArrayList<IntentFilter> = run {
            val videoPlayback: IntentFilter = ...
            ...
            val playControls = IntentFilter().apply {
                addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)
                addAction(MediaControlIntent.ACTION_SEEK)
                addAction(MediaControlIntent.ACTION_GET_STATUS)
                addAction(MediaControlIntent.ACTION_PAUSE)
                addAction(MediaControlIntent.ACTION_RESUME)
                addAction(MediaControlIntent.ACTION_STOP)
            }
            arrayListOf(videoPlayback, playControls)
        }
    }
    ...
}

Java

public final class SampleMediaRouteProvider extends MediaRouteProvider {
    private static final ArrayList<IntentFilter> CONTROL_FILTERS_BASIC;
    static {
        ...
        IntentFilter playControls = new IntentFilter();
        playControls.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);
        playControls.addAction(MediaControlIntent.ACTION_SEEK);
        playControls.addAction(MediaControlIntent.ACTION_GET_STATUS);
        playControls.addAction(MediaControlIntent.ACTION_PAUSE);
        playControls.addAction(MediaControlIntent.ACTION_RESUME);
        playControls.addAction(MediaControlIntent.ACTION_STOP);
        CONTROL_FILTERS_BASIC = new ArrayList<IntentFilter>();
        CONTROL_FILTERS_BASIC.add(videoPlayback);
        CONTROL_FILTERS_BASIC.add(playControls);
    }
    ...
}

Kullanılabilir oynatma kontrolü amaçları hakkında daha fazla bilgi için MediaControlIntent sınıfına bakın.

MediaRouteProviderAçıklayıcı

IntentFilter nesnelerini kullanarak medya rotanızın özelliklerini tanımladıktan sonra, Android medya yönlendiricisi çerçevesine yayınlamak için bir tanımlayıcı nesne oluşturabilirsiniz. Bu açıklayıcı nesne, diğer uygulamaların medya rotanızla nasıl etkileşimde bulunacağını belirleyebilmesi için medya rotanızın özelliklerinin özelliklerini içerir.

Aşağıdaki örnek kod, önceden oluşturulan intent filtrelerinin bir MediaRouteProviderDescriptor öğesine nasıl ekleneceğini ve açıklayıcının medya yönlendirici çerçevesi tarafından kullanılmak üzere nasıl ayarlanacağını gösterir:

Kotlin

class SampleMediaRouteProvider(context: Context) : MediaRouteProvider(context) {

    init {
        publishRoutes()
    }

    private fun publishRoutes() {
        val resources = context.resources
        val routeName: String = resources.getString(R.string.variable_volume_basic_route_name)
        val routeDescription: String = resources.getString(R.string.sample_route_description)
        // Create a route descriptor using previously created IntentFilters
        val routeDescriptor: MediaRouteDescriptor =
                MediaRouteDescriptor.Builder(VARIABLE_VOLUME_BASIC_ROUTE_ID, routeName)
                        .setDescription(routeDescription)
                        .addControlFilters(CONTROL_FILTERS_BASIC)
                        .setPlaybackStream(AudioManager.STREAM_MUSIC)
                        .setPlaybackType(MediaRouter.RouteInfo.PLAYBACK_TYPE_REMOTE)
                        .setVolumeHandling(MediaRouter.RouteInfo.PLAYBACK_VOLUME_VARIABLE)
                        .setVolumeMax(VOLUME_MAX)
                        .setVolume(mVolume)
                        .build()
        // Add the route descriptor to the provider descriptor
        val providerDescriptor: MediaRouteProviderDescriptor =
                MediaRouteProviderDescriptor.Builder()
                        .addRoute(routeDescriptor)
                        .build()

        // Publish the descriptor to the framework
        descriptor = providerDescriptor
    }
    ...
}

Java

public SampleMediaRouteProvider(Context context) {
    super(context);
    publishRoutes();
}

private void publishRoutes() {
    Resources r = getContext().getResources();
    // Create a route descriptor using previously created IntentFilters
    MediaRouteDescriptor routeDescriptor = new MediaRouteDescriptor.Builder(
            VARIABLE_VOLUME_BASIC_ROUTE_ID,
            r.getString(R.string.variable_volume_basic_route_name))
            .setDescription(r.getString(R.string.sample_route_description))
            .addControlFilters(CONTROL_FILTERS_BASIC)
            .setPlaybackStream(AudioManager.STREAM_MUSIC)
            .setPlaybackType(MediaRouter.RouteInfo.PLAYBACK_TYPE_REMOTE)
            .setVolumeHandling(MediaRouter.RouteInfo.PLAYBACK_VOLUME_VARIABLE)
            .setVolumeMax(VOLUME_MAX)
            .setVolume(mVolume)
            .build();
    // Add the route descriptor to the provider descriptor
    MediaRouteProviderDescriptor providerDescriptor =
            new MediaRouteProviderDescriptor.Builder()
            .addRoute(routeDescriptor)
            .build();

    // Publish the descriptor to the framework
    setDescriptor(providerDescriptor);
}

Kullanılabilir açıklayıcı ayarları hakkında daha fazla bilgi için MediaRouteDescriptor ve MediaRouteProviderDescriptor referans belgelerine bakın.

Rotaları Denetleme

Bir uygulama medya yönlendirme sağlayıcınıza bağlandığında sağlayıcı, diğer uygulamalar tarafından rotanıza gönderilen medya yönlendiricisi çerçevesi üzerinden oynatma komutlarını alır. Bu istekleri ele almak için, komutları işleyen ve alıcı cihazınızla gerçek iletişimi gerçekleştiren bir MediaRouteProvider.RouteController sınıfı uygulaması sağlamanız gerekir.

Medya yönlendiricisi çerçevesi, bu sınıfın bir örneğini almak için rota sağlayıcınızın onCreateRouteController() yöntemini çağırır ve ardından istekleri buna yönlendirir. Medya yönlendirmesi sağlayıcınız için uygulamanız gereken MediaRouteProvider.RouteController sınıfının temel yöntemleri şunlardır:

  • onSelect() — Bir uygulama, oynatma için rotanızı seçtiğinde çağrılır. Bu yöntemi, medya oynatma başlamadan önce gerekli olabilecek hazırlık işlerini yapmak için kullanırsınız.
  • onControlRequest(): Belirli oynatma komutlarını alıcı cihaza gönderir.
  • onSetVolume(): Alıcı cihaza, oynatma ses düzeyini belirli bir değere ayarlama isteği gönderir.
  • onUpdateVolume(): Alıcı cihaza, oynatma ses düzeyini belirtilen miktarda değiştirme isteği gönderir.
  • onUnselect(): Bir uygulama, rotanın seçimini kaldırdığında çağrılır.
  • onRelease() — Çerçevenin rotaya artık ihtiyaç duymadığı durumlarda çağrılır ve böylece kaynakları serbest bırakabilir.

Ses seviyesi değişiklikleri hariç tüm oynatma kontrolü istekleri onControlRequest() yöntemine yönlendirilir. Bu yöntemi kullanımınız, kontrol isteklerini ayrıştırmalı ve bunlara uygun şekilde yanıt vermelidir. Aşağıda, uzaktan oynatma medya yönlendirmesi komutlarını işleyen bu yöntemin örneği verilmiştir:

Kotlin

private class SampleRouteController : MediaRouteProvider.RouteController() {
    ...

    override fun onControlRequest(
            intent: Intent,
            callback: MediaRouter.ControlRequestCallback?
    ): Boolean {
        return if (intent.hasCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)) {
            val action = intent.action
            when (action) {
                MediaControlIntent.ACTION_PLAY -> handlePlay(intent, callback)
                MediaControlIntent.ACTION_ENQUEUE -> handleEnqueue(intent, callback)
                MediaControlIntent.ACTION_REMOVE -> handleRemove(intent, callback)
                MediaControlIntent.ACTION_SEEK -> handleSeek(intent, callback)
                MediaControlIntent.ACTION_GET_STATUS -> handleGetStatus(intent, callback)
                MediaControlIntent.ACTION_PAUSE -> handlePause(intent, callback)
                MediaControlIntent.ACTION_RESUME -> handleResume(intent, callback)
                MediaControlIntent.ACTION_STOP -> handleStop(intent, callback)
                MediaControlIntent.ACTION_START_SESSION -> handleStartSession(intent, callback)
                MediaControlIntent.ACTION_GET_SESSION_STATUS ->
                    handleGetSessionStatus(intent, callback)
                MediaControlIntent.ACTION_END_SESSION -> handleEndSession(intent, callback)
                else -> false
            }.also {
                Log.d(TAG, sessionManager.toString())
            }
        } else {
            false
        }
    }
    ...
}

Java

private final class SampleRouteController extends
        MediaRouteProvider.RouteController {
    ...

    @Override
    public boolean onControlRequest(Intent intent, ControlRequestCallback callback) {

        String action = intent.getAction();

        if (intent.hasCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)) {
            boolean success = false;
            if (action.equals(MediaControlIntent.ACTION_PLAY)) {
                success = handlePlay(intent, callback);
            } else if (action.equals(MediaControlIntent.ACTION_ENQUEUE)) {
                success = handleEnqueue(intent, callback);
            } else if (action.equals(MediaControlIntent.ACTION_REMOVE)) {
                success = handleRemove(intent, callback);
            } else if (action.equals(MediaControlIntent.ACTION_SEEK)) {
                success = handleSeek(intent, callback);
            } else if (action.equals(MediaControlIntent.ACTION_GET_STATUS)) {
                success = handleGetStatus(intent, callback);
            } else if (action.equals(MediaControlIntent.ACTION_PAUSE)) {
                success = handlePause(intent, callback);
            } else if (action.equals(MediaControlIntent.ACTION_RESUME)) {
                success = handleResume(intent, callback);
            } else if (action.equals(MediaControlIntent.ACTION_STOP)) {
                success = handleStop(intent, callback);
            } else if (action.equals(MediaControlIntent.ACTION_START_SESSION)) {
                success = handleStartSession(intent, callback);
            } else if (action.equals(MediaControlIntent.ACTION_GET_SESSION_STATUS)) {
                success = handleGetSessionStatus(intent, callback);
            } else if (action.equals(MediaControlIntent.ACTION_END_SESSION)) {
                success = handleEndSession(intent, callback);
            }

            Log.d(TAG, sessionManager.toString());
            return success;
        }
        return false;
    }
    ...
}

MediaRouteProvider.RouteController sınıfının, medya oynatma ekipmanınıza API için sarmalayıcı olarak işlev göreceğini anlamanız önemlidir. Bu sınıftaki yöntemlerin uygulanması, tamamen alıcı cihazınız tarafından sağlanan programatik arayüze bağlıdır.

Örnek Kod

MediaRouter örneği, özel bir medya yönlendirmesi sağlayıcısının nasıl oluşturulacağını gösterir.