@TargetApi(19) public static String getSMSAppPackageName(Context context) { if (VERSION.SDK_INT >= 19) { return Sms.getDefaultSmsPackage(context); } Intent intent = new Intent("android.intent.action.MAIN"); intent.addCategory("android.intent.category.DEFAULT"); intent.setType("vnd.android-dir/mms-sms"); ComponentName componentName = intent.resolveActivity(context.getPackageManager()); if (componentName != null) { return componentName.getPackageName(); } return null; }
/** * Add an SMS to the given URI with the specified thread ID. * * @param resolver the content resolver to use * @param uri the URI to add the message to * @param address the address of the sender * @param body the body of the message * @param subject the pseudo-subject of the message * @param date the timestamp for the message * @param read true if the message has been read, false if not * @param deliveryReport true if a delivery report was requested, false if not * @param threadId the thread_id of the message * @return the URI for the new message * @hide */ public static Uri addMessageToUri(ContentResolver resolver, Uri uri, String address, String body, String subject, Long date, boolean read, boolean deliveryReport, long threadId) { ContentValues values = new ContentValues(7); values.put(Sms.ADDRESS, address); if (date != null) { values.put(Sms.DATE, date); } values.put(Sms.READ, read ? Integer.valueOf(1) : Integer.valueOf(0)); values.put(Sms.SUBJECT, subject); values.put(Sms.BODY, body); if (deliveryReport) { values.put(Sms.STATUS, Sms.STATUS_PENDING); } if (threadId != -1L) { values.put(Sms.THREAD_ID, threadId); } return resolver.insert(uri, values); }
public static void dumpSmsTable(Context context) { LogTag.debug("**** Dump of sms table ****"); Cursor c = context.getContentResolver().query(Sms.CONTENT_URI, SMS_PROJECTION, null, null, "_id DESC"); try { // Only dump the latest 20 messages c.moveToPosition(-1); while (c.moveToNext() && c.getPosition() < 20) { String body = c.getString(COLUMN_SMS_BODY); LogTag.debug("dumpSmsTable " + BaseColumns._ID + ": " + c.getLong(COLUMN_ID) + " " + Sms.THREAD_ID + " : " + c.getLong(DATE) + " " + Sms.ADDRESS + " : " + c.getString(COLUMN_SMS_ADDRESS) + " " + Sms.BODY + " : " + body.substring(0, Math.min(body.length(), 8)) + " " + Sms.DATE + " : " + c.getLong(COLUMN_SMS_DATE) + " " + Sms.TYPE + " : " + c.getInt(COLUMN_SMS_TYPE)); } } finally { c.close(); } }
public static void lockMessage(Context context, MessageItem msgItem, boolean locked) { Uri uri; if ("sms".equals(msgItem.mType)) { uri = Sms.CONTENT_URI; } else { uri = Mms.CONTENT_URI; } final Uri lockUri = ContentUris.withAppendedId(uri, msgItem.mMsgId); final ContentValues values = new ContentValues(1); values.put("locked", locked ? 1 : 0); new Thread(() -> { context.getContentResolver().update(lockUri, values, null, null); }, "MainActivity.lockMessage").start(); }
/** * Get the thread ID of the SMS message with the given URI * @param context The context * @param uri The URI of the SMS message * @return The thread ID, or THREAD_NONE if the URI contains no entries */ public static long getSmsThreadId(Context context, Uri uri) { Cursor cursor = SqliteWrapper.query( context, context.getContentResolver(), uri, SMS_THREAD_ID_PROJECTION, null, null, null); if (cursor == null) { return THREAD_NONE; } try { if (cursor.moveToFirst()) { return cursor.getLong(cursor.getColumnIndex(Sms.THREAD_ID)); } else { return THREAD_NONE; } } finally { cursor.close(); } }
/** * Move all messages that are in the outbox to the failed state and set them to unread. * @return The number of messages that were actually moved */ private int moveOutboxMessagesToFailedBox() { ContentValues values = new ContentValues(3); values.put(Sms.TYPE, Sms.MESSAGE_TYPE_FAILED); values.put(Sms.ERROR_CODE, SmsManager.RESULT_ERROR_GENERIC_FAILURE); values.put(Sms.READ, Integer.valueOf(0)); int messageCount = SqliteWrapper.update( getApplicationContext(), getContentResolver(), Outbox.CONTENT_URI, values, "type = " + Sms.MESSAGE_TYPE_OUTBOX, null); if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE) || LogTag.DEBUG_SEND) { Log.v(TAG, "moveOutboxMessagesToFailedBox messageCount: " + messageCount); } return messageCount; }
@Override protected void onHandleIntent(Intent intent) { // This method is called on a worker thread. Uri messageUri = intent.getData(); byte[] pdu = intent.getByteArrayExtra("pdu"); String format = intent.getStringExtra("format"); SmsMessage message = updateMessageStatus(this, messageUri, pdu, format); // Called on a background thread, so it's OK to block. if (message != null && message.getStatus() < Sms.STATUS_PENDING) { MessagingNotification.blockingUpdateNewMessageIndicator(this, MessagingNotification.THREAD_NONE, message.isStatusReportMessage()); } }
private void updateDraftSmsMessage(final Conversation conv, String contents) { final long threadId = conv.getThreadId(); if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) { LogTag.debug("updateDraftSmsMessage tid=%d, contents=\"%s\"", threadId, contents); } // If we don't have a valid thread, there's nothing to do. if (threadId <= 0) { return; } ContentValues values = new ContentValues(3); values.put(Sms.THREAD_ID, threadId); values.put(Sms.BODY, contents); values.put(Sms.TYPE, Sms.MESSAGE_TYPE_DRAFT); SqliteWrapper.insert(mActivity, mContentResolver, Sms.CONTENT_URI, values); asyncDeleteDraftMmsMessage(conv); mMessageUri = null; }
private void lockMessage(MessageItem msgItem, boolean locked) { Uri uri; if ("sms".equals(msgItem.mType)) { uri = Sms.CONTENT_URI; } else { uri = Mms.CONTENT_URI; } final Uri lockUri = ContentUris.withAppendedId(uri, msgItem.mMsgId); final ContentValues values = new ContentValues(1); values.put("locked", locked ? 1 : 0); new Thread(new Runnable() { @Override public void run() { getContentResolver().update(lockUri, values, null, null); } }, "ComposeMessageActivity.lockMessage").start(); }
@TargetApi(19) public void checkIfDefault() { final String myPackageName = getPackageName(); if (android.os.Build.VERSION.SDK_INT >= 19) { if (!Telephony.Sms.getDefaultSmsPackage(this).equals(myPackageName)) { // App is not default. // Show the "not currently set as the default SMS app" dialog System.out.println(" setting false"); isDefault = false; Intent intent = new Intent(Sms.Intents.ACTION_CHANGE_DEFAULT); intent.putExtra(Sms.Intents.EXTRA_PACKAGE_NAME, getApplicationContext().getPackageName()); startActivityForResult(intent,99); } else{ System.out.println(" setting true"); isDefault = true; } } else isDefault = true; }
private void editSmsMessageItem(MessageItem msgItem) { // When the message being edited is the only message in the conversation, the delete // below does something subtle. The trigger "delete_obsolete_threads_pdu" sees that a // thread contains no messages and silently deletes the thread. Meanwhile, the mConversation // object still holds onto the old thread_id and code thinks there's a backing thread in // the DB when it really has been deleted. Here we try and notice that situation and // clear out the thread_id. Later on, when Conversation.ensureThreadId() is called, we'll // create a new thread if necessary. synchronized(mConversation) { if (mConversation.getMessageCount() <= 1) { mConversation.clearThreadId(); MessagingNotification.setCurrentlyDisplayedThreadId( MessagingNotification.THREAD_NONE); } } // Delete the old undelivered SMS and load its content. Uri uri = ContentUris.withAppendedId(Sms.CONTENT_URI, msgItem.mMsgId); SqliteWrapper.delete(ComposeMessageActivity.this, mContentResolver, uri, null, null); mWorkingMessage.setText(msgItem.mBody); }
private void copyToPhoneMemory(Cursor cursor) { String address = cursor.getString( cursor.getColumnIndexOrThrow("address")); String body = cursor.getString(cursor.getColumnIndexOrThrow("body")); Long date = cursor.getLong(cursor.getColumnIndexOrThrow("date")); try { if (isIncomingMessage(cursor)) { Sms.Inbox.addMessage(mContentResolver, address, body, null, date, true /* read */); } else { Sms.Sent.addMessage(mContentResolver, address, body, null, date); } } catch (SQLiteException e) { SqliteWrapper.checkSQLiteException(this, e); } }
private static void blockingMarkAllSmsMessagesAsSeen(final Context context) { ContentResolver resolver = context.getContentResolver(); Cursor cursor = resolver.query(Sms.Inbox.CONTENT_URI, SEEN_PROJECTION, "seen=0", null, null); int count = 0; if (cursor != null) { try { count = cursor.getCount(); } finally { cursor.close(); } } if (count == 0) { return; } if (DELETEDEBUG || Log.isLoggable(LogTag.APP, Log.VERBOSE)) { Log.d(TAG, "mark " + count + " SMS msgs as seen"); } ContentValues values = new ContentValues(1); values.put("seen", 1); resolver.update(Sms.Inbox.CONTENT_URI, values, "seen=0", null); }
public boolean isMe() { // Logic matches MessageListAdapter.getItemViewType which is used to decide which // type of MessageListItem to create: a left or right justified item depending on whether // the message is incoming or outgoing. boolean isIncomingMms = isMms() && (mBoxId == Mms.MESSAGE_BOX_INBOX || mBoxId == Mms.MESSAGE_BOX_ALL); boolean isIncomingSms = isSms() && (mBoxId == Sms.MESSAGE_TYPE_INBOX || mBoxId == Sms.MESSAGE_TYPE_ALL); return !(isIncomingMms || isIncomingSms); }
public boolean isOutgoingMessage() { boolean isOutgoingMms = isMms() && (mBoxId == Mms.MESSAGE_BOX_OUTBOX); boolean isOutgoingSms = isSms() && ((mBoxId == Sms.MESSAGE_TYPE_FAILED) || (mBoxId == Sms.MESSAGE_TYPE_OUTBOX) || (mBoxId == Sms.MESSAGE_TYPE_QUEUED)); return isOutgoingMms || isOutgoingSms; }
public boolean isFailedMessage() { boolean isFailedMms = isMms() && (mErrorType >= MmsSms.ERR_TYPE_GENERIC_PERMANENT); boolean isFailedSms = isSms() && (mBoxId == Sms.MESSAGE_TYPE_FAILED); return isFailedMms || isFailedSms; }
private List<DeliveryReportItem> getSmsReportItems() { String selection = "_id = " + mMessageId; Cursor c = SqliteWrapper.query(mContext, mContext.getContentResolver(), Sms.CONTENT_URI, SMS_REPORT_STATUS_PROJECTION, selection, null, null); if (c == null) { return null; } try { if (c.getCount() <= 0) { return null; } List<DeliveryReportItem> items = new ArrayList<>(); while (c.moveToNext()) { // For sent messages with delivery reports, we stick the delivery time in the // date_sent column (see MessageStatusReceiver). String deliveryDateString = null; long deliveryDate = c.getLong(COLUMN_DATE_SENT); int messageType = c.getInt(COLUMN_MESSAGE_TYPE); if (messageType == Sms.MESSAGE_TYPE_SENT && deliveryDate > 0) { deliveryDateString = mContext.getString(R.string.delivered_label) + MessageUtils.formatTimeStampString(mContext, deliveryDate, true); } items.add(new DeliveryReportItem( mContext.getString(R.string.recipient_label) + c.getString(COLUMN_RECIPIENT), mContext.getString(R.string.status_label) + getSmsStatusText(c.getInt(COLUMN_DELIVERY_STATUS)), deliveryDateString)); } return items; } finally { c.close(); } }
private String getSmsStatusText(int status) { if (status == Sms.STATUS_NONE) { // No delivery report requested return mContext.getString(R.string.status_none); } else if (status >= Sms.STATUS_FAILED) { // Failure return mContext.getString(R.string.status_failed); } else if (status >= Sms.STATUS_PENDING) { // Pending return mContext.getString(R.string.status_pending); } else { // Success return mContext.getString(R.string.status_received); } }
private boolean queueMessage(long token) throws MmsException { if ((mMessageText == null) || (mNumberOfDests == 0)) { // Don't try to send an empty message. throw new MmsException("Null message body or dest."); } SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext); boolean requestDeliveryReport = prefs.getBoolean( MessagingPreferenceActivity.SMS_DELIVERY_REPORT_MODE, DEFAULT_DELIVERY_REPORT_MODE); for (int i = 0; i < mNumberOfDests; i++) { try { if (LogTag.DEBUG_SEND) { Log.v(TAG, "queueMessage mDests[i]: " + mDests[i] + " mThreadId: " + mThreadId); } log("updating Database with sub = " + mSubscription); Sms.addMessageToUri(mContext.getContentResolver(), Uri.parse("content://sms/queued"), mDests[i], mMessageText, null, mTimestamp, true /* read */, requestDeliveryReport, mThreadId, mSubscription); } catch (SQLiteException e) { if (LogTag.DEBUG_SEND) { Log.e(TAG, "queueMessage SQLiteException", e); } SqliteWrapper.checkSQLiteException(mContext, e); } } // Notify the SmsReceiverService to send the message out mContext.sendBroadcast(new Intent(SmsReceiverService.ACTION_SEND_MESSAGE, null, mContext, SmsReceiver.class)); return false; }
private static final MmsSmsDeliveryInfo getSmsNewDeliveryInfo(Context context) { ContentResolver resolver = context.getContentResolver(); Cursor cursor = SqliteWrapper.query(context, resolver, Sms.CONTENT_URI, SMS_STATUS_PROJECTION, NEW_DELIVERY_SM_CONSTRAINT, null, Sms.DATE); if (cursor == null) { return null; } try { if (!cursor.moveToLast()) { return null; } String address = cursor.getString(COLUMN_SMS_ADDRESS); long timeMillis = 3000; Contact contact = Contact.get(address, false); String name = contact.getNameAndNumber(); return new MmsSmsDeliveryInfo(context.getString(R.string.delivery_toast_body, name), timeMillis); } finally { cursor.close(); } }
private void messageFailedToSend(Uri uri, int error) { if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE) || LogTag.DEBUG_SEND) { Log.v(TAG, "messageFailedToSend msg failed uri: " + uri + " error: " + error); } Sms.moveMessageToFolder(this, uri, Sms.MESSAGE_TYPE_FAILED, error); MessagingNotification.notifySendFailed(getApplicationContext(), true); }
private SmsMessage updateMessageStatus(Context context, Uri messageUri, byte[] pdu, String format) { SmsMessage message = SmsMessage.createFromPdu(pdu, format); if (message == null) { return null; } // Create a "status/#" URL and use it to update the // message's status in the database. Cursor cursor = SqliteWrapper.query(context, context.getContentResolver(), messageUri, ID_PROJECTION, null, null, null); try { if (cursor.moveToFirst()) { int messageId = cursor.getInt(0); Uri updateUri = ContentUris.withAppendedId(STATUS_URI, messageId); int status = message.getStatus(); boolean isStatusReport = message.isStatusReportMessage(); ContentValues contentValues = new ContentValues(2); if (Log.isLoggable(LogTag.TAG, Log.DEBUG)) { log("updateMessageStatus: msgUrl=" + messageUri + ", status=" + status + ", isStatusReport=" + isStatusReport); } contentValues.put(Sms.STATUS, status); contentValues.put(Inbox.DATE_SENT, System.currentTimeMillis()); SqliteWrapper.update(context, context.getContentResolver(), updateUri, contentValues, null, null); } else { error("Can't find message for status update: " + messageUri); } } finally { cursor.close(); } return message; }
private static void blockingMarkAllSmsMessagesAsSeen(final Context context) { ContentResolver resolver = context.getContentResolver(); Cursor cursor = resolver.query(Sms.Inbox.CONTENT_URI, SEEN_PROJECTION, "seen=0", null, null); int count = 0; if (cursor != null) { try { count = cursor.getCount(); } finally { cursor.close(); } } if (count == 0) { return; } if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) { Log.d(TAG, "mark " + count + " SMS msgs as seen"); } ContentValues values = new ContentValues(1); values.put("seen", 1); resolver.update(Sms.Inbox.CONTENT_URI, values, "seen=0", null); }
public void asyncDeleteDraftSmsMessage(Conversation conv) { mHasSmsDraft = false; final long threadId = conv.getThreadId(); if (threadId > 0) { asyncDelete(ContentUris.withAppendedId( Sms.Conversations.CONTENT_URI, threadId), SMS_DRAFT_WHERE, null); } }
private void editSmsMessageItem(MessageItem msgItem) { // When the message being edited is the only message in the // conversation, the delete // below does something subtle. The trigger // "delete_obsolete_threads_pdu" sees that a // thread contains no messages and silently deletes the thread. // Meanwhile, the mConversation // object still holds onto the old thread_id and code thinks there's a // backing thread in // the DB when it really has been deleted. Here we try and notice that // situation and // clear out the thread_id. Later on, when Conversation.ensureThreadId() // is called, we'll // create a new thread if necessary. synchronized (mConversation) { if (mConversation.getMessageCount() <= 1) { mConversation.clearThreadId(); MessagingNotification .setCurrentlyDisplayedThreadId(MessagingNotification.THREAD_NONE); } } // Delete the old undelivered SMS and load its content. Uri uri = ContentUris.withAppendedId(Sms.CONTENT_URI, msgItem.mMsgId); SqliteWrapper.delete(ComposeMessageActivity.this, mContentResolver, uri, null, null); mWorkingMessage.setText(msgItem.mBody); }
private Uri replaceMessage(SmsMessage sms) { ContentValues values = extractContentValues(sms); values.put(Inbox.BODY, sms.getMessageBody()); ContentResolver resolver = getContentResolver(); String originatingAddress = sms.getOriginatingAddress(); int protocolIdentifier = sms.getProtocolIdentifier(); String selection = Sms.ADDRESS + " = ? AND " + Sms.PROTOCOL + " = ?"; String[] selectionArgs = new String[] { originatingAddress, Integer.toString(protocolIdentifier) }; Cursor cursor = SqliteWrapper.query(this, resolver, Inbox.CONTENT_URI, REPLACE_PROJECTION, selection, selectionArgs, null); try { if (cursor.moveToFirst()) { long messageId = cursor.getLong(REPLACE_COLUMN_ID); Uri messageUri = ContentUris.withAppendedId( Sms.CONTENT_URI, messageId); SqliteWrapper.update(this, resolver, messageUri, values, null, null); return messageUri; } } finally { cursor.close(); } return storeMessage(sms); }
private List<DeliveryReportItem> getSmsReportItems() { String selection = "_id = " + mMessageId; Cursor c = SqliteWrapper.query(this, getContentResolver(), Sms.CONTENT_URI, SMS_REPORT_STATUS_PROJECTION, selection, null, null); if (c == null) { return null; } try { if (c.getCount() <= 0) { return null; } List<DeliveryReportItem> items = new ArrayList<DeliveryReportItem>(); while (c.moveToNext()) { // For sent messages with delivery reports, we stick the delivery time in the // date_sent column (see MessageStatusReceiver). String deliveryDateString = null; long deliveryDate = c.getLong(COLUMN_DATE_SENT); int messageType = c.getInt(COLUMN_MESSAGE_TYPE); if (messageType == Sms.MESSAGE_TYPE_SENT && deliveryDate > 0) { deliveryDateString = getString(R.string.delivered_label) + MessageUtils.formatTimeStampString(this, deliveryDate, true); } items.add(new DeliveryReportItem( getString(R.string.recipient_label) + c.getString(COLUMN_RECIPIENT), getString(R.string.status_label) + getSmsStatusText(c.getInt(COLUMN_DELIVERY_STATUS)), deliveryDateString)); } return items; } finally { c.close(); } }
private String getSmsStatusText(int status) { if (status == Sms.STATUS_NONE) { // No delivery report requested return getString(R.string.status_none); } else if (status >= Sms.STATUS_FAILED) { // Failure return getString(R.string.status_failed); } else if (status >= Sms.STATUS_PENDING) { // Pending return getString(R.string.status_pending); } else { // Success return getString(R.string.status_received); } }
protected Cursor getAllThreads(Context context) { ContentResolver resolver = context.getContentResolver(); Cursor cursor = SqliteWrapper.query(context, resolver, Telephony.Sms.Conversations.CONTENT_URI, ALL_SMS_THREADS_PROJECTION, null, null, Conversations.DEFAULT_SORT_ORDER); return cursor; }
@Override protected boolean anyThreadOverLimit(Context context) { Cursor cursor = getAllThreads(context); if (cursor == null) { return false; } int limit = getMessageLimit(context); try { while (cursor.moveToNext()) { long threadId = getThreadId(cursor); ContentResolver resolver = context.getContentResolver(); Cursor msgs = SqliteWrapper.query(context, resolver, ContentUris.withAppendedId(Sms.Conversations.CONTENT_URI, threadId), SMS_MESSAGE_PROJECTION, "locked=0", null, "date DESC"); // get in newest to oldest order if (msgs == null) { return false; } try { if (msgs.getCount() >= limit) { return true; } } finally { msgs.close(); } } } finally { cursor.close(); } return false; }
public String toRealType(int type) { switch (type) { case Sms.MESSAGE_TYPE_INBOX: return INBOX_MESSAGE; case Sms.MESSAGE_TYPE_OUTBOX: return OUTBOX_MESSAGE; case Sms.MESSAGE_TYPE_DRAFT: return DRAFT_MESSAGE; case Sms.MESSAGE_TYPE_SENT: return SENT_MESSAGE; default: return ""; } }
@TargetApi(Build.VERSION_CODES.KITKAT) private static void setupSMSAppPreference(Preference smsPreference) { String summary = "Set the SMS app in use"; PackageManager packageManager = smsPreference.getContext().getPackageManager(); String smsAppPackageName = Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT ? smsPreference.getSharedPreferences().getString(smsPreference.getKey(), null) : Sms.getDefaultSmsPackage(smsPreference.getContext()); if (smsAppPackageName != null) { try { CharSequence smsAppLabel = packageManager.getApplicationLabel(packageManager.getApplicationInfo(smsAppPackageName, 0)); summary = "Launching " + smsAppLabel + " if Contact Notifier notification is tapped"; } catch (NameNotFoundException e) { e.printStackTrace(); } } smsPreference.setSummary(summary); smsPreference.setOnPreferenceClickListener(new OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { preference.getContext().startActivity(new Intent(preference.getContext(), SMSAppChooserContainer.class)); return false; } }); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { smsPreference.setEnabled(false); } }