NotificationService.java revision e6ea907e7cf8eb8f8ab04f238ab834ba970b4f45
1/*
2 * Copyright (C) 2013 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
17package com.android.example.notificationshowcase;
18
19import android.app.AlarmManager;
20import android.app.IntentService;
21import android.app.Notification;
22import android.app.NotificationManager;
23import android.app.PendingIntent;
24import android.content.ComponentName;
25import android.content.ContentResolver;
26import android.content.Context;
27import android.content.Intent;
28import android.content.SharedPreferences;
29import android.database.Cursor;
30import android.graphics.Bitmap;
31import android.graphics.Canvas;
32import android.graphics.Typeface;
33import android.graphics.drawable.BitmapDrawable;
34import android.graphics.drawable.Drawable;
35import android.net.Uri;
36import android.os.SystemClock;
37import android.provider.ContactsContract;
38import android.support.v4.app.NotificationCompat;
39import android.support.v7.preference.PreferenceManager;
40import android.text.SpannableString;
41import android.text.TextUtils;
42import android.text.style.StyleSpan;
43import android.util.Log;
44
45import com.android.example.notificationshowcase.R;
46
47import java.util.ArrayList;
48
49public class NotificationService extends IntentService {
50
51    private static final String TAG = "NotificationService";
52
53    public static final String ACTION_CREATE = "create";
54    public static final String ACTION_DESTROY = "destroy";
55    public static final int NOTIFICATION_ID = 31338;
56    private static final long FADE_TIME_MILLIS = 1000 * 60 * 5;
57
58    public NotificationService() {
59        super(TAG);
60    }
61
62    public NotificationService(String name) {
63        super(name);
64    }
65
66    private static PendingIntent makeCancelAllIntent(Context context) {
67        final Intent intent = new Intent(ACTION_DESTROY);
68        intent.setComponent(new ComponentName(context, NotificationService.class));
69        return PendingIntent.getService(
70                context, 0, intent,
71                PendingIntent.FLAG_UPDATE_CURRENT);
72    }
73
74    private static Bitmap getBitmap(Context context, int resId) {
75        int largeIconWidth = (int) context.getResources()
76                .getDimension(R.dimen.notification_large_icon_width);
77        int largeIconHeight = (int) context.getResources()
78                .getDimension(R.dimen.notification_large_icon_height);
79        Drawable d = context.getResources().getDrawable(resId);
80        Bitmap b = Bitmap.createBitmap(largeIconWidth, largeIconHeight, Bitmap.Config.ARGB_8888);
81        Canvas c = new Canvas(b);
82        d.setBounds(0, 0, largeIconWidth, largeIconHeight);
83        d.draw(c);
84        return b;
85    }
86
87    private static PendingIntent makeEmailIntent(Context context, String who) {
88        final Intent intent = new Intent(android.content.Intent.ACTION_SENDTO,
89                Uri.parse("mailto:" + who));
90        return PendingIntent.getActivity(
91                context, 0, intent,
92                PendingIntent.FLAG_CANCEL_CURRENT);
93    }
94
95    public static Notification makeSmsNotification(Context context, int update, int id, long when) {
96        final SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(context);
97        String sender = context.getString(R.string.sms_sender);
98
99        String personUri = null;
100        if (sharedPref.getBoolean(SettingsActivity.KEY_SMS_PERSON, false)) {
101            Cursor c = null;
102            try {
103                String[] projection = new String[] { ContactsContract.Contacts._ID,
104                        ContactsContract.Contacts.LOOKUP_KEY };
105                String selections = ContactsContract.Contacts.DISPLAY_NAME + " = ?";
106                String[] selectionArgs = { sender };
107                final ContentResolver contentResolver = context.getContentResolver();
108                c = contentResolver.query(ContactsContract.Contacts.CONTENT_URI,
109                        projection, selections, selectionArgs, null);
110                if (c != null && c.getCount() > 0) {
111                    c.moveToFirst();
112                    int lookupIdx = c.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY);
113                    int idIdx = c.getColumnIndex(ContactsContract.Contacts._ID);
114                    String lookupKey = c.getString(lookupIdx);
115                    long contactId = c.getLong(idIdx);
116                    Uri lookupUri = ContactsContract.Contacts.getLookupUri(contactId, lookupKey);
117                    personUri = lookupUri.toString();
118                }
119            } finally {
120                if (c != null) {
121                    c.close();
122                }
123            }
124        }
125
126        if (update > 2) {
127            when = System.currentTimeMillis();
128        }
129        final String priorityName = sharedPref.getString(SettingsActivity.KEY_SMS_PRIORITY, "0");
130        final int priority = Integer.valueOf(priorityName);
131        NotificationCompat.BigTextStyle bigTextStyle = new NotificationCompat.BigTextStyle();
132        bigTextStyle.bigText(context.getString(R.string.sms_message));
133        PendingIntent ci = ToastService.getPendingIntent(context, R.string.sms_click);
134        PendingIntent ai = UpdateService.getPendingIntent(context, update + 1, id, when);
135        NotificationCompat.Builder bigText = new NotificationCompat.Builder(context)
136                .setContentTitle(sender)
137                .setCategory(NotificationCompat.CATEGORY_MESSAGE)
138                .setContentIntent(ci)
139                .setContentText(context.getString(R.string.sms_message))
140                .setWhen(when)
141                .setLargeIcon(getBitmap(context, R.drawable.bucket))
142                .setPriority(priority)
143                .addAction(R.drawable.ic_media_next, context.getString(R.string.sms_reply), ai)
144                .setSmallIcon(R.drawable.stat_notify_talk_text)
145                .setStyle(bigTextStyle)
146                .setOnlyAlertOnce(true);
147
148        if (TextUtils.isEmpty(personUri)) {
149            Log.w(TAG, "failed to find contact for Mike Cleron");
150        } else {
151            bigText.addPerson(personUri);
152            Log.w(TAG, "Mike Cleron is " + personUri);
153        }
154
155        int defaults = 0;
156        if(sharedPref.getBoolean(SettingsActivity.KEY_SMS_NOISY, true)) {
157            String uri = sharedPref.getString(SettingsActivity.KEY_SMS_SOUND, null);
158            if(uri == null) {
159                defaults |= Notification.DEFAULT_SOUND;
160            } else {
161                bigText.setSound(Uri.parse(uri));
162            }
163        }
164        if(sharedPref.getBoolean(SettingsActivity.KEY_SMS_BUZZY, false)) {
165            defaults |= Notification.DEFAULT_VIBRATE;
166        }
167        bigText.setDefaults(defaults);
168
169        return bigText.build();
170    }
171
172    public static Notification makeUploadNotification(Context context, int progress, long when) {
173        PendingIntent pi = ToastService.getPendingIntent(context, R.string.upload_click);
174        NotificationCompat.Builder uploadNotification = new NotificationCompat.Builder(context)
175                .setContentTitle(context.getString(R.string.upload_title))
176                .setContentText(context.getString(R.string.upload_text))
177                .setCategory(NotificationCompat.CATEGORY_PROGRESS)
178                .setPriority(NotificationCompat.PRIORITY_MIN)
179                .setContentIntent(pi)
180                .setWhen(when)
181                .setSmallIcon(R.drawable.ic_menu_upload)
182                .setProgress(100, Math.min(progress, 100), false);
183        return uploadNotification.build();
184    }
185
186    @Override
187    protected void onHandleIntent(Intent intent) {
188        NotificationManager noMa =
189                (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
190        if (ACTION_DESTROY.equals(intent.getAction())) {
191            noMa.cancelAll();
192            return;
193        }
194
195        SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
196        ArrayList<Notification> mNotifications = new ArrayList<Notification>();
197
198        if(sharedPref.getBoolean(SettingsActivity.KEY_SMS_ENABLE, true)) {
199            final int id = mNotifications.size();
200            mNotifications.add(makeSmsNotification(this, 2, id, System.currentTimeMillis()));
201        }
202
203        if(sharedPref.getBoolean(SettingsActivity.KEY_UPLOAD_ENABLE, false)) {
204            final int id = mNotifications.size();
205            final long uploadWhen = System.currentTimeMillis();
206            mNotifications.add(makeUploadNotification(this, 10, uploadWhen));
207            ProgressService.startProgressUpdater(this, id, uploadWhen, 0);
208        }
209
210        if(sharedPref.getBoolean(SettingsActivity.KEY_PHONE_ENABLE, false)) {
211            final int id = mNotifications.size();
212            final PendingIntent fullscreen = FullScreenActivity.getPendingIntent(this, id);
213            PendingIntent ans = PhoneService.getPendingIntent(this, id,
214                    PhoneService.ACTION_ANSWER);
215            PendingIntent ign =
216                    PhoneService.getPendingIntent(this, id, PhoneService.ACTION_IGNORE);
217            NotificationCompat.Builder phoneCall = new NotificationCompat.Builder(this)
218                    .setContentTitle(getString(R.string.call_title))
219                    .setContentText(getString(R.string.call_text))
220                    .setLargeIcon(getBitmap(this, R.drawable.matias_hed))
221                    .setSmallIcon(R.drawable.stat_sys_phone_call)
222                    .setPriority(NotificationCompat.PRIORITY_MAX)
223                    .setCategory(NotificationCompat.CATEGORY_CALL)
224                    .setContentIntent(fullscreen)
225                    .addAction(R.drawable.ic_dial_action_call, getString(R.string.call_answer), ans)
226                    .addAction(R.drawable.ic_end_call, getString(R.string.call_ignore), ign)
227                    .setOngoing(true);
228
229            if(sharedPref.getBoolean(SettingsActivity.KEY_PHONE_FULLSCREEN, false)) {
230                phoneCall.setFullScreenIntent(fullscreen, true);
231            }
232
233            if(sharedPref.getBoolean(SettingsActivity.KEY_PHONE_NOISY, false)) {
234                phoneCall.setDefaults(Notification.DEFAULT_SOUND);
235            }
236
237            if (sharedPref.getBoolean(SettingsActivity.KEY_PHONE_PERSON, false)) {
238                phoneCall.addPerson(Uri.fromParts("tel",
239                        "1 (617) 555-1212", null)
240                        .toString());
241            }
242            mNotifications.add(phoneCall.build());
243        }
244
245        if(sharedPref.getBoolean(SettingsActivity.KEY_TIMER_ENABLE, false)) {
246            PendingIntent pi = ToastService.getPendingIntent(this, R.string.timer_click);
247            mNotifications.add(new NotificationCompat.Builder(this)
248                    .setContentTitle(getString(R.string.timer_title))
249                    .setContentText(getString(R.string.timer_text))
250                    .setCategory(NotificationCompat.CATEGORY_PROGRESS)
251                    .setContentIntent(pi)
252                    .setSmallIcon(R.drawable.stat_notify_alarm)
253                    .setUsesChronometer(true)
254                            .build());
255        }
256
257        if(sharedPref.getBoolean(SettingsActivity.KEY_CALENDAR_ENABLE, false)) {
258            mNotifications.add(new NotificationCompat.Builder(this)
259                    .setContentTitle(getString(R.string.calendar_title))
260                    .setContentText(getString(R.string.calendar_text))
261                    .setCategory(NotificationCompat.CATEGORY_EVENT)
262                    .setWhen(System.currentTimeMillis())
263                    .setSmallIcon(R.drawable.stat_notify_calendar)
264                    .setContentIntent(ToastService.getPendingIntent(this, R.string.calendar_click))
265                    .setContentInfo("7PM")
266                    .addAction(R.drawable.stat_notify_snooze, getString(R.string.calendar_10),
267                            ToastService.getPendingIntent(this, R.string.calendar_10_click))
268                    .addAction(R.drawable.stat_notify_snooze_longer, getString(R.string.calendar_60),
269                            ToastService.getPendingIntent(this, R.string.calendar_60_click))
270                            .addAction(R.drawable.stat_notify_email, "Email",
271                                    makeEmailIntent(this,
272                                            "gabec@example.com,mcleron@example.com,dsandler@example.com"))
273                            .build());
274        }
275
276        if(sharedPref.getBoolean(SettingsActivity.KEY_PICTURE_ENABLE, false)) {
277            BitmapDrawable d =
278                    (BitmapDrawable) getResources().getDrawable(R.drawable.romainguy_rockaway);
279            PendingIntent ci = ToastService.getPendingIntent(this, R.string.picture_click);
280            PendingIntent ai = ToastService.getPendingIntent(this, R.string.picture_add_click);
281            mNotifications.add(new NotificationCompat.BigPictureStyle(
282                    new NotificationCompat.Builder(this)
283                            .setCategory(NotificationCompat.CATEGORY_SOCIAL)
284                            .setContentTitle(getString(R.string.picture_title))
285                            .setContentText(getString(R.string.picture_text))
286                            .setSmallIcon(R.drawable.ic_stat_gplus)
287                            .setContentIntent(ci)
288                            .setLargeIcon(getBitmap(this, R.drawable.romainguy_hed))
289                            .addAction(R.drawable.add, getString(R.string.picture_add), ai)
290                            .setSubText(getString(R.string.picture_sub_text)))
291                    .bigPicture(d.getBitmap())
292                    .build());
293        }
294
295        if(sharedPref.getBoolean(SettingsActivity.KEY_INBOX_ENABLE, false)) {
296            PendingIntent pi = ToastService.getPendingIntent(this, R.string.email_click);
297            mNotifications.add(new NotificationCompat.InboxStyle(
298                    new NotificationCompat.Builder(this)
299                            .setContentTitle(getString(R.string.email_title))
300                            .setContentText(getString(R.string.email_text))
301                            .setSubText(getString(R.string.email_sub_text))
302                            .setCategory(NotificationCompat.CATEGORY_EMAIL)
303                            .setContentIntent(pi)
304                            .setSmallIcon(R.drawable.stat_notify_email))
305                    .setSummaryText("+21 more")
306                    .addLine(getString(R.string.email_a))
307                    .addLine(getString(R.string.email_b))
308                    .addLine(getString(R.string.email_c))
309                    .build());
310        }
311
312        if(sharedPref.getBoolean(SettingsActivity.KEY_SOCIAL_ENABLE, false)) {
313            PendingIntent pi = ToastService.getPendingIntent(this, R.string.social_click);
314            mNotifications.add(new NotificationCompat.Builder(this)
315                    .setContentTitle(getString(R.string.social_title))
316                    .setContentText(getString(R.string.social_text))
317                    .setCategory(NotificationCompat.CATEGORY_SOCIAL)
318                    .setContentIntent(pi)
319                    .setSmallIcon(R.drawable.twitter_icon)
320                    .setNumber(15)
321                    .setPriority(NotificationCompat.PRIORITY_LOW)
322                    .build());
323        }
324
325        for (int i=0; i<mNotifications.size(); i++) {
326            noMa.notify(NOTIFICATION_ID + i, mNotifications.get(i));
327        }
328
329        // always cancel any previous alarm
330        PendingIntent pendingCancel = makeCancelAllIntent(this);
331        AlarmManager alMa = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
332        alMa.cancel(pendingCancel);
333        if(sharedPref.getBoolean(SettingsActivity.KEY_GLOBAL_FADE, false)) {
334            long t = SystemClock.elapsedRealtime() + FADE_TIME_MILLIS;
335            alMa.set(AlarmManager.ELAPSED_REALTIME, t, pendingCancel);
336        }
337    }
338}
339