MediasessionService के साथ बैकग्राउंड में वीडियो चलाने की सुविधा

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

MediasessionService का इस्तेमाल करें

बैकग्राउंड में वीडियो चलाने के लिए, आपके पास Player और MediaSession को एक अलग सेवा में रखा गया है. इससे, आपके ऐप्लिकेशन के बंद होने पर भी, डिवाइस पर मीडिया चलता रहेगा का इस्तेमाल करें.

MediasessionService, मीडिया सेशन को अलग-अलग चलाने की अनुमति देता है
  ऐप्लिकेशन की गतिविधि से
पहली इमेज: MediaSessionService में मीडिया को ऐप्लिकेशन की गतिविधि से अलग चलने के लिए सेशन

किसी सेवा में खिलाड़ी को होस्ट करते समय, आपको MediaSessionService का इस्तेमाल करना चाहिए. ऐसा करने के लिए, MediaSessionService` को बड़ा करने वाली एक क्लास बनाएं और अपना मीडिया सत्र हो सकता है.

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

सेवा की लाइफ़साइकल लागू करें

आपको अपनी सेवा के तीन लाइफ़साइकल तरीके लागू करने होंगे:

  • onCreate() तब कॉल किया जाता है, जब पहला नियंत्रक कनेक्ट होने वाला होता है और सेवा इंस्टैंशिएट होकर शुरू हो जाती है. यह Player को बनाने और MediaSession.
  • onTaskRemoved(Intent) तब कॉल किया जाता है, जब उपयोगकर्ता हाल ही के टास्क. अगर वीडियो चल रहा है, तो ऐप्लिकेशन, सेवा को बनाए रखने का विकल्प चुन सकता है का इस्तेमाल किया जा सकता है. अगर प्लेयर को रोका जाता है, तो यह सेवा इन्हें रोका जाना चाहिए.
  • सेवा को बंद किए जाने पर, onDestroy() को कॉल किया जाता है. सभी संसाधन साथ ही, प्लेयर और सेशन रिलीज़ करना ज़रूरी है.

Kotlin

class PlaybackService : MediaSessionService() {
  private var mediaSession: MediaSession? = null

  // Create your player and media session in the onCreate lifecycle event
  override fun onCreate() {
    super.onCreate()
    val player = ExoPlayer.Builder(this).build()
    mediaSession = MediaSession.Builder(this, player).build()
  }

  // The user dismissed the app from the recent tasks
  override fun onTaskRemoved(rootIntent: Intent?) {
    val player = mediaSession?.player!!
    if (!player.playWhenReady
        || player.mediaItemCount == 0
        || player.playbackState == Player.STATE_ENDED) {
      // Stop the service if not playing, continue playing in the background
      // otherwise.
      stopSelf()
    }
  }

  // Remember to release the player and media session in onDestroy
  override fun onDestroy() {
    mediaSession?.run {
      player.release()
      release()
      mediaSession = null
    }
    super.onDestroy()
  }
}

Java

public class PlaybackService extends MediaSessionService {
  private MediaSession mediaSession = null;

  // Create your Player and MediaSession in the onCreate lifecycle event
  @Override
  public void onCreate() {
    super.onCreate();
    ExoPlayer player = new ExoPlayer.Builder(this).build();
    mediaSession = new MediaSession.Builder(this, player).build();
  }

  // The user dismissed the app from the recent tasks
  @Override
  public void onTaskRemoved(@Nullable Intent rootIntent) {
    Player player = mediaSession.getPlayer();
    if (!player.getPlayWhenReady()
        || player.getMediaItemCount() == 0
        || player.getPlaybackState() == Player.STATE_ENDED) {
      // Stop the service if not playing, continue playing in the background
      // otherwise.
      stopSelf();
    }
  }

  // Remember to release the player and media session in onDestroy
  @Override
  public void onDestroy() {
    mediaSession.getPlayer().release();
    mediaSession.release();
    mediaSession = null;
    super.onDestroy();
  }
}

बैकग्राउंड में वीडियो चलाने के बजाय, ऐप्लिकेशन ये काम कर सकता है: उपयोगकर्ता के ऐप्लिकेशन को खारिज करने पर, किसी भी स्थिति में सेवा को बंद किया जा सकता है:

Kotlin

override fun onTaskRemoved(rootIntent: Intent?) {
  val player = mediaSession.player
  if (player.playWhenReady) {
    // Make sure the service is not in foreground.
    player.pause()
  }
  stopSelf()
}

Java

@Override
public void onTaskRemoved(@Nullable Intent rootIntent) {
  Player player = mediaSession.getPlayer();
  if (player.getPlayWhenReady()) {
    // Make sure the service is not in foreground.
    player.pause();
  }
  stopSelf();
}

मीडिया सेशन का ऐक्सेस दें

अन्य क्लाइंट को अपने मीडिया का ऐक्सेस देने के लिए, onGetSession() तरीके को बदलें वह सेशन जो सेवा के बनाए जाने के दौरान बनाया गया था.

Kotlin

class PlaybackService : MediaSessionService() {
  private var mediaSession: MediaSession? = null
  // [...] lifecycle methods omitted

  override fun onGetSession(controllerInfo: MediaSession.ControllerInfo): MediaSession? =
    mediaSession
}

Java

public class PlaybackService extends MediaSessionService {
  private MediaSession mediaSession = null;
  // [...] lifecycle methods omitted

  @Override
  public MediaSession onGetSession(MediaSession.ControllerInfo controllerInfo) {
    return mediaSession;
  }
}

मेनिफ़ेस्ट में सेवा की जानकारी दें

फ़ोरग्राउंड सेवा चलाने के लिए, ऐप्लिकेशन को अनुमति की ज़रूरत है. जोड़ें मेनिफ़ेस्ट के लिए FOREGROUND_SERVICE अनुमति और एपीआई 34 को टारगेट करने पर और FOREGROUND_SERVICE_MEDIA_PLAYBACK से भी ज़्यादा:

<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />

आपको इंटेंट फ़िल्टर का इस्तेमाल करके, मेनिफ़ेस्ट में अपनी Service क्लास का एलान भी करना होगा कुल MediaSessionService.

<service
    android:name=".PlaybackService"
    android:foregroundServiceType="mediaPlayback"
    android:exported="true">
    <intent-filter>
        <action android:name="androidx.media3.session.MediaSessionService"/>
    </intent-filter>
</service>

आपको एक foregroundServiceType इसमें तब mediaPlayback शामिल होगा, जब आपका ऐप्लिकेशन Android वाले डिवाइस पर चल रहा होगा 10 (एपीआई लेवल 29) और उसके बाद वाले वर्शन.

MediaController का इस्तेमाल करके, प्लेबैक को कंट्रोल करना

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

यूज़र इंटरफ़ेस (यूआई) के निर्देशों को मैनेज करना

MediaSession को कंट्रोलर से उसकी मदद से निर्देश मिलते हैं MediaSession.Callback. MediaSession को शुरू करने से डिफ़ॉल्ट वैल्यू बनती है MediaSession.Callback को लागू करना जो हर तरह की गतिविधि को अपने-आप मैनेज करता है आदेश देता है, जो MediaController आपके प्लेयर को भेजता है.

सूचना

MediaSessionService, आपके लिए अपने-आप एक MediaNotification बनाता है ज़्यादातर मामलों में काम करती है. पब्लिश की गई सूचना, डिफ़ॉल्ट रूप से MediaStyle सूचना जो नई जानकारी के साथ अपडेट रहता है आपके मीडिया सेशन से ली गई है और प्लेबैक कंट्रोल डिस्प्ले किए गए हैं. MediaNotification को आपके सेशन के बारे में पता है और इसका इस्तेमाल करके, दूसरे ऐप्लिकेशन के प्लेबैक को कंट्रोल किया जा सकता है जो एक ही सेशन से जुड़े होते हैं.

उदाहरण के लिए, MediaSessionService का इस्तेमाल करने वाला संगीत स्ट्रीमिंग ऐप्लिकेशन, MediaNotification जो आपके हिसाब से प्लेबैक कंट्रोल के साथ चल रहा मौजूदा मीडिया आइटम MediaSession का कॉन्फ़िगरेशन.

ज़रूरी मेटाडेटा को मीडिया में शामिल किया जा सकता है या इसका एलान किया जा सकता है मीडिया आइटम, जैसा कि नीचे दिए गए स्निपेट में दिखाया गया है:

Kotlin

val mediaItem =
    MediaItem.Builder()
      .setMediaId("media-1")
      .setUri(mediaUri)
      .setMediaMetadata(
        MediaMetadata.Builder()
          .setArtist("David Bowie")
          .setTitle("Heroes")
          .setArtworkUri(artworkUri)
          .build()
      )
      .build()

mediaController.setMediaItem(mediaItem)
mediaController.prepare()
mediaController.play()

Java

MediaItem mediaItem =
    new MediaItem.Builder()
        .setMediaId("media-1")
        .setUri(mediaUri)
        .setMediaMetadata(
            new MediaMetadata.Builder()
                .setArtist("David Bowie")
                .setTitle("Heroes")
                .setArtworkUri(artworkUri)
                .build())
        .build();

mediaController.setMediaItem(mediaItem);
mediaController.prepare();
mediaController.play();

ऐप्लिकेशन, Android मीडिया कंट्रोल के कमांड बटन को अपनी पसंद के मुताबिक बना सकते हैं. और पढ़ें Android मीडिया को कस्टमाइज़ करने के बारे में नियंत्रण.

सूचना को पसंद के मुताबिक बनाना

नोटिफ़िकेशन को कस्टमाइज़ करने के लिए, MediaNotification.Provider DefaultMediaNotificationProvider.Builder के साथ या प्रोवाइडर इंटरफ़ेस को अपनी पसंद के हिसाब से लागू करके. अपने को, आपके MediaSessionService को setMediaNotificationProvider.

वीडियो को फिर से चलाना

मीडिया बटन, Android डिवाइसों और अन्य सहायक डिवाइस (जैसे, कीबोर्ड, माउस, मॉनिटर, वेबकैम वगैरह) पर मौजूद हार्डवेयर बटन होते हैं ब्लूटूथ हेडसेट पर चलाएं या रोकें बटन जैसे डिवाइस. मीडिया3 सेवा चालू रहने के दौरान, यह आपके लिए मीडिया बटन के इनपुट मैनेज करता है.

Media3 मीडिया बटन रिसीवर की जानकारी दें

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

<receiver android:name="androidx.media3.session.MediaButtonReceiver"
  android:exported="true">
  <intent-filter>
    <action android:name="android.intent.action.MEDIA_BUTTON" />
  </intent-filter>
</receiver>

वीडियो को फिर से शुरू करने के लिए कॉलबैक लागू करें

जब किसी ब्लूटूथ डिवाइस या Android सिस्टम के यूज़र इंटरफ़ेस (यूआई) पर फिर से शुरू करने की सुविधा, onPlaybackResumption() कॉलबैक का तरीका इस्तेमाल किया जाता है.

Kotlin

override fun onPlaybackResumption(
    mediaSession: MediaSession,
    controller: ControllerInfo
): ListenableFuture<MediaItemsWithStartPosition> {
  val settable = SettableFuture.create<MediaItemsWithStartPosition>()
  scope.launch {
    // Your app is responsible for storing the playlist and the start position
    // to use here
    val resumptionPlaylist = restorePlaylist()
    settable.set(resumptionPlaylist)
  }
  return settable
}

Java

@Override
public ListenableFuture<MediaItemsWithStartPosition> onPlaybackResumption(
    MediaSession mediaSession,
    ControllerInfo controller
) {
  SettableFuture<MediaItemsWithStartPosition> settableFuture = SettableFuture.create();
  settableFuture.addListener(() -> {
    // Your app is responsible for storing the playlist and the start position
    // to use here
    MediaItemsWithStartPosition resumptionPlaylist = restorePlaylist();
    settableFuture.set(resumptionPlaylist);
  }, MoreExecutors.directExecutor());
  return settableFuture;
}

अगर आपने वीडियो चलाने की स्पीड, रिपीट मोड या शफ़ल मोड, onPlaybackResumption() प्लेयर कॉन्फ़िगर करने का अच्छा स्थान है ये पैरामीटर सेट करने से पहले, Media3 प्लेयर को चालू करेगा. साथ ही, वीडियो देखते समय कॉलबैक पूरा होता है.

बेहतर कंट्रोलर कॉन्फ़िगरेशन और पुराने सिस्टम के साथ काम करने की सुविधा

कंट्रोल करने के लिए, ऐप्लिकेशन के यूज़र इंटरफ़ेस (यूआई) में MediaController का इस्तेमाल करना एक आम स्थिति है प्लेलिस्ट चलाने और उसे दिखाने में मदद मिलती है. साथ ही, सेशन को बिना अनुमति के सार्वजनिक किया जाता है बाहरी क्लाइंट के साथ-साथ मोबाइल या टीवी पर Android मीडिया कंट्रोल और Assistant घड़ियों के लिए Wear OS और कार में Android Auto. Media3 सेशन का डेमो ऐप्लिकेशन एक ऐसे ऐप्लिकेशन का उदाहरण है जो इस तरह की स्थिति लागू करता है.

ये बाहरी क्लाइंट, लेगसी के MediaControllerCompat जैसे एपीआई इस्तेमाल कर सकते हैं AndroidX लाइब्रेरी या Android की android.media.session.MediaController फ़्रेमवर्क शामिल है. Media3, लेगसी लाइब्रेरी के साथ पूरी तरह से पुराने सिस्टम के साथ काम करता है और Android फ़्रेमवर्क एपीआई के साथ इंटरऑपरेबिलिटी (दूसरे सिस्टम के साथ काम करना) की सुविधा देती है.

मीडिया नोटिफ़िकेशन कंट्रोलर का इस्तेमाल करना

यह समझना ज़रूरी है कि ये लेगसी या फ़्रेमवर्क कंट्रोलर, PlaybackState.getActions() फ़्रेमवर्क से लिए गए डेटा और PlaybackState.getCustomActions(). इनकी कार्रवाइयों और कस्टम कार्रवाइयों को तय करने के लिए फ़्रेमवर्क सेशन के दौरान, ऐप्लिकेशन मीडिया सूचना कंट्रोलर का इस्तेमाल कर सकता है और इसके लिए उपलब्ध कमांड और कस्टम लेआउट सेट करें. यह सेवा, मीडिया को कनेक्ट करती है नोटिफ़िकेशन कंट्रोलर को ट्रांसफ़र करता है और सेशन कॉन्फ़िगर करने के लिए, आपके कॉलबैक के onConnect() से ConnectionResult लौटाया गया फ़्रेमवर्क सेशन की कार्रवाइयों और कस्टम कार्रवाइयों का इस्तेमाल करें.

सिर्फ़-मोबाइल के मामले में, कोई ऐप्लिकेशन उपलब्ध निर्देशों को सेट करने के लिए MediaSession.Callback.onConnect() और खास तौर पर फ़्रेमवर्क सेशन के लिए, इस तरह कस्टम लेआउट में बदलाव करें:

Kotlin

override fun onConnect(
  session: MediaSession,
  controller: MediaSession.ControllerInfo
): ConnectionResult {
  if (session.isMediaNotificationController(controller)) {
    val sessionCommands =
      ConnectionResult.DEFAULT_SESSION_COMMANDS.buildUpon()
        .add(customCommandSeekBackward)
        .add(customCommandSeekForward)
        .build()
    val playerCommands =
      ConnectionResult.DEFAULT_PLAYER_COMMANDS.buildUpon()
        .remove(COMMAND_SEEK_TO_PREVIOUS)
        .remove(COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM)
        .remove(COMMAND_SEEK_TO_NEXT)
        .remove(COMMAND_SEEK_TO_NEXT_MEDIA_ITEM)
        .build()
    // Custom layout and available commands to configure the legacy/framework session.
    return AcceptedResultBuilder(session)
      .setCustomLayout(
        ImmutableList.of(
          createSeekBackwardButton(customCommandSeekBackward),
          createSeekForwardButton(customCommandSeekForward))
      )
      .setAvailablePlayerCommands(playerCommands)
      .setAvailableSessionCommands(sessionCommands)
      .build()
  }
  // Default commands with default custom layout for all other controllers.
  return AcceptedResultBuilder(session).build()
}

Java

@Override
public ConnectionResult onConnect(
    MediaSession session, MediaSession.ControllerInfo controller) {
  if (session.isMediaNotificationController(controller)) {
    SessionCommands sessionCommands =
        ConnectionResult.DEFAULT_SESSION_COMMANDS
            .buildUpon()
            .add(customCommandSeekBackward)
            .add(customCommandSeekForward)
            .build();
    Player.Commands playerCommands =
        ConnectionResult.DEFAULT_PLAYER_COMMANDS
            .buildUpon()
            .remove(COMMAND_SEEK_TO_PREVIOUS)
            .remove(COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM)
            .remove(COMMAND_SEEK_TO_NEXT)
            .remove(COMMAND_SEEK_TO_NEXT_MEDIA_ITEM)
            .build();
    // Custom layout and available commands to configure the legacy/framework session.
    return new AcceptedResultBuilder(session)
        .setCustomLayout(
            ImmutableList.of(
                createSeekBackwardButton(customCommandSeekBackward),
                createSeekForwardButton(customCommandSeekForward)))
        .setAvailablePlayerCommands(playerCommands)
        .setAvailableSessionCommands(sessionCommands)
        .build();
  }
  // Default commands without default custom layout for all other controllers.
  return new AcceptedResultBuilder(session).build();
}

Android Auto को कस्टम निर्देश भेजने की अनुमति दें

MediaLibraryService का इस्तेमाल करते समय मोबाइल ऐप्लिकेशन, Android Auto कंट्रोलर की मदद से Android Auto की सुविधा का इस्तेमाल किया जा सकता है सही उपलब्ध कमांड की ज़रूरत होगी. ऐसा न करने पर, Media3 आपके वीडियो को उस कंट्रोलर से आने वाले कस्टम कमांड:

Kotlin

override fun onConnect(
  session: MediaSession,
  controller: MediaSession.ControllerInfo
): ConnectionResult {
  val sessionCommands =
    ConnectionResult.DEFAULT_SESSION_AND_LIBRARY_COMMANDS.buildUpon()
      .add(customCommandSeekBackward)
      .add(customCommandSeekForward)
      .build()
  if (session.isMediaNotificationController(controller)) {
    // [...] See above.
  } else if (session.isAutoCompanionController(controller)) {
    // Available session commands to accept incoming custom commands from Auto.
    return AcceptedResultBuilder(session)
      .setAvailableSessionCommands(sessionCommands)
      .build()
  }
  // Default commands with default custom layout for all other controllers.
  return AcceptedResultBuilder(session).build()
}

Java

@Override
public ConnectionResult onConnect(
    MediaSession session, MediaSession.ControllerInfo controller) {
  SessionCommands sessionCommands =
      ConnectionResult.DEFAULT_SESSION_COMMANDS
          .buildUpon()
          .add(customCommandSeekBackward)
          .add(customCommandSeekForward)
          .build();
  if (session.isMediaNotificationController(controller)) {
    // [...] See above.
  } else if (session.isAutoCompanionController(controller)) {
    // Available commands to accept incoming custom commands from Auto.
    return new AcceptedResultBuilder(session)
        .setAvailableSessionCommands(sessionCommands)
        .build();
  }
  // Default commands without default custom layout for all other controllers.
  return new AcceptedResultBuilder(session).build();
}

सेशन के डेमो ऐप्लिकेशन में ऑटोमोटिव मॉड्यूल, जो Automotive OS की सुविधा के साथ काम करता है. इसके लिए एक अलग APK की ज़रूरत होती है.