/* 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.Bundle; import android.support.v4.app.NotificationCompat.BigPictureStyle; import android.support.v4.app.NotificationManagerCompat; import android.support.v4.app.RemoteInput; 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; /** * Asynchronously handles updating social app posts (and active Notification) with comments from * user. Notification for social app use BigPictureStyle. */ public class BigPictureSocialIntentService extends IntentService { private static final String TAG = "BigPictureService"; public static final String ACTION_COMMENT = "com.example.android.wearable.wear.wearnotifications.handlers.action.COMMENT"; public static final String EXTRA_COMMENT = "com.example.android.wearable.wear.wearnotifications.handlers.extra.COMMENT"; public BigPictureSocialIntentService() { super("BigPictureSocialIntentService"); } @Override protected void onHandleIntent(Intent intent) { Log.d(TAG, "onHandleIntent(): " + intent); if (intent != null) { final String action = intent.getAction(); if (ACTION_COMMENT.equals(action)) { handleActionComment(getMessage(intent)); } } } /** * Handles action for adding a comment from the notification. */ private void handleActionComment(CharSequence comment) { Log.d(TAG, "handleActionComment(): " + comment); if (comment != null) { // TODO: Asynchronously save your message to Database and servers. /* * You have two options for updating your notification (this class uses approach #2): * * 1. Use a new NotificationCompatBuilder to create the Notification. This approach * requires you to get *ALL* the information that existed in the previous * Notification (and updates) and pass it to the builder. This is the approach used in * the MainActivity. * * 2. Use the original NotificationCompatBuilder to create the Notification. This * approach requires you to store a reference to the original builder. The benefit is * you only need the new/updated information. In our case, the comment from the user * regarding the post (which we already have here). * * IMPORTANT NOTE: You shouldn't save/modify the resulting Notification object using * its member variables and/or legacy APIs. If you want to retain anything from update * to update, retain the Builder as option 2 outlines. */ // Retrieves NotificationCompat.Builder used to create initial Notification 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 = recreateBuilderWithBigPictureStyle(); } // Updates active Notification Notification updatedNotification = notificationCompatBuilder // Adds a line and comment below content in Notification .setRemoteInputHistory(new CharSequence[]{comment}) .build(); // Pushes out the updated Notification NotificationManagerCompat notificationManagerCompat = NotificationManagerCompat.from(getApplicationContext()); notificationManagerCompat.notify( StandaloneMainActivity.NOTIFICATION_ID, updatedNotification); } } /* * Extracts CharSequence created from the RemoteInput associated with the Notification. */ private CharSequence getMessage(Intent intent) { Bundle remoteInput = RemoteInput.getResultsFromIntent(intent); if (remoteInput != null) { return remoteInput.getCharSequence(EXTRA_COMMENT); } return null; } /* * 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 recreateBuilderWithBigPictureStyle() { // Main steps for building a BIG_PICTURE_STYLE notification (for more detailed comments on // building this notification, check StandaloneMainActivity.java): // 0. Get your data // 1. Build the BIG_PICTURE_STYLE // 2. Set up main Intent for notification // 3. Set up RemoteInput, so users can input (keyboard and voice) from notification // 4. Build and issue the notification // 0. Get your data (everything unique per Notification) MockDatabase.BigPictureStyleSocialAppData bigPictureStyleSocialAppData = MockDatabase.getBigPictureStyleData(); // 1. Build the BIG_PICTURE_STYLE BigPictureStyle bigPictureStyle = new NotificationCompat.BigPictureStyle() .bigPicture( BitmapFactory.decodeResource( getResources(), bigPictureStyleSocialAppData.getBigImage())) .setBigContentTitle(bigPictureStyleSocialAppData.getBigContentTitle()) .setSummaryText(bigPictureStyleSocialAppData.getSummaryText()); // 2. Set up main Intent for notification Intent mainIntent = new Intent(this, BigPictureSocialMainActivity.class); PendingIntent mainPendingIntent = PendingIntent.getActivity( this, 0, mainIntent, PendingIntent.FLAG_UPDATE_CURRENT ); // 3. Set up a RemoteInput Action, so users can input (keyboard, drawing, voice) directly // from the notification without entering the app. String replyLabel = getString(R.string.reply_label); RemoteInput remoteInput = new RemoteInput.Builder(BigPictureSocialIntentService.EXTRA_COMMENT) .setLabel(replyLabel) .setChoices(bigPictureStyleSocialAppData.getPossiblePostResponses()) .build(); Intent replyIntent = new Intent(this, BigPictureSocialIntentService.class); replyIntent.setAction(BigPictureSocialIntentService.ACTION_COMMENT); PendingIntent replyActionPendingIntent = PendingIntent.getService(this, 0, replyIntent, 0); // Enable action to appear inline on Wear 2.0 (24+). This means it will appear over the // lower portion of the Notification for easy action (only possible for one action). final NotificationCompat.Action.WearableExtender inlineActionForWear2 = new NotificationCompat.Action.WearableExtender() .setHintDisplayActionInline(true) .setHintLaunchesActivity(false); NotificationCompat.Action replyAction = new NotificationCompat.Action.Builder( R.drawable.ic_reply_white_18dp, replyLabel, replyActionPendingIntent) .addRemoteInput(remoteInput) // Add WearableExtender to enable inline actions .extend(inlineActionForWear2) .build(); // 4. Build and issue the notification NotificationCompat.Builder notificationCompatBuilder = new NotificationCompat.Builder(getApplicationContext()); GlobalNotificationBuilder.setNotificationCompatBuilderInstance(notificationCompatBuilder); // Build notification notificationCompatBuilder .setStyle(bigPictureStyle) .setContentTitle(bigPictureStyleSocialAppData.getContentTitle()) .setContentText(bigPictureStyleSocialAppData.getContentText()) .setSmallIcon(R.drawable.ic_launcher) .setLargeIcon(BitmapFactory.decodeResource( getResources(), R.drawable.ic_person_black_48dp)) .setContentIntent(mainPendingIntent) .setColor(getResources().getColor(R.color.colorPrimary)) .setSubText(Integer.toString(1)) .addAction(replyAction) .setCategory(Notification.CATEGORY_SOCIAL) .setPriority(Notification.PRIORITY_HIGH) .setVisibility(Notification.VISIBILITY_PRIVATE) .extend(new NotificationCompat.WearableExtender() .setHintContentIntentLaunchesActivity(true)); for (String name : bigPictureStyleSocialAppData.getParticipants()) { notificationCompatBuilder.addPerson(name); } return notificationCompatBuilder; } }