Home | History | Annotate | Download | only in notificationshowcase
      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 
     17 package com.android.example.notificationshowcase;
     18 
     19 import android.app.AlarmManager;
     20 import android.app.IntentService;
     21 import android.app.Notification;
     22 import android.app.PendingIntent;
     23 import android.content.ComponentName;
     24 import android.content.ContentResolver;
     25 import android.content.Context;
     26 import android.content.Intent;
     27 import android.content.SharedPreferences;
     28 import android.database.Cursor;
     29 import android.graphics.Bitmap;
     30 import android.graphics.Canvas;
     31 import android.graphics.Typeface;
     32 import android.graphics.drawable.BitmapDrawable;
     33 import android.graphics.drawable.Drawable;
     34 import android.net.Uri;
     35 import android.os.SystemClock;
     36 import android.provider.ContactsContract;
     37 import android.support.v4.app.NotificationCompat;
     38 import android.support.v4.app.NotificationManagerCompat;
     39 import android.support.v7.preference.PreferenceManager;
     40 import android.text.SpannableString;
     41 import android.text.TextUtils;
     42 import android.text.style.StyleSpan;
     43 import android.util.Log;
     44 
     45 import com.android.example.notificationshowcase.R;
     46 
     47 import java.util.ArrayList;
     48 
     49 public 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(sharedPref.getBoolean(SettingsActivity.KEY_SMS_ONCE, 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         NotificationManagerCompat noMa = NotificationManagerCompat.from(this);
    189         if (ACTION_DESTROY.equals(intent.getAction())) {
    190             noMa.cancelAll();
    191             return;
    192         }
    193 
    194         SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
    195         ArrayList<Notification> mNotifications = new ArrayList<Notification>();
    196 
    197         if(sharedPref.getBoolean(SettingsActivity.KEY_SMS_ENABLE, true)) {
    198             final int id = mNotifications.size();
    199             mNotifications.add(makeSmsNotification(this, 2, id, System.currentTimeMillis()));
    200         }
    201 
    202         if(sharedPref.getBoolean(SettingsActivity.KEY_UPLOAD_ENABLE, false)) {
    203             final int id = mNotifications.size();
    204             final long uploadWhen = System.currentTimeMillis();
    205             mNotifications.add(makeUploadNotification(this, 10, uploadWhen));
    206             ProgressService.startProgressUpdater(this, id, uploadWhen, 0);
    207         }
    208 
    209         if(sharedPref.getBoolean(SettingsActivity.KEY_PHONE_ENABLE, false)) {
    210             final int id = mNotifications.size();
    211             final PendingIntent fullscreen = FullScreenActivity.getPendingIntent(this, id);
    212             PendingIntent ans = PhoneService.getPendingIntent(this, id,
    213                     PhoneService.ACTION_ANSWER);
    214             PendingIntent ign =
    215                     PhoneService.getPendingIntent(this, id, PhoneService.ACTION_IGNORE);
    216             NotificationCompat.Builder phoneCall = new NotificationCompat.Builder(this)
    217                     .setContentTitle(getString(R.string.call_title))
    218                     .setContentText(getString(R.string.call_text))
    219                     .setLargeIcon(getBitmap(this, R.drawable.matias_hed))
    220                     .setSmallIcon(R.drawable.stat_sys_phone_call)
    221                     .setPriority(NotificationCompat.PRIORITY_MAX)
    222                     .setCategory(NotificationCompat.CATEGORY_CALL)
    223                     .setContentIntent(fullscreen)
    224                     .addAction(R.drawable.ic_dial_action_call, getString(R.string.call_answer), ans)
    225                     .addAction(R.drawable.ic_end_call, getString(R.string.call_ignore), ign)
    226                     .setOngoing(true);
    227 
    228             if(sharedPref.getBoolean(SettingsActivity.KEY_PHONE_FULLSCREEN, false)) {
    229                 phoneCall.setFullScreenIntent(fullscreen, true);
    230             }
    231 
    232             if(sharedPref.getBoolean(SettingsActivity.KEY_PHONE_NOISY, false)) {
    233                 phoneCall.setDefaults(Notification.DEFAULT_SOUND);
    234             }
    235 
    236             if (sharedPref.getBoolean(SettingsActivity.KEY_PHONE_PERSON, false)) {
    237                 phoneCall.addPerson(Uri.fromParts("tel",
    238                         "1 (617) 555-1212", null)
    239                         .toString());
    240             }
    241             mNotifications.add(phoneCall.build());
    242         }
    243 
    244         if(sharedPref.getBoolean(SettingsActivity.KEY_TIMER_ENABLE, false)) {
    245             PendingIntent pi = ToastService.getPendingIntent(this, R.string.timer_click);
    246             mNotifications.add(new NotificationCompat.Builder(this)
    247                     .setContentTitle(getString(R.string.timer_title))
    248                     .setContentText(getString(R.string.timer_text))
    249                     .setCategory(NotificationCompat.CATEGORY_PROGRESS)
    250                     .setContentIntent(pi)
    251                     .setSmallIcon(R.drawable.stat_notify_alarm)
    252                     .setUsesChronometer(true)
    253                             .build());
    254         }
    255 
    256         if(sharedPref.getBoolean(SettingsActivity.KEY_CALENDAR_ENABLE, false)) {
    257             mNotifications.add(new NotificationCompat.Builder(this)
    258                     .setContentTitle(getString(R.string.calendar_title))
    259                     .setContentText(getString(R.string.calendar_text))
    260                     .setCategory(NotificationCompat.CATEGORY_EVENT)
    261                     .setWhen(System.currentTimeMillis())
    262                     .setSmallIcon(R.drawable.stat_notify_calendar)
    263                     .setContentIntent(ToastService.getPendingIntent(this, R.string.calendar_click))
    264                     .setContentInfo("7PM")
    265                     .addAction(R.drawable.stat_notify_snooze, getString(R.string.calendar_10),
    266                             ToastService.getPendingIntent(this, R.string.calendar_10_click))
    267                     .addAction(R.drawable.stat_notify_snooze_longer, getString(R.string.calendar_60),
    268                             ToastService.getPendingIntent(this, R.string.calendar_60_click))
    269                             .addAction(R.drawable.stat_notify_email, "Email",
    270                                     makeEmailIntent(this,
    271                                             "gabec (at) example.com,mcleron (at) example.com,dsandler (at) example.com"))
    272                             .build());
    273         }
    274 
    275         if(sharedPref.getBoolean(SettingsActivity.KEY_PICTURE_ENABLE, false)) {
    276             BitmapDrawable d =
    277                     (BitmapDrawable) getResources().getDrawable(R.drawable.romainguy_rockaway);
    278             PendingIntent ci = ToastService.getPendingIntent(this, R.string.picture_click);
    279             PendingIntent ai = ToastService.getPendingIntent(this, R.string.picture_add_click);
    280             mNotifications.add(new NotificationCompat.BigPictureStyle(
    281                     new NotificationCompat.Builder(this)
    282                             .setCategory(NotificationCompat.CATEGORY_SOCIAL)
    283                             .setContentTitle(getString(R.string.picture_title))
    284                             .setContentText(getString(R.string.picture_text))
    285                             .setSmallIcon(R.drawable.ic_stat_gplus)
    286                             .setContentIntent(ci)
    287                             .setLargeIcon(getBitmap(this, R.drawable.romainguy_hed))
    288                             .addAction(R.drawable.add, getString(R.string.picture_add), ai)
    289                             .setSubText(getString(R.string.picture_sub_text)))
    290                     .bigPicture(d.getBitmap())
    291                     .build());
    292         }
    293 
    294         if(sharedPref.getBoolean(SettingsActivity.KEY_INBOX_ENABLE, false)) {
    295             PendingIntent pi = ToastService.getPendingIntent(this, R.string.email_click);
    296             mNotifications.add(new NotificationCompat.InboxStyle(
    297                     new NotificationCompat.Builder(this)
    298                             .setContentTitle(getString(R.string.email_title))
    299                             .setContentText(getString(R.string.email_text))
    300                             .setSubText(getString(R.string.email_sub_text))
    301                             .setCategory(NotificationCompat.CATEGORY_EMAIL)
    302                             .setContentIntent(pi)
    303                             .setSmallIcon(R.drawable.stat_notify_email))
    304                     .setSummaryText("+21 more")
    305                     .addLine(getString(R.string.email_a))
    306                     .addLine(getString(R.string.email_b))
    307                     .addLine(getString(R.string.email_c))
    308                     .build());
    309         }
    310 
    311         if(sharedPref.getBoolean(SettingsActivity.KEY_SOCIAL_ENABLE, false)) {
    312             PendingIntent pi = ToastService.getPendingIntent(this, R.string.social_click);
    313             mNotifications.add(new NotificationCompat.Builder(this)
    314                     .setContentTitle(getString(R.string.social_title))
    315                     .setContentText(getString(R.string.social_text))
    316                     .setCategory(NotificationCompat.CATEGORY_SOCIAL)
    317                     .setContentIntent(pi)
    318                     .setSmallIcon(R.drawable.twitter_icon)
    319                     .setNumber(15)
    320                     .setPriority(NotificationCompat.PRIORITY_LOW)
    321                     .build());
    322         }
    323 
    324         for (int i=0; i<mNotifications.size(); i++) {
    325             noMa.notify(NOTIFICATION_ID + i, mNotifications.get(i));
    326         }
    327 
    328         // always cancel any previous alarm
    329         PendingIntent pendingCancel = makeCancelAllIntent(this);
    330         AlarmManager alMa = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
    331         alMa.cancel(pendingCancel);
    332         if(sharedPref.getBoolean(SettingsActivity.KEY_GLOBAL_FADE, false)) {
    333             long t = SystemClock.elapsedRealtime() + FADE_TIME_MILLIS;
    334             alMa.set(AlarmManager.ELAPSED_REALTIME, t, pendingCancel);
    335         }
    336     }
    337 }
    338