1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.example.android.support.wearable.notifications;
18
19import android.app.Notification;
20import android.content.Context;
21import android.graphics.BitmapFactory;
22import android.graphics.Color;
23import android.graphics.Typeface;
24import android.support.v4.app.NotificationCompat;
25import android.text.SpannableStringBuilder;
26import android.text.style.ForegroundColorSpan;
27import android.text.style.RelativeSizeSpan;
28import android.text.style.StrikethroughSpan;
29import android.text.style.StyleSpan;
30import android.text.style.SubscriptSpan;
31import android.text.style.SuperscriptSpan;
32import android.text.style.TypefaceSpan;
33import android.text.style.UnderlineSpan;
34import android.view.Gravity;
35
36/**
37 * Collection of notification builder presets.
38 */
39public class NotificationPresets {
40    private static final String EXAMPLE_GROUP_KEY = "example";
41
42    public static final NotificationPreset BASIC = new BasicNotificationPreset();
43    public static final NotificationPreset STYLIZED_TEXT = new StylizedTextNotificationPreset();
44    public static final NotificationPreset INBOX = new InboxNotificationPreset();
45    public static final NotificationPreset BIG_PICTURE = new BigPictureNotificationPreset();
46    public static final NotificationPreset BIG_TEXT = new BigTextNotificationPreset();
47    public static final NotificationPreset BOTTOM_ALIGNED = new BottomAlignedNotificationPreset();
48    public static final NotificationPreset GRAVITY = new GravityNotificationPreset();
49    public static final NotificationPreset CONTENT_ACTION = new ContentActionNotificationPreset();
50    public static final NotificationPreset CONTENT_ICON = new ContentIconNotificationPreset();
51    public static final NotificationPreset MULTIPLE_PAGE = new MultiplePageNotificationPreset();
52    public static final NotificationPreset BUNDLE = new NotificationBundlePreset();
53    public static final NotificationPreset BARCODE = new NotificationBarcodePreset();
54
55    public static final NotificationPreset[] PRESETS = new NotificationPreset[] {
56            BASIC,
57            STYLIZED_TEXT,
58            INBOX,
59            BIG_PICTURE,
60            BIG_TEXT,
61            BOTTOM_ALIGNED,
62            GRAVITY,
63            CONTENT_ACTION,
64            CONTENT_ICON,
65            MULTIPLE_PAGE,
66            BUNDLE,
67            BARCODE
68    };
69
70    private static NotificationCompat.Builder applyBasicOptions(Context context,
71            NotificationCompat.Builder builder, NotificationCompat.WearableExtender wearableOptions,
72            NotificationPreset.BuildOptions options) {
73        builder.setContentTitle(options.titlePreset)
74                .setContentText(options.textPreset)
75                .setSmallIcon(R.mipmap.ic_launcher)
76                .setDeleteIntent(NotificationUtil.getExamplePendingIntent(
77                        context, R.string.example_notification_deleted));
78        options.actionsPreset.apply(context, builder, wearableOptions);
79        options.priorityPreset.apply(builder, wearableOptions);
80        if (options.includeLargeIcon) {
81            builder.setLargeIcon(BitmapFactory.decodeResource(
82                    context.getResources(), R.drawable.example_large_icon));
83        }
84        if (options.isLocalOnly) {
85            builder.setLocalOnly(true);
86        }
87        if (options.hasContentIntent) {
88            builder.setContentIntent(NotificationUtil.getExamplePendingIntent(context,
89                    R.string.content_intent_clicked));
90        }
91        if (options.vibrate) {
92            builder.setVibrate(new long[] {0, 100, 50, 100} );
93        }
94        return builder;
95    }
96
97    private static class BasicNotificationPreset extends NotificationPreset {
98        public BasicNotificationPreset() {
99            super(R.string.basic_example, R.string.example_content_title,
100                R.string.example_content_text);
101        }
102
103        @Override
104        public Notification[] buildNotifications(Context context, BuildOptions options) {
105            NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
106            NotificationCompat.WearableExtender wearableOptions =
107                    new NotificationCompat.WearableExtender();
108            applyBasicOptions(context, builder, wearableOptions, options);
109            builder.extend(wearableOptions);
110            return new Notification[] { builder.build() };
111        }
112    }
113
114    private static class StylizedTextNotificationPreset extends NotificationPreset {
115        public StylizedTextNotificationPreset() {
116            super(R.string.stylized_text_example, R.string.example_content_title,
117                    R.string.example_content_text);
118        }
119
120        @Override
121        public Notification[] buildNotifications(Context context, BuildOptions options) {
122            NotificationCompat.BigTextStyle style = new NotificationCompat.BigTextStyle();
123
124            SpannableStringBuilder title = new SpannableStringBuilder();
125            appendStyled(title, "Stylized", new StyleSpan(Typeface.BOLD_ITALIC));
126            title.append(" title");
127            SpannableStringBuilder text = new SpannableStringBuilder("Stylized text: ");
128            appendStyled(text, "C", new ForegroundColorSpan(Color.RED));
129            appendStyled(text, "O", new ForegroundColorSpan(Color.GREEN));
130            appendStyled(text, "L", new ForegroundColorSpan(Color.BLUE));
131            appendStyled(text, "O", new ForegroundColorSpan(Color.YELLOW));
132            appendStyled(text, "R", new ForegroundColorSpan(Color.MAGENTA));
133            appendStyled(text, "S", new ForegroundColorSpan(Color.CYAN));
134            text.append("; ");
135            appendStyled(text, "1.25x size", new RelativeSizeSpan(1.25f));
136            text.append("; ");
137            appendStyled(text, "0.75x size", new RelativeSizeSpan(0.75f));
138            text.append("; ");
139            appendStyled(text, "underline", new UnderlineSpan());
140            text.append("; ");
141            appendStyled(text, "strikethrough", new StrikethroughSpan());
142            text.append("; ");
143            appendStyled(text, "bold", new StyleSpan(Typeface.BOLD));
144            text.append("; ");
145            appendStyled(text, "italic", new StyleSpan(Typeface.ITALIC));
146            text.append("; ");
147            appendStyled(text, "sans-serif-thin", new TypefaceSpan("sans-serif-thin"));
148            text.append("; ");
149            appendStyled(text, "monospace", new TypefaceSpan("monospace"));
150            text.append("; ");
151            appendStyled(text, "sub", new SubscriptSpan());
152            text.append("script");
153            appendStyled(text, "super", new SuperscriptSpan());
154
155            style.setBigContentTitle(title);
156            style.bigText(text);
157
158            NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
159                    .setStyle(style);
160            NotificationCompat.WearableExtender wearableOptions =
161                    new NotificationCompat.WearableExtender();
162            applyBasicOptions(context, builder, wearableOptions, options);
163            builder.extend(wearableOptions);
164            return new Notification[] { builder.build() };
165        }
166
167        private void appendStyled(SpannableStringBuilder builder, String str, Object... spans) {
168            builder.append(str);
169            for (Object span : spans) {
170                builder.setSpan(span, builder.length() - str.length(), builder.length(), 0);
171            }
172        }
173    }
174
175    private static class InboxNotificationPreset extends NotificationPreset {
176        public InboxNotificationPreset() {
177            super(R.string.inbox_example, R.string.example_content_title,
178                R.string.example_content_text);
179        }
180
181        @Override
182        public Notification[] buildNotifications(Context context, BuildOptions options) {
183            NotificationCompat.InboxStyle style = new NotificationCompat.InboxStyle();
184            style.addLine(context.getString(R.string.inbox_style_example_line1));
185            style.addLine(context.getString(R.string.inbox_style_example_line2));
186            style.addLine(context.getString(R.string.inbox_style_example_line3));
187            style.setBigContentTitle(context.getString(R.string.inbox_style_example_title));
188            style.setSummaryText(context.getString(R.string.inbox_style_example_summary_text));
189
190            NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
191                    .setStyle(style);
192            NotificationCompat.WearableExtender wearableOptions =
193                    new NotificationCompat.WearableExtender();
194            applyBasicOptions(context, builder, wearableOptions, options);
195            builder.extend(wearableOptions);
196            return new Notification[] { builder.build() };
197        }
198    }
199
200    private static class BigPictureNotificationPreset extends NotificationPreset {
201        public BigPictureNotificationPreset() {
202            super(R.string.big_picture_example, R.string.example_content_title,
203                R.string.example_content_text);
204        }
205
206        @Override
207        public Notification[] buildNotifications(Context context, BuildOptions options) {
208            NotificationCompat.BigPictureStyle style = new NotificationCompat.BigPictureStyle();
209            style.bigPicture(BitmapFactory.decodeResource(context.getResources(),
210                    R.drawable.example_big_picture));
211            style.setBigContentTitle(context.getString(R.string.big_picture_style_example_title));
212            style.setSummaryText(context.getString(
213                    R.string.big_picture_style_example_summary_text));
214
215            NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
216                    .setStyle(style);
217            NotificationCompat.WearableExtender wearableOptions =
218                    new NotificationCompat.WearableExtender();
219            applyBasicOptions(context, builder, wearableOptions, options);
220            builder.extend(wearableOptions);
221            return new Notification[] { builder.build() };
222        }
223    }
224
225    private static class BigTextNotificationPreset extends NotificationPreset {
226        public BigTextNotificationPreset() {
227            super(R.string.big_text_example, R.string.example_content_title,
228                R.string.example_content_text);
229        }
230
231        @Override
232        public Notification[] buildNotifications(Context context, BuildOptions options) {
233            NotificationCompat.BigTextStyle style = new NotificationCompat.BigTextStyle();
234            style.bigText(context.getString(R.string.big_text_example_big_text));
235            style.setBigContentTitle(context.getString(R.string.big_text_example_title));
236            style.setSummaryText(context.getString(R.string.big_text_example_summary_text));
237
238            NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
239                    .setStyle(style);
240            NotificationCompat.WearableExtender wearableOptions =
241                    new NotificationCompat.WearableExtender();
242            applyBasicOptions(context, builder, wearableOptions, options);
243            builder.extend(wearableOptions);
244            return new Notification[] { builder.build() };
245        }
246    }
247
248    private static class BottomAlignedNotificationPreset extends NotificationPreset {
249        public BottomAlignedNotificationPreset() {
250            super(R.string.bottom_aligned_example, R.string.example_content_title,
251                R.string.example_content_text);
252        }
253
254        @Override
255        public Notification[] buildNotifications(Context context, BuildOptions options) {
256            NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
257            NotificationCompat.WearableExtender wearableOptions =
258                    new NotificationCompat.WearableExtender();
259            applyBasicOptions(context, builder, wearableOptions, options);
260
261            NotificationCompat.Builder secondPageBuilder = new NotificationCompat.Builder(context);
262            secondPageBuilder.setContentTitle(
263                    context.getString(R.string.second_page_content_title));
264            secondPageBuilder.setContentText(context.getString(R.string.big_text_example_big_text));
265            secondPageBuilder.extend(new NotificationCompat.WearableExtender()
266                            .setStartScrollBottom(true));
267
268            wearableOptions.addPage(secondPageBuilder.build());
269            builder.extend(wearableOptions);
270            return new Notification[] { builder.build() };
271        }
272    }
273
274    private static class GravityNotificationPreset extends NotificationPreset {
275        public GravityNotificationPreset() {
276            super(R.string.gravity_example, R.string.example_content_title,
277                R.string.example_content_text);
278        }
279
280        @Override
281        public Notification[] buildNotifications(Context context, BuildOptions options) {
282            NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
283            NotificationCompat.WearableExtender wearableOptions =
284                    new NotificationCompat.WearableExtender();
285            applyBasicOptions(context, builder, wearableOptions, options);
286
287            NotificationCompat.Builder secondPageBuilder = new NotificationCompat.Builder(context)
288                    .setContentTitle(options.titlePreset)
289                    .setContentText(options.textPreset)
290                    .extend(new NotificationCompat.WearableExtender()
291                            .setGravity(Gravity.CENTER_VERTICAL));
292            wearableOptions.addPage(secondPageBuilder.build());
293
294            NotificationCompat.Builder thirdPageBuilder = new NotificationCompat.Builder(context)
295                    .setContentTitle(options.titlePreset)
296                    .setContentText(options.textPreset)
297                    .extend(new NotificationCompat.WearableExtender()
298                            .setGravity(Gravity.TOP));
299            wearableOptions.addPage(thirdPageBuilder.build());
300
301            wearableOptions.setGravity(Gravity.BOTTOM);
302            builder.extend(wearableOptions);
303            return new Notification[] { builder.build() };
304        }
305    }
306
307    private static class ContentActionNotificationPreset extends NotificationPreset {
308        public ContentActionNotificationPreset() {
309            super(R.string.content_action_example, R.string.example_content_title,
310                R.string.example_content_text);
311        }
312
313        @Override
314        public Notification[] buildNotifications(Context context, BuildOptions options) {
315            Notification secondPage = new NotificationCompat.Builder(context)
316                    .setContentTitle(context.getString(R.string.second_page_content_title))
317                    .setContentText(context.getString(R.string.second_page_content_text))
318                    .extend(new NotificationCompat.WearableExtender()
319                            .setContentAction(1))
320                    .build();
321
322            NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
323            NotificationCompat.Action action = new NotificationCompat.Action.Builder(
324                    R.drawable.ic_result_open, null, NotificationUtil.getExamplePendingIntent(
325                            context, R.string.example_content_action_clicked)).build();
326            NotificationCompat.Action action2 = new NotificationCompat.Action.Builder(
327                    R.drawable.ic_result_open, null, NotificationUtil.getExamplePendingIntent(
328                            context, R.string.example_content_action2_clicked)).build();
329            NotificationCompat.WearableExtender wearableOptions =
330                    new NotificationCompat.WearableExtender()
331                            .addAction(action)
332                            .addAction(action2)
333                            .addPage(secondPage)
334                            .setContentAction(0)
335                            .setHintHideIcon(true);
336            applyBasicOptions(context, builder, wearableOptions, options);
337            builder.extend(wearableOptions);
338            return new Notification[] { builder.build() };
339        }
340
341        @Override
342        public boolean actionsRequired() {
343            return true;
344        }
345    }
346
347    private static class ContentIconNotificationPreset extends NotificationPreset {
348        public ContentIconNotificationPreset() {
349            super(R.string.content_icon_example, R.string.example_content_title,
350                    R.string.example_content_text);
351        }
352
353        @Override
354        public Notification[] buildNotifications(Context context, BuildOptions options) {
355            Notification secondPage = new NotificationCompat.Builder(context)
356                    .setContentTitle(context.getString(R.string.second_page_content_title))
357                    .setContentText(context.getString(R.string.second_page_content_text))
358                    .extend(new NotificationCompat.WearableExtender()
359                            .setContentIcon(R.drawable.content_icon_small)
360                            .setContentIconGravity(Gravity.START))
361                    .build();
362
363            Notification thirdPage = new NotificationCompat.Builder(context)
364                    .setContentTitle(context.getString(R.string.third_page_content_title))
365                    .setContentText(context.getString(R.string.third_page_content_text))
366                    .extend(new NotificationCompat.WearableExtender()
367                            .setContentIcon(R.drawable.content_icon_large))
368                    .build();
369
370            Notification fourthPage = new NotificationCompat.Builder(context)
371                    .setContentTitle(context.getString(R.string.fourth_page_content_title))
372                    .setContentText(context.getString(R.string.fourth_page_content_text))
373                    .extend(new NotificationCompat.WearableExtender()
374                            .setContentIcon(R.drawable.content_icon_large)
375                            .setContentIconGravity(Gravity.START))
376                    .build();
377
378            NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
379            NotificationCompat.WearableExtender wearableOptions =
380                    new NotificationCompat.WearableExtender()
381                            .setHintHideIcon(true)
382                            .setContentIcon(R.drawable.content_icon_small)
383                            .addPage(secondPage)
384                            .addPage(thirdPage)
385                            .addPage(fourthPage);
386            applyBasicOptions(context, builder, wearableOptions, options);
387            builder.extend(wearableOptions);
388            return new Notification[] { builder.build() };
389        }
390    }
391
392    private static class MultiplePageNotificationPreset extends NotificationPreset {
393        public MultiplePageNotificationPreset() {
394            super(R.string.multiple_page_example, R.string.example_content_title,
395                R.string.example_content_text);
396        }
397
398        @Override
399        public Notification[] buildNotifications(Context context, BuildOptions options) {
400            NotificationCompat.Builder secondPageBuilder = new NotificationCompat.Builder(context)
401                    .setContentTitle(context.getString(R.string.second_page_content_title))
402                    .setContentText(context.getString(R.string.second_page_content_text));
403
404            NotificationCompat.Builder firstPageBuilder = new NotificationCompat.Builder(context);
405            NotificationCompat.WearableExtender firstPageWearableOptions =
406                    new NotificationCompat.WearableExtender();
407            applyBasicOptions(context, firstPageBuilder, firstPageWearableOptions, options);
408
409            Integer firstBackground = options.backgroundIds == null
410                    ? null : options.backgroundIds[0];
411            if (firstBackground != null) {
412                NotificationCompat.BigPictureStyle style =
413                        new NotificationCompat.BigPictureStyle();
414                style.bigPicture(BitmapFactory.decodeResource(context.getResources(),
415                        firstBackground));
416                firstPageBuilder.setStyle(style);
417            }
418
419            Integer secondBackground = options.backgroundIds == null
420                    ? null : options.backgroundIds[1];
421            if (secondBackground != null) {
422                NotificationCompat.BigPictureStyle style = new NotificationCompat.BigPictureStyle();
423                style.bigPicture(BitmapFactory.decodeResource(context.getResources(),
424                        secondBackground));
425                secondPageBuilder.setStyle(style);
426            }
427
428            firstPageBuilder.extend(
429                    firstPageWearableOptions.addPage(secondPageBuilder.build()));
430
431            return new Notification[]{ firstPageBuilder.build() };
432        }
433
434        @Override
435        public int countBackgroundPickersRequired() {
436            return 2; // This sample does 2 pages notifications.
437        }
438    }
439
440    private static class NotificationBundlePreset extends NotificationPreset {
441        public NotificationBundlePreset() {
442            super(R.string.bundle_example, R.string.example_content_title,
443                R.string.example_content_text);
444        }
445
446        @Override
447        public Notification[] buildNotifications(Context context, BuildOptions options) {
448            NotificationCompat.Builder childBuilder1 = new NotificationCompat.Builder(context)
449                    .setContentTitle(context.getString(R.string.first_child_content_title))
450                    .setContentText(context.getString(R.string.first_child_content_text))
451                    .setSmallIcon(R.mipmap.ic_launcher)
452                    .setLocalOnly(options.isLocalOnly)
453                    .setGroup(EXAMPLE_GROUP_KEY)
454                    .setSortKey("0");
455
456            NotificationCompat.Builder childBuilder2 = new NotificationCompat.Builder(context)
457                    .setContentTitle(context.getString(R.string.second_child_content_title))
458                    .setContentText(context.getString(R.string.second_child_content_text))
459                    .setSmallIcon(R.mipmap.ic_launcher)
460                    .addAction(R.mipmap.ic_launcher,
461                            context.getString(R.string.second_child_action),
462                            NotificationUtil.getExamplePendingIntent(
463                                    context, R.string.second_child_action_clicked))
464                    .setLocalOnly(options.isLocalOnly)
465                    .setGroup(EXAMPLE_GROUP_KEY)
466                    .setSortKey("1");
467
468            NotificationCompat.Builder summaryBuilder = new NotificationCompat.Builder(context)
469                    .setGroup(EXAMPLE_GROUP_KEY)
470                    .setGroupSummary(true);
471
472            NotificationCompat.WearableExtender summaryWearableOptions =
473                    new NotificationCompat.WearableExtender();
474            applyBasicOptions(context, summaryBuilder, summaryWearableOptions, options);
475            summaryBuilder.extend(summaryWearableOptions);
476
477            return new Notification[] { summaryBuilder.build(), childBuilder1.build(),
478                    childBuilder2.build() };
479        }
480    }
481
482    private static class NotificationBarcodePreset extends NotificationPreset {
483        public NotificationBarcodePreset() {
484            super(R.string.barcode_example, R.string.barcode_content_title,
485                    R.string.barcode_content_text);
486        }
487
488        @Override
489        public Notification[] buildNotifications(Context context, BuildOptions options) {
490            NotificationCompat.Builder secondPageBuilder = new NotificationCompat.Builder(context)
491                    .extend(new NotificationCompat.WearableExtender()
492                            .setHintShowBackgroundOnly(true)
493                            .setBackground(BitmapFactory.decodeResource(context.getResources(),
494                                    R.drawable.qr_code))
495                            .setHintAvoidBackgroundClipping(true)
496                            .setHintScreenTimeout(
497                                    NotificationCompat.WearableExtender.SCREEN_TIMEOUT_LONG));
498
499            NotificationCompat.Builder firstPageBuilder = new NotificationCompat.Builder(context);
500            NotificationCompat.WearableExtender firstPageWearableOptions =
501                    new NotificationCompat.WearableExtender();
502            applyBasicOptions(context, firstPageBuilder, firstPageWearableOptions, options);
503
504            firstPageBuilder.extend(
505                    firstPageWearableOptions.addPage(secondPageBuilder.build()));
506
507            return new Notification[]{ firstPageBuilder.build() };
508        }
509    }
510}
511