/* Copyright 2016 The Android Open Source Project Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package com.example.android.wearable.wear.wearnotifications.handlers; import android.app.IntentService; import android.app.Notification; import android.app.PendingIntent; import android.content.Intent; import android.graphics.BitmapFactory; import android.os.Build; import android.support.v4.app.NotificationCompat.BigTextStyle; import android.support.v4.app.NotificationManagerCompat; import android.support.v7.app.NotificationCompat; import android.util.Log; import com.example.android.wearable.wear.wearnotifications.GlobalNotificationBuilder; import com.example.android.wearable.wear.wearnotifications.R; import com.example.android.wearable.wear.wearnotifications.StandaloneMainActivity; import com.example.android.wearable.wear.wearnotifications.mock.MockDatabase; import java.util.concurrent.TimeUnit; /** * Asynchronously handles snooze and dismiss actions for reminder app (and active Notification). * Notification for for reminder app uses BigTextStyle. */ public class BigTextIntentService extends IntentService { private static final String TAG = "BigTextService"; public static final String ACTION_DISMISS = "com.example.android.wearable.wear.wearnotifications.handlers.action.DISMISS"; public static final String ACTION_SNOOZE = "com.example.android.wearable.wear.wearnotifications.handlers.action.SNOOZE"; private static final long SNOOZE_TIME = TimeUnit.SECONDS.toMillis(5); public BigTextIntentService() { super("BigTextIntentService"); } @Override protected void onHandleIntent(Intent intent) { Log.d(TAG, "onHandleIntent(): " + intent); if (intent != null) { final String action = intent.getAction(); if (ACTION_DISMISS.equals(action)) { handleActionDismiss(); } else if (ACTION_SNOOZE.equals(action)) { handleActionSnooze(); } } } /** * Handles action Dismiss in the provided background thread. */ private void handleActionDismiss() { Log.d(TAG, "handleActionDismiss()"); NotificationManagerCompat notificationManagerCompat = NotificationManagerCompat.from(getApplicationContext()); notificationManagerCompat.cancel(StandaloneMainActivity.NOTIFICATION_ID); } /** * Handles action Snooze in the provided background thread. */ private void handleActionSnooze() { Log.d(TAG, "handleActionSnooze()"); // You could use NotificationManager.getActiveNotifications() if you are targeting SDK 23 // and above, but we are targeting devices with lower SDK API numbers, so we saved the // builder globally and get the notification back to recreate it later. NotificationCompat.Builder notificationCompatBuilder = GlobalNotificationBuilder.getNotificationCompatBuilderInstance(); // Recreate builder from persistent state if app process is killed if (notificationCompatBuilder == null) { // Note: New builder set globally in the method notificationCompatBuilder = recreateBuilderWithBigTextStyle(); } Notification notification; notification = notificationCompatBuilder.build(); if (notification != null) { NotificationManagerCompat notificationManagerCompat = NotificationManagerCompat.from(getApplicationContext()); notificationManagerCompat.cancel(StandaloneMainActivity.NOTIFICATION_ID); try { Thread.sleep(SNOOZE_TIME); } catch (InterruptedException ex) { Thread.currentThread().interrupt(); } notificationManagerCompat.notify(StandaloneMainActivity.NOTIFICATION_ID, notification); } } /* * This recreates the notification from the persistent state in case the app process was killed. * It is basically the same code for creating the Notification from StandaloneMainActivity. */ private NotificationCompat.Builder recreateBuilderWithBigTextStyle() { // Main steps for building a BIG_TEXT_STYLE notification (for more detailed comments on // building this notification, check StandaloneMainActivity.java):: // 0. Get your data // 1. Build the BIG_TEXT_STYLE // 2. Set up main Intent for notification // 3. Create additional Actions for the Notification // 4. Build and issue the notification // 0. Get your data (everything unique per Notification) MockDatabase.BigTextStyleReminderAppData bigTextStyleReminderAppData = MockDatabase.getBigTextStyleData(); // 1. Build the BIG_TEXT_STYLE BigTextStyle bigTextStyle = new NotificationCompat.BigTextStyle() .bigText(bigTextStyleReminderAppData.getBigText()) .setBigContentTitle(bigTextStyleReminderAppData.getBigContentTitle()) .setSummaryText(bigTextStyleReminderAppData.getSummaryText()); // 2. Set up main Intent for notification Intent mainIntent = new Intent(this, BigTextMainActivity.class); PendingIntent mainPendingIntent = PendingIntent.getActivity( this, 0, mainIntent, PendingIntent.FLAG_UPDATE_CURRENT ); // 3. Create additional Actions (Intents) for the Notification // Snooze Action Intent snoozeIntent = new Intent(this, BigTextIntentService.class); snoozeIntent.setAction(BigTextIntentService.ACTION_SNOOZE); PendingIntent snoozePendingIntent = PendingIntent.getService(this, 0, snoozeIntent, 0); NotificationCompat.Action snoozeAction = new NotificationCompat.Action.Builder( R.drawable.ic_alarm_white_48dp, "Snooze", snoozePendingIntent) .build(); // Dismiss Action Intent dismissIntent = new Intent(this, BigTextIntentService.class); dismissIntent.setAction(BigTextIntentService.ACTION_DISMISS); PendingIntent dismissPendingIntent = PendingIntent.getService(this, 0, dismissIntent, 0); NotificationCompat.Action dismissAction = new NotificationCompat.Action.Builder( R.drawable.ic_cancel_white_48dp, "Dismiss", dismissPendingIntent) .build(); // 4. Build and issue the notification NotificationCompat.Builder notificationCompatBuilder = new NotificationCompat.Builder(getApplicationContext()); GlobalNotificationBuilder.setNotificationCompatBuilderInstance(notificationCompatBuilder); notificationCompatBuilder .setStyle(bigTextStyle) .setContentTitle(bigTextStyleReminderAppData.getContentTitle()) .setContentText(bigTextStyleReminderAppData.getContentText()) .setSmallIcon(R.drawable.ic_launcher) .setLargeIcon(BitmapFactory.decodeResource( getResources(), R.drawable.ic_alarm_white_48dp)) .setColor(getResources().getColor(R.color.colorPrimary)) .setCategory(Notification.CATEGORY_REMINDER) .setPriority(Notification.PRIORITY_HIGH) .setVisibility(Notification.VISIBILITY_PUBLIC) .addAction(snoozeAction) .addAction(dismissAction); /* REPLICATE_NOTIFICATION_STYLE_CODE: * You can replicate Notification Style functionality on Wear 2.0 (24+) by not setting the * main content intent, that is, skipping the call setContentIntent(). However, you need to * still allow the user to open the native Wear app from the Notification itself, so you * add an action to launch the app. */ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { // Enables launching app in Wear 2.0 while keeping the old Notification Style behavior. NotificationCompat.Action mainAction = new NotificationCompat.Action.Builder( R.drawable.ic_launcher, "Open", mainPendingIntent) .build(); notificationCompatBuilder.addAction(mainAction); } else { // Wear 1.+ still functions the same, so we set the main content intent. notificationCompatBuilder.setContentIntent(mainPendingIntent); } return notificationCompatBuilder; } }