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