MediaSessionService-এর মাধ্যমে ব্যাকগ্রাউন্ড প্লেব্যাক

অ্যাপ ফোরগ্রাউন্ডে না থাকলেও মিডিয়া চালানোর প্রয়োজন প্রায়ই হয়। যেমন, ব্যবহারকারী ডিভাইস লক করে রাখলে বা অন্য অ্যাপ ব্যবহার করলে, সাধারণত মিউজিক প্লেয়ার মিউজিক চালানো চালিয়ে যায়। Media3 লাইব্রেরি একাধিক ইন্টারফেস প্রদান করে যা আপনাকে ব্যাকগ্রাউন্ড প্লেব্যাক সাপোর্ট করতে দেয়।

MediaSessionService ব্যবহার করা

ব্যাকগ্রাউন্ড প্লেব্যাক চালু করতে, আপনাকে Player এবং MediaSession আলাদা পরিষেবা-এর মধ্যে রাখতে হবে। এর ফলে, আপনার অ্যাপ ফোরগ্রাউন্ডে না থাকলেও ডিভাইস মিডিয়া চালানো চালিয়ে যেতে পারে।

MediaSessionService, অ্যাপের অ্যাক্টিভিটি থেকে আলাদাভাবে
  মিডিয়া সেশন চালানোর অনুমতি দেয়
ছবি ১: MediaSessionService অ্যাপের অ্যাক্টিভিটি থেকে আলাদাভাবে মিডিয়া সেশন চালানোর অনুমতি দেয়

কোনও পরিষেবার মধ্যে প্লেয়ার হোস্ট করার সময়, আপনাকে MediaSessionService ব্যবহার করতে হবে। এটি করতে, MediaSessionService এক্সটেন্ড করে এমন একটি ক্লাস তৈরি করুন এবং এর মধ্যে আপনার মিডিয়া সেশন তৈরি করুন।

MediaSessionService ব্যবহার করার ফলে Google Assistant, সিস্টেম মিডিয়া কন্ট্রোল, পেরিফেরাল ডিভাইসের মিডিয়া বোতাম বা Wear OS-এর মতো কম্প্যানিয়ন ডিভাইসের মতো এক্সটার্নাল ক্লায়েন্ট আপনার পরিষেবা খুঁজে পেতে, সেটির সাথে কানেক্ট করতে এবং প্লেব্যাক কন্ট্রোল করতে পারে। এই সব কিছুই আপনার অ্যাপের UI অ্যাক্টিভিটি অ্যাক্সেস না করেই করা যায়। আসলে, একই সময়ে একই MediaSessionService-এর সাথে একাধিক ক্লায়েন্ট অ্যাপ কানেক্ট করা থাকতে পারে, প্রতিটি অ্যাপের নিজস্ব MediaController থাকে।

পরিষেবার লাইফসাইকেল প্রয়োগ করা

আপনার পরিষেবার দুটি লাইফসাইকেল পদ্ধতি আপনাকে প্রয়োগ করতে হবে:

  • প্রথম কন্ট্রোলার কানেক্ট হওয়ার ঠিক আগে onCreate() কল করা হয় এবং পরিষেবা ইনস্ট্যান্টিয়েট ও শুরু করা হয়। Player ও MediaSession তৈরি করার জন্য এটিই সেরা জায়গা।
  • পরিষেবা বন্ধ করার সময় onDestroy() কল করা হয়। প্লেয়ার ও সেশন সহ সব রিসোর্স রিলিজ করতে হবে।

ব্যবহারকারী সাম্প্রতিক টাস্ক থেকে অ্যাপটি বাতিল করলে কী ঘটবে তা কাস্টমাইজ করতে আপনি ঐচ্ছিকভাবে onTaskRemoved(Intent) ওভাররাইড করতে পারেন। ডিফল্ট হিসেবে, প্লেব্যাক চলতে থাকলে পরিষেবা চালু থাকে, অন্যথায় বন্ধ হয়ে যায়।

Kotlin

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

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

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

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

জাভা

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

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

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

ব্যাকগ্রাউন্ডে প্লেব্যাক চালু রাখার বিকল্প হিসেবে, ব্যবহারকারী অ্যাপ বন্ধ করে দিলে আপনি যেকোনও পরিস্থিতিতে পরিষেবা বন্ধ করতে পারেন:

Kotlin

@OptIn(UnstableApi::class)
override fun onTaskRemoved(rootIntent: Intent?) {
  pauseAllPlayersAndStopSelf()
}

জাভা

@OptIn(markerClass = UnstableApi.class)
@Override
public void onTaskRemoved(@Nullable Intent rootIntent) {
  pauseAllPlayersAndStopSelf();
}

onTaskRemoved-এর অন্য যেকোনও ম্যানুয়াল প্রয়োগের জন্য, প্লেব্যাক চলছে কিনা এবং ফোরগ্রাউন্ড পরিষেবা শুরু হয়েছে কিনা তা চেক করতে আপনি isPlaybackOngoing() ব্যবহার করতে পারেন।

মিডিয়া সেশনে অ্যাক্সেস দিন

পরিষেবা তৈরি করার সময় যে মিডিয়া সেশন তৈরি করা হয়েছিল, অন্যান্য ক্লায়েন্টকে সেটির অ্যাক্সেস দিতে onGetSession() মেথড ওভাররাইড করুন।

Kotlin

class PlaybackService : MediaSessionService() {

  // [...] lifecycle methods omitted

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

জাভা

class PlaybackService extends MediaSessionService {

  // [...] lifecycle methods omitted

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

ম্যানিফেস্টে পরিষেবা ঘোষণা করুন

প্লেব্যাক ফোরগ্রাউন্ড পরিষেবা চালানোর জন্য কোনও অ্যাপের FOREGROUND_SERVICE এবং FOREGROUND_SERVICE_MEDIA_PLAYBACK অনুমতি প্রয়োজন:

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

আপনাকে ম্যানিফেস্টে Service ক্লাসও ঘোষণা করতে হবে, যার মধ্যে MediaSessionService-এর ইনটেন্ট ফিল্টার এবং foregroundServiceType থাকবে, যার মধ্যে mediaPlayback অন্তর্ভুক্ত থাকবে।

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

MediaController ব্যবহার করে প্লেব্যাক কন্ট্রোল করুন

আপনার প্লেয়ার UI সহ অ্যাক্টিভিটি বা ফ্র্যাগমেন্টে, আপনি MediaController ব্যবহার করে UI এবং আপনার মিডিয়া সেশনের মধ্যে একটি লিঙ্ক তৈরি করতে পারবেন। আপনার UI সেশনের মধ্যে প্লেয়ারে আপনার UI থেকে কমান্ড পাঠাতে মিডিয়া কন্ট্রোলার ব্যবহার করে। 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()

জাভা

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

বিজ্ঞপ্তির লাইফসাইকেল

Player-এর প্লেলিস্টে MediaItemটি ইনস্ট্যান্স থাকলেই বিজ্ঞপ্তি তৈরি করা হয়।

Player এবং MediaSession-এর স্ট্যাটাসের উপর ভিত্তি করে সব বিজ্ঞপ্তি অটোমেটিক আপডেট হয়।

ফোরগ্রাউন্ড সার্ভিস চলাকালীন বিজ্ঞপ্তি সরানো যাবে না। বিজ্ঞপ্তিটি অবিলম্বে সরাতে, আপনাকে অবশ্যই Player.release() কল করতে হবে অথবা Player.clearMediaItems() ব্যবহার করে প্লেলিস্টটি মুছে ফেলতে হবে।

প্লেয়ার পজ করা, বন্ধ করা বা ১০ মিনিটের বেশি সময় ধরে কাজ না করলে এবং ব্যবহারকারী কোনও ইন্টার‍্যাকশন না করলে, পরিষেবাটি অটোমেটিক ফোরগ্রাউন্ড সার্ভিস স্টেট থেকে বেরিয়ে আসে যাতে সিস্টেম এটিকে বন্ধ করে দিতে পারে। আপনি প্লেব্যাক আবার শুরু করার ফিচার প্রয়োগ করতে পারেন যাতে ব্যবহারকারী পরিষেবার লাইফসাইকেল রিস্টার্ট করতে এবং পরে কোনও সময়ে প্লেব্যাক আবার শুরু করতে পারেন।

বিজ্ঞপ্তি কাস্টমাইজেশন

বর্তমানে চলছে এমন আইটেমের মেটাডেটা MediaItem.MediaMetadata পরিবর্তন করে কাস্টমাইজ করা যাবে। আপনি আগে থেকে আছে এমন কোনও আইটেমের মেটাডেটা আপডেট করতে চাইলে, প্লেব্যাক বন্ধ না করেই মেটাডেটা আপডেট করতে Player.replaceMediaItem ব্যবহার করতে পারেন।

এছাড়াও, Android মিডিয়া কন্ট্রোলের জন্য কাস্টম মিডিয়া বোতাম সংক্রান্ত পছন্দ সেট করে বিজ্ঞপ্তিতে দেখানো কিছু বোতাম কাস্টমাইজ করতে পারবেন। Android মিডিয়া কন্ট্রোল কাস্টমাইজ করা সম্পর্কে আরও পড়ুন।

বিজ্ঞপ্তি আরও কাস্টমাইজ করতে, DefaultMediaNotificationProvider.Builder ব্যবহার করে অথবা পরিষেবা প্রদানকারী ইন্টারফেসের কাস্টম ইমপ্লিমেন্টেশন তৈরি করে MediaNotification.Provider তৈরি করুন। setMediaNotificationProvider-এর মাধ্যমে আপনার MediaSessionService-এ পরিষেবা প্রদানকারীকে যোগ করুন।

প্লেব্যাক আবার চালু করা

MediaSessionService বন্ধ হয়ে যাওয়ার পরে এবং ডিভাইস রিবুট করার পরেও, ব্যবহারকারীকে প্লেব্যাক আবার শুরু করার সুবিধা দেওয়া যেতে পারে যাতে তিনি পরিষেবা রিস্টার্ট করে যেখানে প্লেব্যাক বন্ধ করেছিলেন সেখান থেকে আবার শুরু করতে পারেন। ডিফল্ট হিসেবে, প্লেব্যাক আবার শুরু করার সুবিধা বন্ধ করা থাকে। এর অর্থ হল, আপনার পরিষেবা চালু না থাকলে ব্যবহারকারী প্লেব্যাক আবার শুরু করতে পারবেন না। এই ফিচার চালু করতে, আপনাকে একটি মিডিয়া বোতাম রিসিভার ঘোষণা করতে হবে এবং onPlaybackResumption পদ্ধতি প্রয়োগ করতে হবে।

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 সিস্টেম UI-এর রিজিউম ফিচার প্লেব্যাক রিজিউম করার অনুরোধ করলে, onPlaybackResumption() কলব্যাক পদ্ধতি কল করা হয়।

Kotlin

override fun onPlaybackResumption(
  mediaSession: MediaSession,
  controller: MediaSession.ControllerInfo,
  isForPlayback: Boolean,
): ListenableFuture<MediaSession.MediaItemsWithStartPosition> {
  val settableFuture = SettableFuture.create<MediaSession.MediaItemsWithStartPosition>()
  settableFuture.addListener(
    {
      // Your app is responsible for storing the playlist, metadata (like title
      // and artwork) of the current item and the start position to use here.
      val resumptionPlaylist = restorePlaylist()
      settableFuture.set(resumptionPlaylist)
    },
    MoreExecutors.directExecutor(),
  )
  return settableFuture
}

জাভা

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

আপনি যদি প্লেব্যাক স্পিড, রিপিট মোড বা শাফেল মোডের মতো অন্যান্য প্যারামিটার স্টোর করে থাকেন, তাহলে Media3 প্লেয়ার প্রস্তুত করার আগে এবং কলব্যাক সম্পূর্ণ হলে প্লেব্যাক শুরু করার আগে এই প্যারামিটারগুলির সাথে প্লেয়ার কনফিগার করার জন্য onPlaybackResumption() একটি ভালো জায়গা।

এই পদ্ধতিটি বুট করার সময় কল করা হয় যাতে ডিভাইসটি রিবুট করার পরে Android সিস্টেম UI রিজিউম করার বিজ্ঞপ্তি তৈরি করা যায়, যেখানে isForPlayback-এর মান false-এ সেট করা থাকে। রিচ বিজ্ঞপ্তির জন্য, নেটওয়ার্ক অ্যাক্সেস এখনও উপলভ্য নাও হতে পারে বলে, স্থানীয়ভাবে উপলভ্য ভ্যালু সহ বর্তমান আইটেমের title এবং artworkData বা artworkUri-এর মতো MediaMetadata ফিল্ড পূরণ করার সাজেশন দেওয়া হয়। এছাড়াও, আপনি MediaMetadata.extras-এ MediaConstants.EXTRAS_KEY_COMPLETION_STATUS এবং MediaConstants.EXTRAS_KEY_COMPLETION_PERCENTAGE যোগ করতে পারেন যাতে প্লেব্যাক পজিশন আবার শুরু করার বিষয়টি উল্লেখ করা যায়।

উন্নত কন্ট্রোলার কনফিগারেশন ও ব্যাকওয়ার্ড কম্প্যাটিবিলিটি

একটি সাধারণ দৃশ্য হল, প্লেব্যাক কন্ট্রোল করা এবং প্লেলিস্ট দেখানোর জন্য অ্যাপ UI-তে MediaController ব্যবহার করা। একই সময়ে, সেশনটি Android মিডিয়া কন্ট্রোল এবং মোবাইল বা টিভিতে Assistant, স্মার্টওয়াচের জন্য Wear OS এবং গাড়িতে Android Auto-র মতো এক্সটার্নাল ক্লায়েন্টের কাছে প্রকাশ করা হয়। Media3 সেশন ডেমো অ্যাপ হল এমন একটি অ্যাপের উদাহরণ যা এই ধরনের পরিস্থিতি প্রয়োগ করে।

এইসব এক্সটার্নাল ক্লায়েন্ট, লিগ্যাসি AndroidX লাইব্রেরির MediaControllerCompat বা Android প্ল্যাটফর্মের android.media.session.MediaController-এর মতো API ব্যবহার করতে পারে। Media3, লিগ্যাসি লাইব্রেরির সাথে সম্পূর্ণ ব্যাকওয়ার্ড কম্প্যাটিবল এবং Android প্ল্যাটফর্ম API-এর সাথে ইন্টারঅপারেবিলিটি প্রদান করে।

বিশ্বস্ত কন্ট্রোলার শনাক্ত করা

যেকোনও অ্যাপ আপনার মিডিয়া সেশন বা লাইব্রেরিতে কানেক্ট করার চেষ্টা করতে পারে। আপনি যদি সিস্টেম কন্ট্রোলার, মিডিয়া কন্টেন্ট কন্ট্রোল করার অনুমতি সহ কন্ট্রোলার এবং আপনার নিজের অ্যাপে অ্যাক্সেস সীমাবদ্ধ করতে চান, তাহলে প্রাথমিক অ্যাক্সেস চেক করার জন্য ControllerInfo.isTrusted() ব্যবহার করতে পারেন। বিকল্প হিসেবে, আপনি আরও নির্দিষ্ট কন্ট্রোলার শনাক্ত করতে পারেন যেমন মিডিয়া বিজ্ঞপ্তি কন্ট্রোলার বা Android Auto কন্ট্রোলার, যেমন নিম্নলিখিত বিভাগে বর্ণনা করা হয়েছে।

মিডিয়া বিজ্ঞপ্তি কন্ট্রোলার ব্যবহার করা

এটি বোঝা গুরুত্বপূর্ণ যে এইসব লিগ্যাসি ও প্ল্যাটফর্ম কন্ট্রোলার একই স্ট্যাটাস শেয়ার করে এবং কন্ট্রোলার অনুযায়ী দৃশ্যমানতা কাস্টমাইজ করা যায় না (যেমন, উপলভ্য PlaybackState.getActions() এবং PlaybackState.getCustomActions())। আপনি মিডিয়া বিজ্ঞপ্তি কন্ট্রোলার ব্যবহার করে প্ল্যাটফর্ম মিডিয়া সেশনে সেট করা স্ট্যাটাস কনফিগার করতে পারেন যাতে এইসব লিগ্যাসি ও প্ল্যাটফর্ম কন্ট্রোলারের সাথে মানানসই হয়।

যেমন, কোনও অ্যাপ উপলভ্য কমান্ড সেট করতে MediaSession.Callback.onConnect()-এর ইমপ্লিমেন্টেশন প্রদান করতে পারে এবং প্ল্যাটফর্ম সেশনের জন্য বিশেষভাবে মিডিয়া বোতামের পছন্দ এইভাবে সেট করতে পারে:

Kotlin

override fun onConnectAsync(
  session: MediaSession,
  controller: MediaSession.ControllerInfo,
): ListenableFuture<ConnectionResult> {
  if (session.isMediaNotificationController(controller)) {
    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 button preferences and commands to configure the platform session.
    return immediateFuture(
      AcceptedResultBuilder(session, controller)
        .setMediaButtonPreferences(listOf(seekBackButton, seekForwardButton))
        .setAvailablePlayerCommands(playerCommands)
        .build()
    )
  }
  // Default commands with default button preferences for all other controllers.
  return immediateFuture(AcceptedResultBuilder(session, controller).build())
}

জাভা

@Override
public ListenableFuture<ConnectionResult> onConnectAsync(
    MediaSession session, MediaSession.ControllerInfo controller) {
  if (session.isMediaNotificationController(controller)) {
    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 button preferences and commands to configure the platform session.
    return immediateFuture(
        new AcceptedResultBuilder(session, controller)
            .setMediaButtonPreferences(ImmutableList.of(seekBackButton, seekForwardButton))
            .setAvailablePlayerCommands(playerCommands)
            .build());
  }
  // Default commands with default button preferences for all other controllers.
  return immediateFuture(new AcceptedResultBuilder(session, controller).build());
}

কাস্টম কমান্ড পাঠাতে Android Auto-কে অনুমতি দিন

MediaLibraryService ব্যবহার করার সময় এবং মোবাইল অ্যাপের মাধ্যমে Android Auto-কে সাপোর্ট করার জন্য, Android Auto কন্ট্রোলারের উপযুক্ত উপলভ্য কমান্ডের প্রয়োজন হয়, অন্যথায় Media3 সেই কন্ট্রোলার থেকে ইনকামিং কাস্টম কমান্ড প্রত্যাখ্যান করবে:

Kotlin

override fun onConnectAsync(
  session: MediaSession,
  controller: MediaSession.ControllerInfo,
): ListenableFuture<ConnectionResult> {
  val sessionCommands =
    ConnectionResult.DEFAULT_SESSION_COMMANDS.buildUpon().add(customCommand).build()
  if (session.isMediaNotificationController(controller)) {
    // ... See above.
  } else if (session.isAutoCompanionController(controller)) {
    // Available commands to accept incoming custom commands from Auto.
    return immediateFuture(
      AcceptedResultBuilder(session, controller)
        .setAvailableSessionCommands(sessionCommands)
        .build()
    )
  }
  // Default commands for all other controllers.
  return immediateFuture(AcceptedResultBuilder(session, controller).build())
}

জাভা

@Override
public ListenableFuture<ConnectionResult> onConnectAsync(
    MediaSession session, MediaSession.ControllerInfo controller) {
  SessionCommands sessionCommands =
      ConnectionResult.DEFAULT_SESSION_COMMANDS.buildUpon().add(customCommand).build();
  if (session.isMediaNotificationController(controller)) {
    // ... See above.
  } else if (session.isAutoCompanionController(controller)) {
    // Available commands to accept incoming custom commands from Auto.
    return immediateFuture(
        new AcceptedResultBuilder(session, controller)
            .setAvailableSessionCommands(sessionCommands)
            .build());
  }
  // Default commands for all other controllers.
  return immediateFuture(new AcceptedResultBuilder(session, controller).build());
}

সেশন ডেমো অ্যাপে একটি অটোমোটিভ মডিউল আছে, যা অটোমোটিভ ওএসের জন্য সাপোর্ট প্রদর্শন করে যার জন্য একটি আলাদা APK প্রয়োজন।