Skip to content

Most visited

Recently visited

navigation
WearNotifications / Application / src / 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.support.v4.app.NotificationCompat.MessagingStyle;
26
import android.support.v4.app.NotificationManagerCompat;
27
import android.support.v4.app.RemoteInput;
28
import android.support.v4.app.TaskStackBuilder;
29
import android.support.v7.app.NotificationCompat;
30
import android.util.Log;
31
 
32
import com.example.android.wearable.wear.wearnotifications.GlobalNotificationBuilder;
33
import com.example.android.wearable.wear.wearnotifications.MainActivity;
34
import com.example.android.wearable.wear.wearnotifications.R;
35
import com.example.android.wearable.wear.wearnotifications.mock.MockDatabase;
36
 
37
/**
38
 * Asynchronously handles updating messaging app posts (and active Notification) with replies from
39
 * user in a conversation. Notification for social app use MessagingStyle.
40
 */
41
public class MessagingIntentService extends IntentService {
42
 
43
    private static final String TAG = "MessagingIntentService";
44
 
45
    public static final String ACTION_REPLY =
46
            "com.example.android.wearable.wear.wearnotifications.handlers.action.REPLY";
47
 
48
    public static final String EXTRA_REPLY =
49
            "com.example.android.wearable.wear.wearnotifications.handlers.extra.REPLY";
50
 
51
 
52
    public MessagingIntentService() {
53
        super("MessagingIntentService");
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_REPLY.equals(action)) {
63
                handleActionReply(getMessage(intent));
64
            }
65
        }
66
    }
67
 
68
    /**
69
     * Handles action for replying to messages from the notification.
70
     */
71
    private void handleActionReply(CharSequence replyCharSequence) {
72
        Log.d(TAG, "handleActionReply(): " + replyCharSequence);
73
 
74
        if (replyCharSequence != 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 reply from the user
89
             *  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 = recreateBuilderWithMessagingStyle();
104
            }
105
 
106
 
107
            // Since we are adding to the MessagingStyle, we need to first retrieve the
108
            // current MessagingStyle from the Notification itself.
109
            Notification notification = notificationCompatBuilder.build();
110
            MessagingStyle messagingStyle =
111
                    NotificationCompat.MessagingStyle
112
                            .extractMessagingStyleFromNotification(notification);
113
 
114
            // Add new message to the MessagingStyle
115
            messagingStyle.addMessage(replyCharSequence, System.currentTimeMillis(), null);
116
 
117
            // Updates the Notification
118
            notification = notificationCompatBuilder
119
                    .setStyle(messagingStyle)
120
                    .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 (for more detailed comments on
147
        // building this notification, check MainActivity.java)::
148
        //      0. Get your data
149
        //      1. Build the MESSAGING_STYLE
150
        //      2. Add support for Wear 1.+
151
        //      3. Set up main Intent for notification
152
        //      4. Set up RemoteInput (users can input directly from notification)
153
        //      5. Build and issue the notification
154
 
155
        // 0. Get your data
156
        MockDatabase.MessagingStyleCommsAppData messagingData =
157
                MockDatabase.getMessagingStyleData();
158
 
159
        // 1. Build the Notification.Style (MESSAGING_STYLE)
160
        String contentTitle = messagingData.getContentTitle();
161
 
162
        MessagingStyle messagingStyle =
163
                new NotificationCompat.MessagingStyle(messagingData.getReplayName())
164
                        .setConversationTitle(contentTitle);
165
 
166
        // Adds all Messages
167
        // Note: Messages include the text, timestamp, and sender
168
        for (MessagingStyle.Message message : messagingData.getMessages()) {
169
            messagingStyle.addMessage(message);
170
        }
171
 
172
 
173
        // 2. Add support for Wear 1.+
174
        String fullMessageForWearVersion1 = messagingData.getFullConversation();
175
 
176
        Notification chatHistoryForWearV1 = new NotificationCompat.Builder(getApplicationContext())
177
                .setStyle(new NotificationCompat.BigTextStyle().bigText(fullMessageForWearVersion1))
178
                .setContentTitle(contentTitle)
179
                .setSmallIcon(R.drawable.ic_launcher)
180
                .setContentText(fullMessageForWearVersion1)
181
                .build();
182
 
183
        NotificationCompat.WearableExtender wearableExtenderForWearVersion1 =
184
                new NotificationCompat.WearableExtender()
185
                        .addPage(chatHistoryForWearV1);
186
 
187
 
188
 
189
        // 3. Set up main Intent for notification
190
        Intent notifyIntent = new Intent(this, MessagingMainActivity.class);
191
 
192
        TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
193
        stackBuilder.addParentStack(MessagingMainActivity.class);
194
        stackBuilder.addNextIntent(notifyIntent);
195
 
196
        PendingIntent mainPendingIntent =
197
                PendingIntent.getActivity(
198
                        this,
199
                        0,
200
                        notifyIntent,
201
                        PendingIntent.FLAG_UPDATE_CURRENT
202
                );
203
 
204
 
205
        // 4. Set up RemoteInput, so users can input (keyboard and voice) from notification
206
        String replyLabel = getString(R.string.reply_label);
207
        RemoteInput remoteInput = new RemoteInput.Builder(MessagingIntentService.EXTRA_REPLY)
208
                .setLabel(replyLabel)
209
                .build();
210
 
211
        PendingIntent replyActionPendingIntent;
212
 
213
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
214
            Intent intent = new Intent(this, MessagingIntentService.class);
215
            intent.setAction(MessagingIntentService.ACTION_REPLY);
216
            replyActionPendingIntent = PendingIntent.getService(this, 0, intent, 0);
217
 
218
        } else {
219
            replyActionPendingIntent = mainPendingIntent;
220
        }
221
 
222
        NotificationCompat.Action replyAction =
223
                new NotificationCompat.Action.Builder(
224
                        R.drawable.ic_reply_white_18dp,
225
                        replyLabel,
226
                        replyActionPendingIntent)
227
                        .addRemoteInput(remoteInput)
228
                        // Allows system to generate replies by context of conversation
229
                        .setAllowGeneratedReplies(true)
230
                        .build();
231
 
232
 
233
        // 5. Build and issue the notification
234
        NotificationCompat.Builder notificationCompatBuilder =
235
                new NotificationCompat.Builder(getApplicationContext());
236
 
237
        GlobalNotificationBuilder.setNotificationCompatBuilderInstance(notificationCompatBuilder);
238
 
239
        notificationCompatBuilder
240
                .setStyle(messagingStyle)
241
                .setContentTitle(contentTitle)
242
                .setContentText(messagingData.getContentText())
243
                .setSmallIcon(R.drawable.ic_launcher)
244
                .setLargeIcon(BitmapFactory.decodeResource(
245
                        getResources(),
246
                        R.drawable.ic_person_black_48dp))
247
                .setContentIntent(mainPendingIntent)
248
                .setColor(getResources().getColor(R.color.colorPrimary))
249
                .setSubText(Integer.toString(messagingData.getNumberOfNewMessages()))
250
                .addAction(replyAction)
251
                .setCategory(Notification.CATEGORY_MESSAGE)
252
                .setPriority(Notification.PRIORITY_HIGH)
253
                .setVisibility(Notification.VISIBILITY_PRIVATE)
254
                .extend(wearableExtenderForWearVersion1);
255
 
256
        for (String name : messagingData.getParticipants()) {
257
            notificationCompatBuilder.addPerson(name);
258
        }
259
 
260
        return notificationCompatBuilder;
261
    }
262
}
This site uses cookies to store your preferences for site-specific language and display options.