Home | History | Annotate | Download | only in messagingservice
      1 /*
      2  * Copyright (C) 2014 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 
     17 package com.example.android.messagingservice;
     18 
     19 import android.app.PendingIntent;
     20 import android.app.Service;
     21 import android.content.Intent;
     22 import android.graphics.BitmapFactory;
     23 import android.os.Handler;
     24 import android.os.IBinder;
     25 import android.os.Message;
     26 import android.os.Messenger;
     27 import android.support.v4.app.NotificationCompat.CarExtender;
     28 import android.support.v4.app.NotificationCompat.CarExtender.UnreadConversation;
     29 import android.support.v4.app.NotificationCompat;
     30 import android.support.v4.app.NotificationManagerCompat;
     31 import android.support.v4.app.RemoteInput;
     32 import android.util.Log;
     33 
     34 import java.util.Iterator;
     35 
     36 public class MessagingService extends Service {
     37     private static final String TAG = MessagingService.class.getSimpleName();
     38 
     39     public static final String READ_ACTION =
     40             "com.example.android.messagingservice.ACTION_MESSAGE_READ";
     41     public static final String REPLY_ACTION =
     42             "com.example.android.messagingservice.ACTION_MESSAGE_REPLY";
     43     public static final String CONVERSATION_ID = "conversation_id";
     44     public static final String EXTRA_VOICE_REPLY = "extra_voice_reply";
     45     public static final int MSG_SEND_NOTIFICATION = 1;
     46     public static final String EOL = "\n";
     47 
     48     private NotificationManagerCompat mNotificationManager;
     49 
     50     private final Messenger mMessenger = new Messenger(new IncomingHandler());
     51 
     52     /**
     53      * Handler of incoming messages from clients.
     54      */
     55     class IncomingHandler extends Handler {
     56         @Override
     57         public void handleMessage(Message msg) {
     58             switch (msg.what) {
     59                 case MSG_SEND_NOTIFICATION:
     60                     int howManyConversations = msg.arg1 <= 0 ? 1 : msg.arg1;
     61                     int messagesPerConv = msg.arg2 <= 0 ? 1 : msg.arg2;
     62                     sendNotification(howManyConversations, messagesPerConv);
     63                     break;
     64                 default:
     65                     super.handleMessage(msg);
     66             }
     67         }
     68     }
     69 
     70     @Override
     71     public void onCreate() {
     72         Log.d(TAG, "onCreate");
     73         mNotificationManager = NotificationManagerCompat.from(getApplicationContext());
     74     }
     75 
     76     @Override
     77     public IBinder onBind(Intent intent) {
     78         Log.d(TAG, "onBind");
     79         return mMessenger.getBinder();
     80     }
     81 
     82     @Override
     83     public int onStartCommand(Intent intent, int flags, int startId) {
     84         Log.d(TAG, "onStartCommand");
     85         return START_STICKY;
     86     }
     87 
     88     @Override
     89     public void onDestroy() {
     90         super.onDestroy();
     91         Log.d(TAG, "onDestroy");
     92     }
     93 
     94     // Creates an intent that will be triggered when a message is marked as read.
     95     private Intent getMessageReadIntent(int id) {
     96         return new Intent()
     97                 .addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES)
     98                 .setAction(READ_ACTION)
     99                 .putExtra(CONVERSATION_ID, id);
    100     }
    101 
    102     // Creates an Intent that will be triggered when a voice reply is received.
    103     private Intent getMessageReplyIntent(int conversationId) {
    104         return new Intent()
    105                 .addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES)
    106                 .setAction(REPLY_ACTION)
    107                 .putExtra(CONVERSATION_ID, conversationId);
    108     }
    109 
    110     private void sendNotification(int howManyConversations, int messagesPerConversation) {
    111         Conversations.Conversation[] conversations = Conversations.getUnreadConversations(
    112                 howManyConversations, messagesPerConversation);
    113         for (Conversations.Conversation conv : conversations) {
    114             sendNotificationForConversation(conv);
    115         }
    116     }
    117 
    118     private void sendNotificationForConversation(Conversations.Conversation conversation) {
    119         // A pending Intent for reads
    120         PendingIntent readPendingIntent = PendingIntent.getBroadcast(getApplicationContext(),
    121                 conversation.getConversationId(),
    122                 getMessageReadIntent(conversation.getConversationId()),
    123                 PendingIntent.FLAG_UPDATE_CURRENT);
    124 
    125         // Build a RemoteInput for receiving voice input in a Car Notification
    126         RemoteInput remoteInput = new RemoteInput.Builder(EXTRA_VOICE_REPLY)
    127                 .setLabel(getApplicationContext().getString(R.string.notification_reply))
    128                 .build();
    129 
    130         // Building a Pending Intent for the reply action to trigger
    131         PendingIntent replyIntent = PendingIntent.getBroadcast(getApplicationContext(),
    132                 conversation.getConversationId(),
    133                 getMessageReplyIntent(conversation.getConversationId()),
    134                 PendingIntent.FLAG_UPDATE_CURRENT);
    135 
    136         // Create the UnreadConversation and populate it with the participant name,
    137         // read and reply intents.
    138         UnreadConversation.Builder unreadConvBuilder =
    139                 new UnreadConversation.Builder(conversation.getParticipantName())
    140                 .setLatestTimestamp(conversation.getTimestamp())
    141                 .setReadPendingIntent(readPendingIntent)
    142                 .setReplyAction(replyIntent, remoteInput);
    143 
    144         // Note: Add messages from oldest to newest to the UnreadConversation.Builder
    145         StringBuilder messageForNotification = new StringBuilder();
    146         for (Iterator<String> messages = conversation.getMessages().iterator();
    147              messages.hasNext(); ) {
    148             String message = messages.next();
    149             unreadConvBuilder.addMessage(message);
    150             messageForNotification.append(message);
    151             if (messages.hasNext()) {
    152                 messageForNotification.append(EOL);
    153             }
    154         }
    155 
    156         NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext())
    157                 .setSmallIcon(R.drawable.notification_icon)
    158                 .setLargeIcon(BitmapFactory.decodeResource(
    159                         getApplicationContext().getResources(), R.drawable.android_contact))
    160                 .setContentText(messageForNotification.toString())
    161                 .setWhen(conversation.getTimestamp())
    162                 .setContentTitle(conversation.getParticipantName())
    163                 .setContentIntent(readPendingIntent)
    164                 .extend(new CarExtender()
    165                         .setUnreadConversation(unreadConvBuilder.build())
    166                         .setColor(getApplicationContext()
    167                                 .getResources().getColor(R.color.default_color_light)));
    168 
    169         MessageLogger.logMessage(getApplicationContext(), "Sending notification "
    170                 + conversation.getConversationId() + " conversation: " + conversation);
    171 
    172         mNotificationManager.notify(conversation.getConversationId(), builder.build());
    173     }
    174 }
    175