├── .google └── packaging.yaml ├── Application ├── build.gradle └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── example │ │ └── android │ │ └── wearable │ │ └── wear │ │ └── wearnotifications │ │ ├── GlobalNotificationBuilder.java │ │ ├── MainActivity.java │ │ └── handlers │ │ ├── BigPictureSocialIntentService.java │ │ ├── BigPictureSocialMainActivity.java │ │ ├── BigTextIntentService.java │ │ ├── BigTextMainActivity.java │ │ ├── InboxMainActivity.java │ │ ├── MessagingIntentService.java │ │ └── MessagingMainActivity.java │ └── res │ ├── drawable-hdpi │ ├── ic_launcher.png │ └── tile.9.png │ ├── drawable-mdpi │ └── ic_launcher.png │ ├── drawable-xhdpi │ └── ic_launcher.png │ ├── drawable-xxhdpi │ └── ic_launcher.png │ ├── drawable-xxxhdpi │ └── ic_launcher.png │ ├── layout │ ├── activity_big_picture_main.xml │ ├── activity_big_text_main.xml │ ├── activity_inbox_main.xml │ ├── activity_main.xml │ └── activity_messaging_main.xml │ ├── values-sw600dp │ ├── template-dimens.xml │ └── template-styles.xml │ ├── values-v11 │ └── template-styles.xml │ ├── values-v21 │ ├── base-colors.xml │ └── base-template-styles.xml │ ├── values-w820dp │ └── dimens.xml │ └── values │ ├── base-strings.xml │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ ├── styles.xml │ ├── template-dimens.xml │ └── template-styles.xml ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── Shared ├── build.gradle └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── example │ │ └── android │ │ └── wearable │ │ └── wear │ │ └── common │ │ ├── mock │ │ └── MockDatabase.java │ │ └── util │ │ └── NotificationUtil.java │ └── res │ ├── drawable-hdpi │ ├── earth.png │ ├── famous_fryer.png │ ├── ic_alarm_white_48dp.png │ ├── ic_cancel_white_48dp.png │ ├── ic_launcher.png │ ├── ic_message_black_18dp.png │ ├── ic_n_white_48dp.png │ ├── ic_person_black_48dp.png │ ├── ic_reply_white_18dp.png │ ├── me_macdonald.png │ └── wendy_wonda.png │ ├── drawable-mdpi │ ├── ic_alarm_white_48dp.png │ ├── ic_cancel_white_48dp.png │ ├── ic_launcher.png │ ├── ic_message_black_18dp.png │ ├── ic_person_black_48dp.png │ └── ic_reply_white_18dp.png │ ├── drawable-xhdpi │ ├── ic_alarm_white_48dp.png │ ├── ic_cancel_white_48dp.png │ ├── ic_launcher.png │ ├── ic_message_black_18dp.png │ ├── ic_person_black_48dp.png │ └── ic_reply_white_18dp.png │ ├── drawable-xxhdpi │ ├── ic_alarm_white_48dp.png │ ├── ic_cancel_white_48dp.png │ ├── ic_launcher.png │ ├── ic_message_black_18dp.png │ ├── ic_person_black_48dp.png │ └── ic_reply_white_18dp.png │ ├── drawable-xxxhdpi │ ├── ic_alarm_white_48dp.png │ ├── ic_cancel_white_48dp.png │ ├── ic_launcher.png │ ├── ic_message_black_18dp.png │ ├── ic_person_black_48dp.png │ └── ic_reply_white_18dp.png │ └── values │ └── strings.xml ├── Wearable ├── build.gradle └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── example │ │ └── android │ │ └── wearable │ │ └── wear │ │ └── wearnotifications │ │ ├── Controller.java │ │ ├── CustomRecyclerAdapter.java │ │ ├── GlobalNotificationBuilder.java │ │ ├── ScalingScrollLayoutCallback.java │ │ ├── StandaloneMainActivity.java │ │ └── handlers │ │ ├── BigPictureSocialIntentService.java │ │ ├── BigPictureSocialMainActivity.java │ │ ├── BigTextIntentService.java │ │ ├── BigTextMainActivity.java │ │ ├── InboxMainActivity.java │ │ ├── MessagingIntentService.java │ │ └── MessagingMainActivity.java │ └── res │ ├── drawable-hdpi │ └── ic_launcher.png │ ├── drawable-mdpi │ └── ic_launcher.png │ ├── drawable-xhdpi │ └── ic_launcher.png │ ├── drawable-xxhdpi │ └── ic_launcher.png │ ├── drawable-xxxhdpi │ └── ic_launcher.png │ ├── layout │ ├── activity_big_picture_main.xml │ ├── activity_big_text_main.xml │ ├── activity_inbox_main.xml │ ├── activity_main.xml │ ├── activity_messaging_main.xml │ └── recycler_row_item.xml │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ ├── values-round │ ├── dimens.xml │ └── strings.xml │ └── values │ ├── colors.xml │ ├── dimens.xml │ └── strings.xml ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── screenshots ├── icon-web.png ├── mobile-1.png ├── mobile-2.png ├── wear-1.png └── wear-2.png └── settings.gradle /.google/packaging.yaml: -------------------------------------------------------------------------------- 1 | 2 | # GOOGLE SAMPLE PACKAGING DATA 3 | # 4 | # This file is used by Google as part of our samples packaging process. 5 | # End users may safely ignore this file. It has no relevance to other systems. 6 | --- 7 | status: PUBLISHED 8 | technologies: [Android] 9 | categories: [Notification, Wearable] 10 | languages: [Java] 11 | solutions: [Mobile] 12 | github: android-WearNotifications 13 | level: INTERMEDIATE 14 | icon: screenshots/icon-web.png 15 | apiRefs: 16 | - android:android.app.Notification 17 | - android:android.support.v4.app.NotificationCompat.BigPictureStyle 18 | - android:android.support.v4.app.NotificationCompat.BigTextStyle 19 | - android:android.support.v4.app.NotificationCompat.InboxStyle 20 | - android:android.support.v4.app.NotificationCompat.MessagingStyle 21 | - android:android.support.v4.app.NotificationManagerCompat 22 | - android:android.support.v4.app.RemoteInput 23 | - android:android.support.v4.app.TaskStackBuilder 24 | - android:android.support.v7.app.AppCompatActivity 25 | - android:android.support.v7.app.NotificationCompat 26 | license: apache2 27 | -------------------------------------------------------------------------------- /Application/build.gradle: -------------------------------------------------------------------------------- 1 | 2 | buildscript { 3 | repositories { 4 | jcenter() 5 | google() 6 | } 7 | 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:3.2.0-beta01' 10 | } 11 | } 12 | 13 | apply plugin: 'com.android.application' 14 | 15 | repositories { 16 | jcenter() 17 | google() 18 | } 19 | 20 | dependencies { 21 | implementation 'androidx.appcompat:appcompat:1.0.0-alpha3' 22 | implementation 'androidx.cardview:cardview:1.0.0-alpha3' 23 | implementation 'com.google.android.material:material:1.0.0-alpha3' 24 | implementation 'androidx.legacy:legacy-support-v13:1.0.0-alpha3' 25 | implementation 'com.google.android.gms:play-services-wearable:15.0.1' 26 | 27 | 28 | implementation project(':Shared') 29 | wearApp project(':Wearable') 30 | } 31 | 32 | // The sample build uses multiple directories to 33 | // keep boilerplate and common code separate from 34 | // the main sample code. 35 | List dirs = [ 36 | 'main', // main sample code; look here for the interesting stuff. 37 | 'common', // components that are reused by multiple samples 38 | 'template'] // boilerplate code that is generated by the sample template process 39 | 40 | android { 41 | compileSdkVersion 28 42 | 43 | buildToolsVersion "27.0.3" 44 | 45 | defaultConfig { 46 | minSdkVersion 18 47 | targetSdkVersion 28 48 | versionCode 1 49 | versionName "1.0" 50 | } 51 | 52 | compileOptions { 53 | sourceCompatibility JavaVersion.VERSION_1_7 54 | targetCompatibility JavaVersion.VERSION_1_7 55 | } 56 | 57 | sourceSets { 58 | main { 59 | dirs.each { dir -> 60 | java.srcDirs "src/${dir}/java" 61 | res.srcDirs "src/${dir}/res" 62 | } 63 | } 64 | androidTest.setRoot('tests') 65 | androidTest.java.srcDirs = ['tests/src'] 66 | 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /Application/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 21 | 22 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 41 | 42 | 43 | 46 | 49 | 50 | 51 | 52 | 55 | 58 | 59 | 60 | 63 | 66 | 67 | 68 | 71 | 72 | 73 | 76 | 77 | 78 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /Application/src/main/java/com/example/android/wearable/wear/wearnotifications/GlobalNotificationBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 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 | package com.example.android.wearable.wear.wearnotifications; 17 | 18 | import androidx.core.app.NotificationCompat; 19 | 20 | /** 21 | * We use a Singleton for a global copy of the NotificationCompat.Builder to update active 22 | * Notifications from other Services/Activities. 23 | * 24 | * You have two options for updating your notifications: 25 | * 26 | * 1. Use a new NotificationCompatBuilder to create the Notification. This approach requires you 27 | * to get *ALL* the information and pass it to the builder. We get all the information from a Mock 28 | * Database and this is the approach used in the MainActivity. 29 | * 30 | * 2. Use an existing NotificationCompatBuilder to create a Notification. This approach requires 31 | * you to store a reference to the original builder. The benefit is you only need the new/updated 32 | * information for an existing notification. We use this approach in the IntentService handlers to 33 | * update existing notifications. 34 | * 35 | * IMPORTANT NOTE 1: You shouldn't save/modify the resulting Notification object using 36 | * its member variables and/or legacy APIs. If you want to retain anything from update 37 | * to update, retain the Builder as option 2 outlines. 38 | * 39 | * IMPORTANT NOTE 2: If the global Notification Builder is lost because the process is killed, you 40 | * should have a way to recreate the Notification Builder from a persistent state. (We do this as 41 | * well in the sample, check the IntentServices.) 42 | */ 43 | public final class GlobalNotificationBuilder { 44 | 45 | private static NotificationCompat.Builder sGlobalNotificationCompatBuilder = null; 46 | 47 | /* 48 | * Empty constructor - We don't initialize builder because we rely on a null state to let us 49 | * know the Application's process was killed. 50 | */ 51 | private GlobalNotificationBuilder() { } 52 | 53 | public static void setNotificationCompatBuilderInstance (NotificationCompat.Builder builder) { 54 | sGlobalNotificationCompatBuilder = builder; 55 | } 56 | 57 | public static NotificationCompat.Builder getNotificationCompatBuilderInstance() { 58 | return sGlobalNotificationCompatBuilder; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Application/src/main/java/com/example/android/wearable/wear/wearnotifications/handlers/BigPictureSocialIntentService.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 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 | package com.example.android.wearable.wear.wearnotifications.handlers; 17 | 18 | import android.app.IntentService; 19 | import android.app.Notification; 20 | import android.app.PendingIntent; 21 | import android.content.Intent; 22 | import android.graphics.BitmapFactory; 23 | import android.os.Build; 24 | import android.os.Bundle; 25 | import android.util.Log; 26 | 27 | import androidx.core.app.NotificationCompat; 28 | import androidx.core.app.NotificationCompat.BigPictureStyle; 29 | import androidx.core.app.NotificationManagerCompat; 30 | import androidx.core.app.RemoteInput; 31 | import androidx.core.app.TaskStackBuilder; 32 | 33 | import com.example.android.wearable.wear.wearnotifications.GlobalNotificationBuilder; 34 | import com.example.android.wearable.wear.wearnotifications.MainActivity; 35 | import com.example.android.wearable.wear.wearnotifications.R; 36 | import com.example.android.wearable.wear.common.mock.MockDatabase; 37 | 38 | /** 39 | * Asynchronously handles updating social app posts (and active Notification) with comments from 40 | * user. Notification for social app use BigPictureStyle. 41 | */ 42 | public class BigPictureSocialIntentService extends IntentService { 43 | 44 | private static final String TAG = "BigPictureService"; 45 | 46 | public static final String ACTION_COMMENT = 47 | "com.example.android.wearable.wear.wearnotifications.handlers.action.COMMENT"; 48 | 49 | public static final String EXTRA_COMMENT = 50 | "com.example.android.wearable.wear.wearnotifications.handlers.extra.COMMENT"; 51 | 52 | public BigPictureSocialIntentService() { 53 | super("BigPictureSocialIntentService"); 54 | } 55 | 56 | @Override 57 | protected void onHandleIntent(Intent intent) { 58 | Log.d(TAG, "onHandleIntent(): " + intent); 59 | 60 | if (intent != null) { 61 | final String action = intent.getAction(); 62 | if (ACTION_COMMENT.equals(action)) { 63 | handleActionComment(getMessage(intent)); 64 | } 65 | } 66 | } 67 | 68 | /** 69 | * Handles action for adding a comment from the notification. 70 | */ 71 | private void handleActionComment(CharSequence comment) { 72 | Log.d(TAG, "handleActionComment(): " + comment); 73 | 74 | if (comment != null) { 75 | 76 | // TODO: Asynchronously save your message to Database and servers. 77 | 78 | /* 79 | * You have two options for updating your notification (this class uses approach #2): 80 | * 81 | * 1. Use a new NotificationCompatBuilder to create the Notification. This approach 82 | * requires you to get *ALL* the information that existed in the previous 83 | * Notification (and updates) and pass it to the builder. This is the approach used in 84 | * the MainActivity. 85 | * 86 | * 2. Use the original NotificationCompatBuilder to create the Notification. This 87 | * approach requires you to store a reference to the original builder. The benefit is 88 | * you only need the new/updated information. In our case, the comment from the user 89 | * regarding the post (which we already have here). 90 | * 91 | * IMPORTANT NOTE: You shouldn't save/modify the resulting Notification object using 92 | * its member variables and/or legacy APIs. If you want to retain anything from update 93 | * to update, retain the Builder as option 2 outlines. 94 | */ 95 | 96 | // Retrieves NotificationCompat.Builder used to create initial Notification 97 | NotificationCompat.Builder notificationCompatBuilder = 98 | GlobalNotificationBuilder.getNotificationCompatBuilderInstance(); 99 | 100 | // Recreate builder from persistent state if app process is killed 101 | if (notificationCompatBuilder == null) { 102 | // Note: New builder set globally in the method 103 | notificationCompatBuilder = recreateBuilderWithBigPictureStyle(); 104 | } 105 | 106 | // Updates active Notification 107 | Notification updatedNotification = notificationCompatBuilder 108 | // Adds a line and comment below content in Notification 109 | .setRemoteInputHistory(new CharSequence[]{comment}) 110 | .build(); 111 | 112 | // Pushes out the updated Notification 113 | NotificationManagerCompat notificationManagerCompat = 114 | NotificationManagerCompat.from(getApplicationContext()); 115 | notificationManagerCompat.notify(MainActivity.NOTIFICATION_ID, updatedNotification); 116 | } 117 | } 118 | 119 | /* 120 | * Extracts CharSequence created from the RemoteInput associated with the Notification. 121 | */ 122 | private CharSequence getMessage(Intent intent) { 123 | Bundle remoteInput = RemoteInput.getResultsFromIntent(intent); 124 | if (remoteInput != null) { 125 | return remoteInput.getCharSequence(EXTRA_COMMENT); 126 | } 127 | return null; 128 | } 129 | 130 | /* 131 | * This recreates the notification from the persistent state in case the app process was killed. 132 | * It is basically the same code for creating the Notification from MainActivity. 133 | */ 134 | private NotificationCompat.Builder recreateBuilderWithBigPictureStyle() { 135 | 136 | // Main steps for building a BIG_PICTURE_STYLE notification (for more detailed comments on 137 | // building this notification, check MainActivity.java): 138 | // 0. Get your data 139 | // 1. Build the BIG_PICTURE_STYLE 140 | // 2. Set up main Intent for notification 141 | // 3. Set up RemoteInput, so users can input (keyboard and voice) from notification 142 | // 4. Build and issue the notification 143 | 144 | // 0. Get your data (everything unique per Notification) 145 | MockDatabase.BigPictureStyleSocialAppData bigPictureStyleSocialAppData = 146 | MockDatabase.getBigPictureStyleData(); 147 | 148 | // 1. Build the BIG_PICTURE_STYLE 149 | BigPictureStyle bigPictureStyle = new NotificationCompat.BigPictureStyle() 150 | .bigPicture( 151 | BitmapFactory.decodeResource( 152 | getResources(), 153 | bigPictureStyleSocialAppData.getBigImage())) 154 | .setBigContentTitle(bigPictureStyleSocialAppData.getBigContentTitle()) 155 | .setSummaryText(bigPictureStyleSocialAppData.getSummaryText()); 156 | 157 | // 2. Set up main Intent for notification 158 | Intent mainIntent = new Intent(this, BigPictureSocialMainActivity.class); 159 | 160 | TaskStackBuilder stackBuilder = TaskStackBuilder.create(this); 161 | stackBuilder.addParentStack(BigPictureSocialMainActivity.class); 162 | stackBuilder.addNextIntent(mainIntent); 163 | 164 | PendingIntent mainPendingIntent = 165 | PendingIntent.getActivity( 166 | this, 167 | 0, 168 | mainIntent, 169 | PendingIntent.FLAG_UPDATE_CURRENT 170 | ); 171 | 172 | // 3. Set up RemoteInput, so users can input (keyboard and voice) from notification 173 | String replyLabel = getString(R.string.reply_label); 174 | RemoteInput remoteInput = 175 | new RemoteInput.Builder(BigPictureSocialIntentService.EXTRA_COMMENT) 176 | .setLabel(replyLabel) 177 | .setChoices(bigPictureStyleSocialAppData.getPossiblePostResponses()) 178 | .build(); 179 | 180 | PendingIntent replyActionPendingIntent; 181 | 182 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { 183 | Intent intent = new Intent(this, BigPictureSocialIntentService.class); 184 | intent.setAction(BigPictureSocialIntentService.ACTION_COMMENT); 185 | replyActionPendingIntent = PendingIntent.getService(this, 0, intent, 0); 186 | 187 | } else { 188 | replyActionPendingIntent = mainPendingIntent; 189 | } 190 | 191 | NotificationCompat.Action replyAction = 192 | new NotificationCompat.Action.Builder( 193 | R.drawable.ic_reply_white_18dp, 194 | replyLabel, 195 | replyActionPendingIntent) 196 | .addRemoteInput(remoteInput) 197 | .build(); 198 | 199 | // 4. Build and issue the notification 200 | NotificationCompat.Builder notificationCompatBuilder = 201 | new NotificationCompat.Builder(getApplicationContext()); 202 | 203 | GlobalNotificationBuilder.setNotificationCompatBuilderInstance(notificationCompatBuilder); 204 | 205 | notificationCompatBuilder 206 | .setStyle(bigPictureStyle) 207 | .setContentTitle(bigPictureStyleSocialAppData.getContentTitle()) 208 | .setContentText(bigPictureStyleSocialAppData.getContentText()) 209 | .setSmallIcon(R.drawable.ic_launcher) 210 | .setLargeIcon(BitmapFactory.decodeResource( 211 | getResources(), 212 | R.drawable.ic_person_black_48dp)) 213 | .setContentIntent(mainPendingIntent) 214 | .setColor(getResources().getColor(R.color.colorPrimary)) 215 | .setSubText(Integer.toString(1)) 216 | .addAction(replyAction) 217 | .setCategory(Notification.CATEGORY_SOCIAL) 218 | .setPriority(Notification.PRIORITY_HIGH) 219 | .setVisibility(Notification.VISIBILITY_PRIVATE); 220 | 221 | // If the phone is in "Do not disturb mode, the user will still be notified if 222 | // the sender(s) is starred as a favorite. 223 | for (String name : bigPictureStyleSocialAppData.getParticipants()) { 224 | notificationCompatBuilder.addPerson(name); 225 | } 226 | 227 | return notificationCompatBuilder; 228 | } 229 | } 230 | -------------------------------------------------------------------------------- /Application/src/main/java/com/example/android/wearable/wear/wearnotifications/handlers/BigPictureSocialMainActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 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 | package com.example.android.wearable.wear.wearnotifications.handlers; 17 | 18 | import android.app.Activity; 19 | import android.app.NotificationManager; 20 | import android.content.Context; 21 | import android.os.Bundle; 22 | 23 | import com.example.android.wearable.wear.wearnotifications.MainActivity; 24 | import com.example.android.wearable.wear.wearnotifications.R; 25 | 26 | /** 27 | * Template class meant to include functionality for your Social App. (This project's main focus 28 | * is on Notification Styles.) 29 | */ 30 | public class BigPictureSocialMainActivity extends Activity { 31 | 32 | @Override 33 | protected void onCreate(Bundle savedInstanceState) { 34 | super.onCreate(savedInstanceState); 35 | setContentView(R.layout.activity_big_picture_main); 36 | 37 | // Cancel Notification 38 | NotificationManager notificationManager = 39 | (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); 40 | 41 | notificationManager.cancel(MainActivity.NOTIFICATION_ID); 42 | 43 | // TODO: Handle and display social post from your database 44 | } 45 | } -------------------------------------------------------------------------------- /Application/src/main/java/com/example/android/wearable/wear/wearnotifications/handlers/BigTextIntentService.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 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 | package com.example.android.wearable.wear.wearnotifications.handlers; 17 | 18 | import android.app.IntentService; 19 | import android.app.Notification; 20 | import android.app.PendingIntent; 21 | import android.content.Intent; 22 | import android.graphics.BitmapFactory; 23 | import android.util.Log; 24 | 25 | import androidx.core.app.NotificationCompat; 26 | import androidx.core.app.NotificationCompat.BigTextStyle; 27 | import androidx.core.app.NotificationManagerCompat; 28 | 29 | import com.example.android.wearable.wear.wearnotifications.GlobalNotificationBuilder; 30 | import com.example.android.wearable.wear.wearnotifications.MainActivity; 31 | import com.example.android.wearable.wear.wearnotifications.R; 32 | import com.example.android.wearable.wear.common.mock.MockDatabase; 33 | 34 | import java.util.concurrent.TimeUnit; 35 | 36 | /** 37 | * Asynchronously handles snooze and dismiss actions for reminder app (and active Notification). 38 | * Notification for for reminder app uses BigTextStyle. 39 | */ 40 | public class BigTextIntentService extends IntentService { 41 | 42 | private static final String TAG = "BigTextService"; 43 | 44 | public static final String ACTION_DISMISS = 45 | "com.example.android.wearable.wear.wearnotifications.handlers.action.DISMISS"; 46 | public static final String ACTION_SNOOZE = 47 | "com.example.android.wearable.wear.wearnotifications.handlers.action.SNOOZE"; 48 | 49 | private static final long SNOOZE_TIME = TimeUnit.SECONDS.toMillis(5); 50 | 51 | public BigTextIntentService() { 52 | super("BigTextIntentService"); 53 | } 54 | 55 | @Override 56 | protected void onHandleIntent(Intent intent) { 57 | Log.d(TAG, "onHandleIntent(): " + intent); 58 | 59 | if (intent != null) { 60 | final String action = intent.getAction(); 61 | if (ACTION_DISMISS.equals(action)) { 62 | handleActionDismiss(); 63 | } else if (ACTION_SNOOZE.equals(action)) { 64 | handleActionSnooze(); 65 | } 66 | } 67 | } 68 | 69 | /** 70 | * Handles action Dismiss in the provided background thread. 71 | */ 72 | private void handleActionDismiss() { 73 | Log.d(TAG, "handleActionDismiss()"); 74 | 75 | NotificationManagerCompat notificationManagerCompat = 76 | NotificationManagerCompat.from(getApplicationContext()); 77 | notificationManagerCompat.cancel(MainActivity.NOTIFICATION_ID); 78 | } 79 | 80 | /** 81 | * Handles action Snooze in the provided background thread. 82 | */ 83 | private void handleActionSnooze() { 84 | Log.d(TAG, "handleActionSnooze()"); 85 | 86 | // You could use NotificationManager.getActiveNotifications() if you are targeting SDK 23 87 | // and above, but we are targeting devices with lower SDK API numbers, so we saved the 88 | // builder globally and get the notification back to recreate it later. 89 | 90 | NotificationCompat.Builder notificationCompatBuilder = 91 | GlobalNotificationBuilder.getNotificationCompatBuilderInstance(); 92 | 93 | // Recreate builder from persistent state if app process is killed 94 | if (notificationCompatBuilder == null) { 95 | // Note: New builder set globally in the method 96 | notificationCompatBuilder = recreateBuilderWithBigTextStyle(); 97 | } 98 | 99 | Notification notification; 100 | notification = notificationCompatBuilder.build(); 101 | 102 | 103 | if (notification != null) { 104 | NotificationManagerCompat notificationManagerCompat = 105 | NotificationManagerCompat.from(getApplicationContext()); 106 | 107 | notificationManagerCompat.cancel(MainActivity.NOTIFICATION_ID); 108 | 109 | try { 110 | Thread.sleep(SNOOZE_TIME); 111 | } catch (InterruptedException ex) { 112 | Thread.currentThread().interrupt(); 113 | } 114 | notificationManagerCompat.notify(MainActivity.NOTIFICATION_ID, notification); 115 | } 116 | 117 | } 118 | 119 | /* 120 | * This recreates the notification from the persistent state in case the app process was killed. 121 | * It is basically the same code for creating the Notification from MainActivity. 122 | */ 123 | private NotificationCompat.Builder recreateBuilderWithBigTextStyle() { 124 | 125 | // Main steps for building a BIG_TEXT_STYLE notification (for more detailed comments on 126 | // building this notification, check MainActivity.java):: 127 | // 0. Get your data 128 | // 1. Build the BIG_TEXT_STYLE 129 | // 2. Set up main Intent for notification 130 | // 3. Create additional Actions for the Notification 131 | // 4. Build and issue the notification 132 | 133 | // 0. Get your data 134 | MockDatabase.BigTextStyleReminderAppData bigTextData = MockDatabase.getBigTextStyleData(); 135 | 136 | // 1. Build the BIG_TEXT_STYLE 137 | BigTextStyle bigTextStyle = new NotificationCompat.BigTextStyle() 138 | .bigText(bigTextData.getBigText()) 139 | .setBigContentTitle(bigTextData.getBigContentTitle()) 140 | .setSummaryText(bigTextData.getSummaryText()); 141 | 142 | 143 | // 2. Set up main Intent for notification 144 | Intent notifyIntent = new Intent(this, BigTextMainActivity.class); 145 | notifyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); 146 | 147 | PendingIntent notifyPendingIntent = 148 | PendingIntent.getActivity( 149 | this, 150 | 0, 151 | notifyIntent, 152 | PendingIntent.FLAG_UPDATE_CURRENT 153 | ); 154 | 155 | 156 | // 3. Create additional Actions (Intents) for the Notification 157 | 158 | // Snooze Action 159 | Intent snoozeIntent = new Intent(this, BigTextIntentService.class); 160 | snoozeIntent.setAction(BigTextIntentService.ACTION_SNOOZE); 161 | 162 | PendingIntent snoozePendingIntent = PendingIntent.getService(this, 0, snoozeIntent, 0); 163 | NotificationCompat.Action snoozeAction = 164 | new NotificationCompat.Action.Builder( 165 | R.drawable.ic_alarm_white_48dp, 166 | "Snooze", 167 | snoozePendingIntent) 168 | .build(); 169 | 170 | 171 | // Dismiss Action 172 | Intent dismissIntent = new Intent(this, BigTextIntentService.class); 173 | dismissIntent.setAction(BigTextIntentService.ACTION_DISMISS); 174 | 175 | PendingIntent dismissPendingIntent = PendingIntent.getService(this, 0, dismissIntent, 0); 176 | NotificationCompat.Action dismissAction = 177 | new NotificationCompat.Action.Builder( 178 | R.drawable.ic_cancel_white_48dp, 179 | "Dismiss", 180 | dismissPendingIntent) 181 | .build(); 182 | 183 | // 4. Build and issue the notification 184 | NotificationCompat.Builder notificationCompatBuilder = 185 | new NotificationCompat.Builder(getApplicationContext()); 186 | 187 | GlobalNotificationBuilder.setNotificationCompatBuilderInstance(notificationCompatBuilder); 188 | 189 | notificationCompatBuilder 190 | .setStyle(bigTextStyle) 191 | .setContentTitle(bigTextData.getContentTitle()) 192 | .setContentText(bigTextData.getContentText()) 193 | .setSmallIcon(R.drawable.ic_launcher) 194 | .setLargeIcon(BitmapFactory.decodeResource( 195 | getResources(), 196 | R.drawable.ic_alarm_white_48dp)) 197 | .setContentIntent(notifyPendingIntent) 198 | .setColor(getResources().getColor(R.color.colorPrimary)) 199 | .setCategory(Notification.CATEGORY_REMINDER) 200 | .setPriority(Notification.PRIORITY_HIGH) 201 | .setVisibility(Notification.VISIBILITY_PUBLIC) 202 | .addAction(snoozeAction) 203 | .addAction(dismissAction); 204 | 205 | return notificationCompatBuilder; 206 | } 207 | } 208 | -------------------------------------------------------------------------------- /Application/src/main/java/com/example/android/wearable/wear/wearnotifications/handlers/BigTextMainActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 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 | package com.example.android.wearable.wear.wearnotifications.handlers; 17 | 18 | import android.app.Activity; 19 | import android.app.NotificationManager; 20 | import android.content.Context; 21 | import android.os.Bundle; 22 | 23 | import com.example.android.wearable.wear.wearnotifications.MainActivity; 24 | import com.example.android.wearable.wear.wearnotifications.R; 25 | 26 | /** 27 | * Template class meant to include functionality for your Reminder/Alarm App. (This project's main 28 | * focus is on Notification Styles.) 29 | */ 30 | public class BigTextMainActivity extends Activity { 31 | 32 | @Override 33 | protected void onCreate(Bundle savedInstanceState) { 34 | super.onCreate(savedInstanceState); 35 | setContentView(R.layout.activity_big_text_main); 36 | 37 | // Cancel Notification 38 | NotificationManager notificationManager = 39 | (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); 40 | 41 | notificationManager.cancel(MainActivity.NOTIFICATION_ID); 42 | 43 | // TODO: Handle and display reminder from your database 44 | } 45 | } -------------------------------------------------------------------------------- /Application/src/main/java/com/example/android/wearable/wear/wearnotifications/handlers/InboxMainActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 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 | package com.example.android.wearable.wear.wearnotifications.handlers; 17 | 18 | import android.app.Activity; 19 | import android.app.NotificationManager; 20 | import android.content.Context; 21 | import android.os.Bundle; 22 | 23 | import com.example.android.wearable.wear.wearnotifications.MainActivity; 24 | import com.example.android.wearable.wear.wearnotifications.R; 25 | 26 | /** 27 | * Template class meant to include functionality for your email app. (This project's main focus 28 | * is on Notification Styles.) 29 | */ 30 | public class InboxMainActivity extends Activity { 31 | 32 | @Override 33 | protected void onCreate(Bundle savedInstanceState) { 34 | super.onCreate(savedInstanceState); 35 | setContentView(R.layout.activity_inbox_main); 36 | 37 | // Cancel Notification 38 | NotificationManager notificationManager = 39 | (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); 40 | 41 | notificationManager.cancel(MainActivity.NOTIFICATION_ID); 42 | 43 | // TODO: Handle and display email from your database 44 | } 45 | } -------------------------------------------------------------------------------- /Application/src/main/java/com/example/android/wearable/wear/wearnotifications/handlers/MessagingIntentService.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 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 | package com.example.android.wearable.wear.wearnotifications.handlers; 17 | 18 | import android.app.IntentService; 19 | import android.app.Notification; 20 | import android.app.PendingIntent; 21 | import android.content.Intent; 22 | import android.graphics.BitmapFactory; 23 | import android.os.Build; 24 | import android.os.Bundle; 25 | import android.util.Log; 26 | 27 | import androidx.core.app.NotificationCompat; 28 | import androidx.core.app.NotificationCompat.Action; 29 | import androidx.core.app.NotificationCompat.MessagingStyle; 30 | import androidx.core.app.NotificationManagerCompat; 31 | import androidx.core.app.Person; 32 | import androidx.core.app.RemoteInput; 33 | import androidx.core.app.TaskStackBuilder; 34 | import androidx.core.content.ContextCompat; 35 | 36 | import com.example.android.wearable.wear.common.mock.MockDatabase; 37 | import com.example.android.wearable.wear.common.util.NotificationUtil; 38 | import com.example.android.wearable.wear.wearnotifications.GlobalNotificationBuilder; 39 | import com.example.android.wearable.wear.wearnotifications.MainActivity; 40 | import com.example.android.wearable.wear.wearnotifications.R; 41 | 42 | /** 43 | * Asynchronously handles updating messaging app posts (and active Notification) with replies from 44 | * user in a conversation. Notification for social app use MessagingStyle. 45 | */ 46 | public class MessagingIntentService extends IntentService { 47 | 48 | private static final String TAG = "MessagingIntentService"; 49 | 50 | public static final String ACTION_REPLY = 51 | "com.example.android.wearable.wear.wearnotifications.handlers.action.REPLY"; 52 | 53 | public static final String EXTRA_REPLY = 54 | "com.example.android.wearable.wear.wearnotifications.handlers.extra.REPLY"; 55 | 56 | public MessagingIntentService() { 57 | super("MessagingIntentService"); 58 | } 59 | 60 | @Override 61 | protected void onHandleIntent(Intent intent) { 62 | Log.d(TAG, "onHandleIntent(): " + intent); 63 | 64 | if (intent != null) { 65 | final String action = intent.getAction(); 66 | if (ACTION_REPLY.equals(action)) { 67 | handleActionReply(getMessage(intent)); 68 | } 69 | } 70 | } 71 | 72 | /** Handles action for replying to messages from the notification. */ 73 | private void handleActionReply(CharSequence replyCharSequence) { 74 | Log.d(TAG, "handleActionReply(): " + replyCharSequence); 75 | 76 | if (replyCharSequence != null) { 77 | 78 | // TODO: Asynchronously save your message to Database and servers. 79 | 80 | /* 81 | * You have two options for updating your notification (this class uses approach #2): 82 | * 83 | * 1. Use a new NotificationCompatBuilder to create the Notification. This approach 84 | * requires you to get *ALL* the information that existed in the previous 85 | * Notification (and updates) and pass it to the builder. This is the approach used in 86 | * the MainActivity. 87 | * 88 | * 2. Use the original NotificationCompatBuilder to create the Notification. This 89 | * approach requires you to store a reference to the original builder. The benefit is 90 | * you only need the new/updated information. In our case, the reply from the user 91 | * which we already have here. 92 | * 93 | * IMPORTANT NOTE: You shouldn't save/modify the resulting Notification object using 94 | * its member variables and/or legacy APIs. If you want to retain anything from update 95 | * to update, retain the Builder as option 2 outlines. 96 | */ 97 | 98 | // Retrieves NotificationCompat.Builder used to create initial Notification 99 | NotificationCompat.Builder notificationCompatBuilder = 100 | GlobalNotificationBuilder.getNotificationCompatBuilderInstance(); 101 | 102 | // Recreate builder from persistent state if app process is killed 103 | if (notificationCompatBuilder == null) { 104 | // Note: New builder set globally in the method 105 | notificationCompatBuilder = recreateBuilderWithMessagingStyle(); 106 | } 107 | 108 | // Since we are adding to the MessagingStyle, we need to first retrieve the 109 | // current MessagingStyle from the Notification itself. 110 | Notification notification = notificationCompatBuilder.build(); 111 | MessagingStyle messagingStyle = 112 | NotificationCompat.MessagingStyle.extractMessagingStyleFromNotification( 113 | notification); 114 | 115 | // Add new message to the MessagingStyle. Set last parameter to null for responses 116 | // from user. 117 | messagingStyle.addMessage(replyCharSequence, System.currentTimeMillis(), (Person) null); 118 | 119 | // Updates the Notification 120 | notification = notificationCompatBuilder.setStyle(messagingStyle).build(); 121 | 122 | // Pushes out the updated Notification 123 | NotificationManagerCompat notificationManagerCompat = 124 | NotificationManagerCompat.from(getApplicationContext()); 125 | notificationManagerCompat.notify(MainActivity.NOTIFICATION_ID, notification); 126 | } 127 | } 128 | 129 | /* 130 | * Extracts CharSequence created from the RemoteInput associated with the Notification. 131 | */ 132 | private CharSequence getMessage(Intent intent) { 133 | Bundle remoteInput = RemoteInput.getResultsFromIntent(intent); 134 | if (remoteInput != null) { 135 | return remoteInput.getCharSequence(EXTRA_REPLY); 136 | } 137 | return null; 138 | } 139 | 140 | /* 141 | * This recreates the notification from the persistent state in case the app process was killed. 142 | * It is basically the same code for creating the Notification from MainActivity. 143 | */ 144 | private NotificationCompat.Builder recreateBuilderWithMessagingStyle() { 145 | 146 | // Main steps for building a MESSAGING_STYLE notification: 147 | // 0. Get your data 148 | // 1. Create/Retrieve Notification Channel for O and beyond devices (26+) 149 | // 2. Build the MESSAGING_STYLE 150 | // 3. Set up main Intent for notification 151 | // 4. Set up RemoteInput (users can input directly from notification) 152 | // 5. Build and issue the notification 153 | 154 | // 0. Get your data (everything unique per Notification) 155 | MockDatabase.MessagingStyleCommsAppData messagingStyleCommsAppData = 156 | MockDatabase.getMessagingStyleData(getApplicationContext()); 157 | 158 | // 1. Create/Retrieve Notification Channel for O and beyond devices (26+). 159 | String notificationChannelId = 160 | NotificationUtil.createNotificationChannel(this, messagingStyleCommsAppData); 161 | 162 | // 2. Build the NotificationCompat.Style (MESSAGING_STYLE). 163 | String contentTitle = messagingStyleCommsAppData.getContentTitle(); 164 | 165 | MessagingStyle messagingStyle = 166 | new MessagingStyle(messagingStyleCommsAppData.getMe()) 167 | /* 168 | *

This API's behavior was changed in SDK version 169 | * {@link Build.VERSION_CODES#P}. If your application's target version is 170 | * less than {@link Build.VERSION_CODES#P}, setting a conversation title to 171 | * a non-null value will make {@link #isGroupConversation()} return 172 | * {@code true} and passing {@code null} will make it return {@code false}. 173 | * This behavior can be overridden by calling 174 | * {@link #setGroupConversation(boolean)} regardless of SDK version. 175 | * In {@code P} and above, this method does not affect group conversation 176 | * settings. 177 | * 178 | * In our case, we use the same title. 179 | */ 180 | .setConversationTitle(contentTitle); 181 | 182 | // Adds all Messages. 183 | // Note: Messages include the text, timestamp, and sender. 184 | for (MessagingStyle.Message message : messagingStyleCommsAppData.getMessages()) { 185 | messagingStyle.addMessage(message); 186 | } 187 | 188 | messagingStyle.setGroupConversation(messagingStyleCommsAppData.isGroupConversation()); 189 | 190 | // 3. Set up main Intent for notification. 191 | Intent notifyIntent = new Intent(this, MessagingMainActivity.class); 192 | 193 | // When creating your Intent, you need to take into account the back state, i.e., what 194 | // happens after your Activity launches and the user presses the back button. 195 | 196 | // There are two options: 197 | // 1. Regular activity - You're starting an Activity that's part of the application's 198 | // normal workflow. 199 | 200 | // 2. Special activity - The user only sees this Activity if it's started from a 201 | // notification. In a sense, the Activity extends the notification by providing 202 | // information that would be hard to display in the notification itself. 203 | 204 | // Even though this sample's MainActivity doesn't link to the Activity this Notification 205 | // launches directly, i.e., it isn't part of the normal workflow, a chat app generally 206 | // always links to individual conversations as part of the app flow, so we will follow 207 | // option 1. 208 | 209 | // For an example of option 2, check out the BIG_TEXT_STYLE example. 210 | 211 | // For more information, check out our dev article: 212 | // https://developer.android.com/training/notify-user/navigation.html 213 | 214 | TaskStackBuilder stackBuilder = TaskStackBuilder.create(this); 215 | // Adds the back stack 216 | stackBuilder.addParentStack(MessagingMainActivity.class); 217 | // Adds the Intent to the top of the stack 218 | stackBuilder.addNextIntent(notifyIntent); 219 | // Gets a PendingIntent containing the entire back stack 220 | PendingIntent mainPendingIntent = 221 | PendingIntent.getActivity(this, 0, notifyIntent, PendingIntent.FLAG_UPDATE_CURRENT); 222 | 223 | // 4. Set up RemoteInput, so users can input (keyboard and voice) from notification. 224 | 225 | // Note: For API <24 (M and below) we need to use an Activity, so the lock-screen present 226 | // the auth challenge. For API 24+ (N and above), we use a Service (could be a 227 | // BroadcastReceiver), so the user can input from Notification or lock-screen (they have 228 | // choice to allow) without leaving the notification. 229 | 230 | // Create the RemoteInput specifying this key. 231 | String replyLabel = getString(R.string.reply_label); 232 | RemoteInput remoteInput = 233 | new RemoteInput.Builder(MessagingIntentService.EXTRA_REPLY) 234 | .setLabel(replyLabel) 235 | // Use machine learning to create responses based on previous messages. 236 | .setChoices(messagingStyleCommsAppData.getReplyChoicesBasedOnLastMessage()) 237 | .build(); 238 | 239 | // Pending intent = 240 | // API <24 (M and below): activity so the lock-screen presents the auth challenge. 241 | // API 24+ (N and above): this should be a Service or BroadcastReceiver. 242 | PendingIntent replyActionPendingIntent; 243 | 244 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { 245 | Intent intent = new Intent(this, MessagingIntentService.class); 246 | intent.setAction(MessagingIntentService.ACTION_REPLY); 247 | replyActionPendingIntent = PendingIntent.getService(this, 0, intent, 0); 248 | 249 | } else { 250 | replyActionPendingIntent = mainPendingIntent; 251 | } 252 | 253 | NotificationCompat.Action replyAction = 254 | new NotificationCompat.Action.Builder( 255 | R.drawable.ic_reply_white_18dp, 256 | replyLabel, 257 | replyActionPendingIntent) 258 | .addRemoteInput(remoteInput) 259 | // Informs system we aren't bringing up our own custom UI for a reply 260 | // action. 261 | .setShowsUserInterface(false) 262 | // Allows system to generate replies by context of conversation. 263 | .setAllowGeneratedReplies(true) 264 | .setSemanticAction(Action.SEMANTIC_ACTION_REPLY) 265 | .build(); 266 | 267 | // 5. Build and issue the notification. 268 | 269 | // Because we want this to be a new notification (not updating current notification), we 270 | // create a new Builder. Later, we update this same notification, so we need to save this 271 | // Builder globally (as outlined earlier). 272 | 273 | NotificationCompat.Builder notificationCompatBuilder = 274 | new NotificationCompat.Builder(getApplicationContext(), notificationChannelId); 275 | 276 | GlobalNotificationBuilder.setNotificationCompatBuilderInstance(notificationCompatBuilder); 277 | 278 | notificationCompatBuilder 279 | // MESSAGING_STYLE sets title and content for API 16 and above devices. 280 | .setStyle(messagingStyle) 281 | // Title for API < 16 devices. 282 | .setContentTitle(contentTitle) 283 | // Content for API < 16 devices. 284 | .setContentText(messagingStyleCommsAppData.getContentText()) 285 | .setSmallIcon(R.drawable.ic_launcher) 286 | .setLargeIcon( 287 | BitmapFactory.decodeResource( 288 | getResources(), R.drawable.ic_person_black_48dp)) 289 | .setContentIntent(mainPendingIntent) 290 | .setDefaults(NotificationCompat.DEFAULT_ALL) 291 | // Set primary color (important for Wear 2.0 Notifications). 292 | .setColor(ContextCompat.getColor(getApplicationContext(), R.color.colorPrimary)) 293 | 294 | // SIDE NOTE: Auto-bundling is enabled for 4 or more notifications on API 24+ (N+) 295 | // devices and all Wear devices. If you have more than one notification and 296 | // you prefer a different summary notification, set a group key and create a 297 | // summary notification via 298 | // .setGroupSummary(true) 299 | // .setGroup(GROUP_KEY_YOUR_NAME_HERE) 300 | 301 | // Number of new notifications for API <24 (M and below) devices. 302 | .setSubText(Integer.toString(messagingStyleCommsAppData.getNumberOfNewMessages())) 303 | .addAction(replyAction) 304 | .setCategory(Notification.CATEGORY_MESSAGE) 305 | 306 | // Sets priority for 25 and below. For 26 and above, 'priority' is deprecated for 307 | // 'importance' which is set in the NotificationChannel. The integers representing 308 | // 'priority' are different from 'importance', so make sure you don't mix them. 309 | .setPriority(messagingStyleCommsAppData.getPriority()) 310 | 311 | // Sets lock-screen visibility for 25 and below. For 26 and above, lock screen 312 | // visibility is set in the NotificationChannel. 313 | .setVisibility(messagingStyleCommsAppData.getChannelLockscreenVisibility()); 314 | 315 | // If the phone is in "Do not disturb" mode, the user may still be notified if the 316 | // sender(s) are in a group allowed through "Do not disturb" by the user. 317 | for (Person name : messagingStyleCommsAppData.getParticipants()) { 318 | notificationCompatBuilder.addPerson(name.getUri()); 319 | } 320 | 321 | return notificationCompatBuilder; 322 | } 323 | } 324 | -------------------------------------------------------------------------------- /Application/src/main/java/com/example/android/wearable/wear/wearnotifications/handlers/MessagingMainActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 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 | package com.example.android.wearable.wear.wearnotifications.handlers; 17 | 18 | import android.app.Activity; 19 | import android.app.NotificationManager; 20 | import android.content.Context; 21 | import android.os.Bundle; 22 | 23 | import com.example.android.wearable.wear.wearnotifications.MainActivity; 24 | import com.example.android.wearable.wear.wearnotifications.R; 25 | 26 | /** 27 | * Template class meant to include functionality for your Messaging App. (This project's main focus 28 | * is on Notification Styles.) 29 | */ 30 | public class MessagingMainActivity extends Activity { 31 | 32 | private static final String TAG = "MessagingMainActivity"; 33 | 34 | @Override 35 | protected void onCreate(Bundle savedInstanceState) { 36 | super.onCreate(savedInstanceState); 37 | setContentView(R.layout.activity_messaging_main); 38 | 39 | // Cancel Notification 40 | NotificationManager notificationManager = 41 | (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); 42 | 43 | notificationManager.cancel(MainActivity.NOTIFICATION_ID); 44 | 45 | // TODO: Handle and display message/conversation from your database 46 | // NOTE: You can retrieve the EXTRA_REMOTE_INPUT_DRAFT sent by the system when a user 47 | // inadvertently closes a messaging notification to pre-populate the reply text field so 48 | // the user can finish their reply. 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Application/src/main/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googlearchive/android-Notifications/8478e47fce7d56d90a967ba16934f291b3fcdce8/Application/src/main/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /Application/src/main/res/drawable-hdpi/tile.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googlearchive/android-Notifications/8478e47fce7d56d90a967ba16934f291b3fcdce8/Application/src/main/res/drawable-hdpi/tile.9.png -------------------------------------------------------------------------------- /Application/src/main/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googlearchive/android-Notifications/8478e47fce7d56d90a967ba16934f291b3fcdce8/Application/src/main/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /Application/src/main/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googlearchive/android-Notifications/8478e47fce7d56d90a967ba16934f291b3fcdce8/Application/src/main/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /Application/src/main/res/drawable-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googlearchive/android-Notifications/8478e47fce7d56d90a967ba16934f291b3fcdce8/Application/src/main/res/drawable-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /Application/src/main/res/drawable-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googlearchive/android-Notifications/8478e47fce7d56d90a967ba16934f291b3fcdce8/Application/src/main/res/drawable-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /Application/src/main/res/layout/activity_big_picture_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 27 | 28 | 37 | 38 | -------------------------------------------------------------------------------- /Application/src/main/res/layout/activity_big_text_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 27 | 28 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /Application/src/main/res/layout/activity_inbox_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 27 | 28 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /Application/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 28 | 29 | 34 | 35 | 43 | 44 | 53 | 54 |