Skip to content

Most visited

Recently visited

navigation
WearNotifications / Wearable / 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.Bundle;
24
import android.support.v4.app.NotificationCompat.MessagingStyle;
25
import android.support.v4.app.NotificationManagerCompat;
26
import android.support.v4.app.RemoteInput;
27
import android.support.v7.app.NotificationCompat;
28
import android.util.Log;
29
 
30
import com.example.android.wearable.wear.wearnotifications.GlobalNotificationBuilder;
31
import com.example.android.wearable.wear.wearnotifications.R;
32
import com.example.android.wearable.wear.wearnotifications.StandaloneMainActivity;
33
import com.example.android.wearable.wear.wearnotifications.mock.MockDatabase;
34
 
35
/**
36
 * Asynchronously handles updating messaging app posts (and active Notification) with replies from
37
 * user in a conversation. Notification for social app use MessagingStyle.
38
 */
39
public class MessagingIntentService extends IntentService {
40
 
41
    private static final String TAG = "MessagingIntentService";
42
 
43
    public static final String ACTION_REPLY =
44
            "com.example.android.wearable.wear.wearnotifications.handlers.action.REPLY";
45
 
46
    public static final String EXTRA_REPLY =
47
            "com.example.android.wearable.wear.wearnotifications.handlers.extra.REPLY";
48
 
49
 
50
    public MessagingIntentService() {
51
        super("MessagingIntentService");
52
    }
53
 
54
    @Override
55
    protected void onHandleIntent(Intent intent) {
56
        Log.d(TAG, "onHandleIntent(): " + intent);
57
 
58
        if (intent != null) {
59
            final String action = intent.getAction();
60
            if (ACTION_REPLY.equals(action)) {
61
                handleActionReply(getMessage(intent));
62
            }
63
        }
64
    }
65
 
66
    /**
67
     * Handles action for replying to messages from the notification.
68
     */
69
    private void handleActionReply(CharSequence replyCharSequence) {
70
        Log.d(TAG, "handleActionReply(): " + replyCharSequence);
71
 
72
        if (replyCharSequence != null) {
73
 
74
            // TODO: Asynchronously save your message to Database and servers.
75
 
76
            /*
77
             * You have two options for updating your notification (this class uses approach #2):
78
             *
79
             *  1. Use a new NotificationCompatBuilder to create the Notification. This approach
80
             *  requires you to get *ALL* the information that existed in the previous
81
             *  Notification (and updates) and pass it to the builder. This is the approach used in
82
             *  the MainActivity.
83
             *
84
             *  2. Use the original NotificationCompatBuilder to create the Notification. This
85
             *  approach requires you to store a reference to the original builder. The benefit is
86
             *  you only need the new/updated information. In our case, the reply from the user
87
             *  which we already have here.
88
             *
89
             *  IMPORTANT NOTE: You shouldn't save/modify the resulting Notification object using
90
             *  its member variables and/or legacy APIs. If you want to retain anything from update
91
             *  to update, retain the Builder as option 2 outlines.
92
             */
93
 
94
            // Retrieves NotificationCompat.Builder used to create initial Notification
95
            NotificationCompat.Builder notificationCompatBuilder =
96
                    GlobalNotificationBuilder.getNotificationCompatBuilderInstance();
97
 
98
            // Recreate builder from persistent state if app process is killed
99
            if (notificationCompatBuilder == null) {
100
                // Note: New builder set globally in the method
101
                notificationCompatBuilder = recreateBuilderWithMessagingStyle();
102
            }
103
 
104
 
105
            // Since we are adding to the MessagingStyle, we need to first retrieve the
106
            // current MessagingStyle from the Notification itself.
107
            Notification notification = notificationCompatBuilder.build();
108
            MessagingStyle messagingStyle =
109
                    NotificationCompat.MessagingStyle
110
                            .extractMessagingStyleFromNotification(notification);
111
 
112
            // Add new message to the MessagingStyle
113
            messagingStyle.addMessage(replyCharSequence, System.currentTimeMillis(), null);
114
 
115
            // Updates the Notification
116
            notification = notificationCompatBuilder
117
                    .setStyle(messagingStyle)
118
                    .build();
119
 
120
            // Pushes out the updated Notification
121
            NotificationManagerCompat notificationManagerCompat =
122
                    NotificationManagerCompat.from(getApplicationContext());
123
            notificationManagerCompat.notify(StandaloneMainActivity.NOTIFICATION_ID, notification);
124
        }
125
    }
126
 
127
    /*
128
     * Extracts CharSequence created from the RemoteInput associated with the Notification.
129
     */
130
    private CharSequence getMessage(Intent intent) {
131
        Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);
132
        if (remoteInput != null) {
133
            return remoteInput.getCharSequence(EXTRA_REPLY);
134
        }
135
        return null;
136
    }
137
 
138
    /*
139
     * This recreates the notification from the persistent state in case the app process was killed.
140
     * It is basically the same code for creating the Notification from MainActivity.
141
     */
142
    private NotificationCompat.Builder recreateBuilderWithMessagingStyle() {
143
 
144
        // Main steps for building a MESSAGING_STYLE notification (for more detailed comments on
145
        // building this notification, check StandaloneMainActivity.java)::
146
        //      0. Get your data
147
        //      1. Build the MESSAGING_STYLE
148
        //      2. Add support for Wear 1.+
149
        //      3. Set up main Intent for notification
150
        //      4. Set up RemoteInput (users can input directly from notification)
151
        //      5. Build and issue the notification
152
 
153
        // 0. Get your data (everything unique per Notification)
154
        MockDatabase.MessagingStyleCommsAppData messagingStyleCommsAppData =
155
                MockDatabase.getMessagingStyleData();
156
 
157
        // 1. Build the Notification.Style (MESSAGING_STYLE)
158
        String contentTitle = messagingStyleCommsAppData.getContentTitle();
159
 
160
        MessagingStyle messagingStyle =
161
                new NotificationCompat.MessagingStyle(messagingStyleCommsAppData.getReplayName())
162
                        .setConversationTitle(contentTitle);
163
 
164
        // Adds all Messages
165
        for (MessagingStyle.Message message : messagingStyleCommsAppData.getMessages()) {
166
            messagingStyle.addMessage(message);
167
        }
168
 
169
 
170
        // 2. Add support for Wear 1.+.
171
        String fullMessageForWearVersion1 = messagingStyleCommsAppData.getFullConversation();
172
 
173
        Notification chatHistoryForWearV1 = new NotificationCompat.Builder(getApplicationContext())
174
                .setStyle(new NotificationCompat.BigTextStyle().bigText(fullMessageForWearVersion1))
175
                .setContentTitle(contentTitle)
176
                .setSmallIcon(R.drawable.ic_launcher)
177
                .setContentText(fullMessageForWearVersion1)
178
                .build();
179
 
180
        // Adds page with all text to support Wear 1.+.
181
        NotificationCompat.WearableExtender wearableExtenderForWearVersion1 =
182
                new NotificationCompat.WearableExtender()
183
                        .setHintContentIntentLaunchesActivity(true)
184
                        .addPage(chatHistoryForWearV1);
185
 
186
        // 3. Set up main Intent for notification
187
        Intent notifyIntent = new Intent(this, MessagingMainActivity.class);
188
 
189
        PendingIntent mainPendingIntent =
190
                PendingIntent.getActivity(
191
                        this,
192
                        0,
193
                        notifyIntent,
194
                        PendingIntent.FLAG_UPDATE_CURRENT
195
                );
196
 
197
 
198
        // 4. Set up a RemoteInput Action, so users can input (keyboard, drawing, voice) directly
199
        // from the notification without entering the app.
200
        String replyLabel = getString(R.string.reply_label);
201
        RemoteInput remoteInput = new RemoteInput.Builder(MessagingIntentService.EXTRA_REPLY)
202
                .setLabel(replyLabel)
203
                .build();
204
 
205
        Intent replyIntent = new Intent(this, MessagingIntentService.class);
206
        replyIntent.setAction(MessagingIntentService.ACTION_REPLY);
207
        PendingIntent replyActionPendingIntent = PendingIntent.getService(this, 0, replyIntent, 0);
208
 
209
        // Enable action to appear inline on Wear 2.0 (24+). This means it will appear over the
210
        // lower portion of the Notification for easy action (only possible for one action).
211
        final NotificationCompat.Action.WearableExtender inlineActionForWear2_0 =
212
                new NotificationCompat.Action.WearableExtender()
213
                        .setHintDisplayActionInline(true)
214
                        .setHintLaunchesActivity(false);
215
 
216
        NotificationCompat.Action replyAction =
217
                new NotificationCompat.Action.Builder(
218
                        R.drawable.ic_reply_white_18dp,
219
                        replyLabel,
220
                        replyActionPendingIntent)
221
                        .addRemoteInput(remoteInput)
222
                        // Allows system to generate replies by context of conversation
223
                        .setAllowGeneratedReplies(true)
224
                        // Add WearableExtender to enable inline actions
225
                        .extend(inlineActionForWear2_0)
226
                        .build();
227
 
228
 
229
        // 5. Build and issue the notification
230
        NotificationCompat.Builder notificationCompatBuilder =
231
                new NotificationCompat.Builder(getApplicationContext());
232
 
233
        GlobalNotificationBuilder.setNotificationCompatBuilderInstance(notificationCompatBuilder);
234
 
235
        // Builds and issues notification
236
        notificationCompatBuilder
237
                .setStyle(messagingStyle)
238
                .setContentTitle(contentTitle)
239
                .setContentText(messagingStyleCommsAppData.getContentText())
240
                .setSmallIcon(R.drawable.ic_launcher)
241
                .setLargeIcon(BitmapFactory.decodeResource(
242
                        getResources(),
243
                        R.drawable.ic_person_black_48dp))
244
                .setContentIntent(mainPendingIntent)
245
                .setColor(getResources().getColor(R.color.colorPrimary))
246
                .setSubText(Integer.toString(messagingStyleCommsAppData.getNumberOfNewMessages()))
247
                .addAction(replyAction)
248
                .setCategory(Notification.CATEGORY_MESSAGE)
249
                .setPriority(Notification.PRIORITY_HIGH)
250
                .setVisibility(Notification.VISIBILITY_PRIVATE)
251
                .extend(wearableExtenderForWearVersion1);
252
 
253
        for (String name : messagingStyleCommsAppData.getParticipants()) {
254
            notificationCompatBuilder.addPerson(name);
255
        }
256
 
257
        return notificationCompatBuilder;
258
    }
259
}
This site uses cookies to store your preferences for site-specific language and display options.