? همه چیز در مورد نوتیفیکیشن در اندروید ۸ یا Oreo!

?اینکه پیاده سازی نوتیفیکیشن در اندروید ۸ تغییر کرده و اینکه از این به بعد باید از notification Channle استفاده کنیم رو احتمالا میدونیم اما خود نوتیفیکیشن چنل چیست؟

?چندباری دیدم بعضی از برنامه نویسها نحوه ی پیاده سازیش رو اوکی کردن اما دقیقا نمیدونن چیه.

?البته خودم هم بار اولی که یک اپ سازمانی دست مدیر سازمان که گوشیش اندروید ۸ بود به خاطر همین قضیه فورس کلوز داد فقط سریعا مشکل رو برطرف کردم بدون اینکه دقیقا بدونم چیه داستان ! :))

?دیدم که بلاگ پوشه(blog.pushe.co) خیلی خوب یه توضیح اجمالی نوشته که اینجا همون رو میارم:

?“ در اندروید ۸ به بعد قابلیت جدیدی برای تعریف کانال نوتیفیکیشن در اپلیکیشن ایجاد شده، به این شکل که می‌تونید در برنامه خودتون یک یا چند کانال نوتیفیکیشن تعریف کنید و در زمان ارسال اعلان پیشرفته با وارد کردن Channel-Id آن کانال، اعلان را برای آن کانال خاصی ارسال کنید و کاربرانی که به انتخاب خودشون آن کانال‌ها را فعال گذاشته‌اند آن را دریافت می‌کنند.

مزیت مهم آن این هست که دیگر نیاز نیست کاربر دریافت نوتیفیکیشن برنامه‌ای را بخاطر علاقه نداشتن به دریافت اعلان خاصی غیرفعال کند، درعوض فقط بعضی کانال‌ها را غیرفعال می‌کند و همچنان از یک یا چند کانال دیگر اعلان می‌گیرد.این امکان برای شناسایی سلایق کاربر نیز برای توسعه دهندگان بسیار مفید است.

کاربرد آن برای کاربر به این صورت هست که با کلیک به مدت چند ثانیه بر روی پوش نوتیفیکیشن،اعلانی باز می شود و در آن امکان غیرفعال کردن کانال اعلان رسیده وجود دارد، همچنین با کلیک بر دکمه all categories وارد تنظیمات دسته بندی کانال‌ها شده و آن ها را بر اساس نیاز و علایق خود فعال و یا غیر فعال می‌کند.”

کانال ها ی یک اپلیکیشن در اندروید ۸  که پس از نگاه داشتن دست بر روی یک نوتیفیکیشن نمایش داده می شوند
کانال ها ی یک اپلیکیشن در اندروید ۸ که پس از نگاه داشتن دست بر روی یک نوتیفیکیشن نمایش داده می شوند

در اندروید ۸ یک چیز باحال دیگه هم اضافه شده به badge که و وقتی یک اپلیکیشن نوتیفیکیشنی داشته باشه که شما هنوز نخوندینش یک نقطه میاد روی آیکنش و با زدن روی اون، نوتیفیکیشن ها را بالاش نشون میده مثل عکس زیر:

badge in android 8
badge in android 8



? بریم سراغ نحوه ی تعریف یک نوتیفیکیشن به همراه channel :
قبل از هرچیز notificationManagerCompat و notificationManager رو به صورت سراسری تعریف کنید و در onCreate به صورت زیر مقدار دهی کنید:

 notificationManagerCompat = NotificationManagerCompat.from(this);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
notificationManager=getSystemService(NotificationManager.class);
} 


?حالا میخواهیم یک متد بنویسیم که کارش تعریف channel هست فقط دقت کنید که از اندروید ۸ به بعد برای اولویت بندی نوتیفیکیشن ها دیگه از setpriority استفاده نمیکنیم و اینجا موقع ساختن channel باید بهشون importance بدیم :

         private void createNotificationChannel1 () {   
               if ( Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ) {    
                CharSequence name = "Name of Channel 1";                     
                String description = "desc about Channel 1";    
                int importance = NotificationManager.IMPORTANCE_DEFAULT; 
                NotificationChannel channel = new NotificationChannel(CHANNEL_ID1, name, importance);                    
               channel.setDescription(description); 
               notificationManager.createNotificationChannel(channel);  
                }         
     }

و بعد موقع تعریف یک نوتیفیکیشن کافیه به این صورت عمل کنیم:

createNotificationChannel1();
Notification newMessageNotification = new NotificationCompat.Builder(MainActivity.this, CHANNEL_ID1 )
        .setSmallIcon(R.drawable.ic_launcher_foreground)
        .setContentTitle("Title3")
        .setContentText("Content Text3")
        .build();
notificationManagerCompat.notify(NOTIFICATION_ID, newMessageNotification);

دیگه اینطوری با توجه به شرطی که گذاشتیم برای چک کردن ورژن اندروید ، همیشه میتونیم از این روش استفاده کنیم تا اگه اندروید ۸ به بالاس نوتیفیکیشن با channel ساخته بشه!


? اما نکته ی دیگه ای که شاید یکم گیج کننده باشه راجع به group ها در نوتیفیکیشن هست و باید بدونیم که کلا دو مدل group داریم:

۱)گروه channel های notification که با کلاس NotificationChannelGroup معرفی می شوند.
شما میتونید یک NotificationChannleGroup بسازید! اینطوری وقتی کاربر وارد دستشو روی نوتیفیکیشن نگه میداره تا channle ها رو ببینه اونها رو دسته بندی شده توی گروه های مختلف میبینه!:
مثلا در زیر گروه Timeline برای یک دسته از کانال ها تعریف شده است و سایر نوتیفیکیشن هایی که گروه ندارن توی دسته ی other قرار می گیرند:

channel groups
channel groups


گروه Business و personal ساخته شده اند و آنهایی که گروه ندارند در other نمایش داده شده اند
گروه Business و personal ساخته شده اند و آنهایی که گروه ندارند در other نمایش داده شده اند

برای ساخت یک همچین گروهی کافیه همونجایی که بالا چک میکردیم که اندروید بالای ۸ هست، یه channelgroup بسازیم که بعد موقع ساختن channel بیاییم و به این گروه setgroup ش کنیم :

   if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            notificationManager = getSystemService(NotificationManager.class);
            notificationChannelGroup1 = new NotificationChannelGroup(CHANNEL_GROUP_ID1 , CHANNEL_GROUP_NAME1);
        }


و بعد کافیه به متدی که بالا نوشتیم برای ساخت channel d یک setgroup اضافه کنیم و id گروه رو بهش بدیم:

    private void createNotificationChannel1 () {  
               if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {     
                CharSequence name = "Channel 1";         
                String description = "Channel 1";             
                int importance = NotificationManager.IMPORTANCE_DEFAULT;     
                NotificationChannel channel = new NotificationChannel(CHANNEL_ID1, name, importance);                 
                channel.setDescription(description);      
                channel.setGroup(CHANNEL_GROUP_ID1);            
                notificationManager.createNotificationChannel(channel);         
        }         
    }


۲) نوع گروه دیگری که در نوتیفیکیشن ها داریم مربوط میشه به نشان دادن چند نوتیفیکیشن در یک منوی باز شونده مثل چیزی که در واتس اپ و تلگرام میبینیم:
راجع به این نوع نوتیفیکیشن ها میتونید با کلید واژه هایی مثل group Notification , cluster Notification ,
bundle Notification و یا Expandable Notification جستجو کنید:

bundle notifications
bundle notifications


? قبل از هرچیز باید بدونیم که این گروه هیچ ربطی به NotificationChannleGroup نداره . از اندروید ۷ به بعد، به صورت پیش فرض وقتی بیش از ۴ نوتیفیکیشن از یک اپلیکیشن ظاهر میشه، به صورت خودکار در یک گروه قرار داده می شوند.
وقتی ما یک سری نوتیفیکیشن خاص را می خواهیم در یک گروه قرار بدیم باید هنگام ساختنشون با متد setgroup به همه شون یک groupID یکسان بدیم.

در خود داکیومنت گوگل راجع به نحوه ی ساخت این گروه ها توضیحی داده شده است که آنطور که گفته شده عمل نمی کند! این موضوع رو بعد از اینکه خودم تست کردم به دوستم هم گفتم و اون هم همین نتیجه رو گرفت و در نهایت دیدیم که برنامه نویس Trello هم توی بلاگش به این موضوع اشاره کرده.

خلاصه اینکه در نهایت روشی که کارامد بود به این صورت است:

ببینید شما اینطوری به قضیه نگاه کنید که گروه خودش یک نوتیفیکیشن هست که یک متد اضافه تر دارد به نام :

.setGroupSummary(true)
.setGroup(GROUP_ID_1) 

و دقت کنید که setgroup رو باید به همه ی نوتیفیکیشن هایی که میخواهید عضو این گروه باشند بدید و به همه شون هم یک groupID یکسان بدید.

پس ما میاییم و builder یک نوتیفیکیشن رو مخصوص یک گروه به صورت زیر تعریف میکنیم :

Notification groupBuilder1 =     
    new NotificationCompat.Builder(this , CHANNEL_ID1)     
            .setSmallIcon(R.drawable.ic_launcher_foreground)       
           .setContentTitle("My App Group1")                 
           .setContentText("Group Title1")             
           .setGroupSummary(true)            
          .setGroup(GROUP_ID_1)            
          .setStyle(new NotificationCompat.BigTextStyle().bigText("Big Text1")).build();

همانطور که میدونید نوتیفیکیشن ها زمانی ساخته می شوند که متد notify از Notification manager صدا زده شود و همانطور که میبینید اینجا ما فقط builder یک نوتیفیکیشن رو تعریف کردیم ، اما پس کی باید بسازیمش؟

هر وقت که میخواهید نوتیفیکیشن بسازید این رو قبلش notify کنید تا مرتب ساخته بشه!

خب اینطوری باعث نمیشه کلی نوتیفیکیشن ساخته بشه؟ نه! و اتفاقا نیازه! چون با هر بار ساختن نوتیفیکیشن مربوط به گروه اون رو آپدیت میکنید! و دوباره روی خودش ساخته میشه و توی دلش نوتیفیکیشن های مربوط به گروه خودشو نشون میده!

فقط باید به چند نکته که البته بدیهی هم هستند دقت کنید:

۱- همیشه id گروهی که ساختید و id ای که به setgroup نوتیفیکیشن میدید یکسان باشند.
۲-گروه و نوتیفیکیشن در یک channel باید باشند ، پس channeID هر دو باید یکسان باشد.

حالا فرض کنید میخوایم یک نوتیفیکیشن بسازیم که توی گروه بالا باشه:

createNotificationChannel1();  
Notification newMessageNotification = new NotificationCompat.Builder(MainActivity.this, CHANNEL_ID1)       
 .setSmallIcon(R.drawable.ic_launcher_foreground)         
.setContentTitle("Title4")         
.setContentText("Content Text4")         
.setGroup(GROUP_ID_1)         
 .build(); 
 notificationManagerCompat.notify(GroupID1, groupBuilder1);    notificationManagerCompat.notify(notificationID1, newMessageNotification); 

در نهایت از دوستم حیدر صاکی که ازش خواستم که این حالات رو تست کنه تا سریعتر به نتیجه برسیم تشکر میکنم.