سلام! من محمدرضا فکری هستم، در این نوشته قصد دارم با شما به ساختار نوتیفیکیشن و استایل های آن در اندروید بپردازیم.
برای مثال، شما دارین با گوشی تون کار می کنید و یک نوتیفیکیشن (معادل انگلیسی: اطلاع، آگاهسازی و ...) از طرف پیام رسانی که ازش استفاده می کنید دریافت می کنید و پیامی که فرستاده شده را در بخش تولبار (Toolbar) نشان می دهد یا روی صفحه برای لحظه ای می آید. معمولا نوع نشان دادن مربوط به بخش نوع پیام و کدنویسی بستگی دارد. نوتیفیکیشن یکی از سرویس های اندروید می باشد.
برای ساختن نوتیفیکیشن باید از ۶ خان بگذریم :-)
شامل:
هدف از این اپلیکیشن آشنایی و کار کردن با نوتیفیکیشن می باشد، پس به یک طراحی ساده نیاز داریم. فقط یک باتن (Button) برای نشان دادن نوتیفیکیشن!
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <Button android:id="@+id/btn_show" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Show notif" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>
چنل چیه؟ و چرا؟ قبل 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("my_notif", "Football", NotificationManager.IMPORTANCE_HIGH) notificationChannel.description = "This channel shows notifications about Football." // set notificationChannel to notificationManager notificationManager.createNotificationChannel(notificationChannel) } } }
اضافه کردن:
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
در بخش application به عنوان name کلاس MyApp را اضافه می کنیم.
یک اکتیویتی جدید بسازید به نام MainActivity2 اسم کلاس کاتلین. activity_main2.xml به عنوان xml.
تگ activity_amin2 را باز کنید و intentFilter را اضافه کنید.
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <uses-permission android:name="android.permission.POST_NOTIFICATIONS" /> <application android:name=".MyApp" android:allowBackup="true" android:dataExtractionRules="@xml/data_extraction_rules" android:fullBackupContent="@xml/backup_rules" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/Theme.Notification" tools:targetApi="31"> <activity android:name=".MainActivity2" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".MainActivity" android:exported="false" /> </application> </manifest>
و بخش کدنویسی(کاتلین) که خودم عاشق این بخشم!!
بعد ست کردن clickListener، نوبت به ساختن نوتیفیکیشن می رسد. برای ساختن نوتیفیکیشن نیازمند notificationManager هستیم، زیرا مسئول نشان دادن می باشد.
val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
برای ساختن نوتیفیکیشن:
val notification = NotificationCompat .Builder(this, "my_notif")
از دیزاین پترن Builder() استفاده می کنیم. ontext و channelId را در ورودی اضافه می کنیم.
بعد، می توانیم تغییراتی مثل اضافه کردن آیکون و نوشته را اعمال کنیم. در آخر نیز build() را اضفه می کنیم، زیرا نوتیفیکیشن در حالت ساخت می باشد و برای اینکه ساختش رسمی شود، build() را ضافه می کنیم.
فرمت های عکس در اندروید: file, bitmap, drawable و ریسورس های دیگر که قابلیت اضافه شدن را داشته باشد یا آدرس اینترتی باشد.
یک توضیح کوتاه درباره اضافه کردن آیکون بزرگ: برای اضافه کردن فایلی که در فایل drawable شما قرار دارد، از BitmapFactory استفاده می کنیم و از تابع decodeResource() برای اضافه کردن استفاده می کنیم. در پارامتر اول resources استفاده می کنیم تا ریسورس های اندروید را به قولی پاس بدهیم :-) باید بعد ساختن به نوتیفیکیشن منجر پوش کنیم
در پارامتر دوم حالت عادی پاس دادن عکس از فایل drawable
سورس کد مربوطه:
val notification = NotificationCompat .Builder(this, "my_notif") .setSmallIcon(android.R.drawable.stat_notify_chat) .setLargeIcon(BitmapFactory.decodeResource(resources, R.drawable.ic_launcher_background)) .setContentTitle("Mohammad-Reza Fekri") .setContentText("Hello. Would like to have a cup of coffee?") .build()
خب، ما می دانیم که 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 :-)
من می خواهم در این اکتیویتی به سه تا از استایل های نوتیفیکیشن بپردازم.
استایل هایی که قرار است بپردازیم: big picture style, big text style, inbox style
به ویو خاصی نیاز ندارم. چون قرار است به سه نوع استایل ها بپردازیم من به سه تا باتن (button) نیاز دارم.
دیزاین ما جوری خواهد بود که سه تا باتن(button) در وسط خواهند بود و زیر هم. از ConstraintL استفاده می کنیم.
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity2"> <Button android:id="@+id/btn1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Big picture style" app:layout_constraintBottom_toTopOf="@+id/btn2" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_chainStyle="packed" /> <Button android:id="@+id/btn2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Big text style" app:layout_constraintBottom_toTopOf="@+id/btn3" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/btn1" /> <Button android:id="@+id/btn3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Inbox style" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/btn2" /> </androidx.constraintlayout.widget.ConstraintLayout>
با تن اول: big picture image
باتن دوم: big text style
با تن سوم: inbox style
خب، خب، رسیدیم به خان آخر، دمت گرم که تا اینجا اومدی :-) بیا بریم ادامه ش :-)
قدم اول: ساختن 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, "my_notif") .setSmallIcon(android.R.drawable.stat_notify_chat) .setLargeIcon( BitmapFactory.decodeResource( resources, R.drawable.img_android ) ) .setContentTitle("Mohammad-Reza Fekri") .setContentText("Hello. Would like to have a cup of coffee?") .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( "Hey you. How are you doing? Hope ur doing well.\n" + "Can we have a meeting about the design of the Application?" + " I think we need to make change. So, this is my opinion about the design.\n" + "Oh my god... , look at me.. I'm really crazy, because this text is for testing my application new-option.\n" + "I'm actually talkative. yes. I think I'm so cool. handsome..., clever... .\n" + "In 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" + "Of course, it's not important that I'm cool or something like this. It's important that I'm trying and going on." ) ).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("Do you wanna seen?") .addLine("Why don't you seen?") .addLine("What's the cause?") .addLine("Come on...") ).build() notificationManager.notify((10..1000).random(), notificationInboxTxtStyle) }
با این حال به این نتیجه می رسیم که چگونه می شود به یک نوتیفیکیشن استایل اعمال کرد.
اینجا هم از InboxStyle() استفاده می کنیم. InboxStyle() به ما این توانایی را می دهد تا نوشته های زیادی رو با توجه به نیاز اضافه کنیم(و همچنین به نوع عملکرد خودش)
در آخر از شما متشکرم که تا اینجا اومدین. لایک و کامنت یادتون نره. امیدوارم مفید بوده باشه برای شما :-)
لینک گیتهاب پروژه: notification-android
لینک سایت اصلی: Notification Overviews