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 23d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport java.util.ArrayList; 24d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport java.util.Comparator; 25d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport java.util.HashSet; 26d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport java.util.Iterator; 27d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport java.util.Set; 28d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport java.util.SortedSet; 29d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport java.util.TreeSet; 3072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 3172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.app.Notification; 3272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.app.NotificationManager; 3372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.app.PendingIntent; 346cc254afc74dee97c7ef356612ae9ec7bc8b77ceTom Taylorimport android.app.TaskStackBuilder; 35d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport android.content.BroadcastReceiver; 3672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.content.ContentResolver; 3772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.content.Context; 3872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.content.Intent; 3970f5af8fd89d66ae246a805d10a50540746319aaWei Huangimport android.content.IntentFilter; 40d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport android.content.SharedPreferences; 41ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylorimport android.content.res.Resources; 4272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.database.Cursor; 43d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport android.database.sqlite.SqliteWrapper; 44429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylorimport android.graphics.Bitmap; 4572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.graphics.Typeface; 46429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylorimport android.graphics.drawable.BitmapDrawable; 47006d49271549ed639ffcd70d94c7650bb3514796Jim Shumaimport android.media.AudioManager; 4872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.net.Uri; 49b0ef8fc2738b210a2bb0490e75eedc1e7b7b491fTom Taylorimport android.os.AsyncTask; 505a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylorimport android.os.Handler; 5172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.preference.PreferenceManager; 52f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport android.provider.Telephony.Mms; 53f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport android.provider.Telephony.Sms; 5472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.text.Spannable; 5572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.text.SpannableString; 56429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylorimport android.text.SpannableStringBuilder; 5772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.text.TextUtils; 5872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.text.style.StyleSpan; 59ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylorimport android.text.style.TextAppearanceSpan; 6072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.util.Log; 61800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERTimport android.widget.Toast; 6272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 63d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.android.mms.LogTag; 6480528ea3bf0b480ad85da602da1b07cd0f5f98b1Tom Taylorimport com.android.mms.MmsConfig; 65d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.android.mms.R; 66d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.android.mms.data.Contact; 67d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.android.mms.data.Conversation; 68d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.android.mms.data.WorkingMessage; 69d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.android.mms.model.SlideModel; 70d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.android.mms.model.SlideshowModel; 71d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.android.mms.ui.ComposeMessageActivity; 72d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.android.mms.ui.ConversationList; 733c307cabb5bd96ed174930ebf17f533bf2a79de7Tom Taylorimport com.android.mms.ui.MessageUtils; 74d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.android.mms.ui.MessagingPreferenceActivity; 75d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.android.mms.util.AddressUtils; 76d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.android.mms.util.DownloadManager; 77d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.android.mms.widget.MmsWidgetProvider; 7880528ea3bf0b480ad85da602da1b07cd0f5f98b1Tom Taylor 79d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.google.android.mms.MmsException; 80d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.google.android.mms.pdu.EncodedStringValue; 81d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.google.android.mms.pdu.GenericPdu; 82d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.google.android.mms.pdu.MultimediaMessagePdu; 83d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.google.android.mms.pdu.PduHeaders; 84d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.google.android.mms.pdu.PduPersister; 8572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 8672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project/** 8772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * This class is used to update the notification indicator. It will check whether 8872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * there are unread messages. If yes, it would show the notification indicator, 8972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * otherwise, hide the indicator. 9072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project */ 9172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectpublic class MessagingNotification { 92c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev 93812391ad832f3fdac054ad3a50af563da16e99b5Wei Huang private static final String TAG = LogTag.APP; 9481b3875142eb12aca44ef95522c1d04e337488cbTom Taylor private static final boolean DEBUG = false; 9572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 9672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static final int NOTIFICATION_ID = 123; 9772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project public static final int MESSAGE_FAILED_NOTIFICATION_ID = 789; 9872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project public static final int DOWNLOAD_FAILED_NOTIFICATION_ID = 531; 99c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev /** 100c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev * This is the volume at which to play the in-conversation notification sound, 101c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev * expressed as a fraction of the system notification volume. 102c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev */ 103c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev private static final float IN_CONVERSATION_NOTIFICATION_VOLUME = 0.25f; 10472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 10572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project // This must be consistent with the column constants below. 10672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static final String[] MMS_STATUS_PROJECTION = new String[] { 10772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project Mms.THREAD_ID, Mms.DATE, Mms._ID, Mms.SUBJECT, Mms.SUBJECT_CHARSET }; 10872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 10972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project // This must be consistent with the column constants below. 11072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static final String[] SMS_STATUS_PROJECTION = new String[] { 11172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project Sms.THREAD_ID, Sms.DATE, Sms.ADDRESS, Sms.SUBJECT, Sms.BODY }; 11272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 11372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project // These must be consistent with MMS_STATUS_PROJECTION and 11472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project // SMS_STATUS_PROJECTION. 11572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static final int COLUMN_THREAD_ID = 0; 11672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static final int COLUMN_DATE = 1; 11772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static final int COLUMN_MMS_ID = 2; 11872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static final int COLUMN_SMS_ADDRESS = 2; 11972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static final int COLUMN_SUBJECT = 3; 12072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static final int COLUMN_SUBJECT_CS = 4; 12172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static final int COLUMN_SMS_BODY = 4; 12272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 123c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev private static final String[] SMS_THREAD_ID_PROJECTION = new String[] { Sms.THREAD_ID }; 124c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev private static final String[] MMS_THREAD_ID_PROJECTION = new String[] { Mms.THREAD_ID }; 125c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev 12672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static final String NEW_INCOMING_SM_CONSTRAINT = 12772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project "(" + Sms.TYPE + " = " + Sms.MESSAGE_TYPE_INBOX 128627007213deb59ef938c80353c8f3598b01478b3Wei Huang + " AND " + Sms.SEEN + " = 0)"; 12972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 130800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT private static final String NEW_DELIVERY_SM_CONSTRAINT = 131c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor "(" + Sms.TYPE + " = " + Sms.MESSAGE_TYPE_SENT 132c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor + " AND " + Sms.STATUS + " = "+ Sms.STATUS_COMPLETE +")"; 133800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT 13472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static final String NEW_INCOMING_MM_CONSTRAINT = 13572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project "(" + Mms.MESSAGE_BOX + "=" + Mms.MESSAGE_BOX_INBOX 136627007213deb59ef938c80353c8f3598b01478b3Wei Huang + " AND " + Mms.SEEN + "=0" 13772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project + " AND (" + Mms.MESSAGE_TYPE + "=" + MESSAGE_TYPE_NOTIFICATION_IND 13872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project + " OR " + Mms.MESSAGE_TYPE + "=" + MESSAGE_TYPE_RETRIEVE_CONF + "))"; 13972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 140429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor private static final NotificationInfoComparator INFO_COMPARATOR = 141429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor new NotificationInfoComparator(); 1425a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor 14372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static final Uri UNDELIVERED_URI = Uri.parse("content://mms-sms/undelivered"); 14472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 14570f5af8fd89d66ae246a805d10a50540746319aaWei Huang 14670f5af8fd89d66ae246a805d10a50540746319aaWei Huang private final static String NOTIFICATION_DELETED_ACTION = 14770f5af8fd89d66ae246a805d10a50540746319aaWei Huang "com.android.mms.NOTIFICATION_DELETED_ACTION"; 14870f5af8fd89d66ae246a805d10a50540746319aaWei Huang 14970f5af8fd89d66ae246a805d10a50540746319aaWei Huang public static class OnDeletedReceiver extends BroadcastReceiver { 150c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev @Override 15170f5af8fd89d66ae246a805d10a50540746319aaWei Huang public void onReceive(Context context, Intent intent) { 15270f5af8fd89d66ae246a805d10a50540746319aaWei Huang if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) { 15370f5af8fd89d66ae246a805d10a50540746319aaWei Huang Log.d(TAG, "[MessagingNotification] clear notification: mark all msgs seen"); 15470f5af8fd89d66ae246a805d10a50540746319aaWei Huang } 15570f5af8fd89d66ae246a805d10a50540746319aaWei Huang 15670f5af8fd89d66ae246a805d10a50540746319aaWei Huang Conversation.markAllConversationsAsSeen(context); 15770f5af8fd89d66ae246a805d10a50540746319aaWei Huang } 158c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev } 159c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev 160c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev public static final long THREAD_ALL = -1; 161c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev public static final long THREAD_NONE = -2; 162c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev /** 163c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev * Keeps track of the thread ID of the conversation that's currently displayed to the user 164c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev */ 165c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev private static long sCurrentlyDisplayedThreadId; 166c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev private static final Object sCurrentlyDisplayedThreadLock = new Object(); 167c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev 16870f5af8fd89d66ae246a805d10a50540746319aaWei Huang private static OnDeletedReceiver sNotificationDeletedReceiver = new OnDeletedReceiver(); 16970f5af8fd89d66ae246a805d10a50540746319aaWei Huang private static Intent sNotificationOnDeleteIntent; 1704ce94b2f607a93ed1a75dad7a8cbde88391a499eTom Taylor private static Handler sHandler = new Handler(); 171429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor private static PduPersister sPduPersister; 172429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor private static final int MAX_BITMAP_DIMEN_DP = 360; 173429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor private static float sScreenDensity; 174429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor 175ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor private static final int MAX_MESSAGES_TO_SHOW = 8; // the maximum number of new messages to 176429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor // show in a single notification. 177429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor 17870f5af8fd89d66ae246a805d10a50540746319aaWei Huang 17972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private MessagingNotification() { 18072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 18172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 18270f5af8fd89d66ae246a805d10a50540746319aaWei Huang public static void init(Context context) { 18370f5af8fd89d66ae246a805d10a50540746319aaWei Huang // set up the intent filter for notification deleted action 18470f5af8fd89d66ae246a805d10a50540746319aaWei Huang IntentFilter intentFilter = new IntentFilter(); 18570f5af8fd89d66ae246a805d10a50540746319aaWei Huang intentFilter.addAction(NOTIFICATION_DELETED_ACTION); 186429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor 187429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor // TODO: should we unregister when the app gets killed? 18870f5af8fd89d66ae246a805d10a50540746319aaWei Huang context.registerReceiver(sNotificationDeletedReceiver, intentFilter); 189429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor sPduPersister = PduPersister.getPduPersister(context); 19070f5af8fd89d66ae246a805d10a50540746319aaWei Huang 19170f5af8fd89d66ae246a805d10a50540746319aaWei Huang // initialize the notification deleted action 19270f5af8fd89d66ae246a805d10a50540746319aaWei Huang sNotificationOnDeleteIntent = new Intent(NOTIFICATION_DELETED_ACTION); 193429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor 194429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor sScreenDensity = context.getResources().getDisplayMetrics().density; 19570f5af8fd89d66ae246a805d10a50540746319aaWei Huang } 19670f5af8fd89d66ae246a805d10a50540746319aaWei Huang 19772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project /** 198c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev * Specifies which message thread is currently being viewed by the user. New messages in that 199c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev * thread will not generate a notification icon and will play the notification sound at a lower 200c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev * volume. Make sure you set this to THREAD_NONE when the UI component that shows the thread is 201c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev * no longer visible to the user (e.g. Activity.onPause(), etc.) 202c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev * @param threadId The ID of the thread that the user is currently viewing. Pass THREAD_NONE 203c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev * if the user is not viewing a thread, or THREAD_ALL if the user is viewing the conversation 204c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev * list (note: that latter one has no effect as of this implementation) 205c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev */ 206c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev public static void setCurrentlyDisplayedThreadId(long threadId) { 207c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev synchronized (sCurrentlyDisplayedThreadLock) { 208c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev sCurrentlyDisplayedThreadId = threadId; 2092d65e7eb956e60c058de876ddbfff504620ce7a3Tom Taylor if (DEBUG) { 2102d65e7eb956e60c058de876ddbfff504620ce7a3Tom Taylor Log.d(TAG, "setCurrentlyDisplayedThreadId: " + sCurrentlyDisplayedThreadId); 2112d65e7eb956e60c058de876ddbfff504620ce7a3Tom Taylor } 212c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev } 213c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev } 214c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev 215c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev /** 216627007213deb59ef938c80353c8f3598b01478b3Wei Huang * Checks to see if there are any "unseen" messages or delivery 21772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * reports. Shows the most recent notification if there is one. 2183b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor * Does its work and query in a worker thread. 21972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * 22072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * @param context the context to use 22172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project */ 2223b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor public static void nonBlockingUpdateNewMessageIndicator(final Context context, 223c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev final long newMsgThreadId, 2243b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor final boolean isStatusMessage) { 225bc7f97ae7d3661a44211d404fe4e187c35afadceTom Taylor if (DEBUG) { 226bc7f97ae7d3661a44211d404fe4e187c35afadceTom Taylor Log.d(TAG, "nonBlockingUpdateNewMessageIndicator: newMsgThreadId: " + 227bc7f97ae7d3661a44211d404fe4e187c35afadceTom Taylor newMsgThreadId + 228bc7f97ae7d3661a44211d404fe4e187c35afadceTom Taylor " sCurrentlyDisplayedThreadId: " + sCurrentlyDisplayedThreadId); 229bc7f97ae7d3661a44211d404fe4e187c35afadceTom Taylor } 2303b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor new Thread(new Runnable() { 231c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev @Override 2323b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor public void run() { 233c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev blockingUpdateNewMessageIndicator(context, newMsgThreadId, isStatusMessage); 2343b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor } 235ddd31c4011b4191035bdfbba05a8edb1785f71afTodor Kalaydjiev }, "MessagingNotification.nonBlockingUpdateNewMessageIndicator").start(); 23672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 23772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 23872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project /** 239627007213deb59ef938c80353c8f3598b01478b3Wei Huang * Checks to see if there are any "unseen" messages or delivery 240429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor * reports and builds a sorted (by delivery date) list of unread notifications. 24172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * 24272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * @param context the context to use 243c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev * @param newMsgThreadId The thread ID of a new message that we're to notify about; if there's 244c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev * no new message, use THREAD_NONE. If we should notify about multiple or unknown thread IDs, 245c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev * use THREAD_ALL. 246c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev * @param isStatusMessage 24772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project */ 248c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev public static void blockingUpdateNewMessageIndicator(Context context, long newMsgThreadId, 249c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor boolean isStatusMessage) { 250d645c8b53ae904bc059ee1ca7232916637c223e5Tom Taylor if (DEBUG) { 251d645c8b53ae904bc059ee1ca7232916637c223e5Tom Taylor Contact.logWithTrace(TAG, "blockingUpdateNewMessageIndicator: newMsgThreadId: " + 252d645c8b53ae904bc059ee1ca7232916637c223e5Tom Taylor newMsgThreadId); 253d645c8b53ae904bc059ee1ca7232916637c223e5Tom Taylor } 25480528ea3bf0b480ad85da602da1b07cd0f5f98b1Tom Taylor final boolean isDefaultSmsApp = MmsConfig.isSmsEnabled(context); 25580528ea3bf0b480ad85da602da1b07cd0f5f98b1Tom Taylor if (!isDefaultSmsApp) { 25680528ea3bf0b480ad85da602da1b07cd0f5f98b1Tom Taylor cancelNotification(context, NOTIFICATION_ID); 25780528ea3bf0b480ad85da602da1b07cd0f5f98b1Tom Taylor if (DEBUG || Log.isLoggable(LogTag.APP, Log.VERBOSE)) { 25880528ea3bf0b480ad85da602da1b07cd0f5f98b1Tom Taylor Log.d(TAG, "blockingUpdateNewMessageIndicator: not the default sms app - skipping " 25980528ea3bf0b480ad85da602da1b07cd0f5f98b1Tom Taylor + "notification"); 26080528ea3bf0b480ad85da602da1b07cd0f5f98b1Tom Taylor } 26180528ea3bf0b480ad85da602da1b07cd0f5f98b1Tom Taylor return; 26280528ea3bf0b480ad85da602da1b07cd0f5f98b1Tom Taylor } 26380528ea3bf0b480ad85da602da1b07cd0f5f98b1Tom Taylor 2644c6c7c65a1033d5cc0d87cc8b0e07a69db1842e8Tom Taylor // notificationSet is kept sorted by the incoming message delivery time, with the 2654c6c7c65a1033d5cc0d87cc8b0e07a69db1842e8Tom Taylor // most recent message first. 2664c6c7c65a1033d5cc0d87cc8b0e07a69db1842e8Tom Taylor SortedSet<NotificationInfo> notificationSet = 2674c6c7c65a1033d5cc0d87cc8b0e07a69db1842e8Tom Taylor new TreeSet<NotificationInfo>(INFO_COMPARATOR); 268c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev 269b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick Set<Long> threads = new HashSet<Long>(4); 2705a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor 2714c6c7c65a1033d5cc0d87cc8b0e07a69db1842e8Tom Taylor addMmsNotificationInfos(context, threads, notificationSet); 2724c6c7c65a1033d5cc0d87cc8b0e07a69db1842e8Tom Taylor addSmsNotificationInfos(context, threads, notificationSet); 27372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 274b98c3af3e015c6e63476f152a7af1a1310cd0e9dTom Taylor if (notificationSet.isEmpty()) { 275b98c3af3e015c6e63476f152a7af1a1310cd0e9dTom Taylor if (DEBUG) { 276b98c3af3e015c6e63476f152a7af1a1310cd0e9dTom Taylor Log.d(TAG, "blockingUpdateNewMessageIndicator: notificationSet is empty, " + 277b98c3af3e015c6e63476f152a7af1a1310cd0e9dTom Taylor "canceling existing notifications"); 278b98c3af3e015c6e63476f152a7af1a1310cd0e9dTom Taylor } 279b98c3af3e015c6e63476f152a7af1a1310cd0e9dTom Taylor cancelNotification(context, NOTIFICATION_ID); 280b98c3af3e015c6e63476f152a7af1a1310cd0e9dTom Taylor } else { 2816d2ba55a4bd1937bbec101ab2a4c005b566b43f8Tom Taylor if (DEBUG || Log.isLoggable(LogTag.APP, Log.VERBOSE)) { 2826d2ba55a4bd1937bbec101ab2a4c005b566b43f8Tom Taylor Log.d(TAG, "blockingUpdateNewMessageIndicator: count=" + notificationSet.size() + 283c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev ", newMsgThreadId=" + newMsgThreadId); 284e14b79584cca1bf7ba60c53bd7e3d6386adbfc59Wei Huang } 285c6be7e1a81769764ce0b51ce03406ad96944d8e5Tom Taylor synchronized (sCurrentlyDisplayedThreadLock) { 286d645c8b53ae904bc059ee1ca7232916637c223e5Tom Taylor if (newMsgThreadId > 0 && newMsgThreadId == sCurrentlyDisplayedThreadId && 287d645c8b53ae904bc059ee1ca7232916637c223e5Tom Taylor threads.contains(newMsgThreadId)) { 288c6be7e1a81769764ce0b51ce03406ad96944d8e5Tom Taylor if (DEBUG) { 289c6be7e1a81769764ce0b51ce03406ad96944d8e5Tom Taylor Log.d(TAG, "blockingUpdateNewMessageIndicator: newMsgThreadId == " + 290c6be7e1a81769764ce0b51ce03406ad96944d8e5Tom Taylor "sCurrentlyDisplayedThreadId so NOT showing notification," + 291c6be7e1a81769764ce0b51ce03406ad96944d8e5Tom Taylor " but playing soft sound. threadId: " + newMsgThreadId); 292c6be7e1a81769764ce0b51ce03406ad96944d8e5Tom Taylor } 293c6be7e1a81769764ce0b51ce03406ad96944d8e5Tom Taylor playInConversationNotificationSound(context); 294c6be7e1a81769764ce0b51ce03406ad96944d8e5Tom Taylor return; 295c6be7e1a81769764ce0b51ce03406ad96944d8e5Tom Taylor } 296c6be7e1a81769764ce0b51ce03406ad96944d8e5Tom Taylor } 2974c6c7c65a1033d5cc0d87cc8b0e07a69db1842e8Tom Taylor updateNotification(context, newMsgThreadId != THREAD_NONE, threads.size(), 2984c6c7c65a1033d5cc0d87cc8b0e07a69db1842e8Tom Taylor notificationSet); 29972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 3005a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor 3013b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor // And deals with delivery reports (which use Toasts). It's safe to call in a worker 3023b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor // thread because the toast will eventually get posted to a handler. 3034c6c7c65a1033d5cc0d87cc8b0e07a69db1842e8Tom Taylor MmsSmsDeliveryInfo delivery = getSmsNewDeliveryInfo(context); 304627007213deb59ef938c80353c8f3598b01478b3Wei Huang if (delivery != null) { 305c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor delivery.deliver(context, isStatusMessage); 306627007213deb59ef938c80353c8f3598b01478b3Wei Huang } 3076db678ea4fb26fcffb06daa30ad7ef64d902b3d2Roger Chen 3086db678ea4fb26fcffb06daa30ad7ef64d902b3d2Roger Chen notificationSet.clear(); 3096db678ea4fb26fcffb06daa30ad7ef64d902b3d2Roger Chen threads.clear(); 31072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 31172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 31272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project /** 313c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev * Play the in-conversation notification sound (it's the regular notification sound, but 314c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev * played at half-volume 315c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev */ 316c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev private static void playInConversationNotificationSound(Context context) { 317c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context); 318c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev String ringtoneStr = sp.getString(MessagingPreferenceActivity.NOTIFICATION_RINGTONE, 319c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev null); 320c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev if (TextUtils.isEmpty(ringtoneStr)) { 321c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev // Nothing to play 322c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev return; 323c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev } 324c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev Uri ringtoneUri = Uri.parse(ringtoneStr); 3254ce94b2f607a93ed1a75dad7a8cbde88391a499eTom Taylor final NotificationPlayer player = new NotificationPlayer(LogTag.APP); 326c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev player.play(context, ringtoneUri, false, AudioManager.STREAM_NOTIFICATION, 327c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev IN_CONVERSATION_NOTIFICATION_VOLUME); 3284ce94b2f607a93ed1a75dad7a8cbde88391a499eTom Taylor 3294ce94b2f607a93ed1a75dad7a8cbde88391a499eTom Taylor // Stop the sound after five seconds to handle continuous ringtones 3304ce94b2f607a93ed1a75dad7a8cbde88391a499eTom Taylor sHandler.postDelayed(new Runnable() { 3314ce94b2f607a93ed1a75dad7a8cbde88391a499eTom Taylor @Override 3324ce94b2f607a93ed1a75dad7a8cbde88391a499eTom Taylor public void run() { 3334ce94b2f607a93ed1a75dad7a8cbde88391a499eTom Taylor player.stop(); 3344ce94b2f607a93ed1a75dad7a8cbde88391a499eTom Taylor } 3354ce94b2f607a93ed1a75dad7a8cbde88391a499eTom Taylor }, 5000); 336c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev } 337c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev 338c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev /** 33935a74a9e0ee7c171c6e17f0eda4b0df0253f8364Ficus Kirkpatrick * Updates all pending notifications, clearing or updating them as 3403b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor * necessary. 34135a74a9e0ee7c171c6e17f0eda4b0df0253f8364Ficus Kirkpatrick */ 342bc7f97ae7d3661a44211d404fe4e187c35afadceTom Taylor public static void blockingUpdateAllNotifications(final Context context, long threadId) { 343d645c8b53ae904bc059ee1ca7232916637c223e5Tom Taylor if (DEBUG) { 344d645c8b53ae904bc059ee1ca7232916637c223e5Tom Taylor Contact.logWithTrace(TAG, "blockingUpdateAllNotifications: newMsgThreadId: " + 345d645c8b53ae904bc059ee1ca7232916637c223e5Tom Taylor threadId); 346d645c8b53ae904bc059ee1ca7232916637c223e5Tom Taylor } 347bc7f97ae7d3661a44211d404fe4e187c35afadceTom Taylor nonBlockingUpdateNewMessageIndicator(context, threadId, false); 348b0ef8fc2738b210a2bb0490e75eedc1e7b7b491fTom Taylor nonBlockingUpdateSendFailedNotification(context); 349627007213deb59ef938c80353c8f3598b01478b3Wei Huang updateDownloadFailedNotification(context); 350c7aa632be8e7d3ebe71f236f534ea2f0af71e04aTom Taylor MmsWidgetProvider.notifyDatasetChanged(context); 35135a74a9e0ee7c171c6e17f0eda4b0df0253f8364Ficus Kirkpatrick } 3525a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor 353800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT private static final class MmsSmsDeliveryInfo { 354c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor public CharSequence mTicker; 355c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor public long mTimeMillis; 356c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor 357c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor public MmsSmsDeliveryInfo(CharSequence ticker, long timeMillis) { 358c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor mTicker = ticker; 359c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor mTimeMillis = timeMillis; 360c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor } 361c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor 362c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor public void deliver(Context context, boolean isStatusMessage) { 363c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor updateDeliveryNotification( 364c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor context, isStatusMessage, mTicker, mTimeMillis); 365c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor } 366800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT } 367800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT 368429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor private static final class NotificationInfo { 369c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev public final Intent mClickIntent; 370ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor public final String mMessage; 371c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev public final CharSequence mTicker; 372c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev public final long mTimeMillis; 373c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev public final String mTitle; 374429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor public final Bitmap mAttachmentBitmap; 375429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor public final Contact mSender; 376429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor public final boolean mIsSms; 377ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor public final int mAttachmentType; 378ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor public final String mSubject; 379ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor public final long mThreadId; 380429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor 381429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor /** 382429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor * @param isSms true if sms, false if mms 383429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor * @param clickIntent where to go when the user taps the notification 384ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor * @param message for a single message, this is the message text 385ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor * @param subject text of mms subject 386429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor * @param ticker text displayed ticker-style across the notification, typically formatted 387429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor * as sender: message 388429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor * @param timeMillis date the message was received 389429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor * @param title for a single message, this is the sender 390429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor * @param attachmentBitmap a bitmap of an attachment, such as a picture or video 391ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor * @param sender contact of the sender 392ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor * @param attachmentType of the mms attachment 393ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor * @param threadId thread this message belongs to 394429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor */ 395429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor public NotificationInfo(boolean isSms, 396ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor Intent clickIntent, String message, String subject, 397429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor CharSequence ticker, long timeMillis, String title, 398ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor Bitmap attachmentBitmap, Contact sender, 399ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor int attachmentType, long threadId) { 400429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor mIsSms = isSms; 40172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project mClickIntent = clickIntent; 402ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor mMessage = message; 403ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor mSubject = subject; 40472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project mTicker = ticker; 40572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project mTimeMillis = timeMillis; 40672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project mTitle = title; 407429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor mAttachmentBitmap = attachmentBitmap; 408429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor mSender = sender; 409ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor mAttachmentType = attachmentType; 410ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor mThreadId = threadId; 41172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 41272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 41372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project public long getTime() { 41472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project return mTimeMillis; 41572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 416ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor 417ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor // This is the message string used in bigText and bigPicture notifications. 418ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor public CharSequence formatBigMessage(Context context) { 419ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor final TextAppearanceSpan notificationSubjectSpan = new TextAppearanceSpan( 420ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor context, R.style.NotificationPrimaryText); 421ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor 422ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor // Change multiple newlines (with potential white space between), into a single new line 423ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor final String message = 424ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor !TextUtils.isEmpty(mMessage) ? mMessage.replaceAll("\\n\\s+", "\n") : ""; 425ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor 426ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(); 427ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor if (!TextUtils.isEmpty(mSubject)) { 428ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor spannableStringBuilder.append(mSubject); 429ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor spannableStringBuilder.setSpan(notificationSubjectSpan, 0, mSubject.length(), 0); 430ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor } 431ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor if (mAttachmentType > WorkingMessage.TEXT) { 432ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor if (spannableStringBuilder.length() > 0) { 433ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor spannableStringBuilder.append('\n'); 434ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor } 435ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor spannableStringBuilder.append(getAttachmentTypeString(context, mAttachmentType)); 436ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor } 437ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor if (mMessage != null) { 438ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor if (spannableStringBuilder.length() > 0) { 439ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor spannableStringBuilder.append('\n'); 440ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor } 441ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor spannableStringBuilder.append(mMessage); 442ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor } 443ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor return spannableStringBuilder; 444ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor } 445ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor 446ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor // This is the message string used in each line of an inboxStyle notification. 447ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor public CharSequence formatInboxMessage(Context context) { 448ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor final TextAppearanceSpan notificationSenderSpan = new TextAppearanceSpan( 449ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor context, R.style.NotificationPrimaryText); 450ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor 451ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor final TextAppearanceSpan notificationSubjectSpan = new TextAppearanceSpan( 452ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor context, R.style.NotificationSubjectText); 453ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor 454ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor // Change multiple newlines (with potential white space between), into a single new line 455ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor final String message = 456ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor !TextUtils.isEmpty(mMessage) ? mMessage.replaceAll("\\n\\s+", "\n") : ""; 457ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor 458ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(); 459ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor final String sender = mSender.getName(); 460ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor if (!TextUtils.isEmpty(sender)) { 461ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor spannableStringBuilder.append(sender); 462ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor spannableStringBuilder.setSpan(notificationSenderSpan, 0, sender.length(), 0); 463ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor } 464ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor String separator = context.getString(R.string.notification_separator); 465ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor if (!mIsSms) { 466ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor if (!TextUtils.isEmpty(mSubject)) { 467ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor if (spannableStringBuilder.length() > 0) { 468ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor spannableStringBuilder.append(separator); 469ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor } 470ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor int start = spannableStringBuilder.length(); 471ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor spannableStringBuilder.append(mSubject); 472ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor spannableStringBuilder.setSpan(notificationSubjectSpan, start, 473ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor start + mSubject.length(), 0); 474ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor } 475ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor if (mAttachmentType > WorkingMessage.TEXT) { 476ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor if (spannableStringBuilder.length() > 0) { 477ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor spannableStringBuilder.append(separator); 478ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor } 479ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor spannableStringBuilder.append(getAttachmentTypeString(context, mAttachmentType)); 480ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor } 481ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor } 482ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor if (message.length() > 0) { 483ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor if (spannableStringBuilder.length() > 0) { 484ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor spannableStringBuilder.append(separator); 485ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor } 486ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor int start = spannableStringBuilder.length(); 487ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor spannableStringBuilder.append(message); 488ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor spannableStringBuilder.setSpan(notificationSubjectSpan, start, 489ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor start + message.length(), 0); 490ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor } 491ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor return spannableStringBuilder; 492ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor } 493ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor 494ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor // This is the summary string used in bigPicture notifications. 495ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor public CharSequence formatPictureMessage(Context context) { 496ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor final TextAppearanceSpan notificationSubjectSpan = new TextAppearanceSpan( 497ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor context, R.style.NotificationPrimaryText); 498ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor 499ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor // Change multiple newlines (with potential white space between), into a single new line 500ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor final String message = 501ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor !TextUtils.isEmpty(mMessage) ? mMessage.replaceAll("\\n\\s+", "\n") : ""; 502ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor 503ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor // Show the subject or the message (if no subject) 504ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(); 505ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor if (!TextUtils.isEmpty(mSubject)) { 506ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor spannableStringBuilder.append(mSubject); 507ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor spannableStringBuilder.setSpan(notificationSubjectSpan, 0, mSubject.length(), 0); 508ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor } 509ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor if (message.length() > 0 && spannableStringBuilder.length() == 0) { 510ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor spannableStringBuilder.append(message); 511ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor spannableStringBuilder.setSpan(notificationSubjectSpan, 0, message.length(), 0); 512ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor } 513ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor return spannableStringBuilder; 514ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor } 51572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 51672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 517ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor // Return a formatted string with all the sender names separated by commas. 518ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor private static CharSequence formatSenders(Context context, 519ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor ArrayList<NotificationInfo> senders) { 520ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor final TextAppearanceSpan notificationSenderSpan = new TextAppearanceSpan( 521ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor context, R.style.NotificationPrimaryText); 522ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor 523ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor String separator = context.getString(R.string.enumeration_comma); // ", " 524ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(); 525ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor int len = senders.size(); 526ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor for (int i = 0; i < len; i++) { 527ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor if (i > 0) { 528ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor spannableStringBuilder.append(separator); 529ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor } 530ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor spannableStringBuilder.append(senders.get(i).mSender.getName()); 531ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor } 532ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor spannableStringBuilder.setSpan(notificationSenderSpan, 0, 533ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor spannableStringBuilder.length(), 0); 534ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor return spannableStringBuilder; 535ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor } 536ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor 537ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor // Return a formatted string with the attachmentType spelled out as a string. For 538ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor // no attachment (or just text), return null. 539ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor private static CharSequence getAttachmentTypeString(Context context, int attachmentType) { 540ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor final TextAppearanceSpan notificationAttachmentSpan = new TextAppearanceSpan( 541ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor context, R.style.NotificationSecondaryText); 542ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor int id = 0; 543ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor switch (attachmentType) { 544ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor case WorkingMessage.AUDIO: id = R.string.attachment_audio; break; 545ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor case WorkingMessage.VIDEO: id = R.string.attachment_video; break; 546ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor case WorkingMessage.SLIDESHOW: id = R.string.attachment_slideshow; break; 547ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor case WorkingMessage.IMAGE: id = R.string.attachment_picture; break; 548ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor } 549ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor if (id > 0) { 550ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor final SpannableString spannableString = new SpannableString(context.getString(id)); 551ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor spannableString.setSpan(notificationAttachmentSpan, 552ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor 0, spannableString.length(), 0); 553ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor return spannableString; 554ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor } 555ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor return null; 556ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor } 557ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor 558429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor /** 559429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor * 560429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor * Sorts by the time a notification was received in descending order -- newer first. 561429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor * 562429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor */ 563429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor private static final class NotificationInfoComparator 564429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor implements Comparator<NotificationInfo> { 565c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev @Override 56672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project public int compare( 567429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor NotificationInfo info1, NotificationInfo info2) { 56872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project return Long.signum(info2.getTime() - info1.getTime()); 56972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 57072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 57172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 572429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor private static final void addMmsNotificationInfos( 5734c6c7c65a1033d5cc0d87cc8b0e07a69db1842e8Tom Taylor Context context, Set<Long> threads, SortedSet<NotificationInfo> notificationSet) { 57472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project ContentResolver resolver = context.getContentResolver(); 5753b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor 5763b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor // This query looks like this when logged: 5773b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor // I/Database( 147): elapsedTime4Sql|/data/data/com.android.providers.telephony/databases/ 5783b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor // mmssms.db|0.362 ms|SELECT thread_id, date, _id, sub, sub_cs FROM pdu WHERE ((msg_box=1 5793b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor // AND seen=0 AND (m_type=130 OR m_type=132))) ORDER BY date desc 5803b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor 58172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project Cursor cursor = SqliteWrapper.query(context, resolver, Mms.CONTENT_URI, 58272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project MMS_STATUS_PROJECTION, NEW_INCOMING_MM_CONSTRAINT, 58372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project null, Mms.DATE + " desc"); 58472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 585b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick if (cursor == null) { 586429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor return; 587b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick } 5885a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor 589b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick try { 590429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor while (cursor.moveToNext()) { 591c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev 592429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor long msgId = cursor.getLong(COLUMN_MMS_ID); 593429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor Uri msgUri = Mms.CONTENT_URI.buildUpon().appendPath( 594429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor Long.toString(msgId)).build(); 595429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor String address = AddressUtils.getFrom(context, msgUri); 5961b8df494e49bf934fe160baea54ab5afc2ff3100Tom Taylor 597429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor Contact contact = Contact.get(address, false); 598429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor if (contact.getSendToVoicemail()) { 599429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor // don't notify, skip this one 600429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor continue; 601429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor } 6021b8df494e49bf934fe160baea54ab5afc2ff3100Tom Taylor 603429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor String subject = getMmsSubject( 604429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor cursor.getString(COLUMN_SUBJECT), cursor.getInt(COLUMN_SUBJECT_CS)); 6053c307cabb5bd96ed174930ebf17f533bf2a79de7Tom Taylor subject = MessageUtils.cleanseMmsSubject(context, subject); 6063c307cabb5bd96ed174930ebf17f533bf2a79de7Tom Taylor 607429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor long threadId = cursor.getLong(COLUMN_THREAD_ID); 608429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor long timeMillis = cursor.getLong(COLUMN_DATE) * 1000; 609b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick 610429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) { 611429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor Log.d(TAG, "addMmsNotificationInfos: count=" + cursor.getCount() + 612429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor ", addr = " + address + ", thread_id=" + threadId); 613429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor } 614e14b79584cca1bf7ba60c53bd7e3d6386adbfc59Wei Huang 615429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor // Extract the message and/or an attached picture from the first slide 616429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor Bitmap attachedPicture = null; 617429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor String messageBody = null; 618ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor int attachmentType = WorkingMessage.TEXT; 619429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor try { 620429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor GenericPdu pdu = sPduPersister.load(msgUri); 621f677c24f07befa52ae977461c56fedeb0ad3eb47Tom Taylor if (pdu != null && pdu instanceof MultimediaMessagePdu) { 622429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor SlideshowModel slideshow = SlideshowModel.createFromPduBody(context, 623429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor ((MultimediaMessagePdu)pdu).getBody()); 624ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor attachmentType = getAttachmentType(slideshow); 625429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor SlideModel firstSlide = slideshow.get(0); 626429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor if (firstSlide != null) { 627429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor if (firstSlide.hasImage()) { 628429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor int maxDim = dp2Pixels(MAX_BITMAP_DIMEN_DP); 629429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor attachedPicture = firstSlide.getImage().getBitmap(maxDim, maxDim); 630429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor } 631429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor if (firstSlide.hasText()) { 632429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor messageBody = firstSlide.getText().getText(); 633429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor } 634429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor } 635429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor } 636429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor } catch (final MmsException e) { 637429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor Log.e(TAG, "MmsException loading uri: " + msgUri, e); 638bc7f97ae7d3661a44211d404fe4e187c35afadceTom Taylor continue; // skip this bad boy -- don't generate an empty notification 639429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor } 640b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick 641ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor NotificationInfo info = getNewMessageNotificationInfo(context, 642ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor false /* isSms */, 643429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor address, 644ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor messageBody, subject, 645ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor threadId, 646ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor timeMillis, 647ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor attachedPicture, 648ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor contact, 649ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor attachmentType); 650429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor 6514c6c7c65a1033d5cc0d87cc8b0e07a69db1842e8Tom Taylor notificationSet.add(info); 652b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick 653429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor threads.add(threadId); 654429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor } 655b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick } finally { 656b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick cursor.close(); 65772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 65872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 65972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 660ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor // Look at the passed in slideshow and determine what type of attachment it is. 661ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor private static int getAttachmentType(SlideshowModel slideshow) { 662ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor int slideCount = slideshow.size(); 663ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor 664ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor if (slideCount == 0) { 665ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor return WorkingMessage.TEXT; 666ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor } else if (slideCount > 1) { 667ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor return WorkingMessage.SLIDESHOW; 668ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor } else { 669ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor SlideModel slide = slideshow.get(0); 670ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor if (slide.hasImage()) { 671ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor return WorkingMessage.IMAGE; 672ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor } else if (slide.hasVideo()) { 673ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor return WorkingMessage.VIDEO; 674ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor } else if (slide.hasAudio()) { 675ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor return WorkingMessage.AUDIO; 676ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor } 677ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor } 678ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor return WorkingMessage.TEXT; 679ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor } 680ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor 681429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor private static final int dp2Pixels(int dip) { 682429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor return (int) (dip * sScreenDensity + 0.5f); 683429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor } 684429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor 6853b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor private static final MmsSmsDeliveryInfo getSmsNewDeliveryInfo(Context context) { 686627007213deb59ef938c80353c8f3598b01478b3Wei Huang ContentResolver resolver = context.getContentResolver(); 687627007213deb59ef938c80353c8f3598b01478b3Wei Huang Cursor cursor = SqliteWrapper.query(context, resolver, Sms.CONTENT_URI, 688627007213deb59ef938c80353c8f3598b01478b3Wei Huang SMS_STATUS_PROJECTION, NEW_DELIVERY_SM_CONSTRAINT, 6896a9c779f0c0dc6cf3ae942ff70fb6c806aa166dcBanavathu, Srinivas Naik null, Sms.DATE); 690800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT 691ac9a5e52dc349faae2a7d8a990ff2b674c61f027Alexander Blom if (cursor == null) { 692627007213deb59ef938c80353c8f3598b01478b3Wei Huang return null; 693ac9a5e52dc349faae2a7d8a990ff2b674c61f027Alexander Blom } 694800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT 695627007213deb59ef938c80353c8f3598b01478b3Wei Huang try { 696ac9a5e52dc349faae2a7d8a990ff2b674c61f027Alexander Blom if (!cursor.moveToLast()) { 697ac9a5e52dc349faae2a7d8a990ff2b674c61f027Alexander Blom return null; 698ac9a5e52dc349faae2a7d8a990ff2b674c61f027Alexander Blom } 699800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT 700627007213deb59ef938c80353c8f3598b01478b3Wei Huang String address = cursor.getString(COLUMN_SMS_ADDRESS); 701627007213deb59ef938c80353c8f3598b01478b3Wei Huang long timeMillis = 3000; 702800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT 703ac9a5e52dc349faae2a7d8a990ff2b674c61f027Alexander Blom Contact contact = Contact.get(address, false); 704ac9a5e52dc349faae2a7d8a990ff2b674c61f027Alexander Blom String name = contact.getNameAndNumber(); 705ac9a5e52dc349faae2a7d8a990ff2b674c61f027Alexander Blom 706ac9a5e52dc349faae2a7d8a990ff2b674c61f027Alexander Blom return new MmsSmsDeliveryInfo(context.getString(R.string.delivery_toast_body, name), 707627007213deb59ef938c80353c8f3598b01478b3Wei Huang timeMillis); 708800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT 709627007213deb59ef938c80353c8f3598b01478b3Wei Huang } finally { 710627007213deb59ef938c80353c8f3598b01478b3Wei Huang cursor.close(); 711627007213deb59ef938c80353c8f3598b01478b3Wei Huang } 712800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT } 713800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT 714429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor private static final void addSmsNotificationInfos( 7154c6c7c65a1033d5cc0d87cc8b0e07a69db1842e8Tom Taylor Context context, Set<Long> threads, SortedSet<NotificationInfo> notificationSet) { 71672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project ContentResolver resolver = context.getContentResolver(); 71772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project Cursor cursor = SqliteWrapper.query(context, resolver, Sms.CONTENT_URI, 71872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project SMS_STATUS_PROJECTION, NEW_INCOMING_SM_CONSTRAINT, 71972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project null, Sms.DATE + " desc"); 72072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 721b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick if (cursor == null) { 722429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor return; 723b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick } 7245a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor 725b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick try { 726429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor while (cursor.moveToNext()) { 727429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor String address = cursor.getString(COLUMN_SMS_ADDRESS); 728b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick 729429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor Contact contact = Contact.get(address, false); 730429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor if (contact.getSendToVoicemail()) { 731429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor // don't notify, skip this one 732429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor continue; 733429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor } 7341b8df494e49bf934fe160baea54ab5afc2ff3100Tom Taylor 735ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor String message = cursor.getString(COLUMN_SMS_BODY); 736429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor long threadId = cursor.getLong(COLUMN_THREAD_ID); 737429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor long timeMillis = cursor.getLong(COLUMN_DATE); 7381b8df494e49bf934fe160baea54ab5afc2ff3100Tom Taylor 739429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) 740429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor { 741429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor Log.d(TAG, "addSmsNotificationInfos: count=" + cursor.getCount() + 742429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor ", addr=" + address + ", thread_id=" + threadId); 743429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor } 744b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick 745e14b79584cca1bf7ba60c53bd7e3d6386adbfc59Wei Huang 746ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor NotificationInfo info = getNewMessageNotificationInfo(context, true /* isSms */, 747ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor address, message, null /* subject */, 748ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor threadId, timeMillis, null /* attachmentBitmap */, 749ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor contact, WorkingMessage.TEXT); 750b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick 7514c6c7c65a1033d5cc0d87cc8b0e07a69db1842e8Tom Taylor notificationSet.add(info); 752429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor 753429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor threads.add(threadId); 754b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick threads.add(cursor.getLong(COLUMN_THREAD_ID)); 75572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 756b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick } finally { 757b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick cursor.close(); 75872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 75972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 76072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 761429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor private static final NotificationInfo getNewMessageNotificationInfo( 762ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor Context context, 763429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor boolean isSms, 76472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project String address, 765ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor String message, 76672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project String subject, 76772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project long threadId, 76872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project long timeMillis, 769429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor Bitmap attachmentBitmap, 770ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor Contact contact, 771ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor int attachmentType) { 772812391ad832f3fdac054ad3a50af563da16e99b5Wei Huang Intent clickIntent = ComposeMessageActivity.createIntent(context, threadId); 773812391ad832f3fdac054ad3a50af563da16e99b5Wei Huang clickIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK 774812391ad832f3fdac054ad3a50af563da16e99b5Wei Huang | Intent.FLAG_ACTIVITY_SINGLE_TOP 775812391ad832f3fdac054ad3a50af563da16e99b5Wei Huang | Intent.FLAG_ACTIVITY_CLEAR_TOP); 77672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 77772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project String senderInfo = buildTickerMessage( 77872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project context, address, null, null).toString(); 77972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project String senderInfoName = senderInfo.substring( 78072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 0, senderInfo.length() - 2); 78172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project CharSequence ticker = buildTickerMessage( 782ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor context, address, subject, message); 78372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 784429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor return new NotificationInfo(isSms, 785ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor clickIntent, message, subject, ticker, timeMillis, 786ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor senderInfoName, attachmentBitmap, contact, attachmentType, threadId); 78772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 78872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 78972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project public static void cancelNotification(Context context, int notificationId) { 79072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project NotificationManager nm = (NotificationManager) context.getSystemService( 79172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project Context.NOTIFICATION_SERVICE); 79272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 793d2f67cfca13a6e415636dc253c371fb76974f5faTom Taylor Log.d(TAG, "cancelNotification"); 79472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project nm.cancel(notificationId); 79572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 79672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 7975a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor private static void updateDeliveryNotification(final Context context, 798c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor boolean isStatusMessage, 7995a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor final CharSequence message, 8005a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor final long timeMillis) { 801c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor if (!isStatusMessage) { 802c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor return; 803c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor } 804c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor 805800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT 806d83675687b1ef742c33bffe8195d7b1852c2c01dTom Taylor if (!MessagingPreferenceActivity.getNotificationEnabled(context)) { 80770f5af8fd89d66ae246a805d10a50540746319aaWei Huang return; 80870f5af8fd89d66ae246a805d10a50540746319aaWei Huang } 809800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT 8104ce94b2f607a93ed1a75dad7a8cbde88391a499eTom Taylor sHandler.post(new Runnable() { 811c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev @Override 812c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor public void run() { 813c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor Toast.makeText(context, message, (int)timeMillis).show(); 814c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor } 815c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor }); 816800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT } 817800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT 818429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor /** 819429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor * updateNotification is *the* main function for building the actual notification handed to 820429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor * the NotificationManager 821429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor * @param context 822429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor * @param isNew if we've got a new message, show the ticker 823429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor * @param uniqueThreadCount 8244c6c7c65a1033d5cc0d87cc8b0e07a69db1842e8Tom Taylor * @param notificationSet the set of notifications to display 825429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor */ 82672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static void updateNotification( 82772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project Context context, 82872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project boolean isNew, 8294c6c7c65a1033d5cc0d87cc8b0e07a69db1842e8Tom Taylor int uniqueThreadCount, 8304c6c7c65a1033d5cc0d87cc8b0e07a69db1842e8Tom Taylor SortedSet<NotificationInfo> notificationSet) { 831429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor // If the user has turned off notifications in settings, don't do any notifying. 832d83675687b1ef742c33bffe8195d7b1852c2c01dTom Taylor if (!MessagingPreferenceActivity.getNotificationEnabled(context)) { 8339ab4d755b862392724b7dbb12e636235a05cb3bdTom Taylor if (DEBUG) { 8349ab4d755b862392724b7dbb12e636235a05cb3bdTom Taylor Log.d(TAG, "updateNotification: notifications turned off in prefs, bailing"); 8359ab4d755b862392724b7dbb12e636235a05cb3bdTom Taylor } 83672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project return; 83772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 83872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 839429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor // Figure out what we've got -- whether all sms's, mms's, or a mixture of both. 8404c6c7c65a1033d5cc0d87cc8b0e07a69db1842e8Tom Taylor final int messageCount = notificationSet.size(); 8414c6c7c65a1033d5cc0d87cc8b0e07a69db1842e8Tom Taylor NotificationInfo mostRecentNotification = notificationSet.first(); 842429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor 843674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler final Notification.Builder noti = new Notification.Builder(context) 844429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor .setWhen(mostRecentNotification.mTimeMillis); 845674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler 846429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor if (isNew) { 847ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor noti.setTicker(mostRecentNotification.mTicker); 848429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor } 849fb7068020e74e431acc9511212d2a6d17258ab9eAdam Powell TaskStackBuilder taskStackBuilder = TaskStackBuilder.create(context); 850b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick 851b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick // If we have more than one unique thread, change the title (which would 852b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick // normally be the contact who sent the message) to a generic one that 853b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick // makes sense for multiple senders, and change the Intent to take the 854b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick // user to the conversation list instead of the specific thread. 855674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler 856429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor // Cases: 857429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor // 1) single message from single thread - intent goes to ComposeMessageActivity 858429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor // 2) multiple messages from single thread - intent goes to ComposeMessageActivity 859429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor // 3) messages from multiple threads - intent goes to ConversationList 860429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor 861ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor final Resources res = context.getResources(); 862429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor String title = null; 86364fefc1c9b26bd6778c318e83cec696abb389c22Daniel Sandler Bitmap avatar = null; 864429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor if (uniqueThreadCount > 1) { // messages from multiple threads 8651fdc24a996e1c2d6a1add1f40260c5e0380f3112Tom Taylor Intent mainActivityIntent = new Intent(Intent.ACTION_MAIN); 866812391ad832f3fdac054ad3a50af563da16e99b5Wei Huang 8671fdc24a996e1c2d6a1add1f40260c5e0380f3112Tom Taylor mainActivityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK 868812391ad832f3fdac054ad3a50af563da16e99b5Wei Huang | Intent.FLAG_ACTIVITY_SINGLE_TOP 869812391ad832f3fdac054ad3a50af563da16e99b5Wei Huang | Intent.FLAG_ACTIVITY_CLEAR_TOP); 870812391ad832f3fdac054ad3a50af563da16e99b5Wei Huang 8711fdc24a996e1c2d6a1add1f40260c5e0380f3112Tom Taylor mainActivityIntent.setType("vnd.android-dir/mms-sms"); 8726cc254afc74dee97c7ef356612ae9ec7bc8b77ceTom Taylor taskStackBuilder.addNextIntent(mainActivityIntent); 873ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor title = context.getString(R.string.message_count_notification, messageCount); 874429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor } else { // same thread, single or multiple messages 875ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor title = mostRecentNotification.mTitle; 876429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor BitmapDrawable contactDrawable = (BitmapDrawable)mostRecentNotification.mSender 877429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor .getAvatar(context, null); 878ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor if (contactDrawable != null) { 879ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor // Show the sender's avatar as the big icon. Contact bitmaps are 96x96 so we 880ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor // have to scale 'em up to 128x128 to fill the whole notification large icon. 88164fefc1c9b26bd6778c318e83cec696abb389c22Daniel Sandler avatar = contactDrawable.getBitmap(); 882ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor if (avatar != null) { 883ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor final int idealIconHeight = 884ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor res.getDimensionPixelSize(android.R.dimen.notification_large_icon_height); 885ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor final int idealIconWidth = 886ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor res.getDimensionPixelSize(android.R.dimen.notification_large_icon_width); 887ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor if (avatar.getHeight() < idealIconHeight) { 888ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor // Scale this image to fit the intended size 889ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor avatar = Bitmap.createScaledBitmap( 890ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor avatar, idealIconWidth, idealIconHeight, true); 891ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor } 892ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor if (avatar != null) { 893ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor noti.setLargeIcon(avatar); 894ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor } 895ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor } 896ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor } 897429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor 8986cc254afc74dee97c7ef356612ae9ec7bc8b77ceTom Taylor taskStackBuilder.addParentStack(ComposeMessageActivity.class); 8996cc254afc74dee97c7ef356612ae9ec7bc8b77ceTom Taylor taskStackBuilder.addNextIntent(mostRecentNotification.mClickIntent); 900b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick } 901ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor // Always have to set the small icon or the notification is ignored 902ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor noti.setSmallIcon(R.drawable.stat_notify_sms); 903ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor 904429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor NotificationManager nm = (NotificationManager) 905429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor context.getSystemService(Context.NOTIFICATION_SERVICE); 90672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 907b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick // Update the notification. 908674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler noti.setContentTitle(title) 9096cc254afc74dee97c7ef356612ae9ec7bc8b77ceTom Taylor .setContentIntent( 9106cc254afc74dee97c7ef356612ae9ec7bc8b77ceTom Taylor taskStackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT)) 911e858f1252faf8c9a228d834d94c43fa6fefd73f3John Spurlock .setCategory(Notification.CATEGORY_MESSAGE) 912ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor .setPriority(Notification.PRIORITY_DEFAULT); // TODO: set based on contact coming 913ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor // from a favorite. 914429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor 9154c99d70732d5bf20d34da3ce76753e00c7ae7c39Christoph Studer // Tag notification with all senders. 9164c99d70732d5bf20d34da3ce76753e00c7ae7c39Christoph Studer for (NotificationInfo info : notificationSet) { 9174c99d70732d5bf20d34da3ce76753e00c7ae7c39Christoph Studer Uri peopleReferenceUri = info.mSender.getPeopleReferenceUri(); 9184c99d70732d5bf20d34da3ce76753e00c7ae7c39Christoph Studer if (peopleReferenceUri != null) { 9194c99d70732d5bf20d34da3ce76753e00c7ae7c39Christoph Studer noti.addPerson(peopleReferenceUri.toString()); 9204c99d70732d5bf20d34da3ce76753e00c7ae7c39Christoph Studer } 9214c99d70732d5bf20d34da3ce76753e00c7ae7c39Christoph Studer } 9224c99d70732d5bf20d34da3ce76753e00c7ae7c39Christoph Studer 923674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler int defaults = 0; 92472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 92572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project if (isNew) { 926d83675687b1ef742c33bffe8195d7b1852c2c01dTom Taylor SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context); 927006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma 92890e32e59610d4a395716b1cfa9c8b041b45e3d4eTom Taylor boolean vibrate = false; 92990e32e59610d4a395716b1cfa9c8b041b45e3d4eTom Taylor if (sp.contains(MessagingPreferenceActivity.NOTIFICATION_VIBRATE)) { 93090e32e59610d4a395716b1cfa9c8b041b45e3d4eTom Taylor // The most recent change to the vibrate preference is to store a boolean 93190e32e59610d4a395716b1cfa9c8b041b45e3d4eTom Taylor // value in NOTIFICATION_VIBRATE. If prefs contain that preference, use that 93290e32e59610d4a395716b1cfa9c8b041b45e3d4eTom Taylor // first. 93390e32e59610d4a395716b1cfa9c8b041b45e3d4eTom Taylor vibrate = sp.getBoolean(MessagingPreferenceActivity.NOTIFICATION_VIBRATE, 93490e32e59610d4a395716b1cfa9c8b041b45e3d4eTom Taylor false); 93590e32e59610d4a395716b1cfa9c8b041b45e3d4eTom Taylor } else if (sp.contains(MessagingPreferenceActivity.NOTIFICATION_VIBRATE_WHEN)) { 93690e32e59610d4a395716b1cfa9c8b041b45e3d4eTom Taylor // This is to support the pre-JellyBean MR1.1 version of vibrate preferences 93790e32e59610d4a395716b1cfa9c8b041b45e3d4eTom Taylor // when vibrate was a tri-state setting. As soon as the user opens the Messaging 93890e32e59610d4a395716b1cfa9c8b041b45e3d4eTom Taylor // app's settings, it will migrate this setting from NOTIFICATION_VIBRATE_WHEN 93990e32e59610d4a395716b1cfa9c8b041b45e3d4eTom Taylor // to the boolean value stored in NOTIFICATION_VIBRATE. 94090e32e59610d4a395716b1cfa9c8b041b45e3d4eTom Taylor String vibrateWhen = 94190e32e59610d4a395716b1cfa9c8b041b45e3d4eTom Taylor sp.getString(MessagingPreferenceActivity.NOTIFICATION_VIBRATE_WHEN, null); 94290e32e59610d4a395716b1cfa9c8b041b45e3d4eTom Taylor vibrate = "always".equals(vibrateWhen); 94390e32e59610d4a395716b1cfa9c8b041b45e3d4eTom Taylor } 94490e32e59610d4a395716b1cfa9c8b041b45e3d4eTom Taylor if (vibrate) { 945674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler defaults |= Notification.DEFAULT_VIBRATE; 94672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 94772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 948627007213deb59ef938c80353c8f3598b01478b3Wei Huang String ringtoneStr = sp.getString(MessagingPreferenceActivity.NOTIFICATION_RINGTONE, 949627007213deb59ef938c80353c8f3598b01478b3Wei Huang null); 950674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler noti.setSound(TextUtils.isEmpty(ringtoneStr) ? null : Uri.parse(ringtoneStr)); 951d2f67cfca13a6e415636dc253c371fb76974f5faTom Taylor Log.d(TAG, "updateNotification: new message, adding sound to the notification"); 95272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 95372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 954674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler defaults |= Notification.DEFAULT_LIGHTS; 955674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler 956674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler noti.setDefaults(defaults); 95772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 95870f5af8fd89d66ae246a805d10a50540746319aaWei Huang // set up delete intent 959674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler noti.setDeleteIntent(PendingIntent.getBroadcast(context, 0, 960674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler sNotificationOnDeleteIntent, 0)); 96170f5af8fd89d66ae246a805d10a50540746319aaWei Huang 962674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler final Notification notification; 963429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor 964ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor if (messageCount == 1) { 965ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor // We've got a single message 966ca7b54a002b5bc627171d1b275cb016bf1105da2Daniel Sandler 967ca7b54a002b5bc627171d1b275cb016bf1105da2Daniel Sandler // This sets the text for the collapsed form: 968ca7b54a002b5bc627171d1b275cb016bf1105da2Daniel Sandler noti.setContentText(mostRecentNotification.formatBigMessage(context)); 969ca7b54a002b5bc627171d1b275cb016bf1105da2Daniel Sandler 970ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor if (mostRecentNotification.mAttachmentBitmap != null) { 971ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor // The message has a picture, show that 972ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor 973ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor notification = new Notification.BigPictureStyle(noti) 974ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor .bigPicture(mostRecentNotification.mAttachmentBitmap) 975ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor // This sets the text for the expanded picture form: 976ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor .setSummaryText(mostRecentNotification.formatPictureMessage(context)) 977ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor .build(); 978ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor } else { 979ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor // Show a single notification -- big style with the text of the whole message 980ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor notification = new Notification.BigTextStyle(noti) 981ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor .bigText(mostRecentNotification.formatBigMessage(context)) 982ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor .build(); 983ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor } 9846d2ba55a4bd1937bbec101ab2a4c005b566b43f8Tom Taylor if (DEBUG) { 9856d2ba55a4bd1937bbec101ab2a4c005b566b43f8Tom Taylor Log.d(TAG, "updateNotification: single message notification"); 9866d2ba55a4bd1937bbec101ab2a4c005b566b43f8Tom Taylor } 987ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor } else { 988ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor // We've got multiple messages 989ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor if (uniqueThreadCount == 1) { 990ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor // We've got multiple messages for the same thread. 991ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor // Starting with the oldest new message, display the full text of each message. 992ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor // Begin a line for each subsequent message. 993429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor SpannableStringBuilder buf = new SpannableStringBuilder(); 994ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor NotificationInfo infos[] = 9954c6c7c65a1033d5cc0d87cc8b0e07a69db1842e8Tom Taylor notificationSet.toArray(new NotificationInfo[messageCount]); 996ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor int len = infos.length; 997ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor for (int i = len - 1; i >= 0; i--) { 998ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor NotificationInfo info = infos[i]; 999ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor 1000ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor buf.append(info.formatBigMessage(context)); 1001429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor 1002ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor if (i != 0) { 1003ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor buf.append('\n'); 1004ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor } 1005ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor } 1006ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor 1007ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor noti.setContentText(context.getString(R.string.message_count_notification, 1008ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor messageCount)); 1009ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor 1010ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor // Show a single notification -- big style with the text of all the messages 1011ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor notification = new Notification.BigTextStyle(noti) 1012ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor .bigText(buf) 10134c6c7c65a1033d5cc0d87cc8b0e07a69db1842e8Tom Taylor // Forcibly show the last line, with the app's smallIcon in it, if we 101464fefc1c9b26bd6778c318e83cec696abb389c22Daniel Sandler // kicked the smallIcon out with an avatar bitmap 101564fefc1c9b26bd6778c318e83cec696abb389c22Daniel Sandler .setSummaryText((avatar == null) ? null : " ") 1016ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor .build(); 10176d2ba55a4bd1937bbec101ab2a4c005b566b43f8Tom Taylor if (DEBUG) { 10186d2ba55a4bd1937bbec101ab2a4c005b566b43f8Tom Taylor Log.d(TAG, "updateNotification: multi messages for single thread"); 10196d2ba55a4bd1937bbec101ab2a4c005b566b43f8Tom Taylor } 1020ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor } else { 1021ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor // Build a set of the most recent notification per threadId. 10224c6c7c65a1033d5cc0d87cc8b0e07a69db1842e8Tom Taylor HashSet<Long> uniqueThreads = new HashSet<Long>(messageCount); 1023ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor ArrayList<NotificationInfo> mostRecentNotifPerThread = 1024ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor new ArrayList<NotificationInfo>(); 10254c6c7c65a1033d5cc0d87cc8b0e07a69db1842e8Tom Taylor Iterator<NotificationInfo> notifications = notificationSet.iterator(); 1026ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor while (notifications.hasNext()) { 1027ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor NotificationInfo notificationInfo = notifications.next(); 1028ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor if (!uniqueThreads.contains(notificationInfo.mThreadId)) { 1029ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor uniqueThreads.add(notificationInfo.mThreadId); 1030ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor mostRecentNotifPerThread.add(notificationInfo); 1031ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor } 1032ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor } 1033ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor // When collapsed, show all the senders like this: 1034ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor // Fred Flinstone, Barry Manilow, Pete... 1035ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor noti.setContentText(formatSenders(context, mostRecentNotifPerThread)); 1036ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor Notification.InboxStyle inboxStyle = new Notification.InboxStyle(noti); 1037ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor 1038ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor // We have to set the summary text to non-empty so the content text doesn't show 1039ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor // up when expanded. 1040ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor inboxStyle.setSummaryText(" "); 1041ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor 1042ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor // At this point we've got multiple messages in multiple threads. We only 1043ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor // want to show the most recent message per thread, which are in 1044ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor // mostRecentNotifPerThread. 1045ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor int uniqueThreadMessageCount = mostRecentNotifPerThread.size(); 1046ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor int maxMessages = Math.min(MAX_MESSAGES_TO_SHOW, uniqueThreadMessageCount); 1047ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor 1048ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor for (int i = 0; i < maxMessages; i++) { 1049ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor NotificationInfo info = mostRecentNotifPerThread.get(i); 1050ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor inboxStyle.addLine(info.formatInboxMessage(context)); 1051ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor } 1052ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor notification = inboxStyle.build(); 10536db678ea4fb26fcffb06daa30ad7ef64d902b3d2Roger Chen 10546db678ea4fb26fcffb06daa30ad7ef64d902b3d2Roger Chen uniqueThreads.clear(); 10556db678ea4fb26fcffb06daa30ad7ef64d902b3d2Roger Chen mostRecentNotifPerThread.clear(); 10566db678ea4fb26fcffb06daa30ad7ef64d902b3d2Roger Chen 1057ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor if (DEBUG) { 1058ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor Log.d(TAG, "updateNotification: multi messages," + 1059ee0f8ea8d8739358387443b4fe7d1d9edf44f601Tom Taylor " showing inboxStyle notification"); 1060429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor } 10619ab4d755b862392724b7dbb12e636235a05cb3bdTom Taylor } 1062674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler } 1063674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler 106472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project nm.notify(NOTIFICATION_ID, notification); 106572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 106672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 106772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project protected static CharSequence buildTickerMessage( 106872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project Context context, String address, String subject, String body) { 106933a87f96f8c625aa10131a77a3968c97c4ec5a62Ficus Kirkpatrick String displayAddress = Contact.get(address, true).getName(); 10705a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor 107172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project StringBuilder buf = new StringBuilder( 107272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project displayAddress == null 107372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project ? "" 107472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project : displayAddress.replace('\n', ' ').replace('\r', ' ')); 107572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project buf.append(':').append(' '); 107672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 107772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project int offset = buf.length(); 107872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project if (!TextUtils.isEmpty(subject)) { 107972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project subject = subject.replace('\n', ' ').replace('\r', ' '); 108072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project buf.append(subject); 108172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project buf.append(' '); 108272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 108372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 108472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project if (!TextUtils.isEmpty(body)) { 108572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project body = body.replace('\n', ' ').replace('\r', ' '); 108672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project buf.append(body); 108772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 108872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 108972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project SpannableString spanText = new SpannableString(buf.toString()); 109072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project spanText.setSpan(new StyleSpan(Typeface.BOLD), 0, offset, 109172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 109272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 109372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project return spanText; 109472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 109572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 109672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static String getMmsSubject(String sub, int charset) { 109772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project return TextUtils.isEmpty(sub) ? "" 109872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project : new EncodedStringValue(charset, PduPersister.getBytes(sub)).getString(); 109972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 110072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 110172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project public static void notifyDownloadFailed(Context context, long threadId) { 1102b3cb9bbf929f70cb4855f03e4bfbed749022cf1bFicus Kirkpatrick notifyFailed(context, true, threadId, false); 110372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 110472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 11055d2d0046ada7b53205e537d8675d32a8785e8d1dThe Android Open Source Project public static void notifySendFailed(Context context) { 1106b3cb9bbf929f70cb4855f03e4bfbed749022cf1bFicus Kirkpatrick notifyFailed(context, false, 0, false); 110772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 110872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 1109b3cb9bbf929f70cb4855f03e4bfbed749022cf1bFicus Kirkpatrick public static void notifySendFailed(Context context, boolean noisy) { 1110b3cb9bbf929f70cb4855f03e4bfbed749022cf1bFicus Kirkpatrick notifyFailed(context, false, 0, noisy); 1111b3cb9bbf929f70cb4855f03e4bfbed749022cf1bFicus Kirkpatrick } 11125a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor 1113b3cb9bbf929f70cb4855f03e4bfbed749022cf1bFicus Kirkpatrick private static void notifyFailed(Context context, boolean isDownload, long threadId, 1114b3cb9bbf929f70cb4855f03e4bfbed749022cf1bFicus Kirkpatrick boolean noisy) { 111572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project // TODO factor out common code for creating notifications 1116d83675687b1ef742c33bffe8195d7b1852c2c01dTom Taylor boolean enabled = MessagingPreferenceActivity.getNotificationEnabled(context); 111772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project if (!enabled) { 111872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project return; 111972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 112072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 112172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project // Strategy: 112272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project // a. If there is a single failure notification, tapping on the notification goes 112372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project // to the compose view. 11245a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor // b. If there are two failure it stays in the thread view. Selecting one undelivered 112572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project // thread will dismiss one undelivered notification but will still display the 112672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project // notification.If you select the 2nd undelivered one it will dismiss the notification. 11275a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor 11287015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev long[] msgThreadId = {0, 1}; // Dummy initial values, just to initialize the memory 112972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project int totalFailedCount = getUndeliveredMessageCount(context, msgThreadId); 11307015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev if (totalFailedCount == 0 && !isDownload) { 11317015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev return; 11327015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev } 11337015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev // The getUndeliveredMessageCount method puts a non-zero value in msgThreadId[1] if all 11347015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev // failures are from the same thread. 11357015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev // If isDownload is true, we're dealing with 1 specific failure; therefore "all failed" are 11367015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev // indeed in the same thread since there's only 1. 11377015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev boolean allFailedInSameThread = (msgThreadId[1] != 0) || isDownload; 11385a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor 113972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project Intent failedIntent; 114072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project Notification notification = new Notification(); 114172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project String title; 114272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project String description; 114372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project if (totalFailedCount > 1) { 114472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project description = context.getString(R.string.notification_failed_multiple, 114572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project Integer.toString(totalFailedCount)); 114672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project title = context.getString(R.string.notification_failed_multiple_title); 114772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } else { 114872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project title = isDownload ? 114972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project context.getString(R.string.message_download_failed_title) : 115072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project context.getString(R.string.message_send_failed_title); 11515a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor 115272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project description = context.getString(R.string.message_failed_body); 11537015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev } 11547015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev 1155fb7068020e74e431acc9511212d2a6d17258ab9eAdam Powell TaskStackBuilder taskStackBuilder = TaskStackBuilder.create(context); 11567015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev if (allFailedInSameThread) { 1157836945de572ac80fd6f6a7bf59036d4cce801410The Android Open Source Project failedIntent = new Intent(context, ComposeMessageActivity.class); 115895817b166d415114bac89ca0946c3717ae229526Tom Taylor if (isDownload) { 115995817b166d415114bac89ca0946c3717ae229526Tom Taylor // When isDownload is true, the valid threadId is passed into this function. 116095817b166d415114bac89ca0946c3717ae229526Tom Taylor failedIntent.putExtra("failed_download_flag", true); 116195817b166d415114bac89ca0946c3717ae229526Tom Taylor } else { 11627015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev threadId = msgThreadId[0]; 116395817b166d415114bac89ca0946c3717ae229526Tom Taylor failedIntent.putExtra("undelivered_flag", true); 11645a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor } 11655a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor failedIntent.putExtra("thread_id", threadId); 11666cc254afc74dee97c7ef356612ae9ec7bc8b77ceTom Taylor taskStackBuilder.addParentStack(ComposeMessageActivity.class); 11677015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev } else { 11687015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev failedIntent = new Intent(context, ConversationList.class); 116972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 11706cc254afc74dee97c7ef356612ae9ec7bc8b77ceTom Taylor taskStackBuilder.addNextIntent(failedIntent); 117172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 117272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project notification.icon = R.drawable.stat_notify_sms_failed; 117372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 117472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project notification.tickerText = title; 117572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 11766cc254afc74dee97c7ef356612ae9ec7bc8b77ceTom Taylor notification.setLatestEventInfo(context, title, description, 11776cc254afc74dee97c7ef356612ae9ec7bc8b77ceTom Taylor taskStackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT)); 117872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 1179b3cb9bbf929f70cb4855f03e4bfbed749022cf1bFicus Kirkpatrick if (noisy) { 1180d83675687b1ef742c33bffe8195d7b1852c2c01dTom Taylor SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context); 1181e3baaa51cd25b52c7a24e381319926b9da00abdfWei Huang boolean vibrate = sp.getBoolean(MessagingPreferenceActivity.NOTIFICATION_VIBRATE, 1182e3baaa51cd25b52c7a24e381319926b9da00abdfWei Huang false /* don't vibrate by default */); 1183b3cb9bbf929f70cb4855f03e4bfbed749022cf1bFicus Kirkpatrick if (vibrate) { 1184b3cb9bbf929f70cb4855f03e4bfbed749022cf1bFicus Kirkpatrick notification.defaults |= Notification.DEFAULT_VIBRATE; 1185b3cb9bbf929f70cb4855f03e4bfbed749022cf1bFicus Kirkpatrick } 118672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 1187e3baaa51cd25b52c7a24e381319926b9da00abdfWei Huang String ringtoneStr = sp.getString(MessagingPreferenceActivity.NOTIFICATION_RINGTONE, 1188e3baaa51cd25b52c7a24e381319926b9da00abdfWei Huang null); 1189b3cb9bbf929f70cb4855f03e4bfbed749022cf1bFicus Kirkpatrick notification.sound = TextUtils.isEmpty(ringtoneStr) ? null : Uri.parse(ringtoneStr); 1190b3cb9bbf929f70cb4855f03e4bfbed749022cf1bFicus Kirkpatrick } 11915a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor 1192429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor NotificationManager notificationMgr = (NotificationManager) 1193429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor context.getSystemService(Context.NOTIFICATION_SERVICE); 1194429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor 119572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project if (isDownload) { 1196429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor notificationMgr.notify(DOWNLOAD_FAILED_NOTIFICATION_ID, notification); 119772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } else { 1198429f4c0b2a6ada384e30af31644f1edba0284b4dTom Taylor notificationMgr.notify(MESSAGE_FAILED_NOTIFICATION_ID, notification); 119972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 120072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 12015a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor 12027015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev /** 12037015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev * Query the DB and return the number of undelivered messages (total for both SMS and MMS) 12047015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev * @param context The context 12057015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev * @param threadIdResult A container to put the result in, according to the following rules: 12067015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev * threadIdResult[0] contains the thread id of the first message. 12077015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev * threadIdResult[1] is nonzero if the thread ids of all the messages are the same. 12087015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev * You can pass in null for threadIdResult. 12097015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev * You can pass in a threadIdResult of size 1 to avoid the comparison of each thread id. 12107015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev */ 121172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static int getUndeliveredMessageCount(Context context, long[] threadIdResult) { 121272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project Cursor undeliveredCursor = SqliteWrapper.query(context, context.getContentResolver(), 1213c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev UNDELIVERED_URI, MMS_THREAD_ID_PROJECTION, "read=0", null, null); 121472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project if (undeliveredCursor == null) { 121572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project return 0; 121672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 121772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project int count = undeliveredCursor.getCount(); 121872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project try { 121972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project if (threadIdResult != null && undeliveredCursor.moveToFirst()) { 122072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project threadIdResult[0] = undeliveredCursor.getLong(0); 12215a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor 12222f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project if (threadIdResult.length >= 2) { 12232f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project // Test to see if all the undelivered messages belong to the same thread. 12242f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project long firstId = threadIdResult[0]; 12252f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project while (undeliveredCursor.moveToNext()) { 12262f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project if (undeliveredCursor.getLong(0) != firstId) { 12272f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project firstId = 0; 12282f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project break; 12292f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project } 12302f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project } 12312f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project threadIdResult[1] = firstId; // non-zero if all ids are the same 12322f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project } 123372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 123472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } finally { 123572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project undeliveredCursor.close(); 123672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 123772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project return count; 123872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 123972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 1240b0ef8fc2738b210a2bb0490e75eedc1e7b7b491fTom Taylor public static void nonBlockingUpdateSendFailedNotification(final Context context) { 1241b0ef8fc2738b210a2bb0490e75eedc1e7b7b491fTom Taylor new AsyncTask<Void, Void, Integer>() { 1242b0ef8fc2738b210a2bb0490e75eedc1e7b7b491fTom Taylor protected Integer doInBackground(Void... none) { 1243b0ef8fc2738b210a2bb0490e75eedc1e7b7b491fTom Taylor return getUndeliveredMessageCount(context, null); 1244b0ef8fc2738b210a2bb0490e75eedc1e7b7b491fTom Taylor } 1245b0ef8fc2738b210a2bb0490e75eedc1e7b7b491fTom Taylor 1246b0ef8fc2738b210a2bb0490e75eedc1e7b7b491fTom Taylor protected void onPostExecute(Integer result) { 1247b0ef8fc2738b210a2bb0490e75eedc1e7b7b491fTom Taylor if (result < 1) { 1248b0ef8fc2738b210a2bb0490e75eedc1e7b7b491fTom Taylor cancelNotification(context, MESSAGE_FAILED_NOTIFICATION_ID); 1249b0ef8fc2738b210a2bb0490e75eedc1e7b7b491fTom Taylor } else { 1250b0ef8fc2738b210a2bb0490e75eedc1e7b7b491fTom Taylor // rebuild and adjust the message count if necessary. 1251b0ef8fc2738b210a2bb0490e75eedc1e7b7b491fTom Taylor notifySendFailed(context); 1252b0ef8fc2738b210a2bb0490e75eedc1e7b7b491fTom Taylor } 1253b0ef8fc2738b210a2bb0490e75eedc1e7b7b491fTom Taylor } 1254b0ef8fc2738b210a2bb0490e75eedc1e7b7b491fTom Taylor }.execute(); 125572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 12565a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor 12575a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor /** 12582f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project * If all the undelivered messages belong to "threadId", cancel the notification. 12592f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project */ 12602f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project public static void updateSendFailedNotificationForThread(Context context, long threadId) { 12612f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project long[] msgThreadId = {0, 0}; 12625a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor if (getUndeliveredMessageCount(context, msgThreadId) > 0 12632f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project && msgThreadId[0] == threadId 12642f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project && msgThreadId[1] != 0) { 12652f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project cancelNotification(context, MESSAGE_FAILED_NOTIFICATION_ID); 12662f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project } 12672f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project } 12685a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor 126972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project private static int getDownloadFailedMessageCount(Context context) { 127072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project // Look for any messages in the MMS Inbox that are of the type 127172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project // NOTIFICATION_IND (i.e. not already downloaded) and in the 127272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project // permanent failure state. If there are none, cancel any 127372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project // failed download notification. 127472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project Cursor c = SqliteWrapper.query(context, context.getContentResolver(), 127572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project Mms.Inbox.CONTENT_URI, null, 127672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project Mms.MESSAGE_TYPE + "=" + 127772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project String.valueOf(PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND) + 127872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project " AND " + Mms.STATUS + "=" + 127972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project String.valueOf(DownloadManager.STATE_PERMANENT_FAILURE), 128072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project null, null); 128172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project if (c == null) { 128272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project return 0; 128372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 128472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project int count = c.getCount(); 128572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project c.close(); 128672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project return count; 128772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 128872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project 128972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project public static void updateDownloadFailedNotification(Context context) { 129072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project if (getDownloadFailedMessageCount(context) < 1) { 129172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project cancelNotification(context, DOWNLOAD_FAILED_NOTIFICATION_ID); 129272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 129372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project } 12945a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor 129595817b166d415114bac89ca0946c3717ae229526Tom Taylor public static boolean isFailedToDeliver(Intent intent) { 129695817b166d415114bac89ca0946c3717ae229526Tom Taylor return (intent != null) && intent.getBooleanExtra("undelivered_flag", false); 129795817b166d415114bac89ca0946c3717ae229526Tom Taylor } 129895817b166d415114bac89ca0946c3717ae229526Tom Taylor 129995817b166d415114bac89ca0946c3717ae229526Tom Taylor public static boolean isFailedToDownload(Intent intent) { 130095817b166d415114bac89ca0946c3717ae229526Tom Taylor return (intent != null) && intent.getBooleanExtra("failed_download_flag", false); 130195817b166d415114bac89ca0946c3717ae229526Tom Taylor } 1302c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev 1303c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev /** 1304c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev * Get the thread ID of the SMS message with the given URI 1305c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev * @param context The context 1306c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev * @param uri The URI of the SMS message 1307c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev * @return The thread ID, or THREAD_NONE if the URI contains no entries 1308c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev */ 1309c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev public static long getSmsThreadId(Context context, Uri uri) { 1310c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev Cursor cursor = SqliteWrapper.query( 1311c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev context, 1312c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev context.getContentResolver(), 1313c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev uri, 1314c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev SMS_THREAD_ID_PROJECTION, 1315c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev null, 1316c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev null, 1317c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev null); 1318c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev 1319c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev if (cursor == null) { 1320d645c8b53ae904bc059ee1ca7232916637c223e5Tom Taylor if (DEBUG) { 1321d645c8b53ae904bc059ee1ca7232916637c223e5Tom Taylor Log.d(TAG, "getSmsThreadId uri: " + uri + " NULL cursor! returning THREAD_NONE"); 1322d645c8b53ae904bc059ee1ca7232916637c223e5Tom Taylor } 1323c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev return THREAD_NONE; 1324c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev } 1325c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev 1326c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev try { 1327c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev if (cursor.moveToFirst()) { 13287ecebc423d3fb8e9d8b5703780582f5a486aa742yoohyun.choi int columnIndex = cursor.getColumnIndex(Sms.THREAD_ID); 13297ecebc423d3fb8e9d8b5703780582f5a486aa742yoohyun.choi if (columnIndex < 0) { 13307ecebc423d3fb8e9d8b5703780582f5a486aa742yoohyun.choi if (DEBUG) { 13317ecebc423d3fb8e9d8b5703780582f5a486aa742yoohyun.choi Log.d(TAG, "getSmsThreadId uri: " + uri + 13327ecebc423d3fb8e9d8b5703780582f5a486aa742yoohyun.choi " Couldn't read row 0, col -1! returning THREAD_NONE"); 13337ecebc423d3fb8e9d8b5703780582f5a486aa742yoohyun.choi } 13347ecebc423d3fb8e9d8b5703780582f5a486aa742yoohyun.choi return THREAD_NONE; 13357ecebc423d3fb8e9d8b5703780582f5a486aa742yoohyun.choi } 13367ecebc423d3fb8e9d8b5703780582f5a486aa742yoohyun.choi long threadId = cursor.getLong(columnIndex); 1337d645c8b53ae904bc059ee1ca7232916637c223e5Tom Taylor if (DEBUG) { 1338d645c8b53ae904bc059ee1ca7232916637c223e5Tom Taylor Log.d(TAG, "getSmsThreadId uri: " + uri + 1339d645c8b53ae904bc059ee1ca7232916637c223e5Tom Taylor " returning threadId: " + threadId); 1340d645c8b53ae904bc059ee1ca7232916637c223e5Tom Taylor } 1341d645c8b53ae904bc059ee1ca7232916637c223e5Tom Taylor return threadId; 1342c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev } else { 1343d645c8b53ae904bc059ee1ca7232916637c223e5Tom Taylor if (DEBUG) { 1344d645c8b53ae904bc059ee1ca7232916637c223e5Tom Taylor Log.d(TAG, "getSmsThreadId uri: " + uri + 1345d645c8b53ae904bc059ee1ca7232916637c223e5Tom Taylor " NULL cursor! returning THREAD_NONE"); 1346d645c8b53ae904bc059ee1ca7232916637c223e5Tom Taylor } 1347c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev return THREAD_NONE; 1348c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev } 1349c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev } finally { 1350c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev cursor.close(); 1351c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev } 1352c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev } 1353c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev 1354c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev /** 1355c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev * Get the thread ID of the MMS message with the given URI 1356c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev * @param context The context 1357c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev * @param uri The URI of the SMS message 1358c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev * @return The thread ID, or THREAD_NONE if the URI contains no entries 1359c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev */ 1360c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev public static long getThreadId(Context context, Uri uri) { 1361c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev Cursor cursor = SqliteWrapper.query( 1362c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev context, 1363c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev context.getContentResolver(), 1364c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev uri, 1365c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev MMS_THREAD_ID_PROJECTION, 1366c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev null, 1367c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev null, 1368c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev null); 1369c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev 1370c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev if (cursor == null) { 1371d645c8b53ae904bc059ee1ca7232916637c223e5Tom Taylor if (DEBUG) { 1372d645c8b53ae904bc059ee1ca7232916637c223e5Tom Taylor Log.d(TAG, "getThreadId uri: " + uri + " NULL cursor! returning THREAD_NONE"); 1373d645c8b53ae904bc059ee1ca7232916637c223e5Tom Taylor } 1374c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev return THREAD_NONE; 1375c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev } 1376c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev 1377c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev try { 1378c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev if (cursor.moveToFirst()) { 13797ecebc423d3fb8e9d8b5703780582f5a486aa742yoohyun.choi int columnIndex = cursor.getColumnIndex(Mms.THREAD_ID); 13807ecebc423d3fb8e9d8b5703780582f5a486aa742yoohyun.choi if (columnIndex < 0) { 13817ecebc423d3fb8e9d8b5703780582f5a486aa742yoohyun.choi if (DEBUG) { 13827ecebc423d3fb8e9d8b5703780582f5a486aa742yoohyun.choi Log.d(TAG, "getThreadId uri: " + uri + 13837ecebc423d3fb8e9d8b5703780582f5a486aa742yoohyun.choi " Couldn't read row 0, col -1! returning THREAD_NONE"); 13847ecebc423d3fb8e9d8b5703780582f5a486aa742yoohyun.choi } 13857ecebc423d3fb8e9d8b5703780582f5a486aa742yoohyun.choi return THREAD_NONE; 13867ecebc423d3fb8e9d8b5703780582f5a486aa742yoohyun.choi } 13877ecebc423d3fb8e9d8b5703780582f5a486aa742yoohyun.choi long threadId = cursor.getLong(columnIndex); 1388d645c8b53ae904bc059ee1ca7232916637c223e5Tom Taylor if (DEBUG) { 1389d645c8b53ae904bc059ee1ca7232916637c223e5Tom Taylor Log.d(TAG, "getThreadId uri: " + uri + 1390d645c8b53ae904bc059ee1ca7232916637c223e5Tom Taylor " returning threadId: " + threadId); 1391d645c8b53ae904bc059ee1ca7232916637c223e5Tom Taylor } 1392d645c8b53ae904bc059ee1ca7232916637c223e5Tom Taylor return threadId; 1393c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev } else { 1394d645c8b53ae904bc059ee1ca7232916637c223e5Tom Taylor if (DEBUG) { 1395d645c8b53ae904bc059ee1ca7232916637c223e5Tom Taylor Log.d(TAG, "getThreadId uri: " + uri + 1396d645c8b53ae904bc059ee1ca7232916637c223e5Tom Taylor " NULL cursor! returning THREAD_NONE"); 1397d645c8b53ae904bc059ee1ca7232916637c223e5Tom Taylor } 1398c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev return THREAD_NONE; 1399c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev } 1400c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev } finally { 1401c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev cursor.close(); 1402c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev } 1403c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev } 140472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project} 1405