EmailNotificationController.java revision d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577e
1899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki/* 2899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki * Copyright (C) 2010 The Android Open Source Project 3899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki * 4899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki * Licensed under the Apache License, Version 2.0 (the "License"); 5899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki * you may not use this file except in compliance with the License. 6899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki * You may obtain a copy of the License at 7899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki * 8899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki * http://www.apache.org/licenses/LICENSE-2.0 9899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki * 10899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki * Unless required by applicable law or agreed to in writing, software 11899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki * distributed under the License is distributed on an "AS IS" BASIS, 12899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki * See the License for the specific language governing permissions and 14899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki * limitations under the License. 15899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki */ 16899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki 17899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onukipackage com.android.email; 18899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki 19899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onukiimport com.android.email.activity.ContactStatusLoader; 20899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onukiimport com.android.email.activity.Welcome; 21d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blankimport com.android.email.activity.setup.AccountSettingsXL; 22899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onukiimport com.android.email.mail.Address; 23899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onukiimport com.android.email.provider.EmailContent; 24899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onukiimport com.android.email.provider.EmailContent.Account; 25d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blankimport com.android.email.provider.EmailContent.Attachment; 26899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onukiimport com.android.email.provider.EmailContent.Message; 27899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki 28899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onukiimport android.app.Notification; 29899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onukiimport android.app.NotificationManager; 30899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onukiimport android.app.PendingIntent; 31899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onukiimport android.content.Context; 32d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blankimport android.content.Intent; 33899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onukiimport android.graphics.Bitmap; 34899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onukiimport android.graphics.BitmapFactory; 35899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onukiimport android.media.AudioManager; 36899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onukiimport android.net.Uri; 37899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onukiimport android.text.TextUtils; 38899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki 39899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki/** 40899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki * Class that manages notifications. 41899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki * 42899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki * TODO Gather all notification related code here 43899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki */ 44899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onukipublic class NotificationController { 45899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki public static final int NOTIFICATION_ID_SECURITY_NEEDED = 1; 46899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki public static final int NOTIFICATION_ID_EXCHANGE_CALENDAR_ADDED = 2; 47d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank public static final int NOTIFICATION_ID_ATTACHMENT_WARNING = 3; 48d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank 49d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank private static final int NOTIFICATION_ID_BASE_NEW_MESSAGES = 0x10000000; 50d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank private static final int NOTIFICATION_ID_BASE_LOGIN_WARNING = 0x20000000; 51899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki 52899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki private static NotificationController sInstance; 53899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki private final Context mContext; 54899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki private final NotificationManager mNotificationManager; 55899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki private final AudioManager mAudioManager; 56899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki 57899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki /** Constructor */ 58899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki private NotificationController(Context context) { 59899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki mContext = context.getApplicationContext(); 60899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki mNotificationManager = (NotificationManager) context.getSystemService( 61899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki Context.NOTIFICATION_SERVICE); 62899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); 63899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki } 64899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki 65899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki /** Singleton access */ 66899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki public static synchronized NotificationController getInstance(Context context) { 67899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki if (sInstance == null) { 68899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki sInstance = new NotificationController(context); 69899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki } 70899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki return sInstance; 71899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki } 72899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki 73899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki /** 74899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki * @return the "new message" notification ID for an account. It just assumes 75899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki * accountID won't be too huge. Any other smarter/cleaner way? 76899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki */ 77899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki private int getNewMessageNotificationId(long accountId) { 78d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank return (int) (NOTIFICATION_ID_BASE_NEW_MESSAGES + accountId); 79899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki } 80899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki 81899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki /** 82899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki * Dismiss new message notification 83899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki * 84899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki * @param accountId ID of the target account, or -1 for all accounts. 85899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki */ 86899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki public void cancelNewMessageNotification(long accountId) { 87899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki if (accountId == -1) { 88899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki new Utility.ForEachAccount(mContext) { 89899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki @Override 90899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki protected void performAction(long accountId) { 91899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki cancelNewMessageNotification(accountId); 92899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki } 93899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki }.execute(); 94899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki } else { 95899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki mNotificationManager.cancel(getNewMessageNotificationId(accountId)); 96899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki } 97899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki } 98899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki 99899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki /** 100899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki * Show (or update) the "new message" notification. 101899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki */ 102899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki public void showNewMessageNotification(final long accountId, final int unseenMessageCount, 103899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki final int justFetchedCount) { 104899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki Utility.runAsync(new Runnable() { 105899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki @Override 106899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki public void run() { 107899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki Notification n = createNewMessageNotification(accountId, unseenMessageCount, 108899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki justFetchedCount); 109899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki if (n == null) { 110899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki return; 111899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki } 112899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki mNotificationManager.notify(getNewMessageNotificationId(accountId), n); 113899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki } 114899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki }); 115899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki } 116899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki 117899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki /** 118899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki * @return The sender's photo, if available, or null. 119899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki * 120899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki * Don't call it on the UI thread. 121899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki */ 122899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki private Bitmap getSenderPhoto(Message message) { 123899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki Address sender = Address.unpackFirst(message.mFrom); 124899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki if (sender == null) { 125899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki return null; 126899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki } 127899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki String email = sender.getAddress(); 128899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki if (TextUtils.isEmpty(email)) { 129899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki return null; 130899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki } 131899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki return ContactStatusLoader.load(mContext, email).mPhoto; 132899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki } 133899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki 134899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki private Bitmap[] getNotificationBitmaps(Bitmap senderPhoto) { 135899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki // TODO Should we cache these objects? (bitmaps and arrays) 136899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki // They don't have to be on this process's memory once we post a notification request to 137899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki // the system, and decodeResource() seems to be reasonably fast. We don't want them to 138899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki // take up memory when not necessary. 139899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki Bitmap appIcon = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.icon); 140899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki if (senderPhoto == null) { 141899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki return new Bitmap[] {appIcon}; 142899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki } else { 143899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki return new Bitmap[] {senderPhoto, appIcon}; 144899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki } 145899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki } 146899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki 147899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki /** 148899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki * Create a notification 149899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki * 150899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki * Don't call it on the UI thread. 151899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki * 152899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki * TODO Test it when the UI is settled. 153899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki */ 154899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki private Notification createNewMessageNotification(long accountId, int unseenMessageCount, 155899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki int justFetchedCount) { 156899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki final Account account = Account.restoreAccountWithId(mContext, accountId); 157899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki if (account == null) { 158899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki return null; 159899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki } 160899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki // Get the latest message 161899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki final Message message = Message.getLatestMessage(mContext, accountId); 162899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki if (message == null) { 163899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki return null; // no message found??? 164899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki } 165899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki 166899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki final String senderName = Address.toFriendly(Address.unpack(message.mFrom)); 167899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki final String subject = message.mSubject; 168899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki final Bitmap senderPhoto = getSenderPhoto(message); 169899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki 170899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki // Intent to open inbox 171899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki PendingIntent contentIntent = PendingIntent.getActivity(mContext, 0, 172899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki Welcome.createOpenAccountInboxIntent(mContext, accountId), 173899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki PendingIntent.FLAG_UPDATE_CURRENT); 174899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki 175899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki final String notificationTitle; 176899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki if (justFetchedCount == 1) { 177899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki notificationTitle = senderName; 178899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki } else { 179899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki notificationTitle = mContext.getResources().getQuantityString( 180899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki R.plurals.notification_sender_name_multi_messages, justFetchedCount - 1, 181899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki senderName, justFetchedCount - 1); 182899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki } 183899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki final String content = subject; 184899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki final String numNewMessages; 185899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki final int numAccounts = EmailContent.count(mContext, Account.CONTENT_URI); 186899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki if (numAccounts == 1) { 187899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki numNewMessages = mContext.getResources().getQuantityString( 188899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki R.plurals.notification_num_new_messages_single_account, unseenMessageCount, 189899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki unseenMessageCount, account.mDisplayName); 190899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki } else { 191899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki numNewMessages = mContext.getResources().getQuantityString( 192899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki R.plurals.notification_num_new_messages_multi_account, unseenMessageCount, 193899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki unseenMessageCount, account.mDisplayName); 194899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki } 195899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki 196899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki Notification notification = new Notification(R.drawable.stat_notify_email_generic, 197899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki mContext.getString(R.string.notification_new_title), System.currentTimeMillis()); 198899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki notification.setLatestEventInfo(mContext, notificationTitle, subject, contentIntent); 199899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki 200899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki notification.tickerTitle = notificationTitle; 201899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki // STOPSHIPO numNewMessages should be the 3rd line on expanded notification. But it's not 202899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki // clear how to do that yet. 203899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki // For now we just append it to subject. 204899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki notification.tickerSubtitle = subject + " " + numNewMessages; 205899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki notification.tickerIcons = getNotificationBitmaps(senderPhoto); 206899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki 207899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki setupNotificationSoundAndVibrationFromAccount(notification, account); 208899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki return notification; 209899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki } 210899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki 211899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki private boolean isRingerModeSilent() { 212899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki return mAudioManager.getRingerMode() != AudioManager.RINGER_MODE_NORMAL; 213899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki } 214899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki 215899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki private void setupNotificationSoundAndVibrationFromAccount(Notification notification, 216899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki Account account) { 217899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki final int flags = account.mFlags; 218899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki final String ringtoneUri = account.mRingtoneUri; 219899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki final boolean vibrate = (flags & Account.FLAGS_VIBRATE_ALWAYS) != 0; 220899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki final boolean vibrateWhenSilent = (flags & Account.FLAGS_VIBRATE_WHEN_SILENT) != 0; 221899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki 222899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki notification.sound = (ringtoneUri == null) ? null : Uri.parse(ringtoneUri); 223899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki 224899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki if (vibrate || (vibrateWhenSilent && isRingerModeSilent())) { 225899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki notification.defaults |= Notification.DEFAULT_VIBRATE; 226899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki } 227899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki 228899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki // This code is identical to that used by Gmail and GTalk for notifications 229899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki notification.flags |= Notification.FLAG_SHOW_LIGHTS; 230899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki notification.defaults |= Notification.DEFAULT_LIGHTS; 231899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki } 232d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank 233d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank /** 234d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank * Generic warning notification 235d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank */ 236d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank public void showWarningNotification(int id, String tickerText, String notificationText, 237d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank Intent intent) { 238d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank PendingIntent pendingIntent = 239d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank PendingIntent.getActivity(mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); 240d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank Notification n = new Notification(android.R.drawable.stat_notify_error, tickerText, 241d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank System.currentTimeMillis()); 242d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank n.setLatestEventInfo(mContext, tickerText, notificationText, pendingIntent); 243d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank n.flags = Notification.FLAG_AUTO_CANCEL; 244d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank mNotificationManager.notify(id, n); 245d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank } 246d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank 247d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank /** 248d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank * Alert the user that an attachment couldn't be forwarded. This is a very unusual case, and 249d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank * perhaps we shouldn't even send a notification. For now, it's helpful for debugging. 250d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank */ 251d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank public void showDownloadForwardFailedNotification(Attachment att) { 252d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank showWarningNotification(NOTIFICATION_ID_ATTACHMENT_WARNING, 253d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank mContext.getString(R.string.forward_download_failed_ticker), 254d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank mContext.getString(R.string.forward_download_failed_notification, 255d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank att.mFileName), 256d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank Welcome.createOpenCombinedOutboxIntent(mContext)); 257d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank } 258d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank 259d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank /** 260d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank * Alert the user that login failed for the specified account 261d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank */ 262d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank private int getLoginFailedNotificationId(long accountId) { 263d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank return NOTIFICATION_ID_BASE_LOGIN_WARNING + (int)accountId; 264d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank } 265d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank 266d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank // NOTE: DO NOT CALL THIS METHOD FROM THE UI THREAD (DATABASE ACCESS) 267d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank public void showLoginFailedNotification(long accountId) { 268d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank final Account account = Account.restoreAccountWithId(mContext, accountId); 269d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank if (account == null) return; 270d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank showWarningNotification(getLoginFailedNotificationId(accountId), 271d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank mContext.getString(R.string.login_failed_ticker, account.mDisplayName), 272d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank mContext.getString(R.string.login_failed_notification), 273d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank AccountSettingsXL.createAccountSettingsIntent(mContext, accountId)); 274d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank } 275d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank 276d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank public void cancelLoginFailedNotification(long accountId) { 277d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank mNotificationManager.cancel(getLoginFailedNotificationId(accountId)); 278d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank } 279899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki} 280