বিজ্ঞপ্তি তৈরি করা

আপনার অ্যাপ ব্যবহার না করার সময়, বিজ্ঞপ্তি অ্যাপে হওয়া ইভেন্ট সম্পর্কে সংক্ষিপ্ত ও সময়মতো তথ্য প্রদান করে। এই ডকুমেন্টে দেখানো হয়েছে যে কীভাবে বিভিন্ন ফিচার সহ বিজ্ঞপ্তি তৈরি করতে হয়। Android-এ কীভাবে বিজ্ঞপ্তি দেখানো হয় সেই সম্পর্কে জানতে, বিজ্ঞপ্তির ওভারভিউ দেখুন। বিজ্ঞপ্তি ব্যবহার করে এমন নমুনা কোডের জন্য, GitHub-এ SociaLite নমুনা দেখুন।

এই পৃষ্ঠার কোড AndroidX লাইব্রেরির NotificationCompat API ব্যবহার করে। এইসব API আপনাকে Android 9 (API লেভেল 28)-এর সাথে মানানসই রেখেও Android-এর নতুন ভার্সনে উপলভ্য ফিচার যোগ করতে দেয়। তবে, ইনলাইন উত্তর অ্যাকশনের মতো কিছু ফিচার আগের ভার্সনে কাজ করে না।

সাধারণ বিজ্ঞপ্তি তৈরি করা

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

ছবি ১. আইকন, শীর্ষক ও কিছু টেক্সট সহ বিজ্ঞপ্তি।

বিজ্ঞপ্তির প্রতিটি অংশ সম্পর্কে আরও বিবরণ পেতে, বিজ্ঞপ্তির অ্যানাটমি সম্পর্কে পড়ুন।

রানটাইম অনুমতি ঘোষণা করা

Android 13 (API লেভেল 33) ও এর পরের যেকোনও ভার্সনে, কোনও অ্যাপ থেকে ছাড় না পাওয়া (ফোরগ্রাউন্ড পরিষেবা (FGS) সহ) বিজ্ঞপ্তি পোস্ট করার জন্য রানটাইম অনুমতি কাজ করে।

আপনার অ্যাপের ম্যানিফেস্ট ফাইলে যে অনুমতি ঘোষণা করতে হবে তা নিম্নলিখিত কোড স্নিপেটে দেখা যায়:

<manifest ...>
    <uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
    <application ...>
        ...
    </application>
</manifest>

রানটাইম অনুমতি সম্পর্কে আরও বিবরণের জন্য, বিজ্ঞপ্তি রানটাইম অনুমতি দেখুন।

বিজ্ঞপ্তির কন্টেন্ট সেট করা

শুরু করতে, একটি NotificationCompat.Builder অবজেক্ট ব্যবহার করে বিজ্ঞপ্তিটির কন্টেন্ট ও চ্যানেল সেট করুন। নিচের উদাহরণে দেখানো হয়েছে কীভাবে নিম্নলিখিত বিষয় সহ বিজ্ঞপ্তি তৈরি করতে হয়:

  • setSmallIcon()-এর সেট করা একটি ছোট আইকন। এটিই একমাত্র ব্যবহারকারী-দৃশ্যমান কন্টেন্ট যা প্রয়োজন।

  • setContentTitle()-এর সেট করা শীর্ষক।

  • setContentText()-এর সেট করা বডি টেক্সট।

  • setPriority()-এর সেট করা বিজ্ঞপ্তি সংক্রান্ত অগ্রাধিকার। অগ্রাধিকার নির্ধারণ করে যে Android 7.1 ও তার আগের ভার্সনে বিজ্ঞপ্তিটি কতটা বেশি ইনট্রুসিভ। Android 8.0 ও তার পরের যেকোনও ভার্সনের জন্য, পরবর্তী বিভাগে দেখানো চ্যানেল ইম্পর্ট্যান্স সেট করুন।

val textTitle = "Title"
val textContent = "Content"
val builder = NotificationCompat.Builder(context, CHANNEL_ID)
    .setSmallIcon(R.drawable.ic_logo)
    .setContentTitle(textTitle)
    .setContentText(textContent)
    .setPriority(NotificationCompat.PRIORITY_DEFAULT)

NotificationCompat.Builder কনস্ট্রাক্টরকে আপনার চ্যানেল আইডি দিতে হবে। Android 8.0 (API লেভেল 26) ও পরবর্তী ভার্সনের সাথে মানানসই হওয়ার জন্য এটি প্রয়োজন, তবে আগের ভার্সন এটি উপেক্ষা করে।

ডিফল্ট হিসেবে, বিজ্ঞপ্তির টেক্সট কন্টেন্ট এক লাইনে ফিট করার জন্য ছোট করে দেওয়া হয়। আপনি এক্সপ্যান্ড করা যায় এমন বিজ্ঞপ্তি তৈরি করে অতিরিক্ত তথ্য দেখাতে পারেন।

ছবি ২. আড়াল করা ও বড় করা অবস্থায় একটি বড় করা যায় এমন বিজ্ঞপ্তি।

আপনার বিজ্ঞপ্তি আরও বড় করতে চাইলে, setStyle() সহ স্টাইল টেমপ্লেট যোগ করে, আপনি একটি এক্সপ্যান্ড করা যায় এমন বিজ্ঞপ্তি চালু করতে পারেন। যেমন, নিচে দেওয়া কোডটি একটি বড় টেক্সট এরিয়া তৈরি করে:

val builder = NotificationCompat.Builder(context, CHANNEL_ID)
    .setSmallIcon(R.drawable.ic_logo)
    .setContentTitle("My notification")
    .setContentText("Much longer text that cannot fit one line...")
    .setStyle(NotificationCompat.BigTextStyle()
        .bigText("Much longer text that cannot fit one line..."))
    .setPriority(NotificationCompat.PRIORITY_DEFAULT)

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

চ্যানেল তৈরি করে তার গুরুত্ব সেট করা

Android 8.0 ও তার পরবর্তী যেকোনও ভার্সনে বিজ্ঞপ্তি ডেলিভার করার আগে, সিস্টেমের সাথে আপনার অ্যাপের বিজ্ঞপ্তি চ্যানেল রেজিস্টার করুন। এর জন্য createNotificationChannel()-এ NotificationChannel-এর ইনস্ট্যান্স পাস করুন। SDK_INT ভার্সনে একটি শর্তের মাধ্যমে নিম্নলিখিত কোড ব্লক করা হয়েছে:

fun createNotificationChannel(context: Context) {
    // Create the NotificationChannel, but only on API 26+ because
    // the NotificationChannel class is not in the Support Library.
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        val name = context.getString(R.string.channel_name)
        val descriptionText = context.getString(R.string.channel_description)
        val importance = NotificationManager.IMPORTANCE_DEFAULT
        val channel = NotificationChannel(CHANNEL_ID, name, importance).apply {
            description = descriptionText
        }
        // Register the channel with the system.
        val notificationManager: NotificationManager =
            context.getSystemService(NotificationManager::class.java) as NotificationManager
        notificationManager.createNotificationChannel(channel)
    }
}

Android 8.0 ও তার পরের যেকোনও ভার্সনে বিজ্ঞপ্তি পোস্ট করার আগে আপনাকে বিজ্ঞপ্তি চ্যানেল তৈরি করতে হবে। আপনার অ্যাপ চালু হলে এই কোডটি এক্সিকিউট করুন। বারবার কল করা নিরাপদ কারণ আগে থেকেই থাকা চ্যানেল তৈরি করলে কিছু হয় না।

NotificationChannel কনস্ট্রাক্টরের জন্য একটি গুরুত্বের লেভেল প্রয়োজন যা NotificationManager কনস্ট্যান্ট ব্যবহার করে। এটি নির্ধারণ করে যে কীভাবে ব্যবহারকারীকে বাধা দেওয়া হবে। Android 7.1 ও তার আগের যেকোনও ভার্সনে কাজ করার জন্য, আগের উদাহরণে দেখানো setPriority()-এর মাধ্যমে প্রায়োরিটি সেট করুন।

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

বিভিন্ন লেভেলের অর্থ কী, সেই সম্পর্কে আরও জানতে, বিজ্ঞপ্তির গুরুত্বের লেভেল সম্পর্কে পড়ুন।

বিজ্ঞপ্তির ট্যাপ অ্যাকশন সেট করা

প্রতিটি বিজ্ঞপ্তি ট্যাপের উত্তর দিতে হবে, সাধারণত আপনার অ্যাপে বিজ্ঞপ্তি সম্পর্কিত অ্যাক্টিভিটি খুলতে হবে। এটি করতে, PendingIntent অবজেক্টের সাথে সংজ্ঞায়িত করা একটি কন্টেন্ট ইনটেন্ট নির্দিষ্ট করুন এবং এটি setContentIntent()-এ পাস করুন।

ব্যবহারকারী বিজ্ঞপ্তিতে ট্যাপ করলে কীভাবে অ্যাক্টিভিটি খোলার জন্য একটি প্রাথমিক ইনটেন্ট তৈরি করতে হয় তা নিম্নলিখিত স্নিপেটে দেখানো হয়েছে:

// Create an explicit intent for an Activity in your app.
val intent = Intent(context, AlertDetails::class.java).apply {
    flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
val pendingIntent: PendingIntent =
    PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE)

val builder = NotificationCompat.Builder(context, CHANNEL_ID)
    .setSmallIcon(R.drawable.ic_logo)
    .setContentTitle("My notification")
    .setContentText("Hello World!")
    .setPriority(NotificationCompat.PRIORITY_DEFAULT)
    // Set the intent that fires when the user taps the notification.
    .setContentIntent(pendingIntent)
    .setAutoCancel(true)

এই কোড setAutoCancel()-কে কল করে, যা ব্যবহারকারী ট্যাপ করলে অটোমেটিক বিজ্ঞপ্তিটি সরিয়ে দেয়।

আগের উদাহরণে ইনটেন্ট ফ্ল্যাগ ব্যবহারকারীর প্রত্যাশিত নেভিগেশন অভিজ্ঞতাকে অক্ষুণ্ণ রাখে, যখন ব্যবহারকারী বিজ্ঞপ্তি ব্যবহার করে আপনার অ্যাপ খোলেন। আপনি যে ধরনের অ্যাক্টিভিটি শুরু করছেন তার উপর নির্ভর করে এটি ব্যবহার করতে পারেন, যা নিম্নলিখিতগুলির মধ্যে একটি হতে পারে:

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

  • আপনার অ্যাপের সাধারণ অ্যাপ ফ্লোতে থাকা অ্যাক্টিভিটি। এই ক্ষেত্রে, অ্যাক্টিভিটি শুরু করলে একটি ব্যাক স্ট্যাক তৈরি হয় যাতে ব্যাক ও আপ বোতাম সম্পর্কে ব্যবহারকারীর প্রত্যাশা পূরণ করা যায়।

বিজ্ঞপ্তি দেখানো

বিজ্ঞপ্তিটি দেখাতে, কল করুন NotificationManagerCompat.notify(), এর মধ্যে বিজ্ঞপ্তির জন্য একটি অনন্য আইডি এবং NotificationCompat.Builder.build()-এর ফলাফল পাস করুন। নিচের উদাহরণে এটি দেখানো হয়েছে:

with(NotificationManagerCompat.from(context)) {
    if (ActivityCompat.checkSelfPermission(
            context,
            Manifest.permission.POST_NOTIFICATIONS
        ) != PackageManager.PERMISSION_GRANTED
    ) {
        // TODO: Consider calling ActivityCompat#requestPermissions here
        // to request the missing permissions, and then overriding
        // public fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>,
        //                                        grantResults: IntArray)
        // to handle the case where the user grants the permission. See the documentation
        // for ActivityCompat#requestPermissions for more details.

        return@with
    }
    // notificationId is a unique int for each notification that you must define.
    notify(notificationId, builder.build())

NotificationManagerCompat.notify()-এ পাস করা বিজ্ঞপ্তি আইডি সেভ করুন, কারণ আপনি যখন আপডেট করতে বা বিজ্ঞপ্তি সরিয়ে দিতে চাইবেন তখন এটি আপনার প্রয়োজন হবে।

এছাড়াও, Android 13 ও তার পরবর্তী যেকোনও ভার্সনে চলা ডিভাইসে প্রাথমিক বিজ্ঞপ্তি পরীক্ষা করতে, ম্যানুয়ালি বিজ্ঞপ্তি চালু করুন অথবা বিজ্ঞপ্তি অনুরোধ করার জন্য একটি ডায়ালগ তৈরি করুন।

অ্যাকশন বোতাম যোগ করা

বিজ্ঞপ্তিতে সর্বাধিক তিনটি অ্যাকশন বোতাম থাকতে পারে, যা ব্যবহারকারীকে দ্রুত উত্তর দিতে সাহায্য করে, যেমন রিমাইন্ডার স্নুজ করা বা টেক্সট মেসেজের উত্তর দেওয়া। কিন্তু ব্যবহারকারী বিজ্ঞপ্তিতে ট্যাপ করলেযে অ্যাকশন পারফর্ম করা হয়, এইসব অ্যাকশন বোতামে সেই অ্যাকশন ডুপ্লিকেট করা যাবে না।

ছবি ৩. একটি অ্যাকশন বোতাম সহ বিজ্ঞপ্তি।

অ্যাকশন বোতাম যোগ করতে, addAction() মেথডে PendingIntent পাস করুন। এটি বিজ্ঞপ্তি ডিফল্ট ট্যাপ অ্যাকশন সেট-আপ করার মতো, তবে অ্যাক্টিভিটি লঞ্চ করার পরিবর্তে, আপনি অন্য কাজ করতে পারেন, যেমন, ব্যাকগ্রাউন্ডে কাজ করে এমন BroadcastReceiver শুরু করা, যাতে আগে থেকেই খোলা থাকা অ্যাপে অ্যাকশন কোনও বাধা সৃষ্টি না করে।

যেমন, নিম্নলিখিত কোডটি দেখায় যে কীভাবে একটি নির্দিষ্ট গ্রাহককে ব্রডকাস্ট পাঠাতে হয়:

val ACTION_SNOOZE = "snooze"
val snoozeIntent = Intent(context, MyBroadcastReceiver::class.java).apply {
    action = ACTION_SNOOZE
    putExtra(EXTRA_NOTIFICATION_ID, 0)
}
val snoozePendingIntent: PendingIntent =
    PendingIntent.getBroadcast(context, 0, snoozeIntent, PendingIntent.FLAG_IMMUTABLE)
val builder = NotificationCompat.Builder(context, CHANNEL_ID)
    .setSmallIcon(R.drawable.ic_logo)
    .setContentTitle("My notification")
    .setContentText("Hello World!")
    .setPriority(NotificationCompat.PRIORITY_DEFAULT)
    .setContentIntent(pendingIntent)
    .addAction(R.drawable.snooze, context.getString(R.string.snooze),
        snoozePendingIntent)

ব্যাকগ্রাউন্ড ওয়ার্ক চালানোর জন্য BroadcastReceiver তৈরি করা সম্পর্কে আরও জানতে, ব্রডকাস্টের ওভারভিউ দেখুন।

আপনি যদি এর পরিবর্তে মিডিয়া প্লেব্যাক বোতাম সহ বিজ্ঞপ্তি তৈরি করতে চান, যেমন ট্র্যাক পজ ও স্কিপ করা, তাহলে কীভাবে মিডিয়া কন্ট্রোল সহ বিজ্ঞপ্তি তৈরি করতে হয় তা দেখুন।

সরাসরি উত্তর দেওয়ার অ্যাকশন যোগ করা

Android 7.0 (API লেভেল 24)-এ চালু হওয়া সরাসরি উত্তর দেওয়ার অ্যাকশন, ব্যবহারকারীদের সরাসরি বিজ্ঞপ্তিতে টেক্সট লিখতে দেয়। অ্যাক্টিভিটি না খুলেই টেক্সটটি আপনার অ্যাপে ডেলিভার করা হয়। যেমন, আপনি সরাসরি উত্তর দেওয়ার অ্যাকশন ব্যবহার করে ব্যবহারকারীকে টেক্সট মেসেজের উত্তর দিতে বা বিজ্ঞপ্তির মধ্যে থেকে টাস্ক তালিকা আপডেট করতে দিতে পারেন।

ছবি ৪. "উত্তর দিন" বোতামে ট্যাপ করলে টেক্সট ইনপুট খুলে যায়।

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

উত্তর দেওয়ার বোতাম যোগ করুন

সরাসরি উত্তর দেওয়ার সুবিধা আছে এমন বিজ্ঞপ্তি অ্যাকশন তৈরি করতে, এইসব ধাপ অনুসরণ করুন:

RemoteInput.Builder -এর একটি ইনস্ট্যান্স তৈরি করুন যা আপনি বিজ্ঞপ্তি অ্যাকশনে যোগ করতে পারবেন। এই ক্লাসের কনস্ট্রাক্টর একটি স্ট্রিং গ্রহণ করে যা সিস্টেম টেক্সট ইনপুটের জন্য কী হিসেবে ব্যবহার করে। আপনার অ্যাপ পরে ইনপুটের টেক্সট রিট্রিভ করতে সেই কী ব্যবহার করে।

// Key for the string that's delivered in the action's intent.
val replyLabel: String = context.resources.getString(R.string.reply_label)
val remoteInput: RemoteInput = RemoteInput.Builder(KEY_TEXT_REPLY).run {
    setLabel(replyLabel)
    build()
}

উত্তরের অ্যাকশনের জন্য PendingIntent তৈরি করো।

// Build a PendingIntent for the reply action to trigger.
val replyPendingIntent: PendingIntent =
    PendingIntent.getBroadcast(context,
        conversationId,
        getMessageReplyIntent(conversationId),
        PendingIntent.FLAG_MUTABLE)

কল করলে এটি উপেক্ষা করা হয়

addRemoteInput() ব্যবহার করে কোনও অ্যাকশনের সাথে RemoteInput অবজেক্ট অ্যাটাচ করুন।

// Create the reply action and add the remote input.
val action: NotificationCompat.Action =
    NotificationCompat.Action.Builder(R.drawable.reply,
        context.getString(R.string.reply_label), replyPendingIntent)
        .addRemoteInput(remoteInput)
        .build()

কোনও বিজ্ঞপ্তিতে অ্যাকশন প্রয়োগ করুন এবং বিজ্ঞপ্তিটি ইস্যু করুন।

// Build the notification and add the action.
val newMessageNotification = NotificationCompat.Builder(context, CHANNEL_ID)
    .setSmallIcon(R.drawable.ic_message)
    .setContentTitle(context.getString(R.string.title))
    .setContentText(context.getString(R.string.content))
    .addAction(action)
    .build()

// Issue the notification.
NotificationManagerCompat.from(context).notify(notificationId, newMessageNotification)

ব্যবহারকারী যখন বিজ্ঞপ্তি অ্যাকশন ট্রিগার করেন, তখন সিস্টেম তাকে উত্তর ইনপুট করার জন্য প্রম্পট করে, যেমনটি ৪ নম্বর ছবিতে দেখানো হয়েছে।

উত্তর থেকে ব্যবহারকারীর ইনপুট ফিরিয়ে আনা

বিজ্ঞপ্তির উত্তর দেওয়ার UI থেকে ব্যবহারকারীর ইনপুট পেতে, RemoteInput.getResultsFromIntent() কল করুন এবং এর মধ্যে আপনার BroadcastReceiver-এর পাওয়া Intent পাস করুন:

private fun getMessageText(intent: Intent): CharSequence? {
    return RemoteInput.getResultsFromIntent(intent)?.getCharSequence(KEY_TEXT_REPLY)
}

টেক্সট প্রসেস করার পরে, একই আইডি ও ট্যাগ ব্যবহার করা হলে, NotificationManagerCompat.notify() কল করে বিজ্ঞপ্তি আপডেট করুন। সরাসরি উত্তর দেওয়ার UI লুকাতে এবং ব্যবহারকারীকে কনফার্ম করতে যে তার উত্তর পাওয়া গেছে এবং সঠিকভাবে প্রসেস করা হয়েছে, এটি প্রয়োজনীয়।

// Build a new notification, which informs the user that the system
// handled their interaction with the previous notification.
val repliedNotification = NotificationCompat.Builder(context, CHANNEL_ID)
    .setSmallIcon(R.drawable.message)
    .setContentText(context.getString(R.string.replied))
    .build()

// Issue the new notification.
NotificationManagerCompat.from(context).notify(notificationId, repliedNotification)

অন্যান্য ডেটা ফিরিয়ে আনা

RemoteInput-এর সাথে অন্যান্য ডেটা টাইপ ম্যানেজ করার পদ্ধতি একই রকম। নিচের উদাহরণে ইনপুট হিসেবে ছবি ব্যবহার করা হয়েছে।

val replyLabel: String = context.resources.getString(R.string.reply_label)
val remoteInput: RemoteInput = RemoteInput.Builder(KEY_REPLY).run {
    setLabel(replyLabel)
    // Allow for image data types in the input.
    // This method can be used again to allow for other data types.
    setAllowDataType("image/*", true)
    build()
}

RemoteInput#getDataResultsFromIntent কল করে সংশ্লিষ্ট ডেটা এক্সট্র্যাক্ট করুন।

class ReplyReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        val dataResults = RemoteInput.getDataResultsFromIntent(intent, KEY_REPLY)
        val imageUri: Uri? = dataResults?.get("image/*") as? Uri

        if (imageUri != null) {
            // Extract the image
            context.contentResolver.openInputStream(imageUri)?.use { inputStream ->
                val bitmap = BitmapFactory.decodeStream(inputStream)
                // Display the image
                // ...
            }
        }
    }

    companion object {
        const val KEY_REPLY = "key_reply"
        const val KEY_TEXT_REPLY = "key_text_reply"
    }
}

এই নতুন বিজ্ঞপ্তি নিয়ে কাজ করার সময়, প্রাপকের onReceive() মেথডে পাস করা প্রসঙ্গ ব্যবহার করুন।

setRemoteInputHistory() কল করে বিজ্ঞপ্তির নিচে উত্তরটি যোগ করুন। তবে, আপনি যদি কোনও মেসেজিং অ্যাপ তৈরি করেন, তাহলে মেসেজিং-স্টাইল বিজ্ঞপ্তি তৈরি করুন এবং কথোপকথনে নতুন মেসেজ যোগ করুন।

মেসেজিং অ্যাপ থেকে পাওয়া বিজ্ঞপ্তি সম্পর্কে আরও পরামর্শ পেতে, মেসেজিং অ্যাপের পেশাদার পদ্ধতি দেখুন।

জরুরি মেসেজ দেখানো

আপনার অ্যাপকে হয়ত জরুরি, সময়-সংবেদনশীল মেসেজ দেখাতে হবে, যেমন ইনকামিং ফোন কল বা বাজতে থাকা অ্যালার্ম। এইসব পরিস্থিতিতে, আপনি বিজ্ঞপ্তির সাথে ফুল-স্ক্রিন ইনটেন্ট অ্যাসোসিয়েট করতে পারবেন।

বিজ্ঞপ্তিটি দেখানো হলে, ডিভাইসের লক স্ট্যাটাসের উপর নির্ভর করে ব্যবহারকারীরা নিম্নলিখিতগুলির মধ্যে একটি দেখতে পাবেন:

  • ব্যবহারকারীর ডিভাইস লক করা থাকলে, একটি ফুল-স্ক্রিন অ্যাক্টিভিটি দেখা যায় যা লকস্ক্রিনকে ঢেকে দেয়।
  • ব্যবহারকারীর ডিভাইস আনলক করা থাকলে, বিজ্ঞপ্তিটি একটি বড় আকারে দেখা যায় যার মধ্যে বিজ্ঞপ্তি ম্যানেজ করা বা বাতিল করার বিকল্প থাকে।

নিচের কোড স্নিপেট থেকে বোঝা যাবে যে কীভাবে আপনার বিজ্ঞপ্তি ফুল-স্ক্রিন ইনটেন্টের সাথে যুক্ত করতে হয়:

val fullScreenIntent = Intent(context, ImportantActivity::class.java)
val fullScreenPendingIntent = PendingIntent.getActivity(context, 0,
    fullScreenIntent, PendingIntent.FLAG_IMMUTABLE)

val builder = NotificationCompat.Builder(context, CHANNEL_ID)
    .setSmallIcon(R.drawable.ic_logo)
    .setContentTitle("My notification")
    .setContentText("Hello World!")
    .setPriority(NotificationCompat.PRIORITY_DEFAULT)
    .setFullScreenIntent(fullScreenPendingIntent, true)

লক স্ক্রিনের দৃশ্যমানতা সেট করা

লক স্ক্রিন থেকে বিজ্ঞপ্তিতে দৃশ্যমান বিবরণের লেভেল কন্ট্রোল করতে, setVisibility() কল করুন এবং নিম্নলিখিত ভ্যালুগুলির মধ্যে একটি নির্দিষ্ট করুন:

  • VISIBILITY_PUBLIC: লক স্ক্রিনে বিজ্ঞপ্তির সম্পূর্ণ কন্টেন্ট দেখা যায়।

  • VISIBILITY_SECRET: লক স্ক্রিনে বিজ্ঞপ্তির কোনও অংশই দেখা যায় না।

  • VISIBILITY_PRIVATE: লক স্ক্রিনে শুধু প্রাথমিক তথ্য, যেমন বিজ্ঞপ্তির আইকন ও কন্টেন্টের নাম দেখানো হয়। বিজ্ঞপ্তির সম্পূর্ণ কন্টেন্ট দেখা যাচ্ছে না।

আপনি VISIBILITY_PRIVATE সেট করলে, বিজ্ঞপ্তির কন্টেন্টের একটি বিকল্প ভার্সনও দিতে পারবেন যা নির্দিষ্ট বিবরণ লুকিয়ে রাখে। যেমন, কোনও এসএমএস অ্যাপ এমন বিজ্ঞপ্তি দেখাতে পারে যাতে লেখা থাকে,"আপনি ৩টি নতুন টেক্সট মেসেজ পেয়েছেন" কিন্তু মেসেজের কন্টেন্ট ও প্রেরককে লুকিয়ে রাখে। এই বিকল্প বিজ্ঞপ্তি প্রদান করতে, প্রথমে NotificationCompat.Builder-এর মাধ্যমে স্বাভাবিকভাবে বিকল্প বিজ্ঞপ্তি তৈরি করুন। তারপর, setPublicVersion() ব্যবহার করে সাধারণ বিজ্ঞপ্তির সাথে বিকল্প বিজ্ঞপ্তি অ্যাটাচ করুন।

মনে রাখবেন, ব্যবহারকারী সবসময়ই চূড়ান্তভাবে নিয়ন্ত্রণ করতে পারেন যে তার বিজ্ঞপ্তি লক স্ক্রিনে দেখা যাবে কিনা এবং আপনার অ্যাপের বিজ্ঞপ্তি চ্যানেল অনুযায়ী সেগুলি নিয়ন্ত্রণ করতে পারেন।

বিজ্ঞপ্তি আপডেট করা

আপনি বিজ্ঞপ্তি ইস্যু করার পরে সেটি আপডেট করতে, আগে যে আইডি ব্যবহার করেছিলেন সেটি NotificationManagerCompat.notify()-কে আবার দিন। আগের বিজ্ঞপ্তি বাতিল করা হলে, তার পরিবর্তে একটি নতুন বিজ্ঞপ্তি তৈরি করা হয়।

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

বিজ্ঞপ্তি সরিয়ে দেওয়া

নিচে উল্লেখ করা কোনও একটি ঘটনা না ঘটা পর্যন্ত বিজ্ঞপ্তি দেখা যাবে:

  • ব্যবহারকারী বিজ্ঞপ্তিটি বাতিল করে দেন।
  • আপনি বিজ্ঞপ্তি তৈরি করার সময় setAutoCancel() কল করলে ব্যবহারকারী বিজ্ঞপ্তিতে ট্যাপ করেন।
  • আপনি নির্দিষ্ট বিজ্ঞপ্তি আইডির জন্য cancel() কল করেন। এছাড়াও, এই পদ্ধতি চলমান বিজ্ঞপ্তি মুছে দেয়।
  • আপনি cancelAll() কল করেন, যা আপনার আগে ইস্যু করা সব বিজ্ঞপ্তি সরিয়ে দেয়।
  • setTimeoutAfter() ব্যবহার করে বিজ্ঞপ্তি তৈরি করার সময় আপনি টাইম-আউট সেট করলে, নির্দিষ্ট করা সময়সীমা শেষ হয়ে যায়। প্রয়োজন হলে, নির্দিষ্ট টাইম-আউট সময়সীমা শেষ হওয়ার আগে আপনি বিজ্ঞপ্তি বাতিল করতে পারবেন।

মেসেজিং অ্যাপের জন্য পেশাদার পদ্ধতি

আপনার মেসেজিং ও চ্যাট অ্যাপের জন্য বিজ্ঞপ্তি তৈরি করার সময় এখানে তালিকাভুক্ত পেশাদার পদ্ধতিগুলি বিবেচনা করুন।

MessagingStyle ব্যবহার করা

Android 7.0 (API লেভেল 24) থেকে শুরু করে, Android মেসেজিং কন্টেন্টের জন্য বিশেষভাবে একটি বিজ্ঞপ্তি স্টাইল টেমপ্লেট প্রদান করে। NotificationCompat.MessagingStyle ক্লাস ব্যবহার করে, আপনি বিজ্ঞপ্তিতে দেখানো লেবেলের মধ্যে কথোপকথনের শিরোনাম, অতিরিক্ত মেসেজ এবং বিজ্ঞপ্তির কন্টেন্ট ভিউ সহ আরও অনেক কিছু পরিবর্তন করতে পারবেন।

MessagingStyle ক্লাস ব্যবহার করে কীভাবে কোনও বিজ্ঞপ্তির স্টাইল কাস্টমাইজ করতে হয় তা নিম্নলিখিত কোড স্নিপেট থেকে জানতে পারবেন।

val message1 = NotificationCompat.MessagingStyle.Message(
    messages[0].text,
    messages[0].time,
    messages[0].sender
)
val message2 = NotificationCompat.MessagingStyle.Message(
    messages[1].text,
    messages[1].time,
    messages[1].sender
)
notification = NotificationCompat.Builder(context, CHANNEL_ID)
    .setSmallIcon(R.drawable.ic_logo)
    .setStyle(
        NotificationCompat.MessagingStyle(Person.Builder().setName("Me").build())
            .addMessage(message1)
            .addMessage(message2)
    )
    .build()

Android 9.0 (API লেভেল 28) থেকে শুরু করে, বিজ্ঞপ্তি ও এর অবতারের অপ্টিমাল রেন্ডারিং পেতে Person ক্লাস ব্যবহার করাও প্রয়োজন।

NotificationCompat.MessagingStyle ব্যবহার করার সময়, নিম্নলিখিত কাজগুলি করুন:

  • দু'জনের বেশি লোকজনের সাথে গ্রুপ চ্যাটের জন্য নাম সেট করতে MessagingStyle.setConversationTitle() বলুন। ভাল কথোপকথনের শিরোনাম হতে পারে গ্রুপ চ্যাটের নাম অথবা সেটির কোনও নাম না থাকলে, কথোপকথনে অংশগ্রহণকারীদের তালিকা। এটি না থাকলে, মেসেজটি ভুল করে কথোপকথনে সবচেয়ে সাম্প্রতিক মেসেজ প্রেরকের সাথে হওয়া ব্যক্তিগত কথোপকথনের অংশ হিসেবে ধরে নেওয়া হতে পারে।
  • ছবি সহ মিডিয়া মেসেজ যোগ করতে MessagingStyle.setData() পদ্ধতি ব্যবহার করুন। প্যাটার্ন ইমেজ/*-এর MIME ধরন কাজ করে।

সরাসরি উত্তর দেওয়া

সরাসরি উত্তর দেওয়ার ফিচারের সাহায্যে ব্যবহারকারী কোনও মেসেজের ইনলাইন উত্তর দিতে পারেন।

  • ইনলাইন উত্তর অ্যাকশনের মাধ্যমে ব্যবহারকারী উত্তর দেওয়ার পরে, MessagingStyle বিজ্ঞপ্তি আপডেট করতে MessagingStyle.addMessage() ব্যবহার করুন এবং বিজ্ঞপ্তি প্রত্যাহার বা বাতিল করবেন না। বিজ্ঞপ্তি বাতিল না করলে ব্যবহারকারী বিজ্ঞপ্তি থেকে একাধিক উত্তর পাঠাতে পারবেন।
  • Wear OS-এর সাথে ইনলাইন উত্তর দেওয়ার অ্যাকশন মানানসই করতে, Action.WearableExtender.setHintDisplayInlineAction(true)-এ কল করুন।
  • বিজ্ঞপ্তিতে পুরনো মেসেজ যোগ করে সরাসরি উত্তর দেওয়া কথোপকথনে প্রসঙ্গ যোগ করতে addHistoricMessage() পদ্ধতি ব্যবহার করুন।

স্মার্ট রিপ্লাই চালু করা

  • স্মার্ট রিপ্লাই চালু করতে, উত্তর দেওয়ার অ্যাকশনে গিয়ে setAllowGeneratedResponses(true)-এ কল করুন। এর ফলে, Wear OS ডিভাইসে বিজ্ঞপ্তি ব্রিজ করা হলে, ব্যবহারকারীদের কাছে স্মার্ট রিপ্লাই উত্তর উপলভ্য হয়। স্মার্ট রিপ্লাইয়ের উত্তর সম্পূর্ণভাবে ওয়াচেই থাকা মেশিন লার্নিং মডেলের মাধ্যমে তৈরি করা হয়। এর জন্য NotificationCompat.MessagingStyle বিজ্ঞপ্তি থেকে পাওয়া প্রাসঙ্গিক তথ্য ব্যবহার করা হয় এবং উত্তর তৈরি করার জন্য ইন্টারনেটে কোনও ডেটা আপলোড করা হয় না।

বিজ্ঞপ্তির মেটাডেটা যোগ করা

  • ডিভাইস বিরক্ত করবে না মোডে থাকাকালীন আপনার অ্যাপের বিজ্ঞপ্তি কীভাবে ম্যানেজ করতে হবে তা সিস্টেমকে জানাতে বিজ্ঞপ্তি মেটাডেটা অ্যাসাইন করুন। যেমন, ডিস্টার্ব করবেন না মোড ওভাররাইড করতে addPerson() বা setCategory(Notification.CATEGORY_MESSAGE) পদ্ধতি ব্যবহার করুন।