Medya denetimleri

Android'deki medya kontrolleri, Hızlı Ayarlar'ın yakınında bulunur. Birden fazla uygulamadan gelen oturumlar, kaydırılabilir bir bantta düzenlenir. Bant, oturumları şu sırayla listeler:

  • Telefonda yerel olarak oynatılan akışlar
  • Harici cihazlarda veya yayınlama oturumlarında algılananlar gibi uzaktan yayınlar
  • Son oynatıldıkları sırayla, devam ettirilebilir önceki oturumlar

Android 13'ten (API düzeyi 33) itibaren, kullanıcıların medya oynatan uygulamalar için zengin bir medya kontrolleri grubuna erişebilmesini sağlamak amacıyla medya kontrollerindeki işlem düğmeleri Player durumundan türetilir.

Böylece, cihazlar arasında tutarlı bir medya kumandası grubu ve daha iyi bir medya kumandası deneyimi sunabilirsiniz.

Şekil 1'de, bunun sırasıyla telefon ve tablet cihazlarda nasıl göründüğüne dair bir örnek gösterilmektedir.

Telefon ve tablet cihazlarda nasıl göründükleri açısından medya denetimleri (düğmelerin nasıl görünebileceğini gösteren örnek bir parça örneği kullanılarak)
Şekil 1: Telefon ve tablet cihazlardaki medya kontrolleri

Sistem, aşağıdaki tabloda açıklandığı gibi Player durumuna göre en fazla beş işlem düğmesi gösterir. Kompakt modda yalnızca ilk üç işlem yuvası gösterilir. Bu, Auto, Asistan ve Wear OS gibi diğer Android platformlarında medya kontrollerinin nasıl oluşturulduğuyla uyumludur.

Alan Ölçütler İşlem
1 playWhenReady yanlışsa veya mevcut oynatma durumu STATE_ENDED ise. Oynat
playWhenReady doğruysa ve mevcut oynatma durumu STATE_BUFFERING ise. Yükleme döner simgesi
playWhenReady doğruysa ve mevcut oynatma durumu STATE_READY ise. Duraklat
2 Oynatıcı komutu COMMAND_SEEK_TO_PREVIOUS veya COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM kullanılabilir. Önceki
Oynatıcı komutu COMMAND_SEEK_TO_PREVIOUS veya COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM kullanılamaz. Ayrıca, özel düzendeki ve henüz yerleştirilmemiş bir özel komut, alanı doldurmak için kullanılabilir. Özel
Oturum ekstraları, EXTRAS_KEY_SLOT_RESERVATION_SEEK_TO_PREV anahtarı için true boole değeri içerir. Boş
3 Oynatıcı komutu COMMAND_SEEK_TO_NEXT veya COMMAND_SEEK_TO_NEXT_MEDIA_ITEM kullanılabilir. Sonraki
Oynatıcı komutu COMMAND_SEEK_TO_NEXT veya COMMAND_SEEK_TO_NEXT_MEDIA_ITEM kullanılamaz. Ayrıca, özel düzendeki ve henüz yerleştirilmemiş bir özel komut, alanı doldurmak için kullanılabilir. Özel
Oturum ekstraları, EXTRAS_KEY_SLOT_RESERVATION_SEEK_TO_NEXT anahtarı için true boole değeri içerir. Boş
4 Özel düzendeki henüz yerleştirilmemiş bir özel komut, alanı doldurmak için kullanılabilir. Özel
5 Özel düzendeki henüz yerleştirilmemiş bir özel komut, alanı doldurmak için kullanılabilir. Özel

Özel komutlar, özel düzene eklendikleri sıraya göre yerleştirilir.

Komut düğmelerini özelleştirme

Jetpack Media3 ile sistem medya kontrollerini özelleştirmek için MediaSessionService uygularken oturumun özel düzenini ve denetleyicilerin mevcut komutlarını uygun şekilde ayarlayabilirsiniz:

  1. onCreate() içinde bir MediaSession oluşturun ve komut düğmelerinin özel düzenini tanımlayın.

  2. MediaSession.Callback.onConnect()'te, ConnectionResult'te özel komutlar da dahil olmak üzere kullanılabilir komutlarını tanımlayarak denetleyicilere yetki verin.

  3. MediaSession.Callback.onCustomCommand() bölümünde, kullanıcı tarafından seçilen özel komuta yanıt verin.

Kotlin

class PlaybackService : MediaSessionService() {
  private val customCommandFavorites = SessionCommand(ACTION_FAVORITES, Bundle.EMPTY)
  private var mediaSession: MediaSession? = null

  override fun onCreate() {
    super.onCreate()
    val favoriteButton =
      CommandButton.Builder()
        .setDisplayName("Save to favorites")
        .setIconResId(R.drawable.favorite_icon)
        .setSessionCommand(customCommandFavorites)
        .build()
    val player = ExoPlayer.Builder(this).build()
    // Build the session with a custom layout.
    mediaSession =
      MediaSession.Builder(this, player)
        .setCallback(MyCallback())
        .setCustomLayout(ImmutableList.of(favoriteButton))
        .build()
  }

  private inner class MyCallback : MediaSession.Callback {
    override fun onConnect(
      session: MediaSession,
      controller: MediaSession.ControllerInfo
    ): ConnectionResult {
    // Set available player and session commands.
    return AcceptedResultBuilder(session)
      .setAvailablePlayerCommands(
        ConnectionResult.DEFAULT_PLAYER_COMMANDS.buildUpon()
          .remove(COMMAND_SEEK_TO_NEXT)
          .remove(COMMAND_SEEK_TO_NEXT_MEDIA_ITEM)
          .remove(COMMAND_SEEK_TO_PREVIOUS)
          .remove(COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM)
          .build()
      )
      .setAvailableSessionCommands(
        ConnectionResult.DEFAULT_SESSION_COMMANDS.buildUpon()
          .add(customCommandFavorites)
          .build()
      )
      .build()
    }

    override fun onCustomCommand(
      session: MediaSession,
      controller: MediaSession.ControllerInfo,
      customCommand: SessionCommand,
      args: Bundle
    ): ListenableFuture {
      if (customCommand.customAction == ACTION_FAVORITES) {
        // Do custom logic here
        saveToFavorites(session.player.currentMediaItem)
        return Futures.immediateFuture(SessionResult(SessionResult.RESULT_SUCCESS))
      }
      return super.onCustomCommand(session, controller, customCommand, args)
    }
  }
}

Java

public class PlaybackService extends MediaSessionService {
  private static final SessionCommand CUSTOM_COMMAND_FAVORITES =
      new SessionCommand("ACTION_FAVORITES", Bundle.EMPTY);
  @Nullable private MediaSession mediaSession;

  public void onCreate() {
    super.onCreate();
    CommandButton favoriteButton =
        new CommandButton.Builder()
            .setDisplayName("Save to favorites")
            .setIconResId(R.drawable.favorite_icon)
            .setSessionCommand(CUSTOM_COMMAND_FAVORITES)
            .build();
    Player player = new ExoPlayer.Builder(this).build();
    // Build the session with a custom layout.
    mediaSession =
        new MediaSession.Builder(this, player)
            .setCallback(new MyCallback())
            .setCustomLayout(ImmutableList.of(favoriteButton))
            .build();
  }

  private static class MyCallback implements MediaSession.Callback {
    @Override
    public ConnectionResult onConnect(
        MediaSession session, MediaSession.ControllerInfo controller) {
      // Set available player and session commands.
      return new AcceptedResultBuilder(session)
          .setAvailablePlayerCommands(
              ConnectionResult.DEFAULT_PLAYER_COMMANDS.buildUpon()
                .remove(COMMAND_SEEK_TO_NEXT)
                .remove(COMMAND_SEEK_TO_NEXT_MEDIA_ITEM)
                .remove(COMMAND_SEEK_TO_PREVIOUS)
                .remove(COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM)
                .build())
          .setAvailableSessionCommands(
              ConnectionResult.DEFAULT_SESSION_COMMANDS.buildUpon()
                .add(CUSTOM_COMMAND_FAVORITES)
                .build())
          .build();
    }

    public ListenableFuture onCustomCommand(
        MediaSession session,
        MediaSession.ControllerInfo controller,
        SessionCommand customCommand,
        Bundle args) {
      if (customCommand.customAction.equals(CUSTOM_COMMAND_FAVORITES.customAction)) {
        // Do custom logic here
        saveToFavorites(session.getPlayer().getCurrentMediaItem());
        return Futures.immediateFuture(new SessionResult(SessionResult.RESULT_SUCCESS));
      }
      return MediaSession.Callback.super.onCustomCommand(
          session, controller, customCommand, args);
    }
  }
}

Sistem gibi istemcilerin medya uygulamanıza bağlanabilmesi için MediaSession'ünüzü yapılandırma hakkında daha fazla bilgi edinmek istiyorsanız Diğer istemcilere kontrol verme başlıklı makaleyi inceleyin.

Jetpack Media3 ile bir MediaSession uyguladığınızda PlaybackState, medya oynatıcıyla otomatik olarak güncel tutulur. Benzer şekilde, bir MediaSessionService uyguladığınızda kitaplık sizin için otomatik olarak bir MediaStyle bildirimi yayınlar ve bu bildirimi güncel tutar.

İşlem düğmelerine yanıt verme

Kullanıcı, sistem medya kontrollerindeki bir işlem düğmesine dokunduğunda sistem MediaController, MediaSession cihazınıza oynatma komutu gönderir. MediaSession daha sonra bu komutları oynatıcıya iletir. Media3'ün Player arayüzünde tanımlanan komutlar, medya oturumu tarafından otomatik olarak işlenir.

Özel komutlara nasıl yanıt vereceğinizle ilgili bilgi için Özel komut ekleme başlıklı makaleyi inceleyin.

Android 13'ten önceki davranış

Sistem kullanıcı arayüzü, geriye dönük uyumluluk için Android 13'ü hedeflemek üzere güncellenmeyen veya PlaybackState bilgilerini içermeyen uygulamalar için bildirim işlemlerini kullanan alternatif bir düzen sunmaya devam eder. İşlem düğmeleri, MediaStyle bildirimine eklenmiş Notification.Action listesinden türetilir. Sistem, en fazla beş işlemi eklendikleri sırayla gösterir. Kompakt modda, setShowActionsInCompactView() parametresine iletilen değerlere göre üç adede kadar düğme gösterilir.

Özel işlemler, PlaybackState'e eklendikleri sıraya göre yerleştirilir.

Aşağıdaki kod örneğinde, MediaStyle bildirimine nasıl işlem ekleneceği gösterilmektedir :

Kotlin

import androidx.core.app.NotificationCompat
import androidx.media3.session.MediaStyleNotificationHelper

var notification = NotificationCompat.Builder(context, CHANNEL_ID)
        // Show controls on lock screen even when user hides sensitive content.
        .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
        .setSmallIcon(R.drawable.ic_stat_player)
        // Add media control buttons that invoke intents in your media service
        .addAction(R.drawable.ic_prev, "Previous", prevPendingIntent) // #0
        .addAction(R.drawable.ic_pause, "Pause", pausePendingIntent) // #1
        .addAction(R.drawable.ic_next, "Next", nextPendingIntent) // #2
        // Apply the media style template
        .setStyle(MediaStyleNotificationHelper.MediaStyle(mediaSession)
                .setShowActionsInCompactView(1 /* #1: pause button */))
        .setContentTitle("Wonderful music")
        .setContentText("My Awesome Band")
        .setLargeIcon(albumArtBitmap)
        .build()

Java

import androidx.core.app.NotificationCompat;
import androidx.media3.session.MediaStyleNotificationHelper;

NotificationCompat.Builder notification = new NotificationCompat.Builder(context, CHANNEL_ID)
        .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
        .setSmallIcon(R.drawable.ic_stat_player)
        .addAction(R.drawable.ic_prev, "Previous", prevPendingIntent)
        .addAction(R.drawable.ic_pause, "Pause", pausePendingIntent)
        .addAction(R.drawable.ic_next, "Next", nextPendingIntent)
        .setStyle(new MediaStyleNotificationHelper.MediaStyle(mediaSession)
                .setShowActionsInCompactView(1 /* #1: pause button */))
        .setContentTitle("Wonderful music")
        .setContentText("My Awesome Band")
        .setLargeIcon(albumArtBitmap)
        .build();

Medyayı devam ettirme desteği

Medya devam ettirme özelliği, kullanıcıların uygulamayı başlatmak zorunda kalmadan önceki oturumları banttan yeniden başlatmasına olanak tanır. Oynatma başladığında kullanıcı, medya kontrolleriyle normal şekilde etkileşim kurar.

Oynatma işlemini devam ettirme özelliğini Ayarlar uygulamasındaki Ses > Medya seçenekleri altından etkinleştirebilir veya devre dışı bırakabilirsiniz. Kullanıcı, genişletilmiş bantta kaydırdıktan sonra görünen dişli simgesine dokunarak da Ayarlar'a erişebilir.

Media3, medya oynatmanın devam etmesini desteklemeyi kolaylaştırmak için API'ler sunar. Bu özelliği uygulamayla ilgili yardım için Media3 ile oynatmayı devam ettirme dokümanlarını inceleyin.

Eski medya API'lerini kullanma

Bu bölümde, eski MediaCompat API'leri kullanılarak sistem medya denetimleriyle nasıl entegrasyon yapılacağı açıklanmaktadır.

Sistem, MediaSession'nin MediaMetadata'sinden aşağıdaki bilgileri alır ve kullanılabilir olduğunda gösterir:

  • METADATA_KEY_ALBUM_ART_URI
  • METADATA_KEY_TITLE
  • METADATA_KEY_DISPLAY_TITLE
  • METADATA_KEY_ARTIST
  • METADATA_KEY_DURATION (Süre ayarlanmamışsa ilerleme durumu kaydırma çubuğunda gösterilmez)

Geçerli ve doğru bir medya kontrolü bildirimi alabilmeniz için METADATA_KEY_TITLE veya METADATA_KEY_DISPLAY_TITLE meta verilerinin değerini, şu anda oynatılan medyanın başlığına ayarlayın.

Medya oynatıcı, şu anda oynatılan medyanın geçtiği süreyi ve MediaSession PlaybackState ile eşlenen bir arama çubuğunu gösterir.

Medya oynatıcı, MediaSession PlaybackState ile eşlenen bir arama çubuğuyla birlikte, oynatılmakta olan medyanın ilerleme durumunu gösterir. Arama çubuğu, kullanıcıların konumu değiştirmesine olanak tanır ve medya öğesinin geçen süresini gösterir. Arama çubuğunun etkinleştirilebilmesi için PlaybackState.Builder#setActions'ü uygulamanız ve ACTION_SEEK_TO'u eklemeniz gerekir.

Alan İşlem Ölçütler
1 Oynat PlaybackState'nin mevcut durumu aşağıdakilerden biri olmalıdır:
  • STATE_NONE
  • STATE_STOPPED
  • STATE_PAUSED
  • STATE_ERROR
Yükleme döner simgesi PlaybackState'nin mevcut durumu aşağıdakilerden biridir:
  • STATE_CONNECTING
  • STATE_BUFFERING
Duraklat PlaybackState öğesinin mevcut durumu yukarıdakilerden hiçbiri değil.
2 Önceki PlaybackState işlemleri ACTION_SKIP_TO_PREVIOUS içerir.
Özel PlaybackState işlemler ACTION_SKIP_TO_PREVIOUS içermez ve PlaybackState özel işlemler henüz yerleştirilmemiş bir özel işlem içerir.
Boş PlaybackState extras, SESSION_EXTRAS_KEY_SLOT_RESERVATION_SKIP_TO_PREV anahtarı için true boole değeri içerir.
3 Sonraki PlaybackState işlemleri ACTION_SKIP_TO_NEXT içerir.
Özel PlaybackState işlemler ACTION_SKIP_TO_NEXT içermez ve PlaybackState özel işlemler henüz yerleştirilmemiş bir özel işlem içerir.
Boş PlaybackState extras, SESSION_EXTRAS_KEY_SLOT_RESERVATION_SKIP_TO_NEXT anahtarı için true boole değeri içerir.
4 Özel PlaybackState özel işlemler henüz yerleştirilmemiş bir özel işlem içeriyor.
5 Özel PlaybackState özel işlemler henüz yerleştirilmemiş bir özel işlem içeriyor.

Standart işlemler ekleme

Aşağıdaki kod örnekleri, PlaybackState standart ve özel işlemlerin nasıl ekleneceğini göstermektedir.

Oynatma, duraklatma, önceki ve sonraki işlemleri medya oturumu için PlaybackState içinde ayarlayın.

Kotlin

val session = MediaSessionCompat(context, TAG)
val playbackStateBuilder = PlaybackStateCompat.Builder()
val style = NotificationCompat.MediaStyle()

// For this example, the media is currently paused:
val state = PlaybackStateCompat.STATE_PAUSED
val position = 0L
val playbackSpeed = 1f
playbackStateBuilder.setState(state, position, playbackSpeed)

// And the user can play, skip to next or previous, and seek
val stateActions = PlaybackStateCompat.ACTION_PLAY
    or PlaybackStateCompat.ACTION_PLAY_PAUSE
    or PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS
    or PlaybackStateCompat.ACTION_SKIP_TO_NEXT
    or PlaybackStateCompat.ACTION_SEEK_TO // adding the seek action enables seeking with the seekbar
playbackStateBuilder.setActions(stateActions)

// ... do more setup here ...

session.setPlaybackState(playbackStateBuilder.build())
style.setMediaSession(session.sessionToken)
notificationBuilder.setStyle(style)

Java

MediaSessionCompat session = new MediaSessionCompat(context, TAG);
PlaybackStateCompat.Builder playbackStateBuilder = new PlaybackStateCompat.Builder();
NotificationCompat.MediaStyle style = new NotificationCompat.MediaStyle();

// For this example, the media is currently paused:
int state = PlaybackStateCompat.STATE_PAUSED;
long position = 0L;
float playbackSpeed = 1f;
playbackStateBuilder.setState(state, position, playbackSpeed);

// And the user can play, skip to next or previous, and seek
long stateActions = PlaybackStateCompat.ACTION_PLAY
    | PlaybackStateCompat.ACTION_PLAY_PAUSE
    | PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS
    | PlaybackStateCompat.ACTION_SKIP_TO_NEXT
    | PlaybackStateCompat.ACTION_SEEK_TO; // adding this enables the seekbar thumb
playbackStateBuilder.setActions(stateActions);

// ... do more setup here ...

session.setPlaybackState(playbackStateBuilder.build());
style.setMediaSession(session.getSessionToken());
notificationBuilder.setStyle(style);

Önceki veya sonraki alanlarda herhangi bir düğme istemiyorsanız ACTION_SKIP_TO_PREVIOUS veya ACTION_SKIP_TO_NEXT eklemeyin. Bunun yerine oturuma ek öğeler ekleyin:

Kotlin

session.setExtras(Bundle().apply {
    putBoolean(SESSION_EXTRAS_KEY_SLOT_RESERVATION_SKIP_TO_PREV, true)
    putBoolean(SESSION_EXTRAS_KEY_SLOT_RESERVATION_SKIP_TO_NEXT, true)
})

Java

Bundle extras = new Bundle();
extras.putBoolean(SESSION_EXTRAS_KEY_SLOT_RESERVATION_SKIP_TO_PREV, true);
extras.putBoolean(SESSION_EXTRAS_KEY_SLOT_RESERVATION_SKIP_TO_NEXT, true);
session.setExtras(extras);

Özel işlem ekleme

Medya kontrollerinde göstermek istediğiniz diğer işlemler için bir PlaybackStateCompat.CustomAction oluşturabilir ve bunu PlaybackState'a ekleyebilirsiniz. Bu işlemler, eklendikleri sıraya göre gösterilir.

Kotlin

val customAction = PlaybackStateCompat.CustomAction.Builder(
    "com.example.MY_CUSTOM_ACTION", // action ID
    "Custom Action", // title - used as content description for the button
    R.drawable.ic_custom_action
).build()

playbackStateBuilder.addCustomAction(customAction)

Java

PlaybackStateCompat.CustomAction customAction = new PlaybackStateCompat.CustomAction.Builder(
        "com.example.MY_CUSTOM_ACTION", // action ID
        "Custom Action", // title - used as content description for the button
        R.drawable.ic_custom_action
).build();

playbackStateBuilder.addCustomAction(customAction);

PlaybackState işlemlerine yanıt verme

Kullanıcı bir düğmeye dokunduğunda SystemUI, MediaSession'a geri komut göndermek için MediaController.TransportControls'u kullanır. Bu etkinliklere uygun şekilde yanıt verebilecek bir geri çağırma işlevi kaydetmeniz gerekir.

Kotlin

val callback = object: MediaSession.Callback() {
    override fun onPlay() {
        // start playback
    }

    override fun onPause() {
        // pause playback
    }

    override fun onSkipToPrevious() {
        // skip to previous
    }

    override fun onSkipToNext() {
        // skip to next
    }

    override fun onSeekTo(pos: Long) {
        // jump to position in track
    }

    override fun onCustomAction(action: String, extras: Bundle?) {
        when (action) {
            CUSTOM_ACTION_1 -> doCustomAction1(extras)
            CUSTOM_ACTION_2 -> doCustomAction2(extras)
            else -> {
                Log.w(TAG, "Unknown custom action $action")
            }
        }
    }

}

session.setCallback(callback)

Java

MediaSession.Callback callback = new MediaSession.Callback() {
    @Override
    public void onPlay() {
        // start playback
    }

    @Override
    public void onPause() {
        // pause playback
    }

    @Override
    public void onSkipToPrevious() {
        // skip to previous
    }

    @Override
    public void onSkipToNext() {
        // skip to next
    }

    @Override
    public void onSeekTo(long pos) {
        // jump to position in track
    }

    @Override
    public void onCustomAction(String action, Bundle extras) {
        if (action.equals(CUSTOM_ACTION_1)) {
            doCustomAction1(extras);
        } else if (action.equals(CUSTOM_ACTION_2)) {
            doCustomAction2(extras);
        } else {
            Log.w(TAG, "Unknown custom action " + action);
        }
    }
};

Medyayı devam ettirme

Oynatıcı uygulamanızın hızlı ayar ayarları alanında görünmesi için geçerli bir MediaSession jetonu içeren bir MediaStyle bildirimi oluşturmanız gerekir.

MediaStyle bildiriminin başlığını görüntülemek için NotificationBuilder.setContentTitle() öğesini kullanın.

Medya oynatıcının marka simgesini görüntülemek için NotificationBuilder.setSmallIcon() simgesini kullanın.

Uygulamaların oynatmayı devam ettirme özelliğini desteklemesi için MediaBrowserService ve MediaSession uygulamalarını kullanması gerekir. MediaSession, onPlay() geri arama işlevini uygulamalıdır.

MediaBrowserService uygulaması

Cihaz açıldıktan sonra sistem, en son kullanılan beş medya uygulamasını arar ve her uygulamadan oynatmayı yeniden başlatmak için kullanılabilecek kontroller sağlar.

Sistem, SystemUI üzerinden MediaBrowserService cihazınızla iletişim kurmaya çalışır. Uygulamanız bu tür bağlantılara izin vermelidir. Aksi takdirde oynatmanın devam ettirilmesini destekleyemez.

SystemUI'den gelen bağlantılar, paket adı com.android.systemui ve imza kullanılarak tanımlanıp doğrulanabilir. SystemUI, platform imzasıyla imzalanır. Platform imzasıyla karşılaştırma yapmayı gösteren bir örneği UAMP uygulamasında bulabilirsiniz.

Oynatma işleminin devam ettirilmesini desteklemek için MediaBrowserService'ün aşağıdaki davranışları uygulaması gerekir:

  • onGetRoot(), kısa sürede null olmayan bir kök döndürmelidir. Diğer karmaşık mantıklar onLoadChildren()

  • Kök medya kimliğinde onLoadChildren() çağrıldığında sonuçta bir FLAG_PLAYABLE alt öğesi bulunmalıdır.

  • MediaBrowserService, EXTRA_RECENT sorgusu aldığında en son oynatılan medya öğesini döndürmelidir. Döndürülen değer, genel işlev yerine gerçek bir medya öğesi olmalıdır.

  • MediaBrowserService, boş olmayan bir başlık ve altyazı içeren uygun bir MediaDescription sağlamalıdır. Ayrıca bir simge URI'si veya simge bitmap'i de ayarlanmalıdır.

Aşağıdaki kod örnekleri, onGetRoot() değerinin nasıl uygulanacağını göstermektedir.

Kotlin

override fun onGetRoot(
    clientPackageName: String,
    clientUid: Int,
    rootHints: Bundle?
): BrowserRoot? {
    ...
    // Verify that the specified package is SystemUI. You'll need to write your 
    // own logic to do this.
    if (isSystem(clientPackageName, clientUid)) {
        rootHints?.let {
            if (it.getBoolean(BrowserRoot.EXTRA_RECENT)) {
                // Return a tree with a single playable media item for resumption.
                val extras = Bundle().apply {
                    putBoolean(BrowserRoot.EXTRA_RECENT, true)
                }
                return BrowserRoot(MY_RECENTS_ROOT_ID, extras)
            }
        }
        // You can return your normal tree if the EXTRA_RECENT flag is not present.
        return BrowserRoot(MY_MEDIA_ROOT_ID, null)
    }
    // Return an empty tree to disallow browsing.
    return BrowserRoot(MY_EMPTY_ROOT_ID, null)

Java

@Override
public BrowserRoot onGetRoot(String clientPackageName, int clientUid,
    Bundle rootHints) {
    ...
    // Verify that the specified package is SystemUI. You'll need to write your
    // own logic to do this.
    if (isSystem(clientPackageName, clientUid)) {
        if (rootHints != null) {
            if (rootHints.getBoolean(BrowserRoot.EXTRA_RECENT)) {
                // Return a tree with a single playable media item for resumption.
                Bundle extras = new Bundle();
                extras.putBoolean(BrowserRoot.EXTRA_RECENT, true);
                return new BrowserRoot(MY_RECENTS_ROOT_ID, extras);
            }
        }
        // You can return your normal tree if the EXTRA_RECENT flag is not present.
        return new BrowserRoot(MY_MEDIA_ROOT_ID, null);
    }
    // Return an empty tree to disallow browsing.
    return new BrowserRoot(MY_EMPTY_ROOT_ID, null);
}