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