ویژگیها و استایلهای مختلف نوتیفیکیشن در اندروید
در این قسمت از سری مباحث آموزش برنامه نویسی اندروید به نحوه ساخت انواع نوتیفیکیشن یا اعلان در اندروید پرداخته و طریقه پیاده سازی استایلهای مختلف و ویژگیها و امکانات متنوعی که برای نوتیفیکیشن معرفی شده را بررسی و تمرین میکنیم.
- آشنایی با ساختار نوتیفیکیشن (Notification) در سیستم عامل اندروید
- معرفی متد PendingIntent جهت تعامل کاربر با نوتیفیکیشنها و هدایت وی به مقصد موردنظر
- کار با دکمههای Action در نوتیفیکیشن
- تفاوت نحوه نمایش اکشنها در نسخههای قدیم و جدید اندروید
- نمایش متن طولانی در اعلان به وسیله استایل BigTextStyle و گنجاندن خلاصه متن در نوتیفیکیشن
- معرفی نوتیفیکیشنهایی که باز و بسته میشوند (Expandable Notification)
- نمایش تصویر بزرگ در Notification با استفاده از استایل BigPictureStyle
- نحوه تبدیل تصاویر با فرمت JPG و PNG به Bitmap در اندروید
- نمایش لیست پیغامهای دریافتی توسط InboxStyle
- حذف و یا لغو نوتیفیکیشن پس از انجام یک عمل خاص و یا بصورت خودکار و پس از گذشت زمان مشخص
- مدیریت Notification Badge از قبیل نحوه نمایش اعلانها و همچنین تعداد پیغامهای دریافتی
- نحوه غیر فعال کردن Notification Badge یا Notification Dots
- حذف یک Notification Channel از روی سیستم عامل اندروید توسط deleteNotificationChannel
این مبحث در قالب PDF و در ۲۷ صفحه تهیه شده که در ادامه چند صفحهی ابتدایی را مشاهده میکنید:
در قسمت قبل با نحوه ساخت نوتیفیکیشن در اندروید آشنا شدیم. در این مبحث قصد دارم انواع نوتیفیکیشن، حالتها و امکانات مختلف قابل پیاده سازی برای اعلانهای اندرویدی را معرفی کنم.
برای این قسمت پروژه جدیدی نمیسازم و از همان پروژه قسمت قبل استفاده میکنم.
ساختار نوتیفیکیشن اندروید
به نام خدا. قبل از ادامه مبحث ابتدا بهتر است ساختار نوتیفیکیشنی که در مبحث قبل ساختیم را مرور کنیم. هرکدام از اجزاء اعلان را به ترتیب شماره توضیح میدهم:
۱: آیکون کوچک (Small icon): این آیکون توسط setSmallIcon ساخته شده که تعریف آن برای نوتیفیکیشن الزامی است.
۲: در اینجا نام اپلیکیشنی که نوتیفیکیشن را اجرا کرده نمایش داده میشود.
۳: زمان ساخت نوتیفیکیشن را نشان میدهد. البته میتوان این قسمت را به دلخواه تغییر داد و یا حذف کرد.
۴: آیکون بزرگ (Large icon): این آیکون توسط setLargeIcon ساخته شده و کاربرد آن نمایش یک آیکون یا تصویر بزرگ در کنار پیغام است.
۵: عنوان نوتیفیکیشن
۶: متن نوتیفیکیشن
انواع نوتیفیکیشن در اندروید
اعلانها یا همان Notification را به روشهای مختلفی میتوان پیاده سازی کرد که هرکدام کاربرد مختص خود را داراست. یک نوتیفیکیشن صرفا پیام مختصری را به کاربر اطلاع میدهد. دیگری جزئیات بیشتری در اختیار کاربر قرار داده و او را به سمت یک اکتیویتی در اپلیکیشن و یا یک صفحه وب هدایت میکند. و انواع دیگری از نحوه ساخت و اجرای نوتیفیکیشن وجود دارد که در اینجا تعدادی را بررسی میکنیم.
استفاده از PendingIntent و ساخت Action برای نوتیفیکیشن
نوتیفیکیشنی که قبلا ساختیم صرفا یک پیغام را به کاربر نمایش میدهد و غیر از بستن آن، کاربر هیچگونه تعاملی نمیتواند با این پیغام داشته باشد. در صورتی که ما به این تعامل نیاز داریم. اگر اعلان مربوط به یک تخفیف است، میبایست کاربر را به صفحه مرتبط با آن هدایت کند. در اینجا از pendingIntent استفاده میکنیم. قبلا با نحوه کار با intent در اندروید آشنا شدیم. حالا در نوتیفیکیشن هم با استفاده از اینتنت تعیین میکنیم بعد از لمس اعلان توسط کاربر، چه عملی صورت پذیرد.
پروژه Notification را باز میکنم. ابتدا یک دکمه با عنوان PendingIntent Notification به Layout اکتیویتی اضافه میکنم:
سپس طبق کد زیر یک نوتیفیکیشن دیگر داخل اکتیویتی میسازم:
package ir.android_studio.notification; import androidx.appcompat.app.AppCompatActivity; import androidx.core.app.NotificationCompat; import android.app.NotificationChannel; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.graphics.BitmapFactory; import android.graphics.Color; import android.media.RingtoneManager; import android.os.Build; import android.os.Bundle; import android.view.View; import android.widget.Button; public class MainActivity extends AppCompatActivity { Button simpleButton, pendingButton; NotificationManager notifManager; String offerChannelId = "Offers"; PendingIntent mpIntent; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); simpleButton = findViewById(R.id.simple_notif); pendingButton = findViewById(R.id.pending_notif); notifManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); Intent pIntent = new Intent(this, CartActivity.class); mpIntent = PendingIntent.getActivity(this, 0, pIntent, PendingIntent.FLAG_UPDATE_CURRENT); simpleButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { createNotifChannel(); simpleNotification(); } }); pendingButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { createNotifChannel(); pendingNotification(); } }); } private void createNotifChannel() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { String offerChannelName = "Shop offers"; String offerChannelDescription= "Best offers for customers"; int offerChannelImportance = NotificationManager.IMPORTANCE_DEFAULT; NotificationChannel notifChannel = new NotificationChannel(offerChannelId, offerChannelName, offerChannelImportance); notifChannel.setDescription(offerChannelDescription); //notifChannel.enableVibration(true); notifChannel.enableLights(true); notifChannel.setLightColor(Color.GREEN); notifManager.createNotificationChannel(notifChannel); } } public void simpleNotification() { NotificationCompat.Builder sNotifBuilder = new NotificationCompat.Builder(this, offerChannelId) .setSmallIcon(R.drawable.notif_icon) .setContentTitle("بروزرسانی") .setContentText("یک نسخه جدید از برنامه آماده دریافت است") .setVibrate(new long[]{100,500,500,500,500,500}) .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.android)) .setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)) .setVisibility(NotificationCompat.VISIBILITY_PUBLIC); notifManager.notify(1, sNotifBuilder.build()); } public void pendingNotification() { NotificationCompat.Builder pNotifBuilder = new NotificationCompat.Builder(this, offerChannelId) .setSmallIcon(R.drawable.notif_icon) .setContentTitle("تخفیف پنجاه درصدی!") .setContentText("پنجاه درصد تخفیف به مناسبت طلوع خورشید") .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.android)) .setContentIntent(mpIntent); notifManager.notify(2, pNotifBuilder.build()); } }
در کد فوق ابتدا pendingButton را به دکمه مربوطه در لِی اوت متصل کردم. سپس یک شیء از Intent با نام mIntent ساختم:
Intent pIntent = new Intent(this, CartActivity.class);
به جهت ملموس بودن نتیجه کار، یک اکتیویتی با نام CartActivity به پروژه اضافه کرده و به اینتنت معرفی کردم.
mpIntent = PendingIntent.getActivity(this, 0, pIntent, PendingIntent.FLAG_UPDATE_CURRENT);
سپس با استفاده از متد PendingIntent و getActivity تعیین میکنم با لمس نوتیفیکیشن، pIntent اجرا شود. این متد ۴ پارامتر میگیرد که در جدول زیر معرفی شده:
اولی Context است که this وارد کردم. پارامتر دوم یک مقدار از جنس int است که به عنوان یک کد درخواست خصوصی تلقی میشود. من برای این نوتیفیکیشن مقدار ۰ قرار دادم. پارامتر سوم اینتنتی است که قبلا تعریف کردم یعنی pIntent. آخرین پارامتر یعنی flags جهت تعیین وضعیت اینتنت است که من در اینجا از نوع FLAG_UPDATE_CURRENT انتخاب کردم.
در قدم بعد یک تابع با نام pendingNotification به کلاس اضافه کردم. ۴ متد نخست این تابع مشابه simpleNotification است که در مبحث قبل توضیحات لازم ارائه شده.
public void pendingNotification() { NotificationCompat.Builder pNotifBuilder = new NotificationCompat.Builder(this, offerChannelId) .setSmallIcon(R.drawable.notif_icon) .setContentTitle("تخفیف پنجاه درصدی!") .setContentText("پنجاه درصد تخفیف به مناسبت طلوع خورشید") .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.android)) .setContentIntent(mpIntent); notifManager.notify(2, pNotifBuilder.build()); }
توسط setContentIntent اینتنتی که قبلا ساختم را به نوتیفیکیشن معرفی میکنم.
در نهایت متد setOnClickListener مربوط به دکمه pendingButton را ساخته و توابع مرتبط با کانال و نوتیفیکیشن را فراخوانی میکنم. (برای سایر نوتیفیکیشنها نیز همین مراحل تکرار میشود؛ یعنی اضافه کردن دکمه در Layout، ساخت متد setOnClickListener و فراخوانی توابع کانال و نوتیفیکیشن مربوط به آن درون این متد).
پروژه را اجرا کرده و روی دکمه PendingIntent Notification کلیک میکنم:
با کلیک روی نوتیفیکیشن، به اکتیویتی CartActivity هدایت شدم. اما یک ایراد وجود دارد. به نوار وضعیت تصویر دوم دقت کنید. هنوز آیکون نوتیفیکیشن مشاهده میشود. یعنی با وجود اینکه کاربر روی نوتیفیکیشن کلیک کرده و به مقصد مدنظر منتقل شده، اعلان همچنان باقی مانده که لازم است این مشکل را رفع کنیم. اینکار توسط متد setAutoCancel انجام میپذیرد:
NotificationCompat.Builder pNotifBuilder = new NotificationCompat.Builder(this, offerChannelId) .setSmallIcon(R.drawable.notif_icon) .setContentTitle("تخفیف پنجاه درصدی!") .setContentText("پنجاه درصد تخفیف به مناسبت طلوع خورشید") .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.android)) .setContentIntent(mpIntent) .setAutoCancel(true);
با اجرای مجدد پروژه، بعد از کلیک روی Notification، علاوه بر انتقال کاربر به صفحه CartActivity نوتیفیکیشن نیز حذف میشود.
علاوه بر کلیک روی نوتیفیکیشن، میتوان دکمههایی به اعلان افزود که برای هرکدام نیز یک intent مجزا تعریف شده باشد. این دکمهها یک Action مینامیم.
برای مثال، نوتیفیکیشن برنامه مدیریت پیامک عموما دو گزینه دارد. اولی Reply جهت پاسخ دادن به پیامک دریافتی و دومی Mark as read که با لمس این دکمه، پیامک از حالت “خوانده نشده” به “خوانده شده” تغییر وضعیت پیدا میکند.
من متد setContentIntent را غیرفعال کرده و بجای آن دو Action به نوتیفیکیشن اضافه میکنم:
NotificationCompat.Builder pNotifBuilder = new NotificationCompat.Builder(this, offerChannelId) .setSmallIcon(R.drawable.notif_icon) .setContentTitle("تخفیف پنجاه درصدی!") .setContentText("پنجاه درصد تخفیف به مناسبت طلوع خورشید") .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.android)) //.setContentIntent(mpIntent) .addAction(R.drawable.notif_icon, "Buy", mpIntent) .addAction(R.drawable.notif_icon, "Product details", mpIntent) .setAutoCancel(true);
addAction سه ورودی میگیرد:
ورودی اول: برای هر گزینه میتوان یک آیکون تعریف کرد. البته توجه داشته باشید از اندروید Nougat به بعد برای سادگی بیشتر محیط نوتیفیکیشن، این آیکونها نمایش داده نمیشوند.
ورودی دوم: عنوان اکشن است که برای اکشن اول “Buy” و اکشن دوم “Product details” وارد کردم.
ورودی سوم: PendingIntent ای که قبلا تعریف شده.
مجدد پروژه را اجرا میکنم:
دو اکشن به انتهای نوتیفیکیشن اضافه شده که البته در این مثال هردو یک عملکرد دارند؛ یعنی هدایت به CartActivity.
همانطور که قبلا اشاره کردم، از اندروید N و به بالاتر، آیکون گزینهها نمایش داده نمیشود. اما روی دیوایسهای پایینتر از این نسخه، آیکونها در کنار عنوان دکمه وجود دارد. پروژه را روی یک دیوایس با API 23 اجرا کردم:
نمایش متن بزرگ در نوتیفیکیشن توسط BigTextStyle
گاهی اوقات لازم است متن طولانی تری در نوتیفیکیشن به کاربر نمایش دهیم. اگر برای متن طولانی از setContentText استفاده کنیم تنها چند کلمه ابتدای آن قابل مشاهده خواهد بود. اینجاست که استایلها در نوتیفیکیشن امکان شخصی سازی بیشتری به ما میدهند. به کد زیر دقت کنید:
public void bigTextNotification() { NotificationCompat.BigTextStyle bStyle = new NotificationCompat.BigTextStyle() .bigText("لورم ایپسوم متنی است که ساختگی برای طراحی و چاپ آن مورد است. صنعت چاپ زمانی لازم بود شرایطی شما باید فکر ثبت نام و طراحی، لازمه خروج می باشد ") .setBigContentTitle("نوتیفیکیشن طولانی") .setSummaryText("خلاصه متن طولانی"); NotificationCompat.Builder bNotifBuilder = new NotificationCompat.Builder(this, offerChannelId) .setSmallIcon(R.drawable.notif_icon) .setContentTitle("تخفیف پنجاه درصدی! ") .setContentText("پنجاه درصد تخفیف به مناسبت طلوع خورشید") .setStyle(bStyle); notifManager.notify(3, bNotifBuilder.build()); }
مانند قبل یک تابع جدید به کلاس اضافه کردم. نام این تابع را bigTextNotification گذاشتم.
در NotificationCompat امکان تعریف Style ها را داریم. در اینجا من از BigTextStyle یک شیء با نام bStyle ایجاد کردهام که ۳ ویژگی برای آن تعریف شده.
جهت مطالعه ادامه آموزش، فایل PDF را دانلود نمائید
توجه : سورس پروژه درون پوشه Exercises قرار دارد
با توجه به اینکه آموزشهای پایه با قیمت پایین در اختیار کاربر قرار گرفته و درآمد حاصل صرف تامین هزینههای وب سایت و تهیه آموزشهای آتی میشود، به اشتراک گذاری این فایل با دیگران خلاف اخلاق است.
تعداد صفحات : ۲۶
حجم : ۲ مگابایت
قیمت : ۱۶ هزار تومان
توجه: صرفا در صورتی از درگاه پشتیبان استفاده کنید که قادر به پرداخت از طریق سبد دانلود نباشید.
افزودن به سبد دانلود درگاه پشتیبان
سلام میشه راهنمایی کنید چطور میشه نوتیفیکیشنی مثل برنامه باد صبا طراحی کرد که در همه دستگاه ها یکسان نمایش داده بشه؟ من از RemoteView استفاده کردم….. اما باز در ورژن های مختلف اندروید یکسان نمایش داده نیمشه؟
واقعا که واسه دریافت نسخه پی دی اف پول می گیرید! شرم آوره. آدم با لپتاب خودش بره پرینت بگیره از صفحه به صرفه تره.
بزرگوار PDF های غیر رایگان نسخه کامل آموزش هستن. در واقع متن موجود در صفحه وب سایت فقط بخشی از آموزش هست
سلام.
بنده یک سوالی داشتم.
الان تمام چیزهایی که فرمودید در این پست و قبلی به نحوی بود که نوتیفیکیشن از درون اکتیویتی فراخوانی میشد.
در آموزش سرویس نیز در Forground services نوتیفیکیشن از داخل سرویس فراخوانی میشد و خود سرویس نیز از درون اکتیویتی فراخوانی میشد.
تلگرام ، واتساپ ، اینستاگرام و … اگر توجه کنید یک سیستمی دارند که وقتی شما انلاین میشوید لیست اخرین پیام های دریافتی رو بدون اینکه نیاز باشه شما وارد اپلیکیشن شوید برای شما در غالب نوتیفیکیشن ارسال میکند.
من باید چجوری بدون ورود به اکتیویتی سرویس رو فعال کنم تا نوتیفیکیشن رو ارسال کنه؟
بعد مورد مشابهش رو شما در تماس واتساپ یا حتی خود تلفن همراهتون هم دیده اید که بدون اینکه توی اپلیکیشن باشید ناگهان زنگ میخورد.
حتی اگر یه اسمی چیزی هم به من معرفی کنید که من برم سرچ کنم خیلی خوب میشه.
چون من اصلا هیچی تو سایت های خارجی و داخلی پیدا نکردم.
ممنون میشم راهنمایی کنید.
سرویس ها وقتی برنامه در پس زمینه هم در حال اجرا باشه فعال هست و اساسا کاربردش هم همینه. لطفا مبحث زیر رو مطالعه بفرمایید:
https://android-studio.ir/android-service