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