172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project/* 272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * Copyright (C) 2008 Esmertec AG. 372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * 572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * you may not use this file except in compliance with the License. 772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * You may obtain a copy of the License at 872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * 972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 1072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * 1172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software 1272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 1372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * See the License for the specific language governing permissions and 1572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * limitations under the License. 1672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project */ 1772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 1872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectpackage com.android.mms.transaction; 1972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 20f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport static com.google.android.mms.pdu.PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND; 21f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport static com.google.android.mms.pdu.PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF; 2272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 2372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport com.android.mms.R; 24812391ad832f3fdac054ad3a50af563da16e99b5Wei Huangimport com.android.mms.LogTag; 2533a87f96f8c625aa10131a77a3968c97c4ec5a62Ficus Kirkpatrickimport com.android.mms.data.Contact; 2670c73e05a792832aa28da751cdaf3fa83a7b8113Ficus Kirkpatrickimport com.android.mms.data.Conversation; 2772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport com.android.mms.ui.ComposeMessageActivity; 2872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport com.android.mms.ui.ConversationList; 2972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport com.android.mms.ui.MessagingPreferenceActivity; 3072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport com.android.mms.util.AddressUtils; 3172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport com.android.mms.util.DownloadManager; 3272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 33f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport com.google.android.mms.pdu.EncodedStringValue; 34f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport com.google.android.mms.pdu.PduHeaders; 35f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport com.google.android.mms.pdu.PduPersister; 36fd644551e8506266aad2b76463b51b44154ed62fTom Taylorimport android.database.sqlite.SqliteWrapper; 3772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 3872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.app.Notification; 3972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.app.NotificationManager; 4072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.app.PendingIntent; 4172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.content.ContentResolver; 4272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.content.Context; 4372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.content.Intent; 4472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.content.SharedPreferences; 4570f5af8fd89d66ae246a805d10a50540746319aaWei Huangimport android.content.BroadcastReceiver; 4670f5af8fd89d66ae246a805d10a50540746319aaWei Huangimport android.content.IntentFilter; 4772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.database.Cursor; 4872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.graphics.Typeface; 49006d49271549ed639ffcd70d94c7650bb3514796Jim Shumaimport android.media.AudioManager; 5072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.net.Uri; 515a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylorimport android.os.Handler; 5272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.preference.PreferenceManager; 53d83675687b1ef742c33bffe8195d7b1852c2c01dTom Taylorimport android.provider.Settings; 54f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport android.provider.Telephony.Mms; 55f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport android.provider.Telephony.Sms; 5672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.text.Spannable; 5772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.text.SpannableString; 5872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.text.TextUtils; 5972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.text.style.StyleSpan; 6072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.util.Log; 61800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERTimport android.widget.Toast; 6272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 6372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport java.util.Comparator; 64b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrickimport java.util.HashSet; 65b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrickimport java.util.Set; 6672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport java.util.SortedSet; 6772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport java.util.TreeSet; 6872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 6972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project/** 7072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * This class is used to update the notification indicator. It will check whether 7172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * there are unread messages. If yes, it would show the notification indicator, 7272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * otherwise, hide the indicator. 7372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project */ 7472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectpublic class MessagingNotification { 75812391ad832f3fdac054ad3a50af563da16e99b5Wei Huang private static final String TAG = LogTag.APP; 7672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 7772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static final int NOTIFICATION_ID = 123; 7872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project public static final int MESSAGE_FAILED_NOTIFICATION_ID = 789; 7972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project public static final int DOWNLOAD_FAILED_NOTIFICATION_ID = 531; 8072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 8172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project // This must be consistent with the column constants below. 8272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static final String[] MMS_STATUS_PROJECTION = new String[] { 8372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project Mms.THREAD_ID, Mms.DATE, Mms._ID, Mms.SUBJECT, Mms.SUBJECT_CHARSET }; 8472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 8572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project // This must be consistent with the column constants below. 8672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static final String[] SMS_STATUS_PROJECTION = new String[] { 8772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project Sms.THREAD_ID, Sms.DATE, Sms.ADDRESS, Sms.SUBJECT, Sms.BODY }; 8872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 8972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project // These must be consistent with MMS_STATUS_PROJECTION and 9072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project // SMS_STATUS_PROJECTION. 9172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static final int COLUMN_THREAD_ID = 0; 9272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static final int COLUMN_DATE = 1; 9372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static final int COLUMN_MMS_ID = 2; 9472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static final int COLUMN_SMS_ADDRESS = 2; 9572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static final int COLUMN_SUBJECT = 3; 9672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static final int COLUMN_SUBJECT_CS = 4; 9772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static final int COLUMN_SMS_BODY = 4; 9872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 9972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static final String NEW_INCOMING_SM_CONSTRAINT = 10072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project "(" + Sms.TYPE + " = " + Sms.MESSAGE_TYPE_INBOX 101627007213deb59ef938c80353c8f3598b01478b3Wei Huang + " AND " + Sms.SEEN + " = 0)"; 10272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 103800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT private static final String NEW_DELIVERY_SM_CONSTRAINT = 104c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor "(" + Sms.TYPE + " = " + Sms.MESSAGE_TYPE_SENT 105c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor + " AND " + Sms.STATUS + " = "+ Sms.STATUS_COMPLETE +")"; 106800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT 10772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static final String NEW_INCOMING_MM_CONSTRAINT = 10872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project "(" + Mms.MESSAGE_BOX + "=" + Mms.MESSAGE_BOX_INBOX 109627007213deb59ef938c80353c8f3598b01478b3Wei Huang + " AND " + Mms.SEEN + "=0" 11072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project + " AND (" + Mms.MESSAGE_TYPE + "=" + MESSAGE_TYPE_NOTIFICATION_IND 11172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project + " OR " + Mms.MESSAGE_TYPE + "=" + MESSAGE_TYPE_RETRIEVE_CONF + "))"; 11272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 11372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static final MmsSmsNotificationInfoComparator INFO_COMPARATOR = 11472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project new MmsSmsNotificationInfoComparator(); 1155a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor 11672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static final Uri UNDELIVERED_URI = Uri.parse("content://mms-sms/undelivered"); 11772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 11870f5af8fd89d66ae246a805d10a50540746319aaWei Huang 11970f5af8fd89d66ae246a805d10a50540746319aaWei Huang private final static String NOTIFICATION_DELETED_ACTION = 12070f5af8fd89d66ae246a805d10a50540746319aaWei Huang "com.android.mms.NOTIFICATION_DELETED_ACTION"; 12170f5af8fd89d66ae246a805d10a50540746319aaWei Huang 12270f5af8fd89d66ae246a805d10a50540746319aaWei Huang public static class OnDeletedReceiver extends BroadcastReceiver { 12370f5af8fd89d66ae246a805d10a50540746319aaWei Huang public void onReceive(Context context, Intent intent) { 12470f5af8fd89d66ae246a805d10a50540746319aaWei Huang if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) { 12570f5af8fd89d66ae246a805d10a50540746319aaWei Huang Log.d(TAG, "[MessagingNotification] clear notification: mark all msgs seen"); 12670f5af8fd89d66ae246a805d10a50540746319aaWei Huang } 12770f5af8fd89d66ae246a805d10a50540746319aaWei Huang 12870f5af8fd89d66ae246a805d10a50540746319aaWei Huang Conversation.markAllConversationsAsSeen(context); 12970f5af8fd89d66ae246a805d10a50540746319aaWei Huang } 13070f5af8fd89d66ae246a805d10a50540746319aaWei Huang }; 13170f5af8fd89d66ae246a805d10a50540746319aaWei Huang private static OnDeletedReceiver sNotificationDeletedReceiver = new OnDeletedReceiver(); 13270f5af8fd89d66ae246a805d10a50540746319aaWei Huang private static Intent sNotificationOnDeleteIntent; 1335a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor private static Handler mToastHandler = new Handler(); 13470f5af8fd89d66ae246a805d10a50540746319aaWei Huang 13572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private MessagingNotification() { 13672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 13772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 13870f5af8fd89d66ae246a805d10a50540746319aaWei Huang public static void init(Context context) { 13970f5af8fd89d66ae246a805d10a50540746319aaWei Huang // set up the intent filter for notification deleted action 14070f5af8fd89d66ae246a805d10a50540746319aaWei Huang IntentFilter intentFilter = new IntentFilter(); 14170f5af8fd89d66ae246a805d10a50540746319aaWei Huang intentFilter.addAction(NOTIFICATION_DELETED_ACTION); 14270f5af8fd89d66ae246a805d10a50540746319aaWei Huang context.registerReceiver(sNotificationDeletedReceiver, intentFilter); 14370f5af8fd89d66ae246a805d10a50540746319aaWei Huang 14470f5af8fd89d66ae246a805d10a50540746319aaWei Huang // initialize the notification deleted action 14570f5af8fd89d66ae246a805d10a50540746319aaWei Huang sNotificationOnDeleteIntent = new Intent(NOTIFICATION_DELETED_ACTION); 14670f5af8fd89d66ae246a805d10a50540746319aaWei Huang } 14770f5af8fd89d66ae246a805d10a50540746319aaWei Huang 14872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project /** 149627007213deb59ef938c80353c8f3598b01478b3Wei Huang * Checks to see if there are any "unseen" messages or delivery 15072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * reports. Shows the most recent notification if there is one. 1513b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor * Does its work and query in a worker thread. 15272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * 15372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * @param context the context to use 15472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project */ 1553b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor public static void nonBlockingUpdateNewMessageIndicator(final Context context, 1563b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor final boolean isNew, 1573b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor final boolean isStatusMessage) { 1583b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor new Thread(new Runnable() { 1593b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor public void run() { 1603b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor blockingUpdateNewMessageIndicator(context, isNew, isStatusMessage); 1613b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor } 1623b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor }).start(); 16372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 16472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 16572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project /** 166627007213deb59ef938c80353c8f3598b01478b3Wei Huang * Checks to see if there are any "unseen" messages or delivery 16772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * reports. Shows the most recent notification if there is one. 16872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * 16972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * @param context the context to use 17072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * @param isNew if notify a new message comes, it should be true, otherwise, false. 17172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project */ 1723b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor public static void blockingUpdateNewMessageIndicator(Context context, boolean isNew, 173c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor boolean isStatusMessage) { 17472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project SortedSet<MmsSmsNotificationInfo> accumulator = 17572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project new TreeSet<MmsSmsNotificationInfo>(INFO_COMPARATOR); 176c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor MmsSmsDeliveryInfo delivery = null; 177b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick Set<Long> threads = new HashSet<Long>(4); 1785a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor 17972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project int count = 0; 18072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project count += accumulateNotificationInfo( 181b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick accumulator, getMmsNewMessageNotificationInfo(context, threads)); 18272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project count += accumulateNotificationInfo( 183b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick accumulator, getSmsNewMessageNotificationInfo(context, threads)); 18472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 18572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project cancelNotification(context, NOTIFICATION_ID); 18672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project if (!accumulator.isEmpty()) { 187e14b79584cca1bf7ba60c53bd7e3d6386adbfc59Wei Huang if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) { 188e14b79584cca1bf7ba60c53bd7e3d6386adbfc59Wei Huang Log.d(TAG, "blockingUpdateNewMessageIndicator: count=" + count + 189e14b79584cca1bf7ba60c53bd7e3d6386adbfc59Wei Huang ", isNew=" + isNew); 190e14b79584cca1bf7ba60c53bd7e3d6386adbfc59Wei Huang } 191b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick accumulator.first().deliver(context, isNew, count, threads.size()); 19272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 1935a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor 1943b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor // And deals with delivery reports (which use Toasts). It's safe to call in a worker 1953b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor // thread because the toast will eventually get posted to a handler. 196627007213deb59ef938c80353c8f3598b01478b3Wei Huang delivery = getSmsNewDeliveryInfo(context); 197627007213deb59ef938c80353c8f3598b01478b3Wei Huang if (delivery != null) { 198c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor delivery.deliver(context, isStatusMessage); 199627007213deb59ef938c80353c8f3598b01478b3Wei Huang } 20072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 20172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 20272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project /** 20335a74a9e0ee7c171c6e17f0eda4b0df0253f8364Ficus Kirkpatrick * Updates all pending notifications, clearing or updating them as 2043b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor * necessary. 20535a74a9e0ee7c171c6e17f0eda4b0df0253f8364Ficus Kirkpatrick */ 206627007213deb59ef938c80353c8f3598b01478b3Wei Huang public static void blockingUpdateAllNotifications(final Context context) { 2073b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor nonBlockingUpdateNewMessageIndicator(context, false, false); 208627007213deb59ef938c80353c8f3598b01478b3Wei Huang updateSendFailedNotification(context); 209627007213deb59ef938c80353c8f3598b01478b3Wei Huang updateDownloadFailedNotification(context); 21035a74a9e0ee7c171c6e17f0eda4b0df0253f8364Ficus Kirkpatrick } 2115a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor 21272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static final int accumulateNotificationInfo( 21372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project SortedSet set, MmsSmsNotificationInfo info) { 21472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project if (info != null) { 21572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project set.add(info); 21672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 21772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project return info.mCount; 21872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 21972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 22072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project return 0; 22172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 22272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 223800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT private static final class MmsSmsDeliveryInfo { 224c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor public CharSequence mTicker; 225c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor public long mTimeMillis; 226c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor 227c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor public MmsSmsDeliveryInfo(CharSequence ticker, long timeMillis) { 228c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor mTicker = ticker; 229c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor mTimeMillis = timeMillis; 230c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor } 231c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor 232c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor public void deliver(Context context, boolean isStatusMessage) { 233c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor updateDeliveryNotification( 234c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor context, isStatusMessage, mTicker, mTimeMillis); 235c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor } 236800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT } 237800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT 23872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static final class MmsSmsNotificationInfo { 23972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project public Intent mClickIntent; 24072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project public String mDescription; 24172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project public int mIconResourceId; 24272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project public CharSequence mTicker; 24372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project public long mTimeMillis; 24472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project public String mTitle; 24572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project public int mCount; 24672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 24772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project public MmsSmsNotificationInfo( 24872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project Intent clickIntent, String description, int iconResourceId, 24972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project CharSequence ticker, long timeMillis, String title, int count) { 25072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project mClickIntent = clickIntent; 25172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project mDescription = description; 25272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project mIconResourceId = iconResourceId; 25372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project mTicker = ticker; 25472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project mTimeMillis = timeMillis; 25572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project mTitle = title; 25672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project mCount = count; 25772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 25872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 259b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick public void deliver(Context context, boolean isNew, int count, int uniqueThreads) { 26072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project updateNotification( 2613c68b6852913222dd982dddd4e39b3e57613c37eWei Huang context, mClickIntent, mDescription, mIconResourceId, isNew, 2623c68b6852913222dd982dddd4e39b3e57613c37eWei Huang (isNew? mTicker : null), // only display the ticker if the message is new 2633c68b6852913222dd982dddd4e39b3e57613c37eWei Huang mTimeMillis, mTitle, count, uniqueThreads); 26472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 26572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 26672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project public long getTime() { 26772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project return mTimeMillis; 26872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 26972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 27072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 27172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static final class MmsSmsNotificationInfoComparator 27272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project implements Comparator<MmsSmsNotificationInfo> { 27372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project public int compare( 27472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project MmsSmsNotificationInfo info1, MmsSmsNotificationInfo info2) { 27572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project return Long.signum(info2.getTime() - info1.getTime()); 27672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 27772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 27872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 2793b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor private static final MmsSmsNotificationInfo getMmsNewMessageNotificationInfo( 280b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick Context context, Set<Long> threads) { 28172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project ContentResolver resolver = context.getContentResolver(); 2823b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor 2833b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor // This query looks like this when logged: 2843b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor // I/Database( 147): elapsedTime4Sql|/data/data/com.android.providers.telephony/databases/ 2853b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor // mmssms.db|0.362 ms|SELECT thread_id, date, _id, sub, sub_cs FROM pdu WHERE ((msg_box=1 2863b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor // AND seen=0 AND (m_type=130 OR m_type=132))) ORDER BY date desc 2873b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor 28872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project Cursor cursor = SqliteWrapper.query(context, resolver, Mms.CONTENT_URI, 28972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project MMS_STATUS_PROJECTION, NEW_INCOMING_MM_CONSTRAINT, 29072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project null, Mms.DATE + " desc"); 29172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 292b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick if (cursor == null) { 293b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick return null; 294b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick } 2955a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor 296b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick try { 297b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick if (!cursor.moveToFirst()) { 298b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick return null; 29972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 300b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick long msgId = cursor.getLong(COLUMN_MMS_ID); 301b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick Uri msgUri = Mms.CONTENT_URI.buildUpon().appendPath( 302b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick Long.toString(msgId)).build(); 303b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick String address = AddressUtils.getFrom(context, msgUri); 3041b8df494e49bf934fe160baea54ab5afc2ff3100Tom Taylor 3051b8df494e49bf934fe160baea54ab5afc2ff3100Tom Taylor Contact contact = Contact.get(address, false); 3061b8df494e49bf934fe160baea54ab5afc2ff3100Tom Taylor if (contact.getSendToVoicemail()) { 3071b8df494e49bf934fe160baea54ab5afc2ff3100Tom Taylor // don't notify 3081b8df494e49bf934fe160baea54ab5afc2ff3100Tom Taylor return null; 3091b8df494e49bf934fe160baea54ab5afc2ff3100Tom Taylor } 3101b8df494e49bf934fe160baea54ab5afc2ff3100Tom Taylor 311b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick String subject = getMmsSubject( 312b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick cursor.getString(COLUMN_SUBJECT), cursor.getInt(COLUMN_SUBJECT_CS)); 313b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick long threadId = cursor.getLong(COLUMN_THREAD_ID); 314b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick long timeMillis = cursor.getLong(COLUMN_DATE) * 1000; 315b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick 316e14b79584cca1bf7ba60c53bd7e3d6386adbfc59Wei Huang if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) { 317e14b79584cca1bf7ba60c53bd7e3d6386adbfc59Wei Huang Log.d(TAG, "getMmsNewMessageNotificationInfo: count=" + cursor.getCount() + 318e14b79584cca1bf7ba60c53bd7e3d6386adbfc59Wei Huang ", first addr = " + address + ", thread_id=" + threadId); 319e14b79584cca1bf7ba60c53bd7e3d6386adbfc59Wei Huang } 320e14b79584cca1bf7ba60c53bd7e3d6386adbfc59Wei Huang 321b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick MmsSmsNotificationInfo info = getNewMessageNotificationInfo( 322b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick address, subject, context, 323b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick R.drawable.stat_notify_mms, null, threadId, 324b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick timeMillis, cursor.getCount()); 325b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick 326b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick threads.add(threadId); 327b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick while (cursor.moveToNext()) { 328b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick threads.add(cursor.getLong(COLUMN_THREAD_ID)); 329b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick } 330b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick 331b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick return info; 332b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick } finally { 333b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick cursor.close(); 33472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 33572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 33672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 3373b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor private static final MmsSmsDeliveryInfo getSmsNewDeliveryInfo(Context context) { 338627007213deb59ef938c80353c8f3598b01478b3Wei Huang ContentResolver resolver = context.getContentResolver(); 339627007213deb59ef938c80353c8f3598b01478b3Wei Huang Cursor cursor = SqliteWrapper.query(context, resolver, Sms.CONTENT_URI, 340627007213deb59ef938c80353c8f3598b01478b3Wei Huang SMS_STATUS_PROJECTION, NEW_DELIVERY_SM_CONSTRAINT, 3416a9c779f0c0dc6cf3ae942ff70fb6c806aa166dcBanavathu, Srinivas Naik null, Sms.DATE); 342800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT 343627007213deb59ef938c80353c8f3598b01478b3Wei Huang if (cursor == null) 344627007213deb59ef938c80353c8f3598b01478b3Wei Huang return null; 345800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT 346627007213deb59ef938c80353c8f3598b01478b3Wei Huang try { 3476a9c779f0c0dc6cf3ae942ff70fb6c806aa166dcBanavathu, Srinivas Naik if (!cursor.moveToLast()) 348627007213deb59ef938c80353c8f3598b01478b3Wei Huang return null; 349800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT 350627007213deb59ef938c80353c8f3598b01478b3Wei Huang String address = cursor.getString(COLUMN_SMS_ADDRESS); 351627007213deb59ef938c80353c8f3598b01478b3Wei Huang long timeMillis = 3000; 352800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT 353627007213deb59ef938c80353c8f3598b01478b3Wei Huang return new MmsSmsDeliveryInfo(String.format( 354627007213deb59ef938c80353c8f3598b01478b3Wei Huang context.getString(R.string.delivery_toast_body), address), 355627007213deb59ef938c80353c8f3598b01478b3Wei Huang timeMillis); 356800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT 357627007213deb59ef938c80353c8f3598b01478b3Wei Huang } finally { 358627007213deb59ef938c80353c8f3598b01478b3Wei Huang cursor.close(); 359627007213deb59ef938c80353c8f3598b01478b3Wei Huang } 360800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT } 361800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT 3623b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor private static final MmsSmsNotificationInfo getSmsNewMessageNotificationInfo( 363b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick Context context, Set<Long> threads) { 36472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project ContentResolver resolver = context.getContentResolver(); 36572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project Cursor cursor = SqliteWrapper.query(context, resolver, Sms.CONTENT_URI, 36672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project SMS_STATUS_PROJECTION, NEW_INCOMING_SM_CONSTRAINT, 36772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project null, Sms.DATE + " desc"); 36872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 369b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick if (cursor == null) { 370b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick return null; 371b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick } 3725a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor 373b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick try { 374b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick if (!cursor.moveToFirst()) { 375b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick return null; 376b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick } 377b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick 378b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick String address = cursor.getString(COLUMN_SMS_ADDRESS); 3791b8df494e49bf934fe160baea54ab5afc2ff3100Tom Taylor 3801b8df494e49bf934fe160baea54ab5afc2ff3100Tom Taylor Contact contact = Contact.get(address, false); 3811b8df494e49bf934fe160baea54ab5afc2ff3100Tom Taylor if (contact.getSendToVoicemail()) { 3821b8df494e49bf934fe160baea54ab5afc2ff3100Tom Taylor // don't notify 3831b8df494e49bf934fe160baea54ab5afc2ff3100Tom Taylor return null; 3841b8df494e49bf934fe160baea54ab5afc2ff3100Tom Taylor } 3851b8df494e49bf934fe160baea54ab5afc2ff3100Tom Taylor 386b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick String body = cursor.getString(COLUMN_SMS_BODY); 387b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick long threadId = cursor.getLong(COLUMN_THREAD_ID); 388b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick long timeMillis = cursor.getLong(COLUMN_DATE); 389b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick 390d83675687b1ef742c33bffe8195d7b1852c2c01dTom Taylor if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) 391e14b79584cca1bf7ba60c53bd7e3d6386adbfc59Wei Huang { 392e14b79584cca1bf7ba60c53bd7e3d6386adbfc59Wei Huang Log.d(TAG, "getSmsNewMessageNotificationInfo: count=" + cursor.getCount() + 393e14b79584cca1bf7ba60c53bd7e3d6386adbfc59Wei Huang ", first addr=" + address + ", thread_id=" + threadId); 394e14b79584cca1bf7ba60c53bd7e3d6386adbfc59Wei Huang } 395e14b79584cca1bf7ba60c53bd7e3d6386adbfc59Wei Huang 396b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick MmsSmsNotificationInfo info = getNewMessageNotificationInfo( 397b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick address, body, context, R.drawable.stat_notify_sms, 398b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick null, threadId, timeMillis, cursor.getCount()); 399b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick 400b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick threads.add(threadId); 401b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick while (cursor.moveToNext()) { 402b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick threads.add(cursor.getLong(COLUMN_THREAD_ID)); 40372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 404b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick 405b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick return info; 406b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick } finally { 407b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick cursor.close(); 40872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 40972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 41072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 41172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static final MmsSmsNotificationInfo getNewMessageNotificationInfo( 41272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project String address, 41372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project String body, 41472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project Context context, 41572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project int iconResourceId, 41672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project String subject, 41772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project long threadId, 41872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project long timeMillis, 41972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project int count) { 420812391ad832f3fdac054ad3a50af563da16e99b5Wei Huang Intent clickIntent = ComposeMessageActivity.createIntent(context, threadId); 421812391ad832f3fdac054ad3a50af563da16e99b5Wei Huang clickIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK 422812391ad832f3fdac054ad3a50af563da16e99b5Wei Huang | Intent.FLAG_ACTIVITY_SINGLE_TOP 423812391ad832f3fdac054ad3a50af563da16e99b5Wei Huang | Intent.FLAG_ACTIVITY_CLEAR_TOP); 42472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 42572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project String senderInfo = buildTickerMessage( 42672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project context, address, null, null).toString(); 42772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project String senderInfoName = senderInfo.substring( 42872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 0, senderInfo.length() - 2); 42972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project CharSequence ticker = buildTickerMessage( 43072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project context, address, subject, body); 43172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 43272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project return new MmsSmsNotificationInfo( 43372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project clickIntent, body, iconResourceId, ticker, timeMillis, 43472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project senderInfoName, count); 43572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 43672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 43772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project public static void cancelNotification(Context context, int notificationId) { 43872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project NotificationManager nm = (NotificationManager) context.getSystemService( 43972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project Context.NOTIFICATION_SERVICE); 44072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 44172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project nm.cancel(notificationId); 44272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 44372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 4445a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor private static void updateDeliveryNotification(final Context context, 445c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor boolean isStatusMessage, 4465a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor final CharSequence message, 4475a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor final long timeMillis) { 448c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor if (!isStatusMessage) { 449c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor return; 450c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor } 451c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor 452800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT 453d83675687b1ef742c33bffe8195d7b1852c2c01dTom Taylor if (!MessagingPreferenceActivity.getNotificationEnabled(context)) { 45470f5af8fd89d66ae246a805d10a50540746319aaWei Huang return; 45570f5af8fd89d66ae246a805d10a50540746319aaWei Huang } 456800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT 457c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor mToastHandler.post(new Runnable() { 458c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor public void run() { 459c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor Toast.makeText(context, message, (int)timeMillis).show(); 460c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor } 461c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor }); 462800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT } 463800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT 46472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static void updateNotification( 46572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project Context context, 46672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project Intent clickIntent, 46772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project String description, 46872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project int iconRes, 46972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project boolean isNew, 47072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project CharSequence ticker, 47172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project long timeMillis, 47272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project String title, 473b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick int messageCount, 474b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick int uniqueThreadCount) { 475d83675687b1ef742c33bffe8195d7b1852c2c01dTom Taylor if (!MessagingPreferenceActivity.getNotificationEnabled(context)) { 47672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project return; 47772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 47872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 479b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick Notification notification = new Notification(iconRes, ticker, timeMillis); 480b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick 481b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick // If we have more than one unique thread, change the title (which would 482b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick // normally be the contact who sent the message) to a generic one that 483b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick // makes sense for multiple senders, and change the Intent to take the 484b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick // user to the conversation list instead of the specific thread. 485b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick if (uniqueThreadCount > 1) { 486b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick title = context.getString(R.string.notification_multiple_title); 487812391ad832f3fdac054ad3a50af563da16e99b5Wei Huang clickIntent = new Intent(Intent.ACTION_MAIN); 488812391ad832f3fdac054ad3a50af563da16e99b5Wei Huang 489812391ad832f3fdac054ad3a50af563da16e99b5Wei Huang clickIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK 490812391ad832f3fdac054ad3a50af563da16e99b5Wei Huang | Intent.FLAG_ACTIVITY_SINGLE_TOP 491812391ad832f3fdac054ad3a50af563da16e99b5Wei Huang | Intent.FLAG_ACTIVITY_CLEAR_TOP); 492812391ad832f3fdac054ad3a50af563da16e99b5Wei Huang 493b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick clickIntent.setType("vnd.android-dir/mms-sms"); 494b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick } 4955a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor 496b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick // If there is more than one message, change the description (which 497b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick // would normally be a snippet of the individual message text) to 498627007213deb59ef938c80353c8f3598b01478b3Wei Huang // a string indicating how many "unseen" messages there are. 499b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick if (messageCount > 1) { 500b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick description = context.getString(R.string.notification_multiple, 501b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick Integer.toString(messageCount)); 502b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick } 50372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 504b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick // Make a startActivity() PendingIntent for the notification. 505810fae756f4d2db00b35d7c9dfead252737abdacTom Taylor PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, clickIntent, 506810fae756f4d2db00b35d7c9dfead252737abdacTom Taylor PendingIntent.FLAG_UPDATE_CURRENT); 50772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 508b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick // Update the notification. 509b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick notification.setLatestEventInfo(context, title, description, pendingIntent); 51072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 51172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project if (isNew) { 512d83675687b1ef742c33bffe8195d7b1852c2c01dTom Taylor SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context); 513006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma String vibrateWhen; 514006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma if (sp.contains(MessagingPreferenceActivity.NOTIFICATION_VIBRATE_WHEN)) { 515006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma vibrateWhen = 516006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma sp.getString(MessagingPreferenceActivity.NOTIFICATION_VIBRATE_WHEN, null); 517006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma } else if (sp.contains(MessagingPreferenceActivity.NOTIFICATION_VIBRATE)) { 518006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma vibrateWhen = sp.getBoolean(MessagingPreferenceActivity.NOTIFICATION_VIBRATE, false) ? 519006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma context.getString(R.string.prefDefault_vibrate_true) : 520006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma context.getString(R.string.prefDefault_vibrate_false); 521006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma } else { 522006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma vibrateWhen = context.getString(R.string.prefDefault_vibrateWhen); 523006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma } 524006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma 525006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma boolean vibrateAlways = vibrateWhen.equals("always"); 526006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma boolean vibrateSilent = vibrateWhen.equals("silent"); 527006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma AudioManager audioManager = 528006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma (AudioManager)context.getSystemService(Context.AUDIO_SERVICE); 529006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma boolean nowSilent = 530006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma audioManager.getRingerMode() == AudioManager.RINGER_MODE_VIBRATE; 531006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma 532006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma if (vibrateAlways || vibrateSilent && nowSilent) { 53372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project notification.defaults |= Notification.DEFAULT_VIBRATE; 53472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 53572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 536627007213deb59ef938c80353c8f3598b01478b3Wei Huang String ringtoneStr = sp.getString(MessagingPreferenceActivity.NOTIFICATION_RINGTONE, 537627007213deb59ef938c80353c8f3598b01478b3Wei Huang null); 53872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project notification.sound = TextUtils.isEmpty(ringtoneStr) ? null : Uri.parse(ringtoneStr); 53972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 54072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 54172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project notification.flags |= Notification.FLAG_SHOW_LIGHTS; 5425227290bbaefe2438cac9b3868a72a12a3339e83Mike Lockwood notification.defaults |= Notification.DEFAULT_LIGHTS; 54372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 54470f5af8fd89d66ae246a805d10a50540746319aaWei Huang // set up delete intent 54570f5af8fd89d66ae246a805d10a50540746319aaWei Huang notification.deleteIntent = PendingIntent.getBroadcast(context, 0, 54670f5af8fd89d66ae246a805d10a50540746319aaWei Huang sNotificationOnDeleteIntent, 0); 54770f5af8fd89d66ae246a805d10a50540746319aaWei Huang 54872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project NotificationManager nm = (NotificationManager) 54972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project context.getSystemService(Context.NOTIFICATION_SERVICE); 55072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 55172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project nm.notify(NOTIFICATION_ID, notification); 55272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 55372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 55472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project protected static CharSequence buildTickerMessage( 55572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project Context context, String address, String subject, String body) { 55633a87f96f8c625aa10131a77a3968c97c4ec5a62Ficus Kirkpatrick String displayAddress = Contact.get(address, true).getName(); 5575a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor 55872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project StringBuilder buf = new StringBuilder( 55972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project displayAddress == null 56072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project ? "" 56172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project : displayAddress.replace('\n', ' ').replace('\r', ' ')); 56272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project buf.append(':').append(' '); 56372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 56472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project int offset = buf.length(); 56572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project if (!TextUtils.isEmpty(subject)) { 56672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project subject = subject.replace('\n', ' ').replace('\r', ' '); 56772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project buf.append(subject); 56872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project buf.append(' '); 56972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 57072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 57172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project if (!TextUtils.isEmpty(body)) { 57272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project body = body.replace('\n', ' ').replace('\r', ' '); 57372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project buf.append(body); 57472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 57572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 57672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project SpannableString spanText = new SpannableString(buf.toString()); 57772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project spanText.setSpan(new StyleSpan(Typeface.BOLD), 0, offset, 57872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 57972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 58072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project return spanText; 58172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 58272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 58372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static String getMmsSubject(String sub, int charset) { 58472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project return TextUtils.isEmpty(sub) ? "" 58572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project : new EncodedStringValue(charset, PduPersister.getBytes(sub)).getString(); 58672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 58772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 58872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project public static void notifyDownloadFailed(Context context, long threadId) { 589b3cb9bbf929f70cb4855f03e4bfbed749022cf1bFicus Kirkpatrick notifyFailed(context, true, threadId, false); 59072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 59172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 5925d2d0046ada7b53205e537d8675d32a8785e8d1dThe Android Open Source Project public static void notifySendFailed(Context context) { 593b3cb9bbf929f70cb4855f03e4bfbed749022cf1bFicus Kirkpatrick notifyFailed(context, false, 0, false); 59472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 59572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 596b3cb9bbf929f70cb4855f03e4bfbed749022cf1bFicus Kirkpatrick public static void notifySendFailed(Context context, boolean noisy) { 597b3cb9bbf929f70cb4855f03e4bfbed749022cf1bFicus Kirkpatrick notifyFailed(context, false, 0, noisy); 598b3cb9bbf929f70cb4855f03e4bfbed749022cf1bFicus Kirkpatrick } 5995a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor 600b3cb9bbf929f70cb4855f03e4bfbed749022cf1bFicus Kirkpatrick private static void notifyFailed(Context context, boolean isDownload, long threadId, 601b3cb9bbf929f70cb4855f03e4bfbed749022cf1bFicus Kirkpatrick boolean noisy) { 60272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project // TODO factor out common code for creating notifications 603d83675687b1ef742c33bffe8195d7b1852c2c01dTom Taylor boolean enabled = MessagingPreferenceActivity.getNotificationEnabled(context); 60472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project if (!enabled) { 60572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project return; 60672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 60772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 60872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project NotificationManager nm = (NotificationManager) 60972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project context.getSystemService(Context.NOTIFICATION_SERVICE); 6105a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor 61172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project // Strategy: 61272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project // a. If there is a single failure notification, tapping on the notification goes 61372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project // to the compose view. 6145a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor // b. If there are two failure it stays in the thread view. Selecting one undelivered 61572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project // thread will dismiss one undelivered notification but will still display the 61672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project // notification.If you select the 2nd undelivered one it will dismiss the notification. 6175a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor 6187015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev long[] msgThreadId = {0, 1}; // Dummy initial values, just to initialize the memory 61972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project int totalFailedCount = getUndeliveredMessageCount(context, msgThreadId); 6207015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev if (totalFailedCount == 0 && !isDownload) { 6217015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev return; 6227015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev } 6237015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev // The getUndeliveredMessageCount method puts a non-zero value in msgThreadId[1] if all 6247015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev // failures are from the same thread. 6257015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev // If isDownload is true, we're dealing with 1 specific failure; therefore "all failed" are 6267015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev // indeed in the same thread since there's only 1. 6277015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev boolean allFailedInSameThread = (msgThreadId[1] != 0) || isDownload; 6285a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor 62972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project Intent failedIntent; 63072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project Notification notification = new Notification(); 63172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project String title; 63272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project String description; 63372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project if (totalFailedCount > 1) { 63472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project description = context.getString(R.string.notification_failed_multiple, 63572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project Integer.toString(totalFailedCount)); 63672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project title = context.getString(R.string.notification_failed_multiple_title); 63772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } else { 63872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project title = isDownload ? 63972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project context.getString(R.string.message_download_failed_title) : 64072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project context.getString(R.string.message_send_failed_title); 6415a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor 64272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project description = context.getString(R.string.message_failed_body); 6437015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev } 6447015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev 6457015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev if (allFailedInSameThread) { 646836945de572ac80fd6f6a7bf59036d4cce801410The Android Open Source Project failedIntent = new Intent(context, ComposeMessageActivity.class); 64795817b166d415114bac89ca0946c3717ae229526Tom Taylor if (isDownload) { 64895817b166d415114bac89ca0946c3717ae229526Tom Taylor // When isDownload is true, the valid threadId is passed into this function. 64995817b166d415114bac89ca0946c3717ae229526Tom Taylor failedIntent.putExtra("failed_download_flag", true); 65095817b166d415114bac89ca0946c3717ae229526Tom Taylor } else { 6517015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev threadId = msgThreadId[0]; 65295817b166d415114bac89ca0946c3717ae229526Tom Taylor failedIntent.putExtra("undelivered_flag", true); 6535a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor } 6545a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor failedIntent.putExtra("thread_id", threadId); 6557015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev } else { 6567015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev failedIntent = new Intent(context, ConversationList.class); 65772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 65872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 659b92b26763e49fd9cc34d382dee4d764ef163bde5Ficus Kirkpatrick failedIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); 66072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project PendingIntent pendingIntent = PendingIntent.getActivity( 661810fae756f4d2db00b35d7c9dfead252737abdacTom Taylor context, 0, failedIntent, PendingIntent.FLAG_UPDATE_CURRENT); 66272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 66372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project notification.icon = R.drawable.stat_notify_sms_failed; 66472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 66572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project notification.tickerText = title; 66672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 66772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project notification.setLatestEventInfo(context, title, description, pendingIntent); 66872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 669b3cb9bbf929f70cb4855f03e4bfbed749022cf1bFicus Kirkpatrick if (noisy) { 670d83675687b1ef742c33bffe8195d7b1852c2c01dTom Taylor SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context); 671e3baaa51cd25b52c7a24e381319926b9da00abdfWei Huang boolean vibrate = sp.getBoolean(MessagingPreferenceActivity.NOTIFICATION_VIBRATE, 672e3baaa51cd25b52c7a24e381319926b9da00abdfWei Huang false /* don't vibrate by default */); 673b3cb9bbf929f70cb4855f03e4bfbed749022cf1bFicus Kirkpatrick if (vibrate) { 674b3cb9bbf929f70cb4855f03e4bfbed749022cf1bFicus Kirkpatrick notification.defaults |= Notification.DEFAULT_VIBRATE; 675b3cb9bbf929f70cb4855f03e4bfbed749022cf1bFicus Kirkpatrick } 67672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 677e3baaa51cd25b52c7a24e381319926b9da00abdfWei Huang String ringtoneStr = sp.getString(MessagingPreferenceActivity.NOTIFICATION_RINGTONE, 678e3baaa51cd25b52c7a24e381319926b9da00abdfWei Huang null); 679b3cb9bbf929f70cb4855f03e4bfbed749022cf1bFicus Kirkpatrick notification.sound = TextUtils.isEmpty(ringtoneStr) ? null : Uri.parse(ringtoneStr); 680b3cb9bbf929f70cb4855f03e4bfbed749022cf1bFicus Kirkpatrick } 6815a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor 68272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project if (isDownload) { 68372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project nm.notify(DOWNLOAD_FAILED_NOTIFICATION_ID, notification); 68472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } else { 68572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project nm.notify(MESSAGE_FAILED_NOTIFICATION_ID, notification); 68672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 68772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 6885a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor 6897015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev /** 6907015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev * Query the DB and return the number of undelivered messages (total for both SMS and MMS) 6917015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev * @param context The context 6927015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev * @param threadIdResult A container to put the result in, according to the following rules: 6937015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev * threadIdResult[0] contains the thread id of the first message. 6947015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev * threadIdResult[1] is nonzero if the thread ids of all the messages are the same. 6957015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev * You can pass in null for threadIdResult. 6967015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev * You can pass in a threadIdResult of size 1 to avoid the comparison of each thread id. 6977015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev */ 69872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static int getUndeliveredMessageCount(Context context, long[] threadIdResult) { 69972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project Cursor undeliveredCursor = SqliteWrapper.query(context, context.getContentResolver(), 70035a74a9e0ee7c171c6e17f0eda4b0df0253f8364Ficus Kirkpatrick UNDELIVERED_URI, new String[] { Mms.THREAD_ID }, "read=0", null, null); 70172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project if (undeliveredCursor == null) { 70272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project return 0; 70372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 70472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project int count = undeliveredCursor.getCount(); 70572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project try { 70672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project if (threadIdResult != null && undeliveredCursor.moveToFirst()) { 70772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project threadIdResult[0] = undeliveredCursor.getLong(0); 7085a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor 7092f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project if (threadIdResult.length >= 2) { 7102f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project // Test to see if all the undelivered messages belong to the same thread. 7112f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project long firstId = threadIdResult[0]; 7122f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project while (undeliveredCursor.moveToNext()) { 7132f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project if (undeliveredCursor.getLong(0) != firstId) { 7142f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project firstId = 0; 7152f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project break; 7162f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project } 7172f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project } 7182f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project threadIdResult[1] = firstId; // non-zero if all ids are the same 7192f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project } 72072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 72172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } finally { 72272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project undeliveredCursor.close(); 72372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 72472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project return count; 72572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 72672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 72772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project public static void updateSendFailedNotification(Context context) { 72872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project if (getUndeliveredMessageCount(context, null) < 1) { 72972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project cancelNotification(context, MESSAGE_FAILED_NOTIFICATION_ID); 7305d2d0046ada7b53205e537d8675d32a8785e8d1dThe Android Open Source Project } else { 7315d2d0046ada7b53205e537d8675d32a8785e8d1dThe Android Open Source Project notifySendFailed(context); // rebuild and adjust the message count if necessary. 73272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 73372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 7345a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor 7355a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor /** 7362f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project * If all the undelivered messages belong to "threadId", cancel the notification. 7372f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project */ 7382f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project public static void updateSendFailedNotificationForThread(Context context, long threadId) { 7392f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project long[] msgThreadId = {0, 0}; 7405a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor if (getUndeliveredMessageCount(context, msgThreadId) > 0 7412f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project && msgThreadId[0] == threadId 7422f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project && msgThreadId[1] != 0) { 7432f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project cancelNotification(context, MESSAGE_FAILED_NOTIFICATION_ID); 7442f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project } 7452f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project } 7465a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor 74772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static int getDownloadFailedMessageCount(Context context) { 74872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project // Look for any messages in the MMS Inbox that are of the type 74972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project // NOTIFICATION_IND (i.e. not already downloaded) and in the 75072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project // permanent failure state. If there are none, cancel any 75172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project // failed download notification. 75272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project Cursor c = SqliteWrapper.query(context, context.getContentResolver(), 75372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project Mms.Inbox.CONTENT_URI, null, 75472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project Mms.MESSAGE_TYPE + "=" + 75572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project String.valueOf(PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND) + 75672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project " AND " + Mms.STATUS + "=" + 75772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project String.valueOf(DownloadManager.STATE_PERMANENT_FAILURE), 75872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project null, null); 75972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project if (c == null) { 76072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project return 0; 76172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 76272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project int count = c.getCount(); 76372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project c.close(); 76472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project return count; 76572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 76672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 76772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project public static void updateDownloadFailedNotification(Context context) { 76872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project if (getDownloadFailedMessageCount(context) < 1) { 76972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project cancelNotification(context, DOWNLOAD_FAILED_NOTIFICATION_ID); 77072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 77172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 7725a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor 77395817b166d415114bac89ca0946c3717ae229526Tom Taylor public static boolean isFailedToDeliver(Intent intent) { 77495817b166d415114bac89ca0946c3717ae229526Tom Taylor return (intent != null) && intent.getBooleanExtra("undelivered_flag", false); 77595817b166d415114bac89ca0946c3717ae229526Tom Taylor } 77695817b166d415114bac89ca0946c3717ae229526Tom Taylor 77795817b166d415114bac89ca0946c3717ae229526Tom Taylor public static boolean isFailedToDownload(Intent intent) { 77895817b166d415114bac89ca0946c3717ae229526Tom Taylor return (intent != null) && intent.getBooleanExtra("failed_download_flag", false); 77995817b166d415114bac89ca0946c3717ae229526Tom Taylor } 78072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project} 781