Home | History | Annotate | Download | only in com.example.android.support.wearable.notifications
      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 
     17 package com.example.android.support.wearable.notifications;
     18 
     19 import android.app.Notification;
     20 import android.content.Context;
     21 import android.graphics.BitmapFactory;
     22 import android.graphics.Color;
     23 import android.graphics.Typeface;
     24 import android.support.v4.app.NotificationCompat;
     25 import android.text.SpannableStringBuilder;
     26 import android.text.style.ForegroundColorSpan;
     27 import android.text.style.RelativeSizeSpan;
     28 import android.text.style.StrikethroughSpan;
     29 import android.text.style.StyleSpan;
     30 import android.text.style.SubscriptSpan;
     31 import android.text.style.SuperscriptSpan;
     32 import android.text.style.TypefaceSpan;
     33 import android.text.style.UnderlineSpan;
     34 import android.view.Gravity;
     35 
     36 /**
     37  * Collection of notification builder presets.
     38  */
     39 public 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