Medya denetimleri

Android'deki medya kontrolleri, Hızlı Ayarlar'ın yakınında bulunur. Birden fazla uygulamadaki oturumlar, kaydırılabilir bir ruloda düzenlenir. Döngü, oturumları şu sırayla listeler:

  • Telefonda yerel olarak oynatılan yayınlar
  • Harici cihazlarda veya yayın oturumlarında algılananlar gibi uzaktan yayınlar
  • Önceki devam ettirilebilir oturumlar (en son oynatıldıkları sırayla)

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

Bu sayede, cihazlar arasında tutarlı bir medya denetimi grubu ve daha iyi bir medya denetimi deneyimi sunabilirsiniz.

Şekil 1'de, bunun sırasıyla telefonda ve tablette 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 kontrolleri.
            Düğmelerin nasıl görünebileceğini gösteren örnek bir parça kullanılıyor.
Şekil 1: Telefon ve tablet cihazlarda 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 oluşturulma şekliyle uyumludur.

Alan Ölçütler İşlem
1 playWhenReady yanlış veya mevcut oynatma durumu STATE_ENDED. 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 Medya düğmesi tercihleri, CommandButton.SLOT_BACK için özel bir düğme içerir. Özel
Oynatıcı komutu COMMAND_SEEK_TO_PREVIOUS veya COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM kullanılabilir. Önceki
Ne özel düğme ne de listelenen komutlardan biri kullanılabiliyor. Boş
3 Medya düğmesi tercihlerinde CommandButton.SLOT_FORWARD için özel bir düğme bulunur. Özel
Oynatıcı komutu COMMAND_SEEK_TO_NEXT veya COMMAND_SEEK_TO_NEXT_MEDIA_ITEM kullanılabilir. Sonraki
Ne özel düğme ne de listelenen komutlardan biri kullanılabiliyor. Boş
4 Medya düğmesi tercihlerinde henüz yerleştirilmemiş bir CommandButton.SLOT_OVERFLOW için özel düğme bulunur. Özel
5 Medya düğmesi tercihlerinde henüz yerleştirilmemiş bir CommandButton.SLOT_OVERFLOW için özel düğme bulunur. Özel

Özel taşma düğmeleri, medya düğmesi tercihlerine eklendikleri sırayla yerleştirilir.

Komut düğmelerini özelleştirme

Sistem medya kontrollerini Jetpack Media3 ile özelleştirmek için oturumun medya düğmesi tercihlerini ve kontrol cihazlarının kullanılabilir komutlarını buna göre ayarlayabilirsiniz:

  1. MediaSession oluşturun ve özel komut düğmeleri için medya düğmesi tercihlerini tanımlayın.

  2. MediaSession.Callback.onConnect() içinde, ConnectionResult bölümünde özel komutlar da dahil olmak üzere kullanılabilir komutlarını tanımlayarak kumandaları yetkilendirin.

  3. MediaSession.Callback.onCustomCommand() içinde, kullanıcı tarafından seçilen özel komuta yanıt ver.

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(CommandButton.ICON_HEART_UNFILLED)
        .setDisplayName("Save to favorites")
        .setSessionCommand(customCommandFavorites)
        .build()
    val player = ExoPlayer.Builder(this).build()
    // Build the session with a custom layout.
    mediaSession =
      MediaSession.Builder(this, player)
        .setCallback(MyCallback())
        .setMediaButtonPreferences(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)
      .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(CommandButton.ICON_HEART_UNFILLED)
            .setDisplayName("Save to favorites")
            .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())
            .setMediaButtonPreferences(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)
          .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);
    }
  }
}

MediaSession'nızı, sistem gibi istemcilerin medya uygulamanıza bağlanabileceği şekilde yapılandırma hakkında daha fazla bilgi edinmek için Diğer istemcilere kontrol izni verme başlıklı makaleyi inceleyin.

Jetpack Media3 ile 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 bildirim yayınlar ve güncel tutar.

İşlem düğmelerine yanıt verme

Kullanıcı, sistem medya kontrollerindeki bir işlem düğmesine dokunduğunda sistem, MediaController, MediaSession öğenize bir oynatma komutu gönderir. MediaSession bu komutları oyuncuya devreder. 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.

Medyayı devam ettirme özelliğini destekleme

Medya oynatmaya devam etme ö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şime girer.

Oynatmaya devam etme özelliği, Ayarlar uygulamasında Ses > Medya seçenekleri altında etkinleştirilebilir veya devre dışı bırakılabilir. Kullanıcı, genişletilmiş bantta kaydırdıktan sonra görünen dişli simgesine dokunarak da Ayarlar'a erişebilir.

Media3, medya oynatmaya devam etme özelliğini desteklemeyi kolaylaştıran API'ler sunar. Bu özelliği uygulama hakkında bilgi edinmek için Media3 ile oynatmaya devam etme dokümanına bakın.

Eski medya API'lerini kullanma

Bu bölümde, eski MediaCompat API'lerini kullanarak sistem medya kontrolleriyle nasıl entegrasyon yapılacağı açıklanmaktadır.

Sistem, MediaSession'nın MediaMetadata bölümünden aşağıdaki bilgileri alır ve kullanılabilir olduğunda görüntüler:

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

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

Medya oynatıcıda, şu anda oynatılan medyanın geçen süresi ve MediaSession PlaybackState ile eşlenmiş bir arama çubuğu gösterilir.

Medya oynatıcı, şu anda oynatılan medyanın ilerleme durumunu ve MediaSession PlaybackState tuşuna eşlenmiş bir arama çubuğunu 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ştirilmesi için PlaybackState.Builder#setActions işlevini uygulamanız ve ACTION_SEEK_TO işlevini eklemeniz gerekir.

Alan İşlem Ölçütler
1 Oynat PlaybackState öğesinin mevcut durumu aşağıdakilerden biridir:
  • STATE_NONE
  • STATE_STOPPED
  • STATE_PAUSED
  • STATE_ERROR
Yükleme döner simgesi PlaybackState öğesinin mevcut durumu aşağıdakilerden biridir:
  • STATE_CONNECTING
  • STATE_BUFFERING
Duraklat PlaybackState'ın mevcut durumu yukarıdakilerin hiçbiri değil.
2 Önceki PlaybackState işlemler ACTION_SKIP_TO_PREVIOUS içerir.
Özel PlaybackState işlemleri ACTION_SKIP_TO_PREVIOUS içermiyor ve PlaybackState özel işlemleri henüz yerleştirilmemiş bir özel işlem içeriyor.
Boş PlaybackState extras, SESSION_EXTRAS_KEY_SLOT_RESERVATION_SKIP_TO_PREV anahtarı için bir true boole değeri içerir.
3 Sonraki PlaybackState işlemler ACTION_SKIP_TO_NEXT içerir.
Özel PlaybackState işlemleri ACTION_SKIP_TO_NEXT içermiyor ve PlaybackState özel işlemleri henüz yerleştirilmemiş bir özel işlem içeriyor.
Boş PlaybackState extras, SESSION_EXTRAS_KEY_SLOT_RESERVATION_SKIP_TO_NEXT anahtarı için bir 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 örneklerinde, PlaybackState standart ve özel işlemlerin nasıl ekleneceği gösterilmektedir.

Oynatma, duraklatma, önceki ve sonraki için bu işlemleri medya oturumunun PlaybackState bölümünde 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 yuvalarda düğme istemiyorsanız ACTION_SKIP_TO_PREVIOUS veya ACTION_SKIP_TO_NEXT eklemeyin. Bunun yerine oturuma ekstralar 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şlemler ekleme

Medya kontrollerinde göstermek istediğiniz diğer işlemler için bir PlaybackStateCompat.CustomAction oluşturabilir ve bunu PlaybackState'ye ekleyebilirsiniz. Bu işlemler, eklendikleri sırayla 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, MediaController.TransportControls kullanarak MediaSession'e bir komut gönderir. Bu etkinliklere uygun şekilde yanıt verebilecek bir geri çağırma 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ı 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östermek için NotificationBuilder.setContentTitle() kullanın.

Medya oynatıcıda marka simgesini göstermek için NotificationBuilder.setSmallIcon() kullanın.

Uygulamaların, oynatmaya devam etme özelliğini desteklemek için MediaBrowserService ve MediaSession yöntemlerini uygulaması gerekir. MediaSession, onPlay() geri aramasını uygulamalıdır.

MediaBrowserService uygulaması

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

Sistem, SystemUI'den gelen bir bağlantıyla MediaBrowserService ile iletişime geçmeye çalışır. Uygulamanız bu tür bağlantılara izin vermelidir. Aksi takdirde oynatmaya devam etme özelliği desteklenemez.

SystemUI'den gelen bağlantılar, paket adı com.android.systemui ve imza kullanılarak tanımlanabilir ve doğrulanabilir. SystemUI, platform imzasıyla imzalanır. Platform imzasına karşı nasıl kontrol yapılacağına dair bir örneği UAMP uygulamasında bulabilirsiniz.

Oynatmaya devam etme özelliğinin desteklenmesi için MediaBrowserService şu davranışları uygulamalıdır:

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

  • Kök medya kimliğinde onLoadChildren() çağrıldığında sonuç, FLAG_PLAYABLE alt öğesini içermelidir.

  • 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 title ve subtitle ile uygun bir MediaDescription sağlamalıdır. Ayrıca, bir simge URI'si veya bir simge bit eşlemi de ayarlamalıdır.

Aşağıdaki kod örneklerinde onGetRoot() nasıl uygulanacağı gösterilmektedir.

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);
}

Android 13 Öncesi Davranış

Sistem kullanıcı arayüzü, geriye dönük uyumluluk için Android 13'ü hedefleyecek şekilde güncellenmeyen veya PlaybackState bilgisi içermeyen uygulamalarda bildirim işlemlerini kullanan alternatif bir düzen sağlamaya devam eder. İşlem düğmeleri, MediaStyle bildirimine eklenen Notification.Action listesinden alınır. Sistem, en fazla beş işlemi eklendikleri sırayla gösterir. Kompakt modda, setShowActionsInCompactView() öğesine aktarılan değerlere göre en fazla üç düğme gösterilir.

Özel işlemler, PlaybackState'ya eklendikleri sırayla 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)
// 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(new MediaStyleNotificationHelper.MediaStyle(mediaSession)
.setShowActionsInCompactView(1 /* #1: pause button */))
.setContentTitle("Wonderful music")
.setContentText("My Awesome Band")
.setLargeIcon(albumArtBitmap)
.build();