1 package com.google.android.car.kitchensink.notification; 2 3 import android.annotation.Nullable; 4 import android.app.Notification; 5 import android.app.NotificationChannel; 6 import android.app.NotificationManager; 7 import android.app.PendingIntent; 8 import android.content.Context; 9 import android.content.Intent; 10 import android.graphics.drawable.Icon; 11 import android.media.session.MediaSession; 12 import android.os.Bundle; 13 import android.os.Handler; 14 import android.view.LayoutInflater; 15 import android.view.View; 16 import android.view.ViewGroup; 17 import android.widget.NumberPicker; 18 19 import androidx.core.app.NotificationCompat; 20 import androidx.core.app.NotificationCompat.Action; 21 import androidx.core.app.NotificationCompat.MessagingStyle; 22 import androidx.core.app.Person; 23 import androidx.core.app.RemoteInput; 24 import androidx.core.graphics.drawable.IconCompat; 25 import androidx.fragment.app.Fragment; 26 27 import com.google.android.car.kitchensink.KitchenSinkActivity; 28 import com.google.android.car.kitchensink.R; 29 30 import java.util.ArrayList; 31 import java.util.HashMap; 32 import java.util.List; 33 34 /** 35 * Test fragment that can send all sorts of notifications. 36 */ 37 public class NotificationFragment extends Fragment { 38 private static final String IMPORTANCE_HIGH_ID = "importance_high"; 39 private static final String IMPORTANCE_HIGH_NO_SOUND_ID = "importance_high_no_sound"; 40 private static final String IMPORTANCE_DEFAULT_ID = "importance_default"; 41 private static final String IMPORTANCE_LOW_ID = "importance_low"; 42 private static final String IMPORTANCE_MIN_ID = "importance_min"; 43 private static final String IMPORTANCE_NONE_ID = "importance_none"; 44 private int mCurrentNotificationId; 45 private int mCurrentGroupNotificationCount; 46 private NotificationManager mManager; 47 private Context mContext; 48 private Handler mHandler = new Handler(); 49 private int mCount = 0; 50 private HashMap<Integer, Runnable> mUpdateRunnables = new HashMap<>(); 51 52 @Override onCreate(Bundle savedInstanceState)53 public void onCreate(Bundle savedInstanceState) { 54 super.onCreate(savedInstanceState); 55 mContext = getActivity(); 56 mManager = 57 (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE); 58 59 mManager.createNotificationChannel(new NotificationChannel( 60 IMPORTANCE_HIGH_ID, "Importance High", NotificationManager.IMPORTANCE_HIGH)); 61 62 NotificationChannel noSoundChannel = new NotificationChannel( 63 IMPORTANCE_HIGH_NO_SOUND_ID, "No sound", NotificationManager.IMPORTANCE_HIGH); 64 noSoundChannel.setSound(null, null); 65 mManager.createNotificationChannel(noSoundChannel); 66 67 mManager.createNotificationChannel(new NotificationChannel( 68 IMPORTANCE_DEFAULT_ID, 69 "Importance Default", 70 NotificationManager.IMPORTANCE_DEFAULT)); 71 72 mManager.createNotificationChannel(new NotificationChannel( 73 IMPORTANCE_LOW_ID, "Importance Low", NotificationManager.IMPORTANCE_LOW)); 74 75 mManager.createNotificationChannel(new NotificationChannel( 76 IMPORTANCE_MIN_ID, "Importance Min", NotificationManager.IMPORTANCE_MIN)); 77 78 mManager.createNotificationChannel(new NotificationChannel( 79 IMPORTANCE_NONE_ID, "Importance None", NotificationManager.IMPORTANCE_NONE)); 80 } 81 82 @Override onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState)83 public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, 84 @Nullable Bundle savedInstanceState) { 85 View view = inflater.inflate(R.layout.notification_fragment, container, false); 86 87 initCancelAllButton(view); 88 89 initCarCategoriesButton(view); 90 91 initImportanceHighBotton(view); 92 initImportanceDefaultButton(view); 93 initImportanceLowButton(view); 94 initImportanceMinButton(view); 95 96 initOngoingButton(view); 97 initMessagingStyleButtonForDiffPerson(view); 98 initMessagingStyleButtonForSamePerson(view); 99 initMessagingStyleButtonForLongMessageSamePerson(view); 100 initMessagingStyleButtonForMessageSameGroup(view); 101 initMessagingStyleButtonWithMuteAction(view); 102 initTestMessagesButton(view); 103 initProgressButton(view); 104 initNavigationButton(view); 105 initMediaButton(view); 106 initCallButton(view); 107 initCustomGroupSummaryButton(view); 108 initGroupWithoutSummaryButton(view); 109 initCustomizableMessageButton(view); 110 111 return view; 112 } 113 createServiceIntent(int notificationId, String action)114 private PendingIntent createServiceIntent(int notificationId, String action) { 115 Intent intent = new Intent(mContext, KitchenSinkActivity.class).setAction(action); 116 117 return PendingIntent.getForegroundService(mContext, notificationId, intent, 118 PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE); 119 } 120 initCancelAllButton(View view)121 private void initCancelAllButton(View view) { 122 view.findViewById(R.id.cancel_all_button).setOnClickListener(v -> { 123 for (Runnable runnable : mUpdateRunnables.values()) { 124 mHandler.removeCallbacks(runnable); 125 } 126 mUpdateRunnables.clear(); 127 mManager.cancelAll(); 128 }); 129 } 130 initCarCategoriesButton(View view)131 private void initCarCategoriesButton(View view) { 132 view.findViewById(R.id.category_car_emergency_button).setOnClickListener(v -> { 133 Notification notification = new Notification 134 .Builder(mContext, IMPORTANCE_HIGH_ID) 135 .setContentTitle("Car Emergency") 136 .setContentText("Shows heads-up; Shows on top of the list; Does not group") 137 .setCategory(Notification.CATEGORY_CAR_EMERGENCY) 138 .setSmallIcon(R.drawable.car_ic_mode) 139 .build(); 140 mManager.notify(mCurrentNotificationId++, notification); 141 }); 142 143 view.findViewById(R.id.category_car_warning_button).setOnClickListener(v -> { 144 145 Notification notification = new Notification 146 .Builder(mContext, IMPORTANCE_HIGH_ID) 147 .setContentTitle("Car Warning") 148 .setContentText( 149 "Shows heads-up; Shows on top of the list but below Car Emergency; " 150 + "Does not group") 151 .setCategory(Notification.CATEGORY_CAR_WARNING) 152 .setColor(mContext.getColor(android.R.color.holo_orange_dark)) 153 .setColorized(true) 154 .setSmallIcon(R.drawable.car_ic_mode) 155 .build(); 156 mManager.notify(mCurrentNotificationId++, notification); 157 }); 158 159 view.findViewById(R.id.category_car_info_button).setOnClickListener(v -> { 160 Notification notification = new Notification 161 .Builder(mContext, IMPORTANCE_DEFAULT_ID) 162 .setContentTitle("Car information") 163 .setContentText("Doesn't show heads-up; Importance Default; Groups") 164 .setCategory(Notification.CATEGORY_CAR_INFORMATION) 165 .setColor(mContext.getColor(android.R.color.holo_orange_light)) 166 .setColorized(true) 167 .setSmallIcon(R.drawable.car_ic_mode) 168 .build(); 169 mManager.notify(mCurrentNotificationId++, notification); 170 }); 171 172 } 173 initImportanceHighBotton(View view)174 private void initImportanceHighBotton(View view) { 175 Intent intent = new Intent(mContext, KitchenSinkActivity.class); 176 PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, intent, 177 PendingIntent.FLAG_IMMUTABLE); 178 179 Notification notification1 = new Notification 180 .Builder(mContext, IMPORTANCE_HIGH_ID) 181 .setContentTitle("Importance High: Shows as a heads-up") 182 .setContentText( 183 "Each click generates a new notification. And some " 184 + "looooooong text. " 185 + "Loooooooooooooooooooooong. " 186 + "Loooooooooooooooooooooooooooooooooooooooooooooooooong.") 187 .setSmallIcon(R.drawable.car_ic_mode) 188 .addAction( 189 new Notification.Action.Builder( 190 null, "Long Action (no-op)", pendingIntent).build()) 191 .addAction( 192 new Notification.Action.Builder( 193 null, "Action (no-op)", pendingIntent).build()) 194 .addAction( 195 new Notification.Action.Builder( 196 null, "Long Action (no-op)", pendingIntent).build()) 197 .setColor(mContext.getColor(android.R.color.holo_red_light)) 198 .build(); 199 200 view.findViewById(R.id.importance_high_button).setOnClickListener( 201 v -> mManager.notify(mCurrentNotificationId++, notification1) 202 ); 203 } 204 initImportanceDefaultButton(View view)205 private void initImportanceDefaultButton(View view) { 206 view.findViewById(R.id.importance_default_button).setOnClickListener(v -> { 207 Notification notification = new Notification 208 .Builder(mContext, IMPORTANCE_DEFAULT_ID) 209 .setContentTitle("No heads-up; Importance Default; Groups") 210 .setSmallIcon(R.drawable.car_ic_mode) 211 .build(); 212 mManager.notify(mCurrentNotificationId++, notification); 213 }); 214 } 215 initImportanceLowButton(View view)216 private void initImportanceLowButton(View view) { 217 view.findViewById(R.id.importance_low_button).setOnClickListener(v -> { 218 219 Notification notification = new Notification.Builder(mContext, IMPORTANCE_LOW_ID) 220 .setContentTitle("Importance Low") 221 .setContentText("No heads-up; Below Importance Default; Groups") 222 .setSmallIcon(R.drawable.car_ic_mode) 223 .build(); 224 mManager.notify(mCurrentNotificationId++, notification); 225 }); 226 } 227 initImportanceMinButton(View view)228 private void initImportanceMinButton(View view) { 229 view.findViewById(R.id.importance_min_button).setOnClickListener(v -> { 230 231 Notification notification = new Notification.Builder(mContext, IMPORTANCE_MIN_ID) 232 .setContentTitle("Importance Min") 233 .setContentText("No heads-up; Below Importance Low; Groups") 234 .setSmallIcon(R.drawable.car_ic_mode) 235 .build(); 236 mManager.notify(mCurrentNotificationId++, notification); 237 }); 238 } 239 initOngoingButton(View view)240 private void initOngoingButton(View view) { 241 view.findViewById(R.id.ongoing_button).setOnClickListener(v -> { 242 243 Notification notification = new Notification 244 .Builder(mContext, IMPORTANCE_DEFAULT_ID) 245 .setContentTitle("Persistent/Ongoing Notification") 246 .setContentText("Cannot be dismissed; No heads-up; Importance default; Groups") 247 .setSmallIcon(R.drawable.car_ic_mode) 248 .setOngoing(true) 249 .build(); 250 mManager.notify(mCurrentNotificationId++, notification); 251 }); 252 } 253 initCustomizableMessageButton(View view)254 private void initCustomizableMessageButton(View view) { 255 NumberPicker messagesPicker = view.findViewById(R.id.number_messages); 256 messagesPicker.setMinValue(1); 257 messagesPicker.setMaxValue(25); 258 messagesPicker.setWrapSelectorWheel(true); 259 NumberPicker peoplePicker = view.findViewById(R.id.number_people); 260 peoplePicker.setMinValue(1); 261 peoplePicker.setMaxValue(25); 262 peoplePicker.setWrapSelectorWheel(true); 263 264 view.findViewById(R.id.customizable_message_button).setOnClickListener(v -> { 265 int id = mCurrentNotificationId++; 266 267 int numPeople = peoplePicker.getValue(); 268 int numMessages = messagesPicker.getValue(); 269 270 PendingIntent replyIntent = createServiceIntent(id, "reply"); 271 PendingIntent markAsReadIntent = createServiceIntent(id, "read"); 272 273 List<Person> personList = new ArrayList<>(); 274 275 for (int i = 1; i <= numPeople; i++) { 276 personList.add(new Person.Builder() 277 .setName("Person " + i) 278 .setIcon(IconCompat.createWithResource(v.getContext(), 279 i % 2 == 1 ? R.drawable.avatar1 : R.drawable.avatar2)) 280 .build()); 281 } 282 283 MessagingStyle messagingStyle = 284 new MessagingStyle(personList.get(0)) 285 .setConversationTitle("Customizable Group chat: " + id); 286 if (personList.size() > 1) { 287 messagingStyle.setGroupConversation(true); 288 } 289 290 int messageNumber = 1; 291 for (int i = 0; i < numMessages; i++) { 292 int personNum = i % numPeople; 293 if (personNum == numPeople - 1) { 294 messageNumber++; 295 } 296 Person person = personList.get(personNum); 297 String messageText = person.getName() + "'s " + messageNumber + " message"; 298 messagingStyle.addMessage( 299 new MessagingStyle.Message( 300 messageText, 301 System.currentTimeMillis(), 302 person)); 303 } 304 305 NotificationCompat.Builder notification = new NotificationCompat 306 .Builder(mContext, IMPORTANCE_HIGH_ID) 307 .setContentTitle("Customizable Group chat (Title)") 308 .setContentText("Customizable Group chat (Text)") 309 .setShowWhen(true) 310 .setCategory(Notification.CATEGORY_MESSAGE) 311 .setSmallIcon(R.drawable.car_ic_mode) 312 .setStyle(messagingStyle) 313 .setAutoCancel(true) 314 .setColor(mContext.getColor(android.R.color.holo_green_light)) 315 .addAction( 316 new Action.Builder(R.drawable.ic_check_box, "read", markAsReadIntent) 317 .setSemanticAction(Action.SEMANTIC_ACTION_MARK_AS_READ) 318 .setShowsUserInterface(false) 319 .build()) 320 .addAction( 321 new Action.Builder(R.drawable.ic_check_box, "reply", replyIntent) 322 .setSemanticAction(Action.SEMANTIC_ACTION_REPLY) 323 .setShowsUserInterface(false) 324 .addRemoteInput(new RemoteInput.Builder("input").build()) 325 .build()); 326 327 mManager.notify(id, notification.build()); 328 }); 329 } 330 initMessagingStyleButtonForDiffPerson(View view)331 private void initMessagingStyleButtonForDiffPerson(View view) { 332 view.findViewById(R.id.category_message_diff_person_button).setOnClickListener(v -> { 333 int id = mCurrentNotificationId++; 334 335 PendingIntent replyIntent = createServiceIntent(id, "reply"); 336 PendingIntent markAsReadIntent = createServiceIntent(id, "read"); 337 338 Person person1 = new Person.Builder() 339 .setName("Person " + id) 340 .setIcon(IconCompat.createWithResource(v.getContext(), R.drawable.avatar1)) 341 .build(); 342 Person person2 = new Person.Builder() 343 .setName("Person " + id + 1) 344 .setIcon(IconCompat.createWithResource(v.getContext(), R.drawable.android_logo)) 345 .build(); 346 Person person3 = new Person.Builder() 347 .setName("Person " + id + 2) 348 .setIcon(IconCompat.createWithResource(v.getContext(), R.drawable.avatar2)) 349 .build(); 350 MessagingStyle messagingStyle = 351 new MessagingStyle(person3) 352 .setConversationTitle("Group chat") 353 .addMessage( 354 new MessagingStyle.Message( 355 person1.getName() + "'s message", 356 System.currentTimeMillis(), 357 person1)) 358 .addMessage( 359 new MessagingStyle.Message( 360 person2.getName() + "'s message", 361 System.currentTimeMillis(), 362 person2)) 363 .addMessage( 364 new MessagingStyle.Message( 365 person3.getName() + "'s message; " 366 + "Each click generates a new" 367 + "notification. And some looooooong text. " 368 + "Loooooooooooooooooooooong. " 369 + "Loooooooooooooooooooooooooong." 370 + "Long long long long text.", 371 System.currentTimeMillis(), 372 person3)); 373 374 NotificationCompat.Builder notification = new NotificationCompat 375 .Builder(mContext, IMPORTANCE_HIGH_ID) 376 .setContentTitle("Jane, John, Joe") 377 .setContentText("Group chat") 378 .setShowWhen(true) 379 .setCategory(Notification.CATEGORY_MESSAGE) 380 .setSmallIcon(R.drawable.car_ic_mode) 381 .setStyle(messagingStyle) 382 .setAutoCancel(true) 383 .setColor(mContext.getColor(android.R.color.holo_green_light)) 384 .addAction( 385 new Action.Builder(R.drawable.ic_check_box, "read", markAsReadIntent) 386 .setSemanticAction(Action.SEMANTIC_ACTION_MARK_AS_READ) 387 .setShowsUserInterface(false) 388 .build()) 389 .addAction( 390 new Action.Builder(R.drawable.ic_check_box, "reply", replyIntent) 391 .setSemanticAction(Action.SEMANTIC_ACTION_REPLY) 392 .setShowsUserInterface(false) 393 .addRemoteInput(new RemoteInput.Builder("input").build()) 394 .build()); 395 396 mManager.notify(id, notification.build()); 397 }); 398 } 399 initMessagingStyleButtonForMessageSameGroup(View view)400 private void initMessagingStyleButtonForMessageSameGroup(View view) { 401 int numOfPeople = 3; 402 Person user = new Person.Builder() 403 .setName("User") 404 .setIcon(IconCompat.createWithResource(view.getContext(), R.drawable.avatar1)) 405 .build(); 406 407 MessagingStyle messagingStyle = 408 new MessagingStyle(user) 409 .setConversationTitle("Same group chat") 410 .setGroupConversation(true); 411 412 List<Person> personList = new ArrayList<>(); 413 for (int i = 1; i <= numOfPeople; i++) { 414 personList.add(new Person.Builder() 415 .setName("Person " + i) 416 .setIcon(IconCompat.createWithResource(view.getContext(), 417 i % 2 == 1 ? R.drawable.avatar1 : R.drawable.avatar2)) 418 .build()); 419 } 420 421 view.findViewById(R.id.category_message_same_group_button).setOnClickListener(v -> { 422 mCurrentGroupNotificationCount++; 423 PendingIntent replyIntent = createServiceIntent(123456, "reply"); 424 PendingIntent markAsReadIntent = createServiceIntent(123456, "read"); 425 Person person = personList.get(mCurrentGroupNotificationCount % numOfPeople); 426 String messageText = 427 person.getName() + "'s " + mCurrentGroupNotificationCount + " message"; 428 messagingStyle.addMessage( 429 new MessagingStyle.Message(messageText, System.currentTimeMillis(), person)); 430 431 NotificationCompat.Builder notification = new NotificationCompat 432 .Builder(mContext, IMPORTANCE_HIGH_ID) 433 .setContentTitle("Same Group chat (Title)") 434 .setContentText("Same Group chat (Text)") 435 .setShowWhen(true) 436 .setCategory(Notification.CATEGORY_MESSAGE) 437 .setSmallIcon(R.drawable.car_ic_mode) 438 .setStyle(messagingStyle) 439 .setAutoCancel(true) 440 .addAction( 441 new Action.Builder(R.drawable.ic_check_box, "read", markAsReadIntent) 442 .setSemanticAction(Action.SEMANTIC_ACTION_MARK_AS_READ) 443 .setShowsUserInterface(false) 444 .build()) 445 .addAction( 446 new Action.Builder(R.drawable.ic_check_box, "reply", replyIntent) 447 .setSemanticAction(Action.SEMANTIC_ACTION_REPLY) 448 .setShowsUserInterface(false) 449 .addRemoteInput(new RemoteInput.Builder("input").build()) 450 .build()); 451 452 mManager.notify(123456, notification.build()); 453 }); 454 } 455 initMessagingStyleButtonForSamePerson(View view)456 private void initMessagingStyleButtonForSamePerson(View view) { 457 view.findViewById(R.id.category_message_same_person_button).setOnClickListener(v -> { 458 int id = mCurrentNotificationId++; 459 460 PendingIntent replyIntent = createServiceIntent(id, "reply"); 461 PendingIntent markAsReadIntent = createServiceIntent(id, "read"); 462 463 Person person = new Person.Builder().setName("John Doe").build(); 464 MessagingStyle messagingStyle = 465 new MessagingStyle(person).setConversationTitle("Hello!"); 466 NotificationCompat.Builder builder = new NotificationCompat 467 .Builder(mContext, IMPORTANCE_HIGH_ID) 468 .setContentTitle("Message from someone") 469 .setContentText("hi") 470 .setShowWhen(true) 471 .setCategory(Notification.CATEGORY_MESSAGE) 472 .setSmallIcon(R.drawable.car_ic_mode) 473 .setAutoCancel(true) 474 .setColor(mContext.getColor(android.R.color.holo_green_light)) 475 .addAction( 476 new Action.Builder(R.drawable.ic_check_box, "read", markAsReadIntent) 477 .setSemanticAction(Action.SEMANTIC_ACTION_MARK_AS_READ) 478 .setShowsUserInterface(false) 479 .build()) 480 .addAction( 481 new Action.Builder(R.drawable.ic_check_box, "reply", replyIntent) 482 .setSemanticAction(Action.SEMANTIC_ACTION_REPLY) 483 .setShowsUserInterface(false) 484 .addRemoteInput(new RemoteInput.Builder("input").build()) 485 .build()); 486 487 NotificationCompat.Builder updateNotification = 488 builder.setStyle(messagingStyle.addMessage( 489 new MessagingStyle.Message( 490 "Message " + id, 491 System.currentTimeMillis(), 492 person))); 493 mManager.notify(12345, updateNotification.build()); 494 }); 495 } 496 initMessagingStyleButtonForLongMessageSamePerson(View view)497 private void initMessagingStyleButtonForLongMessageSamePerson(View view) { 498 view.findViewById(R.id.category_long_message_same_person_button).setOnClickListener(v -> { 499 int id = mCurrentNotificationId++; 500 501 PendingIntent replyIntent = createServiceIntent(id, "reply"); 502 PendingIntent markAsReadIntent = createServiceIntent(id, "read"); 503 504 505 Person person = new Person.Builder().setName("John Doe").build(); 506 MessagingStyle messagingStyle = 507 new MessagingStyle(person).setConversationTitle("Hello!"); 508 NotificationCompat.Builder builder = new NotificationCompat 509 .Builder(mContext, IMPORTANCE_HIGH_ID) 510 .setContentTitle("Message from someone") 511 .setContentText("hi") 512 .setShowWhen(true) 513 .setCategory(Notification.CATEGORY_MESSAGE) 514 .setSmallIcon(R.drawable.car_ic_mode) 515 .setAutoCancel(true) 516 .setColor(mContext.getColor(android.R.color.holo_green_light)) 517 .addAction( 518 new Action.Builder(R.drawable.ic_check_box, "read", markAsReadIntent) 519 .setSemanticAction(Action.SEMANTIC_ACTION_MARK_AS_READ) 520 .setShowsUserInterface(false) 521 .build()) 522 .addAction( 523 new Action.Builder(R.drawable.ic_check_box, "reply", replyIntent) 524 .setSemanticAction(Action.SEMANTIC_ACTION_REPLY) 525 .setShowsUserInterface(false) 526 .addRemoteInput(new RemoteInput.Builder("input").build()) 527 .build()); 528 529 String messageText = ""; 530 for (int i = 0; i < 100; i++) { 531 messageText += " test"; 532 } 533 534 NotificationCompat.Builder updateNotification = 535 builder.setStyle(messagingStyle.addMessage( 536 new MessagingStyle.Message( 537 id + messageText, 538 System.currentTimeMillis(), 539 person))); 540 mManager.notify(12345, updateNotification.build()); 541 }); 542 } 543 544 initMessagingStyleButtonWithMuteAction(View view)545 private void initMessagingStyleButtonWithMuteAction(View view) { 546 view.findViewById(R.id.category_message_mute_action_button).setOnClickListener(v -> { 547 int id = mCurrentNotificationId++; 548 549 PendingIntent replyIntent = createServiceIntent(id, "reply"); 550 PendingIntent markAsReadIntent = createServiceIntent(id, "read"); 551 PendingIntent muteIntent = createServiceIntent(id, "mute"); 552 553 Person person = new Person.Builder().setName("John Doe").build(); 554 MessagingStyle messagingStyle = 555 new MessagingStyle(person).setConversationTitle("Hello, try muting me!"); 556 NotificationCompat.Builder builder = new NotificationCompat 557 .Builder(mContext, IMPORTANCE_HIGH_ID) 558 .setContentTitle("Message from someone") 559 .setContentText("Muting notification when " 560 + "mute pending intent is provided by posting app") 561 .setShowWhen(true) 562 .setCategory(Notification.CATEGORY_MESSAGE) 563 .setSmallIcon(R.drawable.car_ic_mode) 564 .setAutoCancel(true) 565 .setColor(mContext.getColor(android.R.color.holo_green_light)) 566 .addAction( 567 new Action.Builder(R.drawable.ic_check_box, "read", markAsReadIntent) 568 .setSemanticAction(Action.SEMANTIC_ACTION_MARK_AS_READ) 569 .setShowsUserInterface(false) 570 .build()) 571 .addAction( 572 new Action.Builder(R.drawable.ic_check_box, "mute", muteIntent) 573 .setSemanticAction(Action.SEMANTIC_ACTION_MUTE) 574 .setShowsUserInterface(false) 575 .build()) 576 .addAction( 577 new Action.Builder(R.drawable.ic_check_box, "reply", replyIntent) 578 .setSemanticAction(Action.SEMANTIC_ACTION_REPLY) 579 .setShowsUserInterface(false) 580 .addRemoteInput(new RemoteInput.Builder("input").build()) 581 .build()); 582 583 builder.setStyle(messagingStyle.addMessage( 584 new MessagingStyle.Message( 585 "Message with mute pending intent" + id, 586 System.currentTimeMillis(), 587 person))); 588 mManager.notify(id, builder.build()); 589 }); 590 } 591 initTestMessagesButton(View view)592 private void initTestMessagesButton(View view) { 593 view.findViewById(R.id.test_message_button).setOnClickListener(v -> { 594 int id = mCurrentNotificationId++; 595 596 PendingIntent replyIntent = createServiceIntent(id, "reply"); 597 PendingIntent markAsReadIntent = createServiceIntent(id, "read"); 598 599 Person person = new Person.Builder().setName("John Doe " + id).build(); 600 MessagingStyle messagingStyle = 601 new MessagingStyle(person).setConversationTitle("Hello!"); 602 NotificationCompat.Builder builder = new NotificationCompat 603 .Builder(mContext, IMPORTANCE_HIGH_ID) 604 .setContentTitle("Message from someone") 605 .setContentText("hi") 606 .setShowWhen(true) 607 .setCategory(Notification.CATEGORY_MESSAGE) 608 .setSmallIcon(R.drawable.car_ic_mode) 609 .setAutoCancel(true) 610 .setColor(mContext.getColor(android.R.color.holo_green_light)) 611 .addAction( 612 new Action.Builder(R.drawable.ic_check_box, "read", markAsReadIntent) 613 .setSemanticAction(Action.SEMANTIC_ACTION_MARK_AS_READ) 614 .setShowsUserInterface(false) 615 .build()) 616 .addAction( 617 new Action.Builder(R.drawable.ic_check_box, "reply", replyIntent) 618 .setSemanticAction(Action.SEMANTIC_ACTION_REPLY) 619 .setShowsUserInterface(false) 620 .addRemoteInput(new RemoteInput.Builder("input").build()) 621 .build()); 622 623 Runnable runnable = new Runnable() { 624 int mCount = 1; 625 626 @Override 627 public void run() { 628 NotificationCompat.Builder updateNotification = 629 builder.setStyle(messagingStyle.addMessage( 630 new MessagingStyle.Message( 631 "Message " + mCount++, 632 System.currentTimeMillis(), 633 person))); 634 mManager.notify(id, updateNotification.build()); 635 if (mCount < 5) { 636 mHandler.postDelayed(this, 6000); 637 } 638 } 639 }; 640 mUpdateRunnables.put(id, runnable); 641 mHandler.post(runnable); 642 }); 643 } 644 initProgressButton(View view)645 private void initProgressButton(View view) { 646 view.findViewById(R.id.progress_button).setOnClickListener(v -> { 647 int id = mCurrentNotificationId++; 648 649 Notification notification = new Notification 650 .Builder(mContext, IMPORTANCE_DEFAULT_ID) 651 .setContentTitle("Progress") 652 .setOngoing(true) 653 .setContentText( 654 "Doesn't show heads-up; Importance Default; Groups; Ongoing (cannot " 655 + "be dismissed)") 656 .setProgress(100, 0, false) 657 .setColor(mContext.getColor(android.R.color.holo_purple)) 658 .setContentInfo("0%") 659 .setSmallIcon(R.drawable.car_ic_mode) 660 .build(); 661 mManager.notify(id, notification); 662 663 Runnable runnable = new Runnable() { 664 int mProgress = 0; 665 666 @Override 667 public void run() { 668 Notification updateNotification = new Notification 669 .Builder(mContext, IMPORTANCE_DEFAULT_ID) 670 .setContentTitle("Progress") 671 .setContentText("Doesn't show heads-up; Importance Default; Groups") 672 .setProgress(100, mProgress, false) 673 .setOngoing(true) 674 .setColor(mContext.getColor(android.R.color.holo_purple)) 675 .setContentInfo(mProgress + "%") 676 .setSmallIcon(R.drawable.car_ic_mode) 677 .build(); 678 mManager.notify(id, updateNotification); 679 mProgress += 5; 680 if (mProgress <= 100) { 681 mHandler.postDelayed(this, 1000); 682 } 683 } 684 }; 685 mUpdateRunnables.put(id, runnable); 686 mHandler.post(runnable); 687 }); 688 } 689 initNavigationButton(View view)690 private void initNavigationButton(View view) { 691 view.findViewById(R.id.navigation_button).setOnClickListener(v -> { 692 693 int id1 = mCurrentNotificationId++; 694 Runnable rightTurnRunnable = new Runnable() { 695 int mDistance = 900; 696 697 @Override 698 public void run() { 699 Notification updateNotification = new Notification 700 .Builder(mContext, IMPORTANCE_HIGH_ID) 701 .setCategory("navigation") 702 .setContentTitle("Navigation") 703 .setContentText("Turn right in " + mDistance + " ft") 704 .setColor(mContext.getColor(android.R.color.holo_green_dark)) 705 .setColorized(true) 706 .setSubText(mDistance + " ft") 707 .setSmallIcon(R.drawable.car_ic_mode) 708 .setOnlyAlertOnce(true) 709 .build(); 710 mManager.notify(id1, updateNotification); 711 mDistance -= 100; 712 if (mDistance >= 0) { 713 mHandler.postDelayed(this, 1000); 714 } else { 715 mManager.cancel(id1); 716 } 717 } 718 }; 719 mUpdateRunnables.put(id1, rightTurnRunnable); 720 mHandler.postDelayed(rightTurnRunnable, 1000); 721 722 int id2 = mCurrentNotificationId++; 723 Runnable exitRunnable = new Runnable() { 724 int mDistance = 20; 725 726 @Override 727 public void run() { 728 Notification updateNotification = new Notification 729 .Builder(mContext, IMPORTANCE_HIGH_ID) 730 .setCategory("navigation") 731 .setContentTitle("Navigation") 732 .setContentText("Exit in " + mDistance + " miles") 733 .setColor(mContext.getColor(android.R.color.holo_green_dark)) 734 .setColorized(true) 735 .setSubText(mDistance + " miles") 736 .setSmallIcon(R.drawable.car_ic_mode) 737 .setOnlyAlertOnce(true) 738 .build(); 739 mManager.notify(id2, updateNotification); 740 mDistance -= 1; 741 if (mDistance >= 0) { 742 mHandler.postDelayed(this, 500); 743 } 744 } 745 }; 746 mUpdateRunnables.put(id2, exitRunnable); 747 mHandler.postDelayed(exitRunnable, 10000); 748 }); 749 } 750 initMediaButton(View view)751 private void initMediaButton(View view) { 752 view.findViewById(R.id.media_button).setOnClickListener(v -> { 753 int id = mCurrentNotificationId++; 754 755 Notification.Builder builder = new Notification 756 .Builder(mContext, IMPORTANCE_DEFAULT_ID) 757 .setContentTitle("Lady Adora") 758 .setContentText("Funny Face") 759 .setColor(mContext.getColor(android.R.color.holo_orange_dark)) 760 .setColorized(true) 761 .setSubText("Some album") 762 .addAction(new Notification.Action(R.drawable.thumb_down, "Thumb down", null)) 763 .addAction(new Notification.Action(R.drawable.skip_prev, "Skip prev", null)) 764 .addAction(new Notification.Action(R.drawable.play_arrow, "Play", null)) 765 .addAction(new Notification.Action(R.drawable.skip_next, "Skip next", null)) 766 .addAction(new Notification.Action(R.drawable.thumb_up, "Thumb up", null)) 767 .setSmallIcon(R.drawable.play_arrow) 768 .setLargeIcon(Icon.createWithResource(mContext, R.drawable.android_logo)); 769 770 Notification.MediaStyle style = new Notification.MediaStyle(); 771 style.setShowActionsInCompactView(1, 2, 3); 772 MediaSession mediaSession = new MediaSession(mContext, "KitchenSink"); 773 style.setMediaSession(mediaSession.getSessionToken()); 774 builder.setStyle(style); 775 mediaSession.release(); 776 777 mManager.notify(id, builder.build()); 778 }); 779 } 780 initCallButton(View view)781 private void initCallButton(View view) { 782 Intent intent = new Intent(mContext, KitchenSinkActivity.class); 783 PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, intent, 784 PendingIntent.FLAG_IMMUTABLE); 785 786 view.findViewById(R.id.category_call_button).setOnClickListener(v -> { 787 Notification notification = new Notification 788 .Builder(mContext, IMPORTANCE_HIGH_ID) 789 .setContentTitle("+1 1231231234") 790 .setContentText("Shows persistent heads-up") 791 .setCategory(Notification.CATEGORY_CALL) 792 .setOngoing(true) 793 .setSmallIcon(R.drawable.car_ic_mode) 794 .setFullScreenIntent(pendingIntent, true) 795 .setColor(mContext.getColor(android.R.color.holo_red_light)) 796 .setColorized(true) 797 .build(); 798 mManager.notify(mCurrentNotificationId++, notification); 799 }); 800 } 801 initCustomGroupSummaryButton(View view)802 private void initCustomGroupSummaryButton(View view) { 803 view.findViewById(R.id.custom_group_summary_button).setOnClickListener(v -> { 804 String groupKey = "GROUP_KEY" + mCurrentNotificationId++; 805 int delay = 500; 806 807 Notification summaryNotification = new Notification 808 .Builder(mContext, IMPORTANCE_HIGH_ID) 809 .setContentTitle("6 New mails") 810 .setContentText("this is some summary") 811 .setSmallIcon(R.drawable.thumb_up) 812 .setLargeIcon(Icon.createWithResource(mContext, R.drawable.avatar1)) 813 .setGroup(groupKey) 814 .setGroupSummary(true) 815 .setStyle(new Notification.InboxStyle() 816 .addLine("line 1") 817 .addLine("line 2") 818 .addLine("line 3") 819 .addLine("line 4") 820 .addLine("line 5") 821 .setBigContentTitle("You've received 6 messages") 822 .setSummaryText("From Alice, Bob, Claire, Douglas..")) 823 .build(); 824 825 mHandler.postDelayed( 826 () -> mManager.notify(mCurrentNotificationId++, summaryNotification), delay); 827 for (int i = 1; i <= 6; i++) { 828 Notification notification = new Notification 829 .Builder(mContext, IMPORTANCE_HIGH_ID) 830 .setContentTitle("Group child " + i) 831 .setSmallIcon(R.drawable.car_ic_mode) 832 .setGroup(groupKey) 833 .setSortKey(Integer.toString(6 - i)) 834 .build(); 835 mHandler.postDelayed(() -> mManager.notify(mCurrentNotificationId++, notification), 836 delay += 5000); 837 } 838 }); 839 } 840 initGroupWithoutSummaryButton(View view)841 private void initGroupWithoutSummaryButton(View view) { 842 view.findViewById(R.id.group_without_summary_button).setOnClickListener(v -> { 843 String groupKey = "GROUP_KEY" + mCurrentNotificationId++; 844 845 for (int i = 1; i <= 6; i++) { 846 Notification notification = new Notification 847 .Builder(mContext, IMPORTANCE_DEFAULT_ID) 848 .setContentTitle("This notification should not group " + i) 849 .setSmallIcon(R.drawable.car_ic_mode) 850 .setGroup(groupKey) 851 .setSortKey(Integer.toString(i)) 852 .build(); 853 mHandler.post(() -> mManager.notify(mCurrentNotificationId++, notification)); 854 } 855 }); 856 } 857 } 858