List of usage examples for android.app Notification CATEGORY_MESSAGE
String CATEGORY_MESSAGE
To view the source code for android.app Notification CATEGORY_MESSAGE.
Click Source Link
From source file:com.android.messaging.datamodel.BugleNotifications.java
private static void processAndSend(final NotificationState state, final boolean silent, final boolean softSound) { final Context context = Factory.get().getApplicationContext(); final NotificationCompat.Builder notifBuilder = new NotificationCompat.Builder(context); notifBuilder.setCategory(Notification.CATEGORY_MESSAGE); // TODO: Need to fix this for multi conversation notifications to rate limit dings. final String conversationId = state.mConversationIds.first(); final Uri ringtoneUri = RingtoneUtil.getNotificationRingtoneUri(state.getRingtoneUri()); // If the notification's conversation is currently observable (focused or in the // conversation list), then play a notification beep at a low volume and don't display an // actual notification. if (softSound) { if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) { LogUtil.v(TAG,//from www . j a v a 2s.c om "processAndSend: fromConversationId == " + "sCurrentlyDisplayedConversationId so NOT showing notification," + " but playing soft sound. conversationId: " + conversationId); } playObservableConversationNotificationSound(ringtoneUri); return; } state.mBaseRequestCode = state.mType; // Set the delete intent (except for bundled wearable notifications, which are dismissed // as a group, either from the wearable or when the summary notification is dismissed from // the host device). if (!(state instanceof BundledMessageNotificationState)) { final PendingIntent clearIntent = state.getClearIntent(); notifBuilder.setDeleteIntent(clearIntent); } updateBuilderAudioVibrate(state, notifBuilder, silent, ringtoneUri, conversationId); // Set the content intent PendingIntent destinationIntent; if (state.mConversationIds.size() > 1) { // We have notifications for multiple conversation, go to the conversation list. destinationIntent = UIIntents.get().getPendingIntentForConversationListActivity(context); } else { // We have a single conversation, go directly to that conversation. destinationIntent = UIIntents.get().getPendingIntentForConversationActivity(context, state.mConversationIds.first(), null /*draft*/); } notifBuilder.setContentIntent(destinationIntent); // TODO: set based on contact coming from a favorite. notifBuilder.setPriority(state.getPriority()); // Save the state of the notification in-progress so when the avatar is loaded, // we can continue building the notification. final NotificationCompat.Style notifStyle = state.build(notifBuilder); state.mNotificationBuilder = notifBuilder; state.mNotificationStyle = notifStyle; if (!state.mPeople.isEmpty()) { final Bundle people = new Bundle(); people.putStringArray(NotificationCompat.EXTRA_PEOPLE, state.mPeople.toArray(new String[state.mPeople.size()])); notifBuilder.addExtras(people); } if (state.mParticipantAvatarsUris != null) { final Uri avatarUri = state.mParticipantAvatarsUris.get(0); final AvatarRequestDescriptor descriptor = new AvatarRequestDescriptor(avatarUri, sIconWidth, sIconHeight, OsUtil.isAtLeastL()); final MediaRequest<ImageResource> imageRequest = descriptor.buildSyncMediaRequest(context); synchronized (sPendingNotifications) { sPendingNotifications.add(state); } // Synchronously load the avatar. final ImageResource avatarImage = MediaResourceManager.get().requestMediaResourceSync(imageRequest); if (avatarImage != null) { ImageResource avatarHiRes = null; try { if (isWearCompanionAppInstalled()) { // For Wear users, we need to request a high-res avatar image to use as the // notification card background. If the sender has a contact photo, we'll // request the display photo from the Contacts provider. Otherwise, we ask // the local content provider for a hi-res version of the generic avatar // (e.g. letter with colored background). avatarHiRes = requestContactDisplayPhoto(context, getDisplayPhotoUri(avatarUri)); if (avatarHiRes == null) { final AvatarRequestDescriptor hiResDesc = new AvatarRequestDescriptor(avatarUri, sWearableImageWidth, sWearableImageHeight, false /* cropToCircle */, true /* isWearBackground */); avatarHiRes = MediaResourceManager.get() .requestMediaResourceSync(hiResDesc.buildSyncMediaRequest(context)); } } // We have to make copies of the bitmaps to hand to the NotificationManager // because the bitmap in the ImageResource is managed and will automatically // get released. Bitmap avatarBitmap = Bitmap.createBitmap(avatarImage.getBitmap()); Bitmap avatarHiResBitmap = (avatarHiRes != null) ? Bitmap.createBitmap(avatarHiRes.getBitmap()) : null; sendNotification(state, avatarBitmap, avatarHiResBitmap); return; } finally { avatarImage.release(); if (avatarHiRes != null) { avatarHiRes.release(); } } } } // We have no avatar. Post the notification anyway. sendNotification(state, null, null); }
From source file:com.android.mms.transaction.MessagingNotification.java
public static void blockingUpdateNewIccMessageIndicator(Context context, String address, String message, int subId, long timeMillis) { final Notification.Builder noti = new Notification.Builder(context).setWhen(timeMillis); Contact contact = Contact.get(address, false); NotificationInfo info = getNewIccMessageNotificationInfo(context, true /* isSms */, address, message, null /* subject */, subId, timeMillis, null /* attachmentBitmap */, contact, WorkingMessage.TEXT); noti.setSmallIcon(R.drawable.stat_notify_sms); NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); // TaskStackBuilder taskStackBuilder = TaskStackBuilder.create(context); // Update the notification. PendingIntent pendingIntent;/*from w w w. jav a 2 s . c o m*/ if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { pendingIntent = PendingIntent.getActivity(context, 0, info.mClickIntent, PendingIntent.FLAG_UPDATE_CURRENT); } else { // Use requestCode to avoid updating all intents of previous notifications pendingIntent = PendingIntent.getActivity(context, ICC_NOTIFICATION_ID_BASE + subId, info.mClickIntent, PendingIntent.FLAG_UPDATE_CURRENT); } String title = info.mTitle; noti.setContentTitle(title).setContentIntent(pendingIntent) //taskStackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT)) .setCategory(Notification.CATEGORY_MESSAGE).setPriority(Notification.PRIORITY_DEFAULT); int defaults = 0; SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context); boolean vibrate = false; if (sp.contains(MessagingPreferenceActivity.NOTIFICATION_VIBRATE)) { // The most recent change to the vibrate preference is to store a boolean // value in NOTIFICATION_VIBRATE. If prefs contain that preference, use that // first. vibrate = sp.getBoolean(MessagingPreferenceActivity.NOTIFICATION_VIBRATE, false); } else if (sp.contains(MessagingPreferenceActivity.NOTIFICATION_VIBRATE_WHEN)) { // This is to support the pre-JellyBean MR1.1 version of vibrate preferences // when vibrate was a tri-state setting. As soon as the user opens the Messaging // app's settings, it will migrate this setting from NOTIFICATION_VIBRATE_WHEN // to the boolean value stored in NOTIFICATION_VIBRATE. String vibrateWhen = sp.getString(MessagingPreferenceActivity.NOTIFICATION_VIBRATE_WHEN, null); vibrate = "always".equals(vibrateWhen); } if (vibrate) { defaults |= Notification.DEFAULT_VIBRATE; } String ringtoneStr = sp.getString(MessagingPreferenceActivity.NOTIFICATION_RINGTONE, null); noti.setSound(TextUtils.isEmpty(ringtoneStr) ? null : Uri.parse(ringtoneStr)); Log.d(TAG, "blockingUpdateNewIccMessageIndicator: adding sound to the notification"); defaults |= Notification.DEFAULT_LIGHTS; noti.setDefaults(defaults); // set up delete intent noti.setDeleteIntent(PendingIntent.getBroadcast(context, 0, sNotificationOnDeleteIntent, 0)); final Notification notification; // This sets the text for the collapsed form: noti.setContentText(info.formatBigMessage(context)); if (info.mAttachmentBitmap != null) { // The message has a picture, show that notification = new Notification.BigPictureStyle(noti).bigPicture(info.mAttachmentBitmap) // This sets the text for the expanded picture form: .setSummaryText(info.formatPictureMessage(context)).build(); } else { // Show a single notification -- big style with the text of the whole message notification = new Notification.BigTextStyle(noti).bigText(info.formatBigMessage(context)).build(); } notifyUserIfFullScreen(context, title); nm.notify(ICC_NOTIFICATION_ID_BASE + subId, notification); }
From source file:com.example.android.wearable.wear.wearnotifications.StandaloneMainActivity.java
private void generateMessagingStyleNotification() { Log.d(TAG, "generateMessagingStyleNotification()"); // Main steps for building a MESSAGING_STYLE notification: // 0. Get your data // 1. Build the MESSAGING_STYLE // 2. Add support for Wear 1.+ // 3. Set up main Intent for notification // 4. Set up RemoteInput (users can input directly from notification) // 5. Build and issue the notification // 0. Get your data (everything unique per Notification) MockDatabase.MessagingStyleCommsAppData messagingStyleCommsAppData = MockDatabase.getMessagingStyleData(); // 1. Build the Notification.Style (MESSAGING_STYLE) String contentTitle = messagingStyleCommsAppData.getContentTitle(); MessagingStyle messagingStyle = new NotificationCompat.MessagingStyle( messagingStyleCommsAppData.getReplayName()) // You could set a different title to appear when the messaging style // is supported on device (24+) if you wish. In our case, we use the same // title. .setConversationTitle(contentTitle); // Adds all Messages // Note: Messages include the text, timestamp, and sender for (MessagingStyle.Message message : messagingStyleCommsAppData.getMessages()) { messagingStyle.addMessage(message); }/*ww w . j ava 2s . c o m*/ // 2. Add support for Wear 1.+ // Since Wear 1.0 doesn't support the MESSAGING_STYLE, we use the BIG_TEXT_STYLE, so all the // text is visible. // This is basically a toString() of all the Messages above. String fullMessageForWearVersion1 = messagingStyleCommsAppData.getFullConversation(); Notification chatHistoryForWearV1 = new NotificationCompat.Builder(getApplicationContext()) .setStyle(new BigTextStyle().bigText(fullMessageForWearVersion1)).setContentTitle(contentTitle) .setSmallIcon(R.drawable.ic_launcher).setContentText(fullMessageForWearVersion1).build(); // Adds page with all text to support Wear 1.+. NotificationCompat.WearableExtender wearableExtenderForWearVersion1 = new NotificationCompat.WearableExtender() .setHintContentIntentLaunchesActivity(true).addPage(chatHistoryForWearV1); // 3. Set up main Intent for notification Intent notifyIntent = new Intent(this, MessagingMainActivity.class); PendingIntent mainPendingIntent = PendingIntent.getActivity(this, 0, notifyIntent, PendingIntent.FLAG_UPDATE_CURRENT); // 4. Set up a RemoteInput Action, so users can input (keyboard, drawing, voice) directly // from the notification without entering the app. // Create the RemoteInput specifying this key. String replyLabel = getString(R.string.reply_label); RemoteInput remoteInput = new RemoteInput.Builder(MessagingIntentService.EXTRA_REPLY).setLabel(replyLabel) .build(); // Create PendingIntent for service that handles input. Intent replyIntent = new Intent(this, MessagingIntentService.class); replyIntent.setAction(MessagingIntentService.ACTION_REPLY); 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) // Allows system to generate replies by context of conversation .setAllowGeneratedReplies(true) // Add WearableExtender to enable inline actions .extend(inlineActionForWear2).build(); // 5. Build and issue the notification // Because we want this to be a new notification (not updating current notification), we // create a new Builder. Later, we update this same notification, so we need to save this // Builder globally (as outlined earlier). NotificationCompat.Builder notificationCompatBuilder = new NotificationCompat.Builder( getApplicationContext()); GlobalNotificationBuilder.setNotificationCompatBuilderInstance(notificationCompatBuilder); // Builds and issues notification notificationCompatBuilder // MESSAGING_STYLE sets title and content for API 24+ (Wear 2.0) devices .setStyle(messagingStyle) // Title for API <24 (Wear 1.+) devices .setContentTitle(contentTitle) // Content for API <24 (Wear 1.+) devices .setContentText(messagingStyleCommsAppData.getContentText()).setSmallIcon(R.drawable.ic_launcher) .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.ic_person_black_48dp)) .setContentIntent(mainPendingIntent) // Set primary color (important for Wear 2.0 Notifications) .setColor(getResources().getColor(R.color.colorPrimary)) // Number of new notifications for API <24 (Wear 1.+) devices .setSubText(Integer.toString(messagingStyleCommsAppData.getNumberOfNewMessages())) .addAction(replyAction).setCategory(Notification.CATEGORY_MESSAGE) .setPriority(Notification.PRIORITY_HIGH) // Hides content on the lock-screen .setVisibility(Notification.VISIBILITY_PRIVATE) // Adds multiple pages for easy consumption on a wear device. .extend(wearableExtenderForWearVersion1); // If the phone is in "Do not disturb mode, the user will still be notified if // the sender(s) is starred as a favorite. for (String name : messagingStyleCommsAppData.getParticipants()) { notificationCompatBuilder.addPerson(name); } Notification notification = notificationCompatBuilder.build(); mNotificationManagerCompat.notify(NOTIFICATION_ID, notification); // Close app to demonstrate notification in steam. finish(); }
From source file:com.example.android.wearable.wear.wearnotifications.MainActivity.java
private void generateMessagingStyleNotification() { Log.d(TAG, "generateMessagingStyleNotification()"); // Main steps for building a MESSAGING_STYLE notification: // 0. Get your data // 1. Build the MESSAGING_STYLE // 2. Add support for Wear 1.+ // 3. Set up main Intent for notification // 4. Set up RemoteInput (users can input directly from notification) // 5. Build and issue the notification // 0. Get your data (everything unique per Notification) MockDatabase.MessagingStyleCommsAppData messagingStyleCommsAppData = MockDatabase.getMessagingStyleData(); // 1. Build the Notification.Style (MESSAGING_STYLE) String contentTitle = messagingStyleCommsAppData.getContentTitle(); MessagingStyle messagingStyle = new NotificationCompat.MessagingStyle( messagingStyleCommsAppData.getReplayName()) // You could set a different title to appear when the messaging style // is supported on device (24+) if you wish. In our case, we use the same // title. .setConversationTitle(contentTitle); // Adds all Messages // Note: Messages include the text, timestamp, and sender for (MessagingStyle.Message message : messagingStyleCommsAppData.getMessages()) { messagingStyle.addMessage(message); }/*w w w. ja va 2 s. c o m*/ // 2. Add support for Wear 1.+ // Since Wear 1.0 doesn't support the MESSAGING_STYLE, we use the BIG_TEXT_STYLE, so all the // text is visible. // This is basically a toString() of all the Messages above. String fullMessageForWearVersion1 = messagingStyleCommsAppData.getFullConversation(); Notification chatHistoryForWearV1 = new NotificationCompat.Builder(getApplicationContext()) .setStyle(new BigTextStyle().bigText(fullMessageForWearVersion1)).setContentTitle(contentTitle) .setSmallIcon(R.drawable.ic_launcher).setContentText(fullMessageForWearVersion1).build(); // Adds page with all text to support Wear 1.+. NotificationCompat.WearableExtender wearableExtenderForWearVersion1 = new NotificationCompat.WearableExtender() .addPage(chatHistoryForWearV1); // 3. Set up main Intent for notification Intent notifyIntent = new Intent(this, MessagingMainActivity.class); // When creating your Intent, you need to take into account the back state, i.e., what // happens after your Activity launches and the user presses the back button. // There are two options: // 1. Regular activity - You're starting an Activity that's part of the application's // normal workflow. // 2. Special activity - The user only sees this Activity if it's started from a // notification. In a sense, the Activity extends the notification by providing // information that would be hard to display in the notification itself. // Even though this sample's MainActivity doesn't link to the Activity this Notification // launches directly, i.e., it isn't part of the normal workflow, a chat app generally // always links to individual conversations as part of the app flow, so we will follow // option 1. // For an example of option 2, check out the BIG_TEXT_STYLE example. // For more information, check out our dev article: // https://developer.android.com/training/notify-user/navigation.html TaskStackBuilder stackBuilder = TaskStackBuilder.create(this); // Adds the back stack stackBuilder.addParentStack(MessagingMainActivity.class); // Adds the Intent to the top of the stack stackBuilder.addNextIntent(notifyIntent); // Gets a PendingIntent containing the entire back stack PendingIntent mainPendingIntent = PendingIntent.getActivity(this, 0, notifyIntent, PendingIntent.FLAG_UPDATE_CURRENT); // 4. Set up RemoteInput, so users can input (keyboard and voice) from notification // Note: For API <24 (M and below) we need to use an Activity, so the lock-screen present // the auth challenge. For API 24+ (N and above), we use a Service (could be a // BroadcastReceiver), so the user can input from Notification or lock-screen (they have // choice to allow) without leaving the notification. // Create the RemoteInput specifying this key String replyLabel = getString(R.string.reply_label); RemoteInput remoteInput = new RemoteInput.Builder(MessagingIntentService.EXTRA_REPLY).setLabel(replyLabel) .build(); // Pending intent = // API <24 (M and below): activity so the lock-screen presents the auth challenge // API 24+ (N and above): this should be a Service or BroadcastReceiver PendingIntent replyActionPendingIntent; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { Intent intent = new Intent(this, MessagingIntentService.class); intent.setAction(MessagingIntentService.ACTION_REPLY); replyActionPendingIntent = PendingIntent.getService(this, 0, intent, 0); } else { replyActionPendingIntent = mainPendingIntent; } NotificationCompat.Action replyAction = new NotificationCompat.Action.Builder( R.drawable.ic_reply_white_18dp, replyLabel, replyActionPendingIntent).addRemoteInput(remoteInput) // Allows system to generate replies by context of conversation .setAllowGeneratedReplies(true).build(); // 5. Build and issue the notification // Because we want this to be a new notification (not updating current notification), we // create a new Builder. Later, we update this same notification, so we need to save this // Builder globally (as outlined earlier). NotificationCompat.Builder notificationCompatBuilder = new NotificationCompat.Builder( getApplicationContext()); GlobalNotificationBuilder.setNotificationCompatBuilderInstance(notificationCompatBuilder); // Builds and issues notification notificationCompatBuilder // MESSAGING_STYLE sets title and content for API 24+ (N and above) devices .setStyle(messagingStyle) // Title for API <24 (M and below) devices .setContentTitle(contentTitle) // Content for API <24 (M and below) devices .setContentText(messagingStyleCommsAppData.getContentText()).setSmallIcon(R.drawable.ic_launcher) .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.ic_person_black_48dp)) .setContentIntent(mainPendingIntent) // Set primary color (important for Wear 2.0 Notifications) .setColor(getResources().getColor(R.color.colorPrimary)) // SIDE NOTE: Auto-bundling is enabled for 4 or more notifications on API 24+ (N+) // devices and all Android Wear devices. If you have more than one notification and // you prefer a different summary notification, set a group key and create a // summary notification via // .setGroupSummary(true) // .setGroup(GROUP_KEY_YOUR_NAME_HERE) // Number of new notifications for API <24 (M and below) devices .setSubText(Integer.toString(messagingStyleCommsAppData.getNumberOfNewMessages())) .addAction(replyAction).setCategory(Notification.CATEGORY_MESSAGE) .setPriority(Notification.PRIORITY_HIGH) // Hides content on the lock-screen .setVisibility(Notification.VISIBILITY_PRIVATE) // Adds multiple pages for easy consumption on a wear device. .extend(wearableExtenderForWearVersion1); // If the phone is in "Do not disturb mode, the user will still be notified if // the sender(s) is starred as a favorite. for (String name : messagingStyleCommsAppData.getParticipants()) { notificationCompatBuilder.addPerson(name); } Notification notification = notificationCompatBuilder.build(); mNotificationManagerCompat.notify(NOTIFICATION_ID, notification); }
From source file:com.android.mms.transaction.MessagingNotification.java
/** * updateNotification is *the* main function for building the actual notification handed to * the NotificationManager//ww w .j a v a 2 s .c om * @param context * @param newThreadId the new thread id * @param uniqueThreadCount * @param notificationSet the set of notifications to display */ private static void updateNotification(Context context, long newThreadId, int uniqueThreadCount, SortedSet<NotificationInfo> notificationSet) { boolean isNew = newThreadId != THREAD_NONE; CMConversationSettings conversationSettings = CMConversationSettings.getOrNew(context, newThreadId); // If the user has turned off notifications in settings, don't do any notifying. if ((isNew && !conversationSettings.getNotificationEnabled()) || !MessagingPreferenceActivity.getNotificationEnabled(context)) { if (DEBUG) { Log.d(TAG, "updateNotification: notifications turned off in prefs, bailing"); } return; } // Figure out what we've got -- whether all sms's, mms's, or a mixture of both. final int messageCount = notificationSet.size(); NotificationInfo mostRecentNotification = notificationSet.first(); final NotificationCompat.Builder noti = new NotificationCompat.Builder(context) .setWhen(mostRecentNotification.mTimeMillis); if (isNew) { noti.setTicker(mostRecentNotification.mTicker); } // If we have more than one unique thread, change the title (which would // normally be the contact who sent the message) to a generic one that // makes sense for multiple senders, and change the Intent to take the // user to the conversation list instead of the specific thread. // Cases: // 1) single message from single thread - intent goes to ComposeMessageActivity // 2) multiple messages from single thread - intent goes to ComposeMessageActivity // 3) messages from multiple threads - intent goes to ConversationList final Resources res = context.getResources(); String title = null; Bitmap avatar = null; PendingIntent pendingIntent = null; boolean isMultiNewMessages = MessageUtils.isMailboxMode() ? messageCount > 1 : uniqueThreadCount > 1; if (isMultiNewMessages) { // messages from multiple threads Intent mainActivityIntent = getMultiThreadsViewIntent(context); pendingIntent = PendingIntent.getActivity(context, 0, mainActivityIntent, PendingIntent.FLAG_UPDATE_CURRENT); title = context.getString(R.string.message_count_notification, messageCount); } else { // same thread, single or multiple messages title = mostRecentNotification.mTitle; avatar = mostRecentNotification.mSender.getAvatar(context); noti.setSubText(mostRecentNotification.mSimName); // no-op in single SIM case if (avatar != null) { // Show the sender's avatar as the big icon. Contact bitmaps are 96x96 so we // have to scale 'em up to 128x128 to fill the whole notification large icon. final int idealIconHeight = res .getDimensionPixelSize(android.R.dimen.notification_large_icon_height); final int idealIconWidth = res.getDimensionPixelSize(android.R.dimen.notification_large_icon_width); noti.setLargeIcon(BitmapUtil.getRoundedBitmap(avatar, idealIconWidth, idealIconHeight)); } pendingIntent = PendingIntent.getActivity(context, 0, mostRecentNotification.mClickIntent, PendingIntent.FLAG_UPDATE_CURRENT); } // Always have to set the small icon or the notification is ignored noti.setSmallIcon(R.drawable.stat_notify_sms); NotificationManagerCompat nm = NotificationManagerCompat.from(context); // Update the notification. noti.setContentTitle(title).setContentIntent(pendingIntent) .setColor(context.getResources().getColor(R.color.mms_theme_color)) .setCategory(Notification.CATEGORY_MESSAGE).setPriority(Notification.PRIORITY_DEFAULT); // TODO: set based on contact coming // from a favorite. // Tag notification with all senders. for (NotificationInfo info : notificationSet) { Uri peopleReferenceUri = info.mSender.getPeopleReferenceUri(); if (peopleReferenceUri != null) { noti.addPerson(peopleReferenceUri.toString()); } } int defaults = 0; if (isNew) { SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context); if (conversationSettings.getVibrateEnabled()) { String pattern = conversationSettings.getVibratePattern(); if (!TextUtils.isEmpty(pattern)) { noti.setVibrate(parseVibratePattern(pattern)); } else { defaults |= Notification.DEFAULT_VIBRATE; } } String ringtoneStr = conversationSettings.getNotificationTone(); noti.setSound(TextUtils.isEmpty(ringtoneStr) ? null : Uri.parse(ringtoneStr)); Log.d(TAG, "updateNotification: new message, adding sound to the notification"); } defaults |= Notification.DEFAULT_LIGHTS; noti.setDefaults(defaults); // set up delete intent noti.setDeleteIntent(PendingIntent.getBroadcast(context, 0, sNotificationOnDeleteIntent, 0)); // See if QuickMessage pop-up support is enabled in preferences boolean qmPopupEnabled = MessagingPreferenceActivity.getQuickMessageEnabled(context); // Set up the QuickMessage intent Intent qmIntent = null; if (mostRecentNotification.mIsSms) { // QuickMessage support is only for SMS qmIntent = new Intent(); qmIntent.setClass(context, QuickMessagePopup.class); qmIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); qmIntent.putExtra(QuickMessagePopup.SMS_FROM_NAME_EXTRA, mostRecentNotification.mSender.getName()); qmIntent.putExtra(QuickMessagePopup.SMS_FROM_NUMBER_EXTRA, mostRecentNotification.mSender.getNumber()); qmIntent.putExtra(QuickMessagePopup.SMS_NOTIFICATION_OBJECT_EXTRA, mostRecentNotification); } // Start getting the notification ready final Notification notification; //Create a WearableExtender to add actions too WearableExtender wearableExtender = new WearableExtender(); if (messageCount == 1 || uniqueThreadCount == 1) { // Add the Quick Reply action only if the pop-up won't be shown already if (!qmPopupEnabled && qmIntent != null) { // This is a QR, we should show the keyboard when the user taps to reply qmIntent.putExtra(QuickMessagePopup.QR_SHOW_KEYBOARD_EXTRA, true); // Create the pending intent and add it to the notification CharSequence qmText = context.getText(R.string.menu_reply); PendingIntent qmPendingIntent = PendingIntent.getActivity(context, 0, qmIntent, PendingIntent.FLAG_UPDATE_CURRENT); noti.addAction(R.drawable.ic_reply, qmText, qmPendingIntent); //Wearable noti.extend(wearableExtender.addAction( new NotificationCompat.Action.Builder(R.drawable.ic_reply, qmText, qmPendingIntent) .build())); } // Add the 'Mark as read' action CharSequence markReadText = context.getText(R.string.qm_mark_read); Intent mrIntent = new Intent(); mrIntent.setClass(context, QmMarkRead.class); mrIntent.putExtra(QmMarkRead.SMS_THREAD_ID, mostRecentNotification.mThreadId); PendingIntent mrPendingIntent = PendingIntent.getBroadcast(context, 0, mrIntent, PendingIntent.FLAG_UPDATE_CURRENT); noti.addAction(R.drawable.ic_mark_read, markReadText, mrPendingIntent); // Add the Call action CharSequence callText = context.getText(R.string.menu_call); Intent callIntent = new Intent(Intent.ACTION_CALL); callIntent.setData(Uri.parse("tel:" + mostRecentNotification.mSender.getNumber())); PendingIntent callPendingIntent = PendingIntent.getActivity(context, 0, callIntent, PendingIntent.FLAG_UPDATE_CURRENT); noti.addAction(R.drawable.ic_menu_call, callText, callPendingIntent); //Wearable noti.extend(wearableExtender.addAction( new NotificationCompat.Action.Builder(R.drawable.ic_menu_call, callText, callPendingIntent) .build())); //Set up remote input String replyLabel = context.getString(R.string.qm_wear_voice_reply); RemoteInput remoteInput = new RemoteInput.Builder(QuickMessageWear.EXTRA_VOICE_REPLY) .setLabel(replyLabel).build(); //Set up pending intent for voice reply Intent voiceReplyIntent = new Intent(context, QuickMessageWear.class); voiceReplyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); voiceReplyIntent.putExtra(QuickMessageWear.SMS_CONATCT, mostRecentNotification.mSender.getName()); voiceReplyIntent.putExtra(QuickMessageWear.SMS_SENDER, mostRecentNotification.mSender.getNumber()); voiceReplyIntent.putExtra(QuickMessageWear.SMS_THEAD_ID, mostRecentNotification.mThreadId); PendingIntent voiceReplyPendingIntent = PendingIntent.getActivity(context, 0, voiceReplyIntent, PendingIntent.FLAG_UPDATE_CURRENT); //Wearable voice reply action NotificationCompat.Action action = new NotificationCompat.Action.Builder(R.drawable.ic_reply, context.getString(R.string.qm_wear_reply_by_voice), voiceReplyPendingIntent) .addRemoteInput(remoteInput).build(); noti.extend(wearableExtender.addAction(action)); } if (messageCount == 1) { // We've got a single message // This sets the text for the collapsed form: noti.setContentText(mostRecentNotification.formatBigMessage(context)); if (mostRecentNotification.mAttachmentBitmap != null) { // The message has a picture, show that NotificationCompat.BigPictureStyle bigPictureStyle = new NotificationCompat.BigPictureStyle(noti) .bigPicture(mostRecentNotification.mAttachmentBitmap) .setSummaryText(mostRecentNotification.formatPictureMessage(context)); notification = noti.setStyle(bigPictureStyle).build(); } else { // Show a single notification -- big style with the text of the whole message NotificationCompat.BigTextStyle bigTextStyle1 = new NotificationCompat.BigTextStyle(noti) .bigText(mostRecentNotification.formatBigMessage(context)); notification = noti.setStyle(bigTextStyle1).build(); } if (DEBUG) { Log.d(TAG, "updateNotification: single message notification"); } } else { // We've got multiple messages if (!isMultiNewMessages) { // We've got multiple messages for the same thread. // Starting with the oldest new message, display the full text of each message. // Begin a line for each subsequent message. SpannableStringBuilder buf = new SpannableStringBuilder(); NotificationInfo infos[] = notificationSet.toArray(new NotificationInfo[messageCount]); int len = infos.length; for (int i = len - 1; i >= 0; i--) { NotificationInfo info = infos[i]; buf.append(info.formatBigMessage(context)); if (i != 0) { buf.append('\n'); } } noti.setContentText(context.getString(R.string.message_count_notification, messageCount)); // Show a single notification -- big style with the text of all the messages NotificationCompat.BigTextStyle bigTextStyle = new NotificationCompat.BigTextStyle(); bigTextStyle.bigText(buf) // Forcibly show the last line, with the app's smallIcon in it, if we // kicked the smallIcon out with an avatar bitmap .setSummaryText((avatar == null) ? null : " "); notification = noti.setStyle(bigTextStyle).build(); if (DEBUG) { Log.d(TAG, "updateNotification: multi messages for single thread"); } } else { // Build a set of the most recent notification per threadId. HashSet<Long> uniqueThreads = new HashSet<Long>(messageCount); ArrayList<NotificationInfo> mostRecentNotifPerThread = new ArrayList<NotificationInfo>(); Iterator<NotificationInfo> notifications = notificationSet.iterator(); while (notifications.hasNext()) { NotificationInfo notificationInfo = notifications.next(); if (!uniqueThreads.contains(notificationInfo.mThreadId)) { uniqueThreads.add(notificationInfo.mThreadId); mostRecentNotifPerThread.add(notificationInfo); } } // When collapsed, show all the senders like this: // Fred Flinstone, Barry Manilow, Pete... noti.setContentText(formatSenders(context, mostRecentNotifPerThread)); NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle(noti); // We have to set the summary text to non-empty so the content text doesn't show // up when expanded. inboxStyle.setSummaryText(" "); // At this point we've got multiple messages in multiple threads. We only // want to show the most recent message per thread, which are in // mostRecentNotifPerThread. int uniqueThreadMessageCount = mostRecentNotifPerThread.size(); int maxMessages = Math.min(MAX_MESSAGES_TO_SHOW, uniqueThreadMessageCount); for (int i = 0; i < maxMessages; i++) { NotificationInfo info = mostRecentNotifPerThread.get(i); inboxStyle.addLine(info.formatInboxMessage(context)); } notification = inboxStyle.build(); uniqueThreads.clear(); mostRecentNotifPerThread.clear(); if (DEBUG) { Log.d(TAG, "updateNotification: multi messages," + " showing inboxStyle notification"); } } } notifyUserIfFullScreen(context, title); nm.notify(NOTIFICATION_ID, notification); // Trigger the QuickMessage pop-up activity if enabled // But don't show the QuickMessage if the user is in a call or the phone is ringing if (qmPopupEnabled && qmIntent != null) { TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); if (tm.getCallState() == TelephonyManager.CALL_STATE_IDLE && !ConversationList.mIsRunning && !ComposeMessageActivity.mIsRunning) { context.startActivity(qmIntent); } } }