MessagingNotification.java revision 674b5045f39aedf85e6a7e38237860d000f46de0
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; 32c7aa632be8e7d3ebe71f236f534ea2f0af71e04aTom Taylorimport com.android.mms.widget.MmsWidgetProvider; 3372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 34f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport com.google.android.mms.pdu.EncodedStringValue; 35f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport com.google.android.mms.pdu.PduHeaders; 36f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport com.google.android.mms.pdu.PduPersister; 37fd644551e8506266aad2b76463b51b44154ed62fTom Taylorimport android.database.sqlite.SqliteWrapper; 3872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 3972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.app.Notification; 4072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.app.NotificationManager; 4172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.app.PendingIntent; 421fdc24a996e1c2d6a1add1f40260c5e0380f3112Tom Taylorimport android.content.ComponentName; 4372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.content.ContentResolver; 4472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.content.Context; 4572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.content.Intent; 4672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.content.SharedPreferences; 4770f5af8fd89d66ae246a805d10a50540746319aaWei Huangimport android.content.BroadcastReceiver; 4870f5af8fd89d66ae246a805d10a50540746319aaWei Huangimport android.content.IntentFilter; 4972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.database.Cursor; 5072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.graphics.Typeface; 51006d49271549ed639ffcd70d94c7650bb3514796Jim Shumaimport android.media.AudioManager; 5272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.net.Uri; 53b0ef8fc2738b210a2bb0490e75eedc1e7b7b491fTom Taylorimport android.os.AsyncTask; 545a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylorimport android.os.Handler; 5572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.preference.PreferenceManager; 56f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport android.provider.Telephony.Mms; 57f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport android.provider.Telephony.Sms; 5872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.text.Spannable; 5972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.text.SpannableString; 6072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.text.TextUtils; 6172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.text.style.StyleSpan; 6272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.util.Log; 63800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERTimport android.widget.Toast; 6472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 6572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport java.util.Comparator; 66b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrickimport java.util.HashSet; 67b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrickimport java.util.Set; 6872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport java.util.SortedSet; 6972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport java.util.TreeSet; 7072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 7172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project/** 7272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * This class is used to update the notification indicator. It will check whether 7372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * there are unread messages. If yes, it would show the notification indicator, 7472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * otherwise, hide the indicator. 7572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project */ 7672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectpublic class MessagingNotification { 77c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev 78812391ad832f3fdac054ad3a50af563da16e99b5Wei Huang private static final String TAG = LogTag.APP; 7972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 8072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static final int NOTIFICATION_ID = 123; 8172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project public static final int MESSAGE_FAILED_NOTIFICATION_ID = 789; 8272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project public static final int DOWNLOAD_FAILED_NOTIFICATION_ID = 531; 83c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev /** 84c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev * This is the volume at which to play the in-conversation notification sound, 85c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev * expressed as a fraction of the system notification volume. 86c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev */ 87c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev private static final float IN_CONVERSATION_NOTIFICATION_VOLUME = 0.25f; 8872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 8972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project // This must be consistent with the column constants below. 9072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static final String[] MMS_STATUS_PROJECTION = new String[] { 9172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project Mms.THREAD_ID, Mms.DATE, Mms._ID, Mms.SUBJECT, Mms.SUBJECT_CHARSET }; 9272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 9372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project // This must be consistent with the column constants below. 9472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static final String[] SMS_STATUS_PROJECTION = new String[] { 9572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project Sms.THREAD_ID, Sms.DATE, Sms.ADDRESS, Sms.SUBJECT, Sms.BODY }; 9672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 9772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project // These must be consistent with MMS_STATUS_PROJECTION and 9872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project // SMS_STATUS_PROJECTION. 9972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static final int COLUMN_THREAD_ID = 0; 10072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static final int COLUMN_DATE = 1; 10172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static final int COLUMN_MMS_ID = 2; 10272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static final int COLUMN_SMS_ADDRESS = 2; 10372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static final int COLUMN_SUBJECT = 3; 10472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static final int COLUMN_SUBJECT_CS = 4; 10572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static final int COLUMN_SMS_BODY = 4; 10672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 107c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev private static final String[] SMS_THREAD_ID_PROJECTION = new String[] { Sms.THREAD_ID }; 108c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev private static final String[] MMS_THREAD_ID_PROJECTION = new String[] { Mms.THREAD_ID }; 109c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev 11072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static final String NEW_INCOMING_SM_CONSTRAINT = 11172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project "(" + Sms.TYPE + " = " + Sms.MESSAGE_TYPE_INBOX 112627007213deb59ef938c80353c8f3598b01478b3Wei Huang + " AND " + Sms.SEEN + " = 0)"; 11372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 114800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT private static final String NEW_DELIVERY_SM_CONSTRAINT = 115c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor "(" + Sms.TYPE + " = " + Sms.MESSAGE_TYPE_SENT 116c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor + " AND " + Sms.STATUS + " = "+ Sms.STATUS_COMPLETE +")"; 117800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT 11872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static final String NEW_INCOMING_MM_CONSTRAINT = 11972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project "(" + Mms.MESSAGE_BOX + "=" + Mms.MESSAGE_BOX_INBOX 120627007213deb59ef938c80353c8f3598b01478b3Wei Huang + " AND " + Mms.SEEN + "=0" 12172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project + " AND (" + Mms.MESSAGE_TYPE + "=" + MESSAGE_TYPE_NOTIFICATION_IND 12272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project + " OR " + Mms.MESSAGE_TYPE + "=" + MESSAGE_TYPE_RETRIEVE_CONF + "))"; 12372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 12472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static final MmsSmsNotificationInfoComparator INFO_COMPARATOR = 12572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project new MmsSmsNotificationInfoComparator(); 1265a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor 12772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static final Uri UNDELIVERED_URI = Uri.parse("content://mms-sms/undelivered"); 12872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 12970f5af8fd89d66ae246a805d10a50540746319aaWei Huang 13070f5af8fd89d66ae246a805d10a50540746319aaWei Huang private final static String NOTIFICATION_DELETED_ACTION = 13170f5af8fd89d66ae246a805d10a50540746319aaWei Huang "com.android.mms.NOTIFICATION_DELETED_ACTION"; 13270f5af8fd89d66ae246a805d10a50540746319aaWei Huang 13370f5af8fd89d66ae246a805d10a50540746319aaWei Huang public static class OnDeletedReceiver extends BroadcastReceiver { 134c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev @Override 13570f5af8fd89d66ae246a805d10a50540746319aaWei Huang public void onReceive(Context context, Intent intent) { 13670f5af8fd89d66ae246a805d10a50540746319aaWei Huang if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) { 13770f5af8fd89d66ae246a805d10a50540746319aaWei Huang Log.d(TAG, "[MessagingNotification] clear notification: mark all msgs seen"); 13870f5af8fd89d66ae246a805d10a50540746319aaWei Huang } 13970f5af8fd89d66ae246a805d10a50540746319aaWei Huang 14070f5af8fd89d66ae246a805d10a50540746319aaWei Huang Conversation.markAllConversationsAsSeen(context); 14170f5af8fd89d66ae246a805d10a50540746319aaWei Huang } 142c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev } 143c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev 144c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev public static final long THREAD_ALL = -1; 145c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev public static final long THREAD_NONE = -2; 146c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev /** 147c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev * Keeps track of the thread ID of the conversation that's currently displayed to the user 148c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev */ 149c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev private static long sCurrentlyDisplayedThreadId; 150c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev private static final Object sCurrentlyDisplayedThreadLock = new Object(); 151c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev 15270f5af8fd89d66ae246a805d10a50540746319aaWei Huang private static OnDeletedReceiver sNotificationDeletedReceiver = new OnDeletedReceiver(); 15370f5af8fd89d66ae246a805d10a50540746319aaWei Huang private static Intent sNotificationOnDeleteIntent; 1545a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor private static Handler mToastHandler = new Handler(); 15570f5af8fd89d66ae246a805d10a50540746319aaWei Huang 15672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private MessagingNotification() { 15772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 15872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 15970f5af8fd89d66ae246a805d10a50540746319aaWei Huang public static void init(Context context) { 16070f5af8fd89d66ae246a805d10a50540746319aaWei Huang // set up the intent filter for notification deleted action 16170f5af8fd89d66ae246a805d10a50540746319aaWei Huang IntentFilter intentFilter = new IntentFilter(); 16270f5af8fd89d66ae246a805d10a50540746319aaWei Huang intentFilter.addAction(NOTIFICATION_DELETED_ACTION); 16370f5af8fd89d66ae246a805d10a50540746319aaWei Huang context.registerReceiver(sNotificationDeletedReceiver, intentFilter); 16470f5af8fd89d66ae246a805d10a50540746319aaWei Huang 16570f5af8fd89d66ae246a805d10a50540746319aaWei Huang // initialize the notification deleted action 16670f5af8fd89d66ae246a805d10a50540746319aaWei Huang sNotificationOnDeleteIntent = new Intent(NOTIFICATION_DELETED_ACTION); 16770f5af8fd89d66ae246a805d10a50540746319aaWei Huang } 16870f5af8fd89d66ae246a805d10a50540746319aaWei Huang 16972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project /** 170c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev * Specifies which message thread is currently being viewed by the user. New messages in that 171c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev * thread will not generate a notification icon and will play the notification sound at a lower 172c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev * volume. Make sure you set this to THREAD_NONE when the UI component that shows the thread is 173c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev * no longer visible to the user (e.g. Activity.onPause(), etc.) 174c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev * @param threadId The ID of the thread that the user is currently viewing. Pass THREAD_NONE 175c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev * if the user is not viewing a thread, or THREAD_ALL if the user is viewing the conversation 176c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev * list (note: that latter one has no effect as of this implementation) 177c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev */ 178c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev public static void setCurrentlyDisplayedThreadId(long threadId) { 179c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev synchronized (sCurrentlyDisplayedThreadLock) { 180c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev sCurrentlyDisplayedThreadId = threadId; 181c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev } 182c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev } 183c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev 184c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev /** 185627007213deb59ef938c80353c8f3598b01478b3Wei Huang * Checks to see if there are any "unseen" messages or delivery 18672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * reports. Shows the most recent notification if there is one. 1873b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor * Does its work and query in a worker thread. 18872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * 18972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * @param context the context to use 19072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project */ 1913b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor public static void nonBlockingUpdateNewMessageIndicator(final Context context, 192c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev final long newMsgThreadId, 1933b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor final boolean isStatusMessage) { 1943b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor new Thread(new Runnable() { 195c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev @Override 1963b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor public void run() { 197c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev blockingUpdateNewMessageIndicator(context, newMsgThreadId, isStatusMessage); 1983b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor } 199ddd31c4011b4191035bdfbba05a8edb1785f71afTodor Kalaydjiev }, "MessagingNotification.nonBlockingUpdateNewMessageIndicator").start(); 20072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 20172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 20272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project /** 203627007213deb59ef938c80353c8f3598b01478b3Wei Huang * Checks to see if there are any "unseen" messages or delivery 20472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * reports. Shows the most recent notification if there is one. 20572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * 20672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * @param context the context to use 207c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev * @param newMsgThreadId The thread ID of a new message that we're to notify about; if there's 208c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev * no new message, use THREAD_NONE. If we should notify about multiple or unknown thread IDs, 209c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev * use THREAD_ALL. 210c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev * @param isStatusMessage 21172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project */ 212c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev public static void blockingUpdateNewMessageIndicator(Context context, long newMsgThreadId, 213c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor boolean isStatusMessage) { 214c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev synchronized (sCurrentlyDisplayedThreadLock) { 215c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev if (newMsgThreadId > 0 && newMsgThreadId == sCurrentlyDisplayedThreadId) { 216c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev playInConversationNotificationSound(context); 217c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev return; 218c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev } 219c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev } 220c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev 22172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project SortedSet<MmsSmsNotificationInfo> accumulator = 22272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project new TreeSet<MmsSmsNotificationInfo>(INFO_COMPARATOR); 223c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor MmsSmsDeliveryInfo delivery = null; 224b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick Set<Long> threads = new HashSet<Long>(4); 2255a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor 22672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project int count = 0; 22772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project count += accumulateNotificationInfo( 228b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick accumulator, getMmsNewMessageNotificationInfo(context, threads)); 22972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project count += accumulateNotificationInfo( 230b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick accumulator, getSmsNewMessageNotificationInfo(context, threads)); 23172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 23272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project cancelNotification(context, NOTIFICATION_ID); 23372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project if (!accumulator.isEmpty()) { 234e14b79584cca1bf7ba60c53bd7e3d6386adbfc59Wei Huang if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) { 235e14b79584cca1bf7ba60c53bd7e3d6386adbfc59Wei Huang Log.d(TAG, "blockingUpdateNewMessageIndicator: count=" + count + 236c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev ", newMsgThreadId=" + newMsgThreadId); 237e14b79584cca1bf7ba60c53bd7e3d6386adbfc59Wei Huang } 238c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev accumulator.first().deliver(context, newMsgThreadId != THREAD_NONE, count, threads.size()); 23972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 2405a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor 2413b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor // And deals with delivery reports (which use Toasts). It's safe to call in a worker 2423b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor // thread because the toast will eventually get posted to a handler. 243627007213deb59ef938c80353c8f3598b01478b3Wei Huang delivery = getSmsNewDeliveryInfo(context); 244627007213deb59ef938c80353c8f3598b01478b3Wei Huang if (delivery != null) { 245c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor delivery.deliver(context, isStatusMessage); 246627007213deb59ef938c80353c8f3598b01478b3Wei Huang } 24772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 24872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 24972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project /** 250c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev * Play the in-conversation notification sound (it's the regular notification sound, but 251c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev * played at half-volume 252c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev */ 253c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev private static void playInConversationNotificationSound(Context context) { 254c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev final AudioManager audioManager = 255c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); 256c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev 257c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context); 258c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev String ringtoneStr = sp.getString(MessagingPreferenceActivity.NOTIFICATION_RINGTONE, 259c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev null); 260c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev if (TextUtils.isEmpty(ringtoneStr)) { 261c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev // Nothing to play 262c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev return; 263c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev } 264c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev Uri ringtoneUri = Uri.parse(ringtoneStr); 265c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev NotificationPlayer player = new NotificationPlayer(LogTag.APP); 266c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev player.play(context, ringtoneUri, false, AudioManager.STREAM_NOTIFICATION, 267c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev IN_CONVERSATION_NOTIFICATION_VOLUME); 268c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev } 269c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev 270c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev /** 27135a74a9e0ee7c171c6e17f0eda4b0df0253f8364Ficus Kirkpatrick * Updates all pending notifications, clearing or updating them as 2723b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor * necessary. 27335a74a9e0ee7c171c6e17f0eda4b0df0253f8364Ficus Kirkpatrick */ 274627007213deb59ef938c80353c8f3598b01478b3Wei Huang public static void blockingUpdateAllNotifications(final Context context) { 275c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev nonBlockingUpdateNewMessageIndicator(context, THREAD_NONE, false); 276b0ef8fc2738b210a2bb0490e75eedc1e7b7b491fTom Taylor nonBlockingUpdateSendFailedNotification(context); 277627007213deb59ef938c80353c8f3598b01478b3Wei Huang updateDownloadFailedNotification(context); 278c7aa632be8e7d3ebe71f236f534ea2f0af71e04aTom Taylor MmsWidgetProvider.notifyDatasetChanged(context); 27935a74a9e0ee7c171c6e17f0eda4b0df0253f8364Ficus Kirkpatrick } 2805a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor 28172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static final int accumulateNotificationInfo( 282c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev SortedSet<MmsSmsNotificationInfo> set, MmsSmsNotificationInfo info) { 28372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project if (info != null) { 28472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project set.add(info); 28572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 28672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project return info.mCount; 28772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 28872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 28972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project return 0; 29072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 29172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 292800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT private static final class MmsSmsDeliveryInfo { 293c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor public CharSequence mTicker; 294c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor public long mTimeMillis; 295c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor 296c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor public MmsSmsDeliveryInfo(CharSequence ticker, long timeMillis) { 297c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor mTicker = ticker; 298c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor mTimeMillis = timeMillis; 299c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor } 300c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor 301c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor public void deliver(Context context, boolean isStatusMessage) { 302c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor updateDeliveryNotification( 303c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor context, isStatusMessage, mTicker, mTimeMillis); 304c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor } 305800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT } 306800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT 30772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static final class MmsSmsNotificationInfo { 308c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev public final Intent mClickIntent; 309c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev public final String mDescription; 310c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev public final int mIconResourceId; 311c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev public final CharSequence mTicker; 312c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev public final long mTimeMillis; 313c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev public final String mTitle; 314c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev public final int mCount; 31572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 31672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project public MmsSmsNotificationInfo( 31772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project Intent clickIntent, String description, int iconResourceId, 31872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project CharSequence ticker, long timeMillis, String title, int count) { 31972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project mClickIntent = clickIntent; 32072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project mDescription = description; 32172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project mIconResourceId = iconResourceId; 32272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project mTicker = ticker; 32372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project mTimeMillis = timeMillis; 32472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project mTitle = title; 32572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project mCount = count; 32672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 32772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 328b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick public void deliver(Context context, boolean isNew, int count, int uniqueThreads) { 32972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project updateNotification( 3303c68b6852913222dd982dddd4e39b3e57613c37eWei Huang context, mClickIntent, mDescription, mIconResourceId, isNew, 3313c68b6852913222dd982dddd4e39b3e57613c37eWei Huang (isNew? mTicker : null), // only display the ticker if the message is new 3323c68b6852913222dd982dddd4e39b3e57613c37eWei Huang mTimeMillis, mTitle, count, uniqueThreads); 33372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 33472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 33572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project public long getTime() { 33672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project return mTimeMillis; 33772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 33872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 33972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 34072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static final class MmsSmsNotificationInfoComparator 34172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project implements Comparator<MmsSmsNotificationInfo> { 342c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev @Override 34372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project public int compare( 34472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project MmsSmsNotificationInfo info1, MmsSmsNotificationInfo info2) { 34572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project return Long.signum(info2.getTime() - info1.getTime()); 34672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 34772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 34872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 3493b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor private static final MmsSmsNotificationInfo getMmsNewMessageNotificationInfo( 350b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick Context context, Set<Long> threads) { 35172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project ContentResolver resolver = context.getContentResolver(); 3523b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor 3533b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor // This query looks like this when logged: 3543b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor // I/Database( 147): elapsedTime4Sql|/data/data/com.android.providers.telephony/databases/ 3553b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor // mmssms.db|0.362 ms|SELECT thread_id, date, _id, sub, sub_cs FROM pdu WHERE ((msg_box=1 3563b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor // AND seen=0 AND (m_type=130 OR m_type=132))) ORDER BY date desc 3573b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor 35872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project Cursor cursor = SqliteWrapper.query(context, resolver, Mms.CONTENT_URI, 35972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project MMS_STATUS_PROJECTION, NEW_INCOMING_MM_CONSTRAINT, 36072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project null, Mms.DATE + " desc"); 36172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 362b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick if (cursor == null) { 363b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick return null; 364b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick } 3655a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor 366b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick try { 367b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick if (!cursor.moveToFirst()) { 368b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick return null; 36972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 370c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev 371b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick long msgId = cursor.getLong(COLUMN_MMS_ID); 372b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick Uri msgUri = Mms.CONTENT_URI.buildUpon().appendPath( 373b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick Long.toString(msgId)).build(); 374b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick String address = AddressUtils.getFrom(context, msgUri); 3751b8df494e49bf934fe160baea54ab5afc2ff3100Tom Taylor 3761b8df494e49bf934fe160baea54ab5afc2ff3100Tom Taylor Contact contact = Contact.get(address, false); 3771b8df494e49bf934fe160baea54ab5afc2ff3100Tom Taylor if (contact.getSendToVoicemail()) { 3781b8df494e49bf934fe160baea54ab5afc2ff3100Tom Taylor // don't notify 3791b8df494e49bf934fe160baea54ab5afc2ff3100Tom Taylor return null; 3801b8df494e49bf934fe160baea54ab5afc2ff3100Tom Taylor } 3811b8df494e49bf934fe160baea54ab5afc2ff3100Tom Taylor 382b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick String subject = getMmsSubject( 383b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick cursor.getString(COLUMN_SUBJECT), cursor.getInt(COLUMN_SUBJECT_CS)); 384b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick long threadId = cursor.getLong(COLUMN_THREAD_ID); 385b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick long timeMillis = cursor.getLong(COLUMN_DATE) * 1000; 386b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick 387e14b79584cca1bf7ba60c53bd7e3d6386adbfc59Wei Huang if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) { 388e14b79584cca1bf7ba60c53bd7e3d6386adbfc59Wei Huang Log.d(TAG, "getMmsNewMessageNotificationInfo: count=" + cursor.getCount() + 389e14b79584cca1bf7ba60c53bd7e3d6386adbfc59Wei Huang ", first addr = " + address + ", thread_id=" + threadId); 390e14b79584cca1bf7ba60c53bd7e3d6386adbfc59Wei Huang } 391e14b79584cca1bf7ba60c53bd7e3d6386adbfc59Wei Huang 392b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick MmsSmsNotificationInfo info = getNewMessageNotificationInfo( 393b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick address, subject, context, 394b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick R.drawable.stat_notify_mms, null, threadId, 395b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick timeMillis, cursor.getCount()); 396b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick 397b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick threads.add(threadId); 398b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick while (cursor.moveToNext()) { 399b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick threads.add(cursor.getLong(COLUMN_THREAD_ID)); 400b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick } 401b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick 402b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick return info; 403b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick } finally { 404b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick cursor.close(); 40572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 40672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 40772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 4083b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor private static final MmsSmsDeliveryInfo getSmsNewDeliveryInfo(Context context) { 409627007213deb59ef938c80353c8f3598b01478b3Wei Huang ContentResolver resolver = context.getContentResolver(); 410627007213deb59ef938c80353c8f3598b01478b3Wei Huang Cursor cursor = SqliteWrapper.query(context, resolver, Sms.CONTENT_URI, 411627007213deb59ef938c80353c8f3598b01478b3Wei Huang SMS_STATUS_PROJECTION, NEW_DELIVERY_SM_CONSTRAINT, 4126a9c779f0c0dc6cf3ae942ff70fb6c806aa166dcBanavathu, Srinivas Naik null, Sms.DATE); 413800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT 414ac9a5e52dc349faae2a7d8a990ff2b674c61f027Alexander Blom if (cursor == null) { 415627007213deb59ef938c80353c8f3598b01478b3Wei Huang return null; 416ac9a5e52dc349faae2a7d8a990ff2b674c61f027Alexander Blom } 417800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT 418627007213deb59ef938c80353c8f3598b01478b3Wei Huang try { 419ac9a5e52dc349faae2a7d8a990ff2b674c61f027Alexander Blom if (!cursor.moveToLast()) { 420ac9a5e52dc349faae2a7d8a990ff2b674c61f027Alexander Blom return null; 421ac9a5e52dc349faae2a7d8a990ff2b674c61f027Alexander Blom } 422800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT 423627007213deb59ef938c80353c8f3598b01478b3Wei Huang String address = cursor.getString(COLUMN_SMS_ADDRESS); 424627007213deb59ef938c80353c8f3598b01478b3Wei Huang long timeMillis = 3000; 425800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT 426ac9a5e52dc349faae2a7d8a990ff2b674c61f027Alexander Blom Contact contact = Contact.get(address, false); 427ac9a5e52dc349faae2a7d8a990ff2b674c61f027Alexander Blom String name = contact.getNameAndNumber(); 428ac9a5e52dc349faae2a7d8a990ff2b674c61f027Alexander Blom 429ac9a5e52dc349faae2a7d8a990ff2b674c61f027Alexander Blom return new MmsSmsDeliveryInfo(context.getString(R.string.delivery_toast_body, name), 430627007213deb59ef938c80353c8f3598b01478b3Wei Huang timeMillis); 431800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT 432627007213deb59ef938c80353c8f3598b01478b3Wei Huang } finally { 433627007213deb59ef938c80353c8f3598b01478b3Wei Huang cursor.close(); 434627007213deb59ef938c80353c8f3598b01478b3Wei Huang } 435800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT } 436800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT 4373b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor private static final MmsSmsNotificationInfo getSmsNewMessageNotificationInfo( 438b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick Context context, Set<Long> threads) { 43972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project ContentResolver resolver = context.getContentResolver(); 44072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project Cursor cursor = SqliteWrapper.query(context, resolver, Sms.CONTENT_URI, 44172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project SMS_STATUS_PROJECTION, NEW_INCOMING_SM_CONSTRAINT, 44272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project null, Sms.DATE + " desc"); 44372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 444b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick if (cursor == null) { 445b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick return null; 446b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick } 4475a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor 448b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick try { 449b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick if (!cursor.moveToFirst()) { 450b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick return null; 451b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick } 452b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick 453b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick String address = cursor.getString(COLUMN_SMS_ADDRESS); 4541b8df494e49bf934fe160baea54ab5afc2ff3100Tom Taylor 4551b8df494e49bf934fe160baea54ab5afc2ff3100Tom Taylor Contact contact = Contact.get(address, false); 4561b8df494e49bf934fe160baea54ab5afc2ff3100Tom Taylor if (contact.getSendToVoicemail()) { 4571b8df494e49bf934fe160baea54ab5afc2ff3100Tom Taylor // don't notify 4581b8df494e49bf934fe160baea54ab5afc2ff3100Tom Taylor return null; 4591b8df494e49bf934fe160baea54ab5afc2ff3100Tom Taylor } 4601b8df494e49bf934fe160baea54ab5afc2ff3100Tom Taylor 461b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick String body = cursor.getString(COLUMN_SMS_BODY); 462b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick long threadId = cursor.getLong(COLUMN_THREAD_ID); 463b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick long timeMillis = cursor.getLong(COLUMN_DATE); 464b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick 465d83675687b1ef742c33bffe8195d7b1852c2c01dTom Taylor if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) 466e14b79584cca1bf7ba60c53bd7e3d6386adbfc59Wei Huang { 467e14b79584cca1bf7ba60c53bd7e3d6386adbfc59Wei Huang Log.d(TAG, "getSmsNewMessageNotificationInfo: count=" + cursor.getCount() + 468e14b79584cca1bf7ba60c53bd7e3d6386adbfc59Wei Huang ", first addr=" + address + ", thread_id=" + threadId); 469e14b79584cca1bf7ba60c53bd7e3d6386adbfc59Wei Huang } 470e14b79584cca1bf7ba60c53bd7e3d6386adbfc59Wei Huang 471b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick MmsSmsNotificationInfo info = getNewMessageNotificationInfo( 472b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick address, body, context, R.drawable.stat_notify_sms, 473b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick null, threadId, timeMillis, cursor.getCount()); 474b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick 475b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick threads.add(threadId); 476b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick while (cursor.moveToNext()) { 477b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick threads.add(cursor.getLong(COLUMN_THREAD_ID)); 47872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 479b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick 480b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick return info; 481b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick } finally { 482b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick cursor.close(); 48372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 48472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 48572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 48672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static final MmsSmsNotificationInfo getNewMessageNotificationInfo( 48772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project String address, 48872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project String body, 48972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project Context context, 49072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project int iconResourceId, 49172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project String subject, 49272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project long threadId, 49372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project long timeMillis, 49472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project int count) { 495812391ad832f3fdac054ad3a50af563da16e99b5Wei Huang Intent clickIntent = ComposeMessageActivity.createIntent(context, threadId); 496812391ad832f3fdac054ad3a50af563da16e99b5Wei Huang clickIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK 497812391ad832f3fdac054ad3a50af563da16e99b5Wei Huang | Intent.FLAG_ACTIVITY_SINGLE_TOP 498812391ad832f3fdac054ad3a50af563da16e99b5Wei Huang | Intent.FLAG_ACTIVITY_CLEAR_TOP); 49972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 50072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project String senderInfo = buildTickerMessage( 50172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project context, address, null, null).toString(); 50272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project String senderInfoName = senderInfo.substring( 50372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 0, senderInfo.length() - 2); 50472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project CharSequence ticker = buildTickerMessage( 50572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project context, address, subject, body); 50672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 50772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project return new MmsSmsNotificationInfo( 50872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project clickIntent, body, iconResourceId, ticker, timeMillis, 50972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project senderInfoName, count); 51072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 51172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 51272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project public static void cancelNotification(Context context, int notificationId) { 51372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project NotificationManager nm = (NotificationManager) context.getSystemService( 51472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project Context.NOTIFICATION_SERVICE); 51572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 51672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project nm.cancel(notificationId); 51772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 51872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 5195a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor private static void updateDeliveryNotification(final Context context, 520c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor boolean isStatusMessage, 5215a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor final CharSequence message, 5225a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor final long timeMillis) { 523c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor if (!isStatusMessage) { 524c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor return; 525c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor } 526c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor 527800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT 528d83675687b1ef742c33bffe8195d7b1852c2c01dTom Taylor if (!MessagingPreferenceActivity.getNotificationEnabled(context)) { 52970f5af8fd89d66ae246a805d10a50540746319aaWei Huang return; 53070f5af8fd89d66ae246a805d10a50540746319aaWei Huang } 531800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT 532c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor mToastHandler.post(new Runnable() { 533c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev @Override 534c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor public void run() { 535c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor Toast.makeText(context, message, (int)timeMillis).show(); 536c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor } 537c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor }); 538800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT } 539800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT 54072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static void updateNotification( 54172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project Context context, 54272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project Intent clickIntent, 54372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project String description, 54472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project int iconRes, 54572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project boolean isNew, 54672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project CharSequence ticker, 54772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project long timeMillis, 54872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project String title, 549b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick int messageCount, 550b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick int uniqueThreadCount) { 551d83675687b1ef742c33bffe8195d7b1852c2c01dTom Taylor if (!MessagingPreferenceActivity.getNotificationEnabled(context)) { 55272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project return; 55372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 55472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 555674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler final Notification.Builder noti = new Notification.Builder(context) 556674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler .setSmallIcon(iconRes) 557674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler .setTicker(ticker) 558674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler .setWhen(timeMillis); 559674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler 5601fdc24a996e1c2d6a1add1f40260c5e0380f3112Tom Taylor Intent[] intents; 561b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick 562b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick // If we have more than one unique thread, change the title (which would 563b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick // normally be the contact who sent the message) to a generic one that 564b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick // makes sense for multiple senders, and change the Intent to take the 565b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick // user to the conversation list instead of the specific thread. 566674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler 567674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler // TODO: use forthcoming notification templates to either: 568674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler // - hoist one message out and show an overflow summary, or 569674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler // - show a digest of the last N threads 570b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick if (uniqueThreadCount > 1) { 571b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick title = context.getString(R.string.notification_multiple_title); 5721fdc24a996e1c2d6a1add1f40260c5e0380f3112Tom Taylor Intent mainActivityIntent = new Intent(Intent.ACTION_MAIN); 573812391ad832f3fdac054ad3a50af563da16e99b5Wei Huang 5741fdc24a996e1c2d6a1add1f40260c5e0380f3112Tom Taylor mainActivityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK 575812391ad832f3fdac054ad3a50af563da16e99b5Wei Huang | Intent.FLAG_ACTIVITY_SINGLE_TOP 576812391ad832f3fdac054ad3a50af563da16e99b5Wei Huang | Intent.FLAG_ACTIVITY_CLEAR_TOP); 577812391ad832f3fdac054ad3a50af563da16e99b5Wei Huang 5781fdc24a996e1c2d6a1add1f40260c5e0380f3112Tom Taylor mainActivityIntent.setType("vnd.android-dir/mms-sms"); 5791fdc24a996e1c2d6a1add1f40260c5e0380f3112Tom Taylor intents = new Intent[1]; 5801fdc24a996e1c2d6a1add1f40260c5e0380f3112Tom Taylor intents[0] = mainActivityIntent; 5811fdc24a996e1c2d6a1add1f40260c5e0380f3112Tom Taylor } else { 5821fdc24a996e1c2d6a1add1f40260c5e0380f3112Tom Taylor // Build a stack of intents so when the user hits back from the ComposeMessageActivity 5831fdc24a996e1c2d6a1add1f40260c5e0380f3112Tom Taylor // we're sending them to, they'll up on ConversationList. 5841fdc24a996e1c2d6a1add1f40260c5e0380f3112Tom Taylor intents = new Intent[2]; 5851fdc24a996e1c2d6a1add1f40260c5e0380f3112Tom Taylor 5861fdc24a996e1c2d6a1add1f40260c5e0380f3112Tom Taylor // First: root activity of the MessagingApp: ConversationList. 5871fdc24a996e1c2d6a1add1f40260c5e0380f3112Tom Taylor // This is a convenient way to make the proper Intent to launch and 5881fdc24a996e1c2d6a1add1f40260c5e0380f3112Tom Taylor // reset an application's task. 5891fdc24a996e1c2d6a1add1f40260c5e0380f3112Tom Taylor intents[0] = Intent.makeRestartActivityTask(new ComponentName(context, 5901fdc24a996e1c2d6a1add1f40260c5e0380f3112Tom Taylor ConversationList.class)); 5911fdc24a996e1c2d6a1add1f40260c5e0380f3112Tom Taylor intents[1] = clickIntent; 592b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick } 5935a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor 594b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick // If there is more than one message, change the description (which 595b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick // would normally be a snippet of the individual message text) to 596627007213deb59ef938c80353c8f3598b01478b3Wei Huang // a string indicating how many "unseen" messages there are. 597674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler 598674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler // TODO: show the most recent message in full plus some indication of older messages in the thread 599b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick if (messageCount > 1) { 600b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick description = context.getString(R.string.notification_multiple, 601b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick Integer.toString(messageCount)); 602b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick } 60372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 604b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick // Make a startActivity() PendingIntent for the notification. 6051fdc24a996e1c2d6a1add1f40260c5e0380f3112Tom Taylor PendingIntent pendingIntent = PendingIntent.getActivities(context, 0, intents, 606810fae756f4d2db00b35d7c9dfead252737abdacTom Taylor PendingIntent.FLAG_UPDATE_CURRENT); 60772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 608b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick // Update the notification. 609674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler noti.setContentTitle(title) 610674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler .setContentText(description) 611674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler .setContentIntent(pendingIntent); 612674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler 613674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler int defaults = 0; 61472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 61572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project if (isNew) { 616d83675687b1ef742c33bffe8195d7b1852c2c01dTom Taylor SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context); 617006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma String vibrateWhen; 618006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma if (sp.contains(MessagingPreferenceActivity.NOTIFICATION_VIBRATE_WHEN)) { 619006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma vibrateWhen = 620006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma sp.getString(MessagingPreferenceActivity.NOTIFICATION_VIBRATE_WHEN, null); 621006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma } else if (sp.contains(MessagingPreferenceActivity.NOTIFICATION_VIBRATE)) { 622006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma vibrateWhen = sp.getBoolean(MessagingPreferenceActivity.NOTIFICATION_VIBRATE, false) ? 623006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma context.getString(R.string.prefDefault_vibrate_true) : 624006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma context.getString(R.string.prefDefault_vibrate_false); 625006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma } else { 626006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma vibrateWhen = context.getString(R.string.prefDefault_vibrateWhen); 627006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma } 628006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma 629006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma boolean vibrateAlways = vibrateWhen.equals("always"); 630006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma boolean vibrateSilent = vibrateWhen.equals("silent"); 631006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma AudioManager audioManager = 632006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma (AudioManager)context.getSystemService(Context.AUDIO_SERVICE); 633006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma boolean nowSilent = 634006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma audioManager.getRingerMode() == AudioManager.RINGER_MODE_VIBRATE; 635006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma 636006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma if (vibrateAlways || vibrateSilent && nowSilent) { 637674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler defaults |= Notification.DEFAULT_VIBRATE; 63872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 63972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 640627007213deb59ef938c80353c8f3598b01478b3Wei Huang String ringtoneStr = sp.getString(MessagingPreferenceActivity.NOTIFICATION_RINGTONE, 641627007213deb59ef938c80353c8f3598b01478b3Wei Huang null); 642674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler noti.setSound(TextUtils.isEmpty(ringtoneStr) ? null : Uri.parse(ringtoneStr)); 64372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 64472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 645674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler defaults |= Notification.DEFAULT_LIGHTS; 646674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler 647674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler noti.setDefaults(defaults); 64872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 64970f5af8fd89d66ae246a805d10a50540746319aaWei Huang // set up delete intent 650674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler noti.setDeleteIntent(PendingIntent.getBroadcast(context, 0, 651674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler sNotificationOnDeleteIntent, 0)); 65270f5af8fd89d66ae246a805d10a50540746319aaWei Huang 65372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project NotificationManager nm = (NotificationManager) 65472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project context.getSystemService(Context.NOTIFICATION_SERVICE); 65572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 656674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler final Notification notification; 657674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler if (messageCount == 1) { 658674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler notification = new Notification.BigTextStyle(noti) 659674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler .bigText(description) 660674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler .build(); 661674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler } else { 662674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler notification = noti.getNotification(); 663674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler } 664674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler 66572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project nm.notify(NOTIFICATION_ID, notification); 66672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 66772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 66872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project protected static CharSequence buildTickerMessage( 66972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project Context context, String address, String subject, String body) { 67033a87f96f8c625aa10131a77a3968c97c4ec5a62Ficus Kirkpatrick String displayAddress = Contact.get(address, true).getName(); 6715a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor 67272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project StringBuilder buf = new StringBuilder( 67372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project displayAddress == null 67472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project ? "" 67572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project : displayAddress.replace('\n', ' ').replace('\r', ' ')); 67672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project buf.append(':').append(' '); 67772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 67872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project int offset = buf.length(); 67972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project if (!TextUtils.isEmpty(subject)) { 68072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project subject = subject.replace('\n', ' ').replace('\r', ' '); 68172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project buf.append(subject); 68272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project buf.append(' '); 68372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 68472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 68572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project if (!TextUtils.isEmpty(body)) { 68672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project body = body.replace('\n', ' ').replace('\r', ' '); 68772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project buf.append(body); 68872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 68972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 69072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project SpannableString spanText = new SpannableString(buf.toString()); 69172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project spanText.setSpan(new StyleSpan(Typeface.BOLD), 0, offset, 69272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 69372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 69472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project return spanText; 69572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 69672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 69772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static String getMmsSubject(String sub, int charset) { 69872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project return TextUtils.isEmpty(sub) ? "" 69972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project : new EncodedStringValue(charset, PduPersister.getBytes(sub)).getString(); 70072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 70172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 70272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project public static void notifyDownloadFailed(Context context, long threadId) { 703b3cb9bbf929f70cb4855f03e4bfbed749022cf1bFicus Kirkpatrick notifyFailed(context, true, threadId, false); 70472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 70572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 7065d2d0046ada7b53205e537d8675d32a8785e8d1dThe Android Open Source Project public static void notifySendFailed(Context context) { 707b3cb9bbf929f70cb4855f03e4bfbed749022cf1bFicus Kirkpatrick notifyFailed(context, false, 0, false); 70872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 70972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 710b3cb9bbf929f70cb4855f03e4bfbed749022cf1bFicus Kirkpatrick public static void notifySendFailed(Context context, boolean noisy) { 711b3cb9bbf929f70cb4855f03e4bfbed749022cf1bFicus Kirkpatrick notifyFailed(context, false, 0, noisy); 712b3cb9bbf929f70cb4855f03e4bfbed749022cf1bFicus Kirkpatrick } 7135a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor 714b3cb9bbf929f70cb4855f03e4bfbed749022cf1bFicus Kirkpatrick private static void notifyFailed(Context context, boolean isDownload, long threadId, 715b3cb9bbf929f70cb4855f03e4bfbed749022cf1bFicus Kirkpatrick boolean noisy) { 71672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project // TODO factor out common code for creating notifications 717d83675687b1ef742c33bffe8195d7b1852c2c01dTom Taylor boolean enabled = MessagingPreferenceActivity.getNotificationEnabled(context); 71872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project if (!enabled) { 71972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project return; 72072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 72172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 72272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project NotificationManager nm = (NotificationManager) 72372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project context.getSystemService(Context.NOTIFICATION_SERVICE); 7245a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor 72572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project // Strategy: 72672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project // a. If there is a single failure notification, tapping on the notification goes 72772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project // to the compose view. 7285a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor // b. If there are two failure it stays in the thread view. Selecting one undelivered 72972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project // thread will dismiss one undelivered notification but will still display the 73072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project // notification.If you select the 2nd undelivered one it will dismiss the notification. 7315a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor 7327015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev long[] msgThreadId = {0, 1}; // Dummy initial values, just to initialize the memory 73372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project int totalFailedCount = getUndeliveredMessageCount(context, msgThreadId); 7347015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev if (totalFailedCount == 0 && !isDownload) { 7357015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev return; 7367015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev } 7377015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev // The getUndeliveredMessageCount method puts a non-zero value in msgThreadId[1] if all 7387015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev // failures are from the same thread. 7397015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev // If isDownload is true, we're dealing with 1 specific failure; therefore "all failed" are 7407015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev // indeed in the same thread since there's only 1. 7417015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev boolean allFailedInSameThread = (msgThreadId[1] != 0) || isDownload; 7425a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor 74372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project Intent failedIntent; 74472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project Notification notification = new Notification(); 74572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project String title; 74672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project String description; 74772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project if (totalFailedCount > 1) { 74872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project description = context.getString(R.string.notification_failed_multiple, 74972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project Integer.toString(totalFailedCount)); 75072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project title = context.getString(R.string.notification_failed_multiple_title); 75172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } else { 75272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project title = isDownload ? 75372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project context.getString(R.string.message_download_failed_title) : 75472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project context.getString(R.string.message_send_failed_title); 7555a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor 75672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project description = context.getString(R.string.message_failed_body); 7577015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev } 7587015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev 7597015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev if (allFailedInSameThread) { 760836945de572ac80fd6f6a7bf59036d4cce801410The Android Open Source Project failedIntent = new Intent(context, ComposeMessageActivity.class); 76195817b166d415114bac89ca0946c3717ae229526Tom Taylor if (isDownload) { 76295817b166d415114bac89ca0946c3717ae229526Tom Taylor // When isDownload is true, the valid threadId is passed into this function. 76395817b166d415114bac89ca0946c3717ae229526Tom Taylor failedIntent.putExtra("failed_download_flag", true); 76495817b166d415114bac89ca0946c3717ae229526Tom Taylor } else { 7657015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev threadId = msgThreadId[0]; 76695817b166d415114bac89ca0946c3717ae229526Tom Taylor failedIntent.putExtra("undelivered_flag", true); 7675a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor } 7685a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor failedIntent.putExtra("thread_id", threadId); 7697015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev } else { 7707015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev failedIntent = new Intent(context, ConversationList.class); 77172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 77272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 773b92b26763e49fd9cc34d382dee4d764ef163bde5Ficus Kirkpatrick failedIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); 77472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project PendingIntent pendingIntent = PendingIntent.getActivity( 775810fae756f4d2db00b35d7c9dfead252737abdacTom Taylor context, 0, failedIntent, PendingIntent.FLAG_UPDATE_CURRENT); 77672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 77772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project notification.icon = R.drawable.stat_notify_sms_failed; 77872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 77972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project notification.tickerText = title; 78072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 78172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project notification.setLatestEventInfo(context, title, description, pendingIntent); 78272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 783b3cb9bbf929f70cb4855f03e4bfbed749022cf1bFicus Kirkpatrick if (noisy) { 784d83675687b1ef742c33bffe8195d7b1852c2c01dTom Taylor SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context); 785e3baaa51cd25b52c7a24e381319926b9da00abdfWei Huang boolean vibrate = sp.getBoolean(MessagingPreferenceActivity.NOTIFICATION_VIBRATE, 786e3baaa51cd25b52c7a24e381319926b9da00abdfWei Huang false /* don't vibrate by default */); 787b3cb9bbf929f70cb4855f03e4bfbed749022cf1bFicus Kirkpatrick if (vibrate) { 788b3cb9bbf929f70cb4855f03e4bfbed749022cf1bFicus Kirkpatrick notification.defaults |= Notification.DEFAULT_VIBRATE; 789b3cb9bbf929f70cb4855f03e4bfbed749022cf1bFicus Kirkpatrick } 79072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 791e3baaa51cd25b52c7a24e381319926b9da00abdfWei Huang String ringtoneStr = sp.getString(MessagingPreferenceActivity.NOTIFICATION_RINGTONE, 792e3baaa51cd25b52c7a24e381319926b9da00abdfWei Huang null); 793b3cb9bbf929f70cb4855f03e4bfbed749022cf1bFicus Kirkpatrick notification.sound = TextUtils.isEmpty(ringtoneStr) ? null : Uri.parse(ringtoneStr); 794b3cb9bbf929f70cb4855f03e4bfbed749022cf1bFicus Kirkpatrick } 7955a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor 79672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project if (isDownload) { 79772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project nm.notify(DOWNLOAD_FAILED_NOTIFICATION_ID, notification); 79872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } else { 79972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project nm.notify(MESSAGE_FAILED_NOTIFICATION_ID, notification); 80072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 80172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 8025a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor 8037015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev /** 8047015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev * Query the DB and return the number of undelivered messages (total for both SMS and MMS) 8057015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev * @param context The context 8067015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev * @param threadIdResult A container to put the result in, according to the following rules: 8077015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev * threadIdResult[0] contains the thread id of the first message. 8087015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev * threadIdResult[1] is nonzero if the thread ids of all the messages are the same. 8097015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev * You can pass in null for threadIdResult. 8107015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev * You can pass in a threadIdResult of size 1 to avoid the comparison of each thread id. 8117015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev */ 81272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static int getUndeliveredMessageCount(Context context, long[] threadIdResult) { 81372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project Cursor undeliveredCursor = SqliteWrapper.query(context, context.getContentResolver(), 814c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev UNDELIVERED_URI, MMS_THREAD_ID_PROJECTION, "read=0", null, null); 81572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project if (undeliveredCursor == null) { 81672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project return 0; 81772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 81872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project int count = undeliveredCursor.getCount(); 81972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project try { 82072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project if (threadIdResult != null && undeliveredCursor.moveToFirst()) { 82172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project threadIdResult[0] = undeliveredCursor.getLong(0); 8225a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor 8232f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project if (threadIdResult.length >= 2) { 8242f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project // Test to see if all the undelivered messages belong to the same thread. 8252f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project long firstId = threadIdResult[0]; 8262f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project while (undeliveredCursor.moveToNext()) { 8272f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project if (undeliveredCursor.getLong(0) != firstId) { 8282f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project firstId = 0; 8292f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project break; 8302f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project } 8312f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project } 8322f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project threadIdResult[1] = firstId; // non-zero if all ids are the same 8332f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project } 83472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 83572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } finally { 83672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project undeliveredCursor.close(); 83772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 83872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project return count; 83972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 84072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 841b0ef8fc2738b210a2bb0490e75eedc1e7b7b491fTom Taylor public static void nonBlockingUpdateSendFailedNotification(final Context context) { 842b0ef8fc2738b210a2bb0490e75eedc1e7b7b491fTom Taylor new AsyncTask<Void, Void, Integer>() { 843b0ef8fc2738b210a2bb0490e75eedc1e7b7b491fTom Taylor protected Integer doInBackground(Void... none) { 844b0ef8fc2738b210a2bb0490e75eedc1e7b7b491fTom Taylor return getUndeliveredMessageCount(context, null); 845b0ef8fc2738b210a2bb0490e75eedc1e7b7b491fTom Taylor } 846b0ef8fc2738b210a2bb0490e75eedc1e7b7b491fTom Taylor 847b0ef8fc2738b210a2bb0490e75eedc1e7b7b491fTom Taylor protected void onPostExecute(Integer result) { 848b0ef8fc2738b210a2bb0490e75eedc1e7b7b491fTom Taylor if (result < 1) { 849b0ef8fc2738b210a2bb0490e75eedc1e7b7b491fTom Taylor cancelNotification(context, MESSAGE_FAILED_NOTIFICATION_ID); 850b0ef8fc2738b210a2bb0490e75eedc1e7b7b491fTom Taylor } else { 851b0ef8fc2738b210a2bb0490e75eedc1e7b7b491fTom Taylor // rebuild and adjust the message count if necessary. 852b0ef8fc2738b210a2bb0490e75eedc1e7b7b491fTom Taylor notifySendFailed(context); 853b0ef8fc2738b210a2bb0490e75eedc1e7b7b491fTom Taylor } 854b0ef8fc2738b210a2bb0490e75eedc1e7b7b491fTom Taylor } 855b0ef8fc2738b210a2bb0490e75eedc1e7b7b491fTom Taylor }.execute(); 85672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 8575a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor 8585a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor /** 8592f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project * If all the undelivered messages belong to "threadId", cancel the notification. 8602f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project */ 8612f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project public static void updateSendFailedNotificationForThread(Context context, long threadId) { 8622f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project long[] msgThreadId = {0, 0}; 8635a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor if (getUndeliveredMessageCount(context, msgThreadId) > 0 8642f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project && msgThreadId[0] == threadId 8652f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project && msgThreadId[1] != 0) { 8662f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project cancelNotification(context, MESSAGE_FAILED_NOTIFICATION_ID); 8672f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project } 8682f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project } 8695a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor 87072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static int getDownloadFailedMessageCount(Context context) { 87172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project // Look for any messages in the MMS Inbox that are of the type 87272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project // NOTIFICATION_IND (i.e. not already downloaded) and in the 87372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project // permanent failure state. If there are none, cancel any 87472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project // failed download notification. 87572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project Cursor c = SqliteWrapper.query(context, context.getContentResolver(), 87672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project Mms.Inbox.CONTENT_URI, null, 87772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project Mms.MESSAGE_TYPE + "=" + 87872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project String.valueOf(PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND) + 87972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project " AND " + Mms.STATUS + "=" + 88072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project String.valueOf(DownloadManager.STATE_PERMANENT_FAILURE), 88172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project null, null); 88272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project if (c == null) { 88372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project return 0; 88472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 88572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project int count = c.getCount(); 88672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project c.close(); 88772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project return count; 88872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 88972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 89072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project public static void updateDownloadFailedNotification(Context context) { 89172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project if (getDownloadFailedMessageCount(context) < 1) { 89272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project cancelNotification(context, DOWNLOAD_FAILED_NOTIFICATION_ID); 89372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 89472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 8955a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor 89695817b166d415114bac89ca0946c3717ae229526Tom Taylor public static boolean isFailedToDeliver(Intent intent) { 89795817b166d415114bac89ca0946c3717ae229526Tom Taylor return (intent != null) && intent.getBooleanExtra("undelivered_flag", false); 89895817b166d415114bac89ca0946c3717ae229526Tom Taylor } 89995817b166d415114bac89ca0946c3717ae229526Tom Taylor 90095817b166d415114bac89ca0946c3717ae229526Tom Taylor public static boolean isFailedToDownload(Intent intent) { 90195817b166d415114bac89ca0946c3717ae229526Tom Taylor return (intent != null) && intent.getBooleanExtra("failed_download_flag", false); 90295817b166d415114bac89ca0946c3717ae229526Tom Taylor } 903c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev 904c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev /** 905c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev * Get the thread ID of the SMS message with the given URI 906c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev * @param context The context 907c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev * @param uri The URI of the SMS message 908c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev * @return The thread ID, or THREAD_NONE if the URI contains no entries 909c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev */ 910c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev public static long getSmsThreadId(Context context, Uri uri) { 911c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev Cursor cursor = SqliteWrapper.query( 912c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev context, 913c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev context.getContentResolver(), 914c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev uri, 915c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev SMS_THREAD_ID_PROJECTION, 916c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev null, 917c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev null, 918c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev null); 919c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev 920c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev if (cursor == null) { 921c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev return THREAD_NONE; 922c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev } 923c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev 924c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev try { 925c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev if (cursor.moveToFirst()) { 926c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev return cursor.getLong(cursor.getColumnIndex(Sms.THREAD_ID)); 927c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev } else { 928c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev return THREAD_NONE; 929c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev } 930c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev } finally { 931c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev cursor.close(); 932c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev } 933c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev } 934c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev 935c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev /** 936c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev * Get the thread ID of the MMS message with the given URI 937c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev * @param context The context 938c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev * @param uri The URI of the SMS message 939c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev * @return The thread ID, or THREAD_NONE if the URI contains no entries 940c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev */ 941c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev public static long getThreadId(Context context, Uri uri) { 942c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev Cursor cursor = SqliteWrapper.query( 943c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev context, 944c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev context.getContentResolver(), 945c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev uri, 946c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev MMS_THREAD_ID_PROJECTION, 947c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev null, 948c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev null, 949c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev null); 950c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev 951c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev if (cursor == null) { 952c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev return THREAD_NONE; 953c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev } 954c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev 955c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev try { 956c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev if (cursor.moveToFirst()) { 957c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev return cursor.getLong(cursor.getColumnIndex(Mms.THREAD_ID)); 958c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev } else { 959c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev return THREAD_NONE; 960c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev } 961c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev } finally { 962c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev cursor.close(); 963c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev } 964c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev } 96572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project} 966