मीडिया ब्राउज़र सेवा बनाना

आपके ऐप्लिकेशन को मेनिफ़ेस्ट में इंटेंट-फ़िल्टर की मदद से, MediaBrowserService के बारे में जानकारी देनी होगी. आप अपनी सेवा का नाम चुन सकते हैं; नीचे दिए गए उदाहरण में, यह "MediaPLAYService" है.

<service android:name=".MediaPlaybackService">
  <intent-filter>
    <action android:name="android.media.browse.MediaBrowserService" />
  </intent-filter>
</service>

ध्यान दें: MediaBrowserService को लागू करने का सुझाव MediaBrowserServiceCompat है. जो media-compat की सहायता लाइब्रेरी पर जाएं. इस पूरे पेज पर "MediaBrowserService" शब्द का मतलब है MediaBrowserServiceCompat पेज चुने जा सकते हैं.

मीडिया सेशन शुरू करें

जब सेवा को onCreate() लाइफ़साइकल कॉलबैक का तरीका मिलता है, तो उसे यह तरीका अपनाना चाहिए:

यह onCreate() कोड इन चरणों को दिखाता है:

Kotlin

private const val MY_MEDIA_ROOT_ID = "media_root_id"
private const val MY_EMPTY_MEDIA_ROOT_ID = "empty_root_id"

class MediaPlaybackService : MediaBrowserServiceCompat() {

    private var mediaSession: MediaSessionCompat? = null
    private lateinit var stateBuilder: PlaybackStateCompat.Builder

    override fun onCreate() {
        super.onCreate()

        // Create a MediaSessionCompat
        mediaSession = MediaSessionCompat(baseContext, LOG_TAG).apply {

            // Enable callbacks from MediaButtons and TransportControls
            setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS
                    or MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS
            )

            // Set an initial PlaybackState with ACTION_PLAY, so media buttons can start the player
            stateBuilder = PlaybackStateCompat.Builder()
                    .setActions(PlaybackStateCompat.ACTION_PLAY
                                    or PlaybackStateCompat.ACTION_PLAY_PAUSE
                    )
            setPlaybackState(stateBuilder.build())

            // MySessionCallback() has methods that handle callbacks from a media controller
            setCallback(MySessionCallback())

            // Set the session's token so that client activities can communicate with it.
            setSessionToken(sessionToken)
        }
    }
}

Java

public class MediaPlaybackService extends MediaBrowserServiceCompat {
    private static final String MY_MEDIA_ROOT_ID = "media_root_id";
    private static final String MY_EMPTY_MEDIA_ROOT_ID = "empty_root_id";

    private MediaSessionCompat mediaSession;
    private PlaybackStateCompat.Builder stateBuilder;

    @Override
    public void onCreate() {
        super.onCreate();

        // Create a MediaSessionCompat
        mediaSession = new MediaSessionCompat(context, LOG_TAG);

        // Enable callbacks from MediaButtons and TransportControls
        mediaSession.setFlags(
              MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS |
              MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);

        // Set an initial PlaybackState with ACTION_PLAY, so media buttons can start the player
        stateBuilder = new PlaybackStateCompat.Builder()
                            .setActions(
                                PlaybackStateCompat.ACTION_PLAY |
                                PlaybackStateCompat.ACTION_PLAY_PAUSE);
        mediaSession.setPlaybackState(stateBuilder.build());

        // MySessionCallback() has methods that handle callbacks from a media controller
        mediaSession.setCallback(new MySessionCallback());

        // Set the session's token so that client activities can communicate with it.
        setSessionToken(mediaSession.getSessionToken());
    }
}

क्लाइंट कनेक्शन प्रबंधित करें

MediaBrowserService में क्लाइंट कनेक्शन को मैनेज करने के दो तरीके होते हैं: onGetRoot() के कंट्रोल सेवा का ऐक्सेस देना ज़रूरी है और onLoadChildren() इससे क्लाइंट को MediaBrowserService के कॉन्टेंट की हैरारकी का मेन्यू बनाने और दिखाने की सुविधा मिलती है.

onGetRoot() की मदद से क्लाइंट कनेक्शन को कंट्रोल करना

onGetRoot() तरीका, कॉन्टेंट हैरारकी का रूट नोड दिखाता है. अगर तरीका शून्य दिखाता है, तो कनेक्शन अस्वीकार कर दिया जाता है.

क्लाइंट को अपनी सेवा से कनेक्ट करने और उसका मीडिया कॉन्टेंट ब्राउज़ करने की अनुमति देने के लिए, onGetRoot() एक गैर-शून्य ब्राउज़र रूट दिखाएगा जो कि एक रूट आईडी है जो आपके कॉन्टेंट की हैरारकी को दिखाता है.

क्लाइंट को बिना ब्राउज़ किए मीडिया सेशन से कनेक्ट करने की अनुमति देने के लिए, onGetRoot() को अब भी एक गैर-शून्य ब्राउज़र रूट रिटर्न करना चाहिए, लेकिन रूट आईडी को खाली कॉन्टेंट की हैरारकी है.

onGetRoot() को आम तौर पर लागू करने पर ऐसा दिख सकता है:

Kotlin

override fun onGetRoot(
        clientPackageName: String,
        clientUid: Int,
        rootHints: Bundle?
): MediaBrowserServiceCompat.BrowserRoot {

    // (Optional) Control the level of access for the specified package name.
    // You'll need to write your own logic to do this.
    return if (allowBrowsing(clientPackageName, clientUid)) {
        // Returns a root ID that clients can use with onLoadChildren() to retrieve
        // the content hierarchy.
        MediaBrowserServiceCompat.BrowserRoot(MY_MEDIA_ROOT_ID, null)
    } else {
        // Clients can connect, but this BrowserRoot is an empty hierarchy
        // so onLoadChildren returns nothing. This disables the ability to browse for content.
        MediaBrowserServiceCompat.BrowserRoot(MY_EMPTY_MEDIA_ROOT_ID, null)
    }
}

Java

@Override
public BrowserRoot onGetRoot(String clientPackageName, int clientUid,
    Bundle rootHints) {

    // (Optional) Control the level of access for the specified package name.
    // You'll need to write your own logic to do this.
    if (allowBrowsing(clientPackageName, clientUid)) {
        // Returns a root ID that clients can use with onLoadChildren() to retrieve
        // the content hierarchy.
        return new BrowserRoot(MY_MEDIA_ROOT_ID, null);
    } else {
        // Clients can connect, but this BrowserRoot is an empty hierarchy
        // so onLoadChildren returns nothing. This disables the ability to browse for content.
        return new BrowserRoot(MY_EMPTY_MEDIA_ROOT_ID, null);
    }
}

कुछ मामलों में, हो सकता है कि आप यह कंट्रोल करना चाहें कि कौन कनेक्ट कर सकता है आपके MediaBrowserService में. ऐक्सेस कंट्रोल लिस्ट (एसीएल) का इस्तेमाल करने का एक तरीका है यह बताता है कि कौनसे कनेक्शन इस्तेमाल किए जा सकते हैं या वैकल्पिक तौर पर इनकी गिनती करता है किन कनेक्शन पर रोक लगानी चाहिए. ACL को लागू करने के उदाहरण के लिए विशिष्ट कनेक्शन की अनुमति देता है, तो पैकेज वैलिडेटर Universal Android Music Player की क्लास में सैंपल के तौर पर मिला है.

आपको कॉन्टेंट की अलग-अलग हैरारकी बनानी चाहिए, जो इस बात पर निर्भर करती हैं कि किस तरह का क्लाइंट क्वेरी कर रहा है. खास तौर पर, Android Auto उपयोगकर्ता ऑडियो ऐप्लिकेशन के साथ इंटरैक्ट करते हैं या नहीं. ज़्यादा जानकारी के लिए, इस डिवाइस के लिए ऑडियो चलाना देखें ऑटो. आपने लोगों तक पहुंचाया मुफ़्त में कनेक्शन के समय पर clientPackageName देखकर, यह तय कर सकता है कि क्लाइंट टाइप करें, और क्लाइंट (या rootHints) के हिसाब से अलग BrowserRoot दिखाएं (अगर कोई है).

कॉन्टेंट को onLoadChildren() की मदद से शेयर करें

क्लाइंट के कनेक्ट होने के बाद, यह यूज़र इंटरफ़ेस (यूआई) को स्थानीय तौर पर दिखाने के लिए, MediaBrowserCompat.subscribe() को बार-बार कॉल करके कॉन्टेंट की हैरारकी को देख सकता है. subscribe() वाला तरीका, सेवा को कॉलबैक onLoadChildren() भेजता है, जो MediaBrowser.MediaItem ऑब्जेक्ट की सूची दिखाता है.

हर MediaItem में एक यूनीक आईडी स्ट्रिंग होती है, जो एक ओपेक टोकन होती है. जब कोई क्लाइंट सबमेन्यू खोलना या कोई आइटम चलाना चाहता है, तब वह आईडी पास कर देता है. आईडी को सही मेन्यू नोड या कॉन्टेंट आइटम से जोड़ने की ज़िम्मेदारी आपकी सेवा की है.

onLoadChildren() को आसानी से लागू करने पर ऐसा दिख सकता है:

Kotlin

override fun onLoadChildren(
        parentMediaId: String,
        result: MediaBrowserServiceCompat.Result<List<MediaBrowserCompat.MediaItem>>
) {
    //  Browsing not allowed
    if (MY_EMPTY_MEDIA_ROOT_ID == parentMediaId) {
        result.sendResult(null)
        return
    }

    // Assume for example that the music catalog is already loaded/cached.

    val mediaItems = emptyList<MediaBrowserCompat.MediaItem>()

    // Check if this is the root menu:
    if (MY_MEDIA_ROOT_ID == parentMediaId) {
        // Build the MediaItem objects for the top level,
        // and put them in the mediaItems list...
    } else {
        // Examine the passed parentMediaId to see which submenu we're at,
        // and put the children of that menu in the mediaItems list...
    }
    result.sendResult(mediaItems)
}

Java

@Override
public void onLoadChildren(final String parentMediaId,
    final Result<List<MediaItem>> result) {

    //  Browsing not allowed
    if (TextUtils.equals(MY_EMPTY_MEDIA_ROOT_ID, parentMediaId)) {
        result.sendResult(null);
        return;
    }

    // Assume for example that the music catalog is already loaded/cached.

    List<MediaItem> mediaItems = new ArrayList<>();

    // Check if this is the root menu:
    if (MY_MEDIA_ROOT_ID.equals(parentMediaId)) {
        // Build the MediaItem objects for the top level,
        // and put them in the mediaItems list...
    } else {
        // Examine the passed parentMediaId to see which submenu we're at,
        // and put the children of that menu in the mediaItems list...
    }
    result.sendResult(mediaItems);
}

ध्यान दें: MediaItem ऑब्जेक्ट, MediaBrowserService के ज़रिए डिलीवर किए गए हैं. आइकन बिटमैप शामिल नहीं होने चाहिए. कॉल करके Uri का इस्तेमाल करें setIconUri() जब आप प्रत्येक आइटम के लिए MediaDescription बनाते हैं.

onLoadChildren() लागू करने के उदाहरण के लिए, Universal Android Music Player सैंपल ऐप्लिकेशन देखें.

मीडिया ब्राउज़र सेवा की लाइफ़साइकल

किसी Android सेवा का व्यवहार इस बात पर निर्भर करता है कि वह एक या उससे ज़्यादा क्लाइंट के लिए शुरू है या बाउंड है. कोई सेवा बनाए जाने के बाद, उसे शुरू किया जा सकता है, बाउंड किया जा सकता है या दोनों काम किए जा सकते हैं. इन सभी स्थितियों में, यह पूरी तरह से काम कर रहा है और वह काम कर सकता है जिसके लिए इसे बनाया गया है. अंतर इस बात पर निर्भर करता है कि सेवा कितने समय तक मौजूद रहेगी. किसी बाउंड सेवा को तब तक खत्म नहीं किया जाता, जब तक उसके सभी बाउंड क्लाइंट बंद नहीं किए जाते. शुरू की गई सेवा को साफ़ तौर पर रोका और बंद किया जा सकता है (यह मानते हुए कि अब वह किसी भी क्लाइंट से जुड़ी नहीं है).

जब किसी दूसरी गतिविधि में चल रहा MediaBrowser, किसी MediaBrowserService से कनेक्ट होता है, तो यह गतिविधि को सेवा से बाइंड करता है. ऐसा होने पर, सेवा सीमित हो जाती है, लेकिन शुरू नहीं होती. यह डिफ़ॉल्ट तरीका, MediaBrowserServiceCompat क्लास में बनाया गया है.

कोई सेवा सिर्फ़ तब खत्म हो जाती है, जब उसके सभी क्लाइंट बाइंडिंग खत्म कर देते हैं. हालांकि, यह सेवा चालू नहीं होती. अगर इस समय आपकी यूज़र इंटरफ़ेस (यूआई) गतिविधि डिसकनेक्ट हो जाती है, तो सेवा खत्म हो जाती है. अगर आपने अब तक कोई संगीत नहीं चलाया है, तो यह समस्या नहीं है. हालांकि, जब वीडियो चलाना शुरू किया जाता है, तो हो सकता है कि वह ऐप्लिकेशन स्विच करने के बाद भी वीडियो सुनना जारी रखे. जब आप किसी दूसरे ऐप्लिकेशन के साथ काम करने के लिए यूज़र इंटरफ़ेस (यूआई) को बाइंड नहीं करते हैं, तब प्लेयर को मिटाया नहीं जा सकता.

इसलिए, आपको यह पक्का करना होगा कि सेवा शुरू होने से पहले ही यह शुरू हो जाए startService() पर कॉल करके खेलने के लिए. ऐप्लिकेशन शुरू की गई सेवा को स्पष्ट रूप से रोका जाना चाहिए, चाहे वह सीमित हो या नहीं. यह यह पक्का करता है कि आपका प्लेयर, कंट्रोल करने वाले यूज़र इंटरफ़ेस (यूआई) के बावजूद परफ़ॉर्म करता रहे गतिविधि की सूचना देने वाली सुविधा बंद हो जाती है.

किसी चालू सेवा को रोकने के लिए, Context.stopService() या stopSelf() पर कॉल करें. सिस्टम तुरंत बंद हो जाता है और सेवा को खत्म कर देता है. हालांकि, अगर एक या उससे ज़्यादा क्लाइंट अब भी सेवा से जुड़े हैं, तो सेवा को रोकने की कॉल तब तक देर से होती है, जब तक कि उसके सभी क्लाइंट की सेवाएं लेना बंद नहीं कर दिया जाता.

MediaBrowserService का लाइफ़साइकल, इसे बनाने के तरीके, इससे जुड़े क्लाइंट की संख्या, और मीडिया सेशन के कॉलबैक से इसे मिलने वाले कॉल से कंट्रोल किया जाता है. खास जानकारी:

  • सेवा तब बनाई जाती है, जब उसे मीडिया बटन के जवाब में शुरू किया जाता है या जब कोई गतिविधि इससे बाइंड होती है (MediaBrowser के ज़रिए कनेक्ट करने के बाद).
  • मीडिया सेशन onPlay() कॉलबैक में ऐसा कोड शामिल होना चाहिए जो startService() को कॉल करता हो. इससे यह पक्का होता है कि सेवा चालू हो और चलती रहे. भले ही, यूज़र इंटरफ़ेस (यूआई) MediaBrowser की सभी गतिविधियां उससे जुड़ी हुई हों.
  • onStop() कॉलबैक को stopSelf() को कॉल करना चाहिए. अगर सेवा शुरू की गई थी, तो यह रुक जाती है. इसके अलावा, अगर किसी सेवा में कोई गतिविधि नहीं है, तो उसे खत्म कर दिया जाता है. अगर ऐसा नहीं होता है, तो सेवा तब तक लागू रहती है, जब तक उसकी सभी गतिविधियां बंद नहीं हो जातीं. (अगर सेवा खत्म होने से पहले बाद में startService() कॉल मिलता है, तो रुके हुए स्टॉप को रद्द कर दिया जाएगा.)

नीचे दिया गया फ़्लोचार्ट यह दिखाता है कि किसी सेवा की लाइफ़साइकल कैसे मैनेज की जाती है. वैरिएबल काउंटर, बाउंड क्लाइंट की संख्या को ट्रैक करता है:

सेवा लाइफ़साइकल

फ़ोरग्राउंड सेवा के साथ MediaStyle सूचनाओं का इस्तेमाल करना

जब कोई सेवा चल रही हो, तो वह फ़ोरग्राउंड में चल रही होनी चाहिए. इससे सिस्टम को पता चलता है कि सेवा उपयोगी काम कर रही है और अगर सिस्टम की मेमोरी कम है, तो सेवा बंद नहीं होनी चाहिए. फ़ोरग्राउंड सेवा को एक सूचना दिखानी चाहिए, ताकि उपयोगकर्ता को इसके बारे में पता चल सके और वह इसे कंट्रोल कर सके. onPlay() कॉलबैक में, सेवा फ़ोरग्राउंड में होनी चाहिए. (ध्यान दें कि यह "फ़ोरग्राउंड" का खास मतलब है. Android, फ़ोरग्राउंड में चलने वाली सेवा का इस्तेमाल प्रोसेस मैनेज करने के लिए करता है. हालांकि, उपयोगकर्ता को बैकग्राउंड में प्लेयर चलाते समय कोई दूसरा ऐप्लिकेशन दिखता है. स्क्रीन पर दिखेगा.)

जब कोई सेवा फ़ोरग्राउंड में चलती है, तो उसके लिए सूचना दिखती है. आम तौर पर, इस सूचना में एक या एक से ज़्यादा ट्रांसपोर्ट कंट्रोल शामिल होते हैं. सूचना में सेशन के मेटाडेटा से ली गई काम की जानकारी भी शामिल होनी चाहिए.

प्लेयर के गेम शुरू होने पर सूचना बनाएं और दिखाएं. ऐसा करने के लिए, सबसे सही जगह MediaSessionCompat.Callback.onPlay() है.

नीचे दिए गए उदाहरण में NotificationCompat.MediaStyle, मीडिया ऐप्लिकेशन के लिए डिज़ाइन किया गया है. इसमें मेटाडेटा और ट्रांसपोर्ट कंट्रोल दिखाने वाली सूचना बनाने का तरीका बताया गया है. सुविधा का तरीका getController() अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है आपको सीधे अपने मीडिया सेशन से मीडिया कंट्रोलर बनाने की सुविधा मिलती है.

Kotlin

// Given a media session and its context (usually the component containing the session)
// Create a NotificationCompat.Builder

// Get the session's metadata
val controller = mediaSession.controller
val mediaMetadata = controller.metadata
val description = mediaMetadata.description

val builder = NotificationCompat.Builder(context, channelId).apply {
    // Add the metadata for the currently playing track
    setContentTitle(description.title)
    setContentText(description.subtitle)
    setSubText(description.description)
    setLargeIcon(description.iconBitmap)

    // Enable launching the player by clicking the notification
    setContentIntent(controller.sessionActivity)

    // Stop the service when the notification is swiped away
    setDeleteIntent(
            MediaButtonReceiver.buildMediaButtonPendingIntent(
                    context,
                    PlaybackStateCompat.ACTION_STOP
            )
    )

    // Make the transport controls visible on the lockscreen
    setVisibility(NotificationCompat.VISIBILITY_PUBLIC)

    // Add an app icon and set its accent color
    // Be careful about the color
    setSmallIcon(R.drawable.notification_icon)
    color = ContextCompat.getColor(context, R.color.primaryDark)

    // Add a pause button
    addAction(
            NotificationCompat.Action(
                    R.drawable.pause,
                    getString(R.string.pause),
                    MediaButtonReceiver.buildMediaButtonPendingIntent(
                            context,
                            PlaybackStateCompat.ACTION_PLAY_PAUSE
                    )
            )
    )

    // Take advantage of MediaStyle features
    setStyle(android.support.v4.media.app.NotificationCompat.MediaStyle()
            .setMediaSession(mediaSession.sessionToken)
            .setShowActionsInCompactView(0)

            // Add a cancel button
            .setShowCancelButton(true)
            .setCancelButtonIntent(
                    MediaButtonReceiver.buildMediaButtonPendingIntent(
                            context,
                            PlaybackStateCompat.ACTION_STOP
                    )
            )
    )
}

// Display the notification and place the service in the foreground
startForeground(id, builder.build())

Java

// Given a media session and its context (usually the component containing the session)
// Create a NotificationCompat.Builder

// Get the session's metadata
MediaControllerCompat controller = mediaSession.getController();
MediaMetadataCompat mediaMetadata = controller.getMetadata();
MediaDescriptionCompat description = mediaMetadata.getDescription();

NotificationCompat.Builder builder = new NotificationCompat.Builder(context, channelId);

builder
    // Add the metadata for the currently playing track
    .setContentTitle(description.getTitle())
    .setContentText(description.getSubtitle())
    .setSubText(description.getDescription())
    .setLargeIcon(description.getIconBitmap())

    // Enable launching the player by clicking the notification
    .setContentIntent(controller.getSessionActivity())

    // Stop the service when the notification is swiped away
    .setDeleteIntent(MediaButtonReceiver.buildMediaButtonPendingIntent(context,
       PlaybackStateCompat.ACTION_STOP))

    // Make the transport controls visible on the lockscreen
    .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)

    // Add an app icon and set its accent color
    // Be careful about the color
    .setSmallIcon(R.drawable.notification_icon)
    .setColor(ContextCompat.getColor(context, R.color.primaryDark))

    // Add a pause button
    .addAction(new NotificationCompat.Action(
        R.drawable.pause, getString(R.string.pause),
        MediaButtonReceiver.buildMediaButtonPendingIntent(context,
            PlaybackStateCompat.ACTION_PLAY_PAUSE)))

    // Take advantage of MediaStyle features
    .setStyle(new MediaStyle()
        .setMediaSession(mediaSession.getSessionToken())
        .setShowActionsInCompactView(0)

        // Add a cancel button
       .setShowCancelButton(true)
       .setCancelButtonIntent(MediaButtonReceiver.buildMediaButtonPendingIntent(context,
           PlaybackStateCompat.ACTION_STOP)));

// Display the notification and place the service in the foreground
startForeground(id, builder.build());

MediaStyle नोटिफ़िकेशन का इस्तेमाल करते समय इनके व्यवहार का ध्यान रखें NotificationCompat की सेटिंग:

  • setContentIntent() का इस्तेमाल करने पर, सूचनाएं मिलते ही आपके लिए सेवा अपने-आप शुरू हो जाती है एक आसान सुविधा है.
  • "गैर-भरोसेमंद" स्थिति में स्थिति लॉकस्क्रीन की तरह, सूचना कॉन्टेंट की डिफ़ॉल्ट सेटिंग VISIBILITY_PRIVATE है. आप शायद यह देखना चाहें कि ट्रांसपोर्ट कंट्रोल को लॉक करें, ताकि आप VISIBILITY_PUBLIC का इस्तेमाल कर सकें.
  • बैकग्राउंड का रंग सेट करते समय सावधानी बरतें. किसी सामान्य सूचना में, Android 5.0 या उसके बाद के वर्शन पर, रंग केवल बैकग्राउंड में लागू होता है छोटा ऐप्लिकेशन आइकॉन. हालांकि, Android 7.0 से पहले की MediaStyle सूचनाओं के लिए, रंग का इस्तेमाल सूचनाओं के पूरे बैकग्राउंड के लिए किया जाता है. अपने बैकग्राउंड के रंग की जांच करें. ऐप पर जाएं यह आंखों के लिए हल्का होता है. साथ ही, ज़्यादा चमकदार या फ़्लोरोसेंट रंगों से बचें.

ये सेटिंग सिर्फ़ तब उपलब्ध होती हैं, जब आप NotificationCompat.MediaStyle का इस्तेमाल कर रहे हों:

  • setMediaSession() का इस्तेमाल करें सूचना को अपने सेशन से जोड़ने के लिए: इससे तीसरे पक्ष के ऐप्लिकेशन को अनुमति मिलती है सेशन को ऐक्सेस और कंट्रोल करने के लिए, साथी डिवाइसों का इस्तेमाल करें.
  • दिखाने के लिए ज़्यादा से ज़्यादा तीन कार्रवाइयां जोड़ने के लिए setShowActionsInCompactView() का इस्तेमाल करें नोटिफ़िकेशन का मानक आकार का contentView. (यहां रोकें बटन तय किया गया है.)
  • Android 5.0 (एपीआई लेवल 21) और उसके बाद के वर्शन में, सूचना को स्वाइप करके रोका जा सकता है प्लेयर बंद हो जाने पर प्लेयर. आप यह नहीं कर सकते में नहीं किया है. उपयोगकर्ताओं को सूचना हटाने और वीडियो चलाने से रोकने के लिए Android 5.0 (एपीआई लेवल 21) से पहले वाले वर्शन के लिए, तो आप setShowCancelButton(true) और setCancelButtonIntent() पर कॉल करके सूचना पाएं.

'रोकें' और 'रद्द करें' बटन जोड़ते समय, आपको अटैच करने के लिए PendingIntent की ज़रूरत होगी को कैसे हाइलाइट करें. MediaButtonReceiver.buildMediaButtonPendingIntent() विधि से कन्वर्ट होने का काम करता है PLAYState कार्रवाई को PendingIntent में बदलें.