نوتیفیکیشن در اندروید | Notification in Android

سلام! من محمدرضا فکری هستم، در این نوشته قصد دارم با شما به ساختار نوتیفیکیشن و استایل های آن در اندروید بپردازیم.android | اندرویدخب، این نوتیفیکیشن چیه؟برای مثال، شما دارین با گوشی تون کار می کنید و یک نوتیفیکیشن (معادل انگلیسی:‌ اطلاع، آگاهسازی و ...) از طرف پیام رسانی که ازش استفاده می کنید دریافت می کنید و پیامی که فرستاده شده را در بخش تولبار (Toolbar) نشان می دهد یا روی صفحه برای لحظه ای می آید. معمولا نوع نشان دادن مربوط به بخش نوع پیام و کدنویسی بستگی دارد. نوتیفیکیشن یکی از سرویس های اندروید می باشد.خب، حالا کدنویسی نوتیفیکیشن چطوریه؟برای ساختن نوتیفیکیشن باید از ۶ خان بگذریم :-) شامل:ساختن ویو activity_main.xmlساخت کلاس MyApp.kt (چنل) آماده کردن فایل AndroidManifest.xml (منیفست) کدنویسی MainActivity.ktکدنویسی activity_main2.xmlکدنویسی MainActivity2.ktnotificationخان اول: ساختن ویو activity_main.xmlهدف از این اپلیکیشن آشنایی و کار کردن با نوتیفیکیشن می باشد، پس به یک طراحی ساده نیاز داریم. فقط یک باتن (Button) برای نشان دادن نوتیفیکیشن!<?xml version=&quot1.0&quot encoding=&quotutf-8&quot?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android=&quothttp://schemas.android.com/apk/res/android&quot xmlns:app=&quothttp://schemas.android.com/apk/res-auto&quot xmlns:tools=&quothttp://schemas.android.com/tools&quot android:layout_width=&quotmatch_parent&quot android:layout_height=&quotmatch_parent&quot tools:context=&quot.MainActivity&quot> <Button android:id=&quot@+id/btn_show&quot android:layout_width=&quotwrap_content&quot android:layout_height=&quotwrap_content&quot android:text=&quotShow notif&quot app:layout_constraintBottom_toBottomOf=&quotparent&quot app:layout_constraintEnd_toEndOf=&quotparent&quot app:layout_constraintStart_toStartOf=&quotparent&quot app:layout_constraintTop_toTopOf=&quotparent&quot /> </androidx.constraintlayout.widget.ConstraintLayout>خروجی کد فوقخان دوم: ساختن چنل | Channelچنل چیه؟ و چرا؟ قبل version: 8 & api-leve: 26 در اندروید، ساختن چنل اجباری نبود و زیاد قابل توجه توسعه دهنده ها نبود، بعد version: 8 & api-leve: 26 ساختن چنل برای توسعه دهنده ها اجباری شد.برای شروع یک کلاس کاتلینی به نام MyApp می سازیم و آن را از Application() ارث بری می کنیم. مرحله بعدی صدا زدن تابع onCreate() می باشد. ما قرار است کدنویسی مربوط به چنل را در این بخش انجام دهیم.این کلاس قبل همه کلاس ها (حتی MainActivity) و سرویس ها اجرا می شود و آخرین کلاسی می باشد که از بین می رود. چنل روی گوشی کاربر برای یکبار ساخته می شود و دفعه بعد نصب override نمی شود. قدم اول در این کلاس ساختن notificationManager می باشد. برای ساختنش آن را مساوی با getSystemService() قرار می دهیم و NOTIFICATION_SERVICE را به ورودی آن قرار می دهیم. برای اینکه می خواهیم یک NotificationManager برگرداند از NotificationManager کست (cast) می کنیم. خب، قدم بعدی توی این خان ساختن notificationChannel می باشد.برای ساختن، notificationChannel را مساوی NotificationChannel() می گذاریم :-)تابع موردنظر از ما id, name, importance درخواست می کند. id یک چیز یونیکی هستش.به عنوان name اسمی را می دهیم که کاربر در تنظیمات می بیند. به عنوان importance کع عنوان زیادی داریم برای اضافه کردن. برای اضافه کردن از NotificationManager استفاده می کنیم.خب، اگر با من همراه بودید، الان درحال دیدن یک ارور خوبی هستید :-) از منظره لذت ببرید، چون خیلی قرار نیست به مدت طولانی ببینید، چون دلیل این می باشد که notificationChannel از ما درخواست این را دارد که یک شرطی را برایش اضافه کنیم. با فشردن کلید های Alt + Enter و انتخاب گزینه دوم را انتخاب کنید. شرط را انتخاب کنید و به بالا انتقال دهید و دو شی که ساختیم را به داخل پرانتز های شرط انتقال می دهیم. این شرط از کرش کردن برنامه جلوگیری می کند. در واقع ورژن گوشی کاربر را بررسی می کند.برای اضافه کردن توضیح اضافی، از description استفاده می کنیم.خب، قدم آخر در این خان با اعمال کردن createNotificationChannel() پایان می رسد. در ورودی آن نیز notificationChannel اضافه می کنیم.import android.app.Application import android.app.NotificationChannel import android.app.NotificationManager import android.os.Build class MyApp : Application() { override fun onCreate() { super.onCreate() /* check the api-level / version | is api-level 26 / version more than 8 or not. */ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { // create notification manager val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager // create notification manager val notificationChannel = NotificationChannel(&quotmy_notif&quot, &quotFootball&quot, NotificationManager.IMPORTANCE_HIGH) notificationChannel.description = &quotThis channel shows notifications about Football.&quot // set notificationChannel to notificationManager notificationManager.createNotificationChannel(notificationChannel) } } }خان سوم: AndroidManifest.xmlاضافه کردن:<uses-permission android:name=&quotandroid.permission.POST_NOTIFICATIONS&quot />در بخش application به عنوان name کلاس MyApp را اضافه می کنیم.یک اکتیویتی جدید بسازید به نام MainActivity2 اسم کلاس کاتلین. activity_main2.xml به عنوان xml.تگ activity_amin2 را باز کنید و intentFilter را اضافه کنید.<?xml version=&quot1.0&quot encoding=&quotutf-8&quot?> <manifest xmlns:android=&quothttp://schemas.android.com/apk/res/android&quot xmlns:tools=&quothttp://schemas.android.com/tools&quot> <uses-permission android:name=&quotandroid.permission.POST_NOTIFICATIONS&quot /> <application android:name=&quot.MyApp&quot android:allowBackup=&quottrue&quot android:dataExtractionRules=&quot@xml/data_extraction_rules&quot android:fullBackupContent=&quot@xml/backup_rules&quot android:icon=&quot@mipmap/ic_launcher&quot android:label=&quot@string/app_name&quot android:supportsRtl=&quottrue&quot android:theme=&quot@style/Theme.Notification&quot tools:targetApi=&quot31&quot> <activity android:name=&quot.MainActivity2&quot android:exported=&quottrue&quot> <intent-filter> <action android:name=&quotandroid.intent.action.MAIN&quot /> <category android:name=&quotandroid.intent.category.LAUNCHER&quot /> </intent-filter> </activity> <activity android:name=&quot.MainActivity&quot android:exported=&quotfalse&quot /> </application> </manifest>خان چهارم: MainActivity.ktو بخش کدنویسی(کاتلین) که خودم عاشق این بخشم!!بعد ست کردن clickListener، نوبت به ساختن نوتیفیکیشن می رسد. برای ساختن نوتیفیکیشن نیازمند notificationManager هستیم، زیرا مسئول نشان دادن می باشد.val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager برای ساختن نوتیفیکیشن:val notification = NotificationCompat .Builder(this, &quotmy_notif&quot)از دیزاین پترن Builder() استفاده می کنیم. ontext و channelId را در ورودی اضافه می کنیم.بعد، می توانیم تغییراتی مثل اضافه کردن آیکون و نوشته را اعمال کنیم. در آخر نیز build() را اضفه می کنیم، زیرا نوتیفیکیشن در حالت ساخت می باشد و برای اینکه ساختش رسمی شود، build() را ضافه می کنیم.Anatomy of a Notification(1) آیکون کوچک(Small icon): با setSmallIcon اعمال می شود.(2) اسم اپلیکیشن: سیتسم به صورت خودکار اعمال می کند.(3) سیستم خودش در صورت نیاز اضافه می کند ولی برای اعمال کردن به صورت دستی: setWhen() و برای پنهان کردن: setShowWhen(false) (4) آیکون بزرگ(Large icon): برای اعمال کردن setLargeIcon() این تابع در ورودی خود عکس از نوع bitmap می گیرد و برای اضافه کردنش از BitmapFactory استفاده می کنیم.(5) عنوان محتوا(content title): setContentTitle() برای اعمال کردن.(6) نوشته عنوان(content text): setContentText() برای اعمال کردن.فرمت های عکس در اندروید: file, bitmap, drawable و ریسورس های دیگر که قابلیت اضافه شدن را داشته باشد یا آدرس اینترتی باشد.یک توضیح کوتاه درباره اضافه کردن آیکون بزرگ: برای اضافه کردن فایلی که در فایل drawable شما قرار دارد، از BitmapFactory استفاده می کنیم و از تابع decodeResource() برای اضافه کردن استفاده می کنیم. در پارامتر اول resources استفاده می کنیم تا ریسورس های اندروید را به قولی پاس بدهیم :-) باید بعد ساختن به نوتیفیکیشن منجر پوش کنیمدر پارامتر دوم حالت عادی پاس دادن عکس از فایل drawableسورس کد مربوطه: val notification = NotificationCompat .Builder(this, &quotmy_notif&quot) .setSmallIcon(android.R.drawable.stat_notify_chat) .setLargeIcon(BitmapFactory.decodeResource(resources, R.drawable.ic_launcher_background)) .setContentTitle(&quotMohammad-Reza Fekri&quot) .setContentText(&quotHello. Would like to have a cup of coffee?&quot) .build()notificationخب، ما می دانیم که MainActivity2 قرار است اول نشان داده شود. ما می خواهیم با استفاده intent وقتی روی نوتیفیکیشن کلیک شد بیاید به MainActivity. پس برای همین intent تعریف می کنیم. ما می خواهیم intent مارا اندروید پر کند، پس برای همین از pendingIntent استفاده می کنیم.کد های زیر را به بالای کلیک لیستنر ادد می کنیم:val intent = Intent(this, MainActivity::class.java) intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK.or(Intent.FLAG_ACTIVITY_CLEAR_TASK) val pendingIntent = PendingIntent.getActivity(this, 12, intent, 0)توضیح intent: از هر جایی که هست به MainActivity بر گردد و فلگ اینتنت را خالی می کنیم (به قولی). تازه سازی صفحه. ما می خواهیم در کل فقط به MainActivity دسترسی داشته باشیم و وقتی روی نوتیفیکیشن کلیک شد به MainActivity برود. (شما می توانید تغییر دهید)توضیح pendingIntent: برای کانتکست this پاس می دهیم. برای کد درخواستی نیز یک عدد تصادفی اضافه می کنیم. بخش سوم نیز یک فلگ از ما درخواست می کند که ما قرار نیست چیزی اضافه کنیم و برای همین عدد 0 را اضافه می کنیم.برای اعمال کردن تغییرات فوق به نوتیفیکیشن قبل build() : .setContentIntent(pendingIntent)وظیفه نشان دادن نوتیفیکیشن برای NotificationManager می باشد. در آخر نیز روی نوتیفیکیشن منجر تابع notify() صدا می زنیم:notificationManager.notify((10..1000).random(), notification)من خواستم که اعداد از ۱۰ تا ۱۰۰۰ به طور رندوم ساخته شوند تا نوتیفیکیشن های بدون وابستگی ساخته شود.خب، اگر چیزی اجرا کنید فکر نکنم چیز جالبی ببینید. پس بیاید بریم برای کامل کردن MainActivity2 :-)styles of notificationخان چهارم: activity_main2.xml من می خواهم در این اکتیویتی به سه تا از استایل های نوتیفیکیشن بپردازم.استایل هایی که قرار است بپردازیم: big picture style, big text style, inbox styleبه ویو خاصی نیاز ندارم. چون قرار است به سه نوع استایل ها بپردازیم من به سه تا باتن (button) نیاز دارم.دیزاین ما جوری خواهد بود که سه تا باتن(button) در وسط خواهند بود و زیر هم. از ConstraintL استفاده می کنیم.<?xml version=&quot1.0&quot encoding=&quotutf-8&quot?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android=&quothttp://schemas.android.com/apk/res/android&quot xmlns:app=&quothttp://schemas.android.com/apk/res-auto&quot xmlns:tools=&quothttp://schemas.android.com/tools&quot android:layout_width=&quotmatch_parent&quot android:layout_height=&quotmatch_parent&quot tools:context=&quot.MainActivity2&quot> <Button android:id=&quot@+id/btn1&quot android:layout_width=&quotwrap_content&quot android:layout_height=&quotwrap_content&quot android:text=&quotBig picture style&quot app:layout_constraintBottom_toTopOf=&quot@+id/btn2&quot app:layout_constraintEnd_toEndOf=&quotparent&quot app:layout_constraintStart_toStartOf=&quotparent&quot app:layout_constraintTop_toTopOf=&quotparent&quot app:layout_constraintVertical_chainStyle=&quotpacked&quot /> <Button android:id=&quot@+id/btn2&quot android:layout_width=&quotwrap_content&quot android:layout_height=&quotwrap_content&quot android:text=&quotBig text style&quot app:layout_constraintBottom_toTopOf=&quot@+id/btn3&quot app:layout_constraintEnd_toEndOf=&quotparent&quot app:layout_constraintStart_toStartOf=&quotparent&quot app:layout_constraintTop_toBottomOf=&quot@+id/btn1&quot /> <Button android:id=&quot@+id/btn3&quot android:layout_width=&quotwrap_content&quot android:layout_height=&quotwrap_content&quot android:text=&quotInbox style&quot app:layout_constraintBottom_toBottomOf=&quotparent&quot app:layout_constraintEnd_toEndOf=&quotparent&quot app:layout_constraintStart_toStartOf=&quotparent&quot app:layout_constraintTop_toBottomOf=&quot@+id/btn2&quot /> </androidx.constraintlayout.widget.ConstraintLayout>با تن اول: big picture imageباتن دوم: big text styleبا تن سوم: inbox styleخان چهارم: MainActivity2خب، خب، رسیدیم به خان آخر، دمت گرم که تا اینجا اومدی :-) بیا بریم ادامه ش :-)قدم اول: ساختن instance ها و شیٔ های مورد نیاز:پس اول از شیٔ notificationManager شروع می کنیم. شیٔ که مورد نظر ما از نوع NotificationManagerخواهد بود و منتظر ما خواهد بود تا پر شود، پس lateinit var خواهد بود. قبل onCreate() تعریف می کنیم تا در کل اکتیویتی دسترسی داشته باشیم.و ما به pendingIntent برای اتصال به اکتیویتی (وقتی به نوتیفیکیشن کلیک شد به MainActivity برود)، این را نیز lateinit var تعریف می کنیم. در داخل تابع onCreate() اینتنتی که در MainActivity ساخته ایم را تکرار می کنیم(هدف از intent برگشت به MainActivity است):val intent = Intent(this, MainActivity::class.java)برای پر کردن pendingIntent که منتظر ما هست، مثل MainActivity پر می کنیم:pendingIntent = PendingIntent.getActivity(this, 12, intent, 0)خب، نوتیفیکیشن را نیز مانند MainActivity درست می کنیم ولی با این تفاوت که از buil() استفاده نمی کنیم چون برای اعمال کردن استایل استفاده خواهیم کرد:val notification = NotificationCompat .Builder(this, &quotmy_notif&quot) .setSmallIcon(android.R.drawable.stat_notify_chat) .setLargeIcon( BitmapFactory.decodeResource( resources, R.drawable.img_android ) ) .setContentTitle(&quotMohammad-Reza Fekri&quot) .setContentText(&quotHello. Would like to have a cup of coffee?&quot) .setContentIntent(pendingIntent)قدم دوم:‌ اعمال کردن onClickListener برا باتن ها و استایل ها:binding.btn1.setOnClickListener { intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK.or(Intent.FLAG_ACTIVITY_CLEAR_TASK) notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager val notificationWithBigPicStyle = notification.setStyle( NotificationCompat.BigPictureStyle() .bigPicture( BitmapFactory.decodeResource( resources, R.drawable.img_humanity ) ) ).build() notificationManager.notify((10..1000).random(), notificationWithBigPicStyle) }توضیح notificationWithBigPicStyle: به نوتیفیکیشنی که گذاشتیم در حالت build بماند setStyle() را اضافه می کنیم. از NotificationCompat استفاده می کنیم و از BigPictureStyle() استفاده می کنیم.این استایل، تابعی به نام bigPicture() دارد و عکس را از نوع Bitmap قبول می کند. بعد از اضافه کردن عکس مورد نظر نوتیفیکیشن را بیلد می کنیم و به notificationManager که وظیفه اش نشان دادن می باشد پاس میدیم :-)binding.btn2.setOnClickListener { intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK.or(Intent.FLAG_ACTIVITY_CLEAR_TASK) notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager val notificationBigTxtStyle = notification.setStyle( NotificationCompat.BigTextStyle().bigText( &quotHey you. How are you doing? Hope ur doing well.\n&quot + &quotCan we have a meeting about the design of the Application?&quot + &quot I think we need to make change. So, this is my opinion about the design.\n&quot + &quotOh my god... , look at me.. I'm really crazy, because this text is for testing my application new-option.\n&quot + &quotI'm actually talkative. yes. I think I'm so cool. handsome..., clever... .\n&quot + &quotIn a couple of days, I'm trying hard to make myself better, and update myself. I meant that I'm trying to make myself cool.\n&quot + &quotOf course, it's not important that I'm cool or something like this. It's important that I'm trying and going on.&quot ) ).build() notificationManager.notify((10..1000).random(), notificationBigTxtStyle) }اولا، به نوشته ها دقتی نکنید? برای کابردی بودن استایل ی چیزایی نوشتم.این استایل اعمال شده به باتن دوم مثل استایل قبلی می باشد فقط با این تفاوت که به جای عکس نوشته نشان می دهد. همچنین از نظر کدنویسی تنها این تفاوت را دارد که از BigTextStyle().bigText() استفاده شده است.binding.btn3.setOnClickListener { intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK.or(Intent.FLAG_ACTIVITY_CLEAR_TASK) notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager val notificationInboxTxtStyle = notification.setStyle( NotificationCompat.InboxStyle() .addLine(&quotDo you wanna seen?&quot) .addLine(&quotWhy don't you seen?&quot) .addLine(&quotWhat's the cause?&quot) .addLine(&quotCome on...&quot) ).build() notificationManager.notify((10..1000).random(), notificationInboxTxtStyle) }با این حال به این نتیجه می رسیم که چگونه می شود به یک نوتیفیکیشن استایل اعمال کرد.اینجا هم از InboxStyle() استفاده می کنیم. InboxStyle() به ما این توانایی را می دهد تا نوشته های زیادی رو با توجه به نیاز اضافه کنیم(و همچنین به نوع عملکرد خودش)در آخر از شما متشکرم که تا اینجا اومدین. لایک و کامنت یادتون نره. امیدوارم مفید بوده باشه برای شما :-)لینک گیتهاب پروژه:‌ notification-androidلینک سایت اصلی: Notification Overviews