একটি মিডিয়া ব্রাউজার পরিষেবা তৈরি করা

আপনার অ্যাপটিকে অবশ্যই তার ম্যানিফেস্টে একটি অভিপ্রায়-ফিল্টার সহ MediaBrowserService ঘোষণা করতে হবে। আপনি আপনার নিজের পরিষেবার নাম চয়ন করতে পারেন; নিম্নলিখিত উদাহরণে, এটি "MediaPlaybackService।"

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

দ্রষ্টব্য: MediaBrowserService এর প্রস্তাবিত বাস্তবায়ন হল MediaBrowserServiceCompat । যা মিডিয়া-কম্প্যাট সমর্থন লাইব্রেরিতে সংজ্ঞায়িত করা হয়েছে। এই পৃষ্ঠা জুড়ে "MediaBrowserService" শব্দটি MediaBrowserServiceCompat এর একটি উদাহরণকে বোঝায়।

মিডিয়া সেশন শুরু করুন

যখন পরিষেবাটি onCreate() লাইফসাইকেল কলব্যাক পদ্ধতি গ্রহণ করে তখন এটি এই পদক্ষেপগুলি সম্পাদন করবে:

নীচের onCreate() কোড এই পদক্ষেপগুলি প্রদর্শন করে:

কোটলিন

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

জাভা

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() একটি নন-নাল BrowserRoot ফেরত দিতে হবে যা একটি রুট আইডি যা আপনার বিষয়বস্তু অনুক্রমের প্রতিনিধিত্ব করে।

ক্লায়েন্টদের ব্রাউজিং ছাড়াই আপনার MediaSession-এর সাথে সংযোগ করার অনুমতি দিতে, onGetRoot() কে এখনও একটি নন-নাল BrowserRoot ফেরত দিতে হবে, কিন্তু রুট আইডি একটি খালি বিষয়বস্তু অনুক্রমের প্রতিনিধিত্ব করবে।

onGetRoot() এর একটি সাধারণ বাস্তবায়ন এইরকম দেখতে পারে:

কোটলিন

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

জাভা

@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) ব্যবহার করা যা নির্দিষ্ট করে কোন সংযোগগুলি অনুমোদিত, অথবা বিকল্পভাবে কোন সংযোগগুলি নিষিদ্ধ করা উচিত তা গণনা করে৷ নির্দিষ্ট সংযোগের অনুমতি দেয় এমন একটি ACL কীভাবে প্রয়োগ করা যায় তার উদাহরণের জন্য, ইউনিভার্সাল অ্যান্ড্রয়েড মিউজিক প্লেয়ার নমুনা অ্যাপে প্যাকেজ ভ্যালিডেটর ক্লাসটি দেখুন।

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

onLoadChildren() এর সাথে বিষয়বস্তু যোগাযোগ

ক্লায়েন্ট সংযোগ করার পরে, এটি UI-এর একটি স্থানীয় প্রতিনিধিত্ব তৈরি করতে MediaBrowserCompat.subscribe() এ বারবার কল করে বিষয়বস্তু অনুক্রমকে অতিক্রম করতে পারে। subscribe() পদ্ধতি পরিষেবাটিতে কলব্যাক onLoadChildren() পাঠায়, যা MediaBrowser.MediaItem অবজেক্টের একটি তালিকা প্রদান করে।

প্রতিটি মিডিয়া আইটেমের একটি অনন্য আইডি স্ট্রিং রয়েছে, যা একটি অস্বচ্ছ টোকেন। যখন একটি ক্লায়েন্ট একটি সাবমেনু খুলতে বা একটি আইটেম খেলতে চায়, এটি আইডি পাস করে। আপনার পরিষেবা উপযুক্ত মেনু নোড বা বিষয়বস্তু আইটেমের সাথে আইডি সংযুক্ত করার জন্য দায়ী৷

onLoadChildren() এর একটি সাধারণ বাস্তবায়ন এইরকম দেখতে পারে:

কোটলিন

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

জাভা

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

দ্রষ্টব্য: MediaBrowserService দ্বারা বিতরণ করা MediaItem বস্তুগুলিতে আইকন বিটম্যাপ থাকা উচিত নয়৷ আপনি প্রতিটি আইটেমের জন্য MediaDescription তৈরি করার সময় setIconUri() কল করার পরিবর্তে একটি Uri ব্যবহার করুন।

কিভাবে onLoadChildren() প্রয়োগ করতে হয় তার একটি উদাহরণের জন্য, ইউনিভার্সাল অ্যান্ড্রয়েড মিউজিক প্লেয়ার নমুনা অ্যাপটি দেখুন।

মিডিয়া ব্রাউজার পরিষেবা জীবনচক্র

একটি অ্যান্ড্রয়েড পরিষেবার আচরণ নির্ভর করে এটি এক বা একাধিক ক্লায়েন্টের সাথে শুরু বা আবদ্ধ কিনা তার উপর। একটি পরিষেবা তৈরি হওয়ার পরে, এটি শুরু, আবদ্ধ বা উভয়ই করা যেতে পারে। এই সমস্ত রাজ্যে, এটি সম্পূর্ণরূপে কার্যকরী এবং এটি করার জন্য ডিজাইন করা কাজ সম্পাদন করতে পারে। পার্থক্য হল পরিষেবা কতক্ষণ থাকবে। একটি আবদ্ধ পরিষেবা ধ্বংস করা হয় না যতক্ষণ না তার সমস্ত আবদ্ধ ক্লায়েন্টদের আবদ্ধ না করা হয়। একটি শুরু করা পরিষেবা স্পষ্টভাবে বন্ধ এবং ধ্বংস করা যেতে পারে (ধরে নিচ্ছে যে এটি আর কোনও ক্লায়েন্টের সাথে আবদ্ধ নয়)।

যখন অন্য একটি ক্রিয়াকলাপে চলমান একটি MediaBrowser একটি MediaBrowserService সাথে সংযোগ করে, তখন এটি পরিষেবাটিকে আবদ্ধ করে, পরিষেবাটিকে আবদ্ধ করে (কিন্তু শুরু হয়নি)৷ এই ডিফল্ট আচরণ MediaBrowserServiceCompat ক্লাসে তৈরি করা হয়েছে।

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

এই কারণে, startService() কল করে যখন পরিষেবাটি প্লে শুরু হয় তখন আপনাকে নিশ্চিত হতে হবে। একটি শুরু করা পরিষেবা অবশ্যই স্পষ্টভাবে বন্ধ করতে হবে, তা আবদ্ধ হোক বা না হোক। এটি নিশ্চিত করে যে নিয়ন্ত্রণকারী UI অ্যাক্টিভিটি বন্ধ করে দিলেও আপনার প্লেয়ার পারফর্ম করতে থাকবে।

একটি শুরু করা পরিষেবা বন্ধ করতে, Context.stopService() বা stopSelf() কল করুন। সিস্টেম যত তাড়াতাড়ি সম্ভব পরিষেবা বন্ধ করে এবং ধ্বংস করে। যাইহোক, যদি এক বা একাধিক ক্লায়েন্ট এখনও পরিষেবার সাথে আবদ্ধ থাকে, পরিষেবা বন্ধ করার কলটি যতক্ষণ না তার সমস্ত ক্লায়েন্ট বন্ধ না করে ততক্ষণ বিলম্বিত হয়।

MediaBrowserService এর জীবনচক্র এটি যেভাবে তৈরি করা হয়েছে, এটির সাথে আবদ্ধ ক্লায়েন্টের সংখ্যা এবং মিডিয়া সেশন কলব্যাক থেকে এটি যে কলগুলি গ্রহণ করে তার দ্বারা নিয়ন্ত্রিত হয়। সংক্ষেপ:

  • পরিষেবাটি তৈরি হয় যখন এটি একটি মিডিয়া বোতামের প্রতিক্রিয়া হিসাবে শুরু করা হয় বা যখন একটি কার্যকলাপ এটির সাথে আবদ্ধ হয় (এর MediaBrowser মাধ্যমে সংযোগ করার পরে)।
  • onPlay() কলব্যাকের মিডিয়া সেশনে এমন কোড অন্তর্ভুক্ত করা উচিত যা startService() কল করে। এটি নিশ্চিত করে যে পরিষেবাটি শুরু হয় এবং চলতে থাকে, এমনকি যখন সমস্ত UI MediaBrowser ক্রিয়াকলাপগুলি এটির সাথে আবদ্ধ থাকে তখনও।
  • onStop() কলব্যাকে stopSelf() কল করা উচিত। যদি পরিষেবাটি শুরু হয় তবে এটি এটি বন্ধ করে দেয়। তদতিরিক্ত, পরিষেবাটি ধ্বংস হয়ে যায় যদি এটির সাথে আবদ্ধ কোনও কার্যক্রম না থাকে। অন্যথায়, পরিষেবাটি তার সমস্ত কার্যক্রম বন্ধ না হওয়া পর্যন্ত আবদ্ধ থাকবে। (যদি পরবর্তী startService() কলটি পরিষেবাটি ধ্বংস হওয়ার আগে গৃহীত হয়, মুলতুবি থাকা স্টপটি বাতিল করা হয়।)

নিম্নলিখিত ফ্লোচার্টটি দেখায় কিভাবে একটি পরিষেবার জীবনচক্র পরিচালিত হয়। পরিবর্তনশীল কাউন্টার আবদ্ধ ক্লায়েন্টের সংখ্যা ট্র্যাক করে:

Service Lifecycle

একটি ফোরগ্রাউন্ড পরিষেবা সহ MediaStyle বিজ্ঞপ্তিগুলি ব্যবহার করে৷

যখন একটি পরিষেবা বাজানো হয়, এটি অগ্রভাগে চলমান হওয়া উচিত। এটি সিস্টেমকে জানতে দেয় যে পরিষেবাটি একটি দরকারী ফাংশন সম্পাদন করছে এবং সিস্টেমের মেমরি কম থাকলে মেরে ফেলা উচিত নয়। একটি ফোরগ্রাউন্ড পরিষেবা অবশ্যই একটি বিজ্ঞপ্তি প্রদর্শন করবে যাতে ব্যবহারকারী এটি সম্পর্কে জানেন এবং ঐচ্ছিকভাবে এটি নিয়ন্ত্রণ করতে পারেন। onPlay() কলব্যাক পরিষেবাটিকে অগ্রভাগে রাখা উচিত। (উল্লেখ্য যে এটি "ফোরগ্রাউন্ড" এর একটি বিশেষ অর্থ৷ যখন অ্যান্ড্রয়েড প্রক্রিয়া পরিচালনার উদ্দেশ্যে অগ্রভাগে পরিষেবাটিকে বিবেচনা করে, ব্যবহারকারীর কাছে প্লেয়ারটি ব্যাকগ্রাউন্ডে বাজছে যখন অন্য কিছু অ্যাপ "ফোরগ্রাউন্ড" এ দৃশ্যমান পর্দা।)

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

প্লেয়ার খেলা শুরু করলে বিজ্ঞপ্তি তৈরি করুন এবং প্রদর্শন করুন। এটি করার সর্বোত্তম স্থান হল MediaSessionCompat.Callback.onPlay() পদ্ধতির ভিতরে।

নীচের উদাহরণটি NotificationCompat.MediaStyle ব্যবহার করে, যা মিডিয়া অ্যাপের জন্য ডিজাইন করা হয়েছে। এটি দেখায় কিভাবে একটি বিজ্ঞপ্তি তৈরি করতে হয় যা মেটাডেটা এবং পরিবহন নিয়ন্ত্রণ প্রদর্শন করে। সুবিধার পদ্ধতি getController() আপনাকে আপনার মিডিয়া সেশন থেকে সরাসরি একটি মিডিয়া কন্ট্রোলার তৈরি করতে দেয়।

কোটলিন

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

জাভা

// 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 হল যাওয়ার উপায়৷
  • ব্যাকগ্রাউন্ড কালার সেট করার সময় সতর্ক থাকুন। অ্যান্ড্রয়েড সংস্করণ 5.0 বা পরবর্তীতে একটি সাধারণ বিজ্ঞপ্তিতে, রঙটি শুধুমাত্র ছোট অ্যাপ আইকনের পটভূমিতে প্রয়োগ করা হয়। কিন্তু Android 7.0-এর আগে MediaStyle বিজ্ঞপ্তিগুলির জন্য, সম্পূর্ণ বিজ্ঞপ্তি ব্যাকগ্রাউন্ডের জন্য রঙ ব্যবহার করা হয়। আপনার পটভূমির রঙ পরীক্ষা করুন। চোখের উপর মৃদু যান এবং অত্যন্ত উজ্জ্বল বা ফ্লুরোসেন্ট রং এড়িয়ে চলুন।

আপনি যখন NotificationCompat.MediaStyle ব্যবহার করছেন শুধুমাত্র তখনই এই সেটিংস উপলব্ধ হবে:

  • আপনার সেশনের সাথে বিজ্ঞপ্তিটি সংযুক্ত করতে setMediaSession() ব্যবহার করুন। এটি তৃতীয় পক্ষের অ্যাপ্লিকেশন এবং সহচর ডিভাইসগুলিকে সেশন অ্যাক্সেস এবং নিয়ন্ত্রণ করতে দেয়৷
  • বিজ্ঞপ্তির মান-আকারের কন্টেন্টভিউতে দেখানোর জন্য 3টি পর্যন্ত অ্যাকশন যোগ করতে setShowActionsInCompactView() ব্যবহার করুন। (এখানে বিরতি বোতামটি নির্দিষ্ট করা আছে।)
  • অ্যান্ড্রয়েড 5.0 (এপিআই স্তর 21) এবং পরবর্তীতে আপনি প্লেয়ারটি বন্ধ করার জন্য একটি বিজ্ঞপ্তি সোয়াইপ করতে পারেন একবার পরিষেবাটি আর অগ্রভাগে চালু না হলে। আপনি আগের সংস্করণে এটি করতে পারবেন না। ব্যবহারকারীদের বিজ্ঞপ্তি সরাতে এবং Android 5.0 (API স্তর 21) এর আগে প্লেব্যাক বন্ধ করার অনুমতি দেওয়ার জন্য, আপনি setShowCancelButton(true) এবং setCancelButtonIntent() কল করে বিজ্ঞপ্তির উপরের-ডান কোণায় একটি বাতিল বোতাম যোগ করতে পারেন।

আপনি যখন বিরতি এবং বাতিল বোতামগুলি যোগ করেন, তখন প্লেব্যাক অ্যাকশনে সংযুক্ত করার জন্য আপনার একটি PendingIntent প্রয়োজন হবে৷ MediaButtonReceiver.buildMediaButtonPendingIntent() পদ্ধতিটি একটি প্লেব্যাকস্টেট অ্যাকশনকে একটি PendingIntent এ রূপান্তর করার কাজ করে।