Android providers的源代码结构如下:

android-2.2-froyo/ com/ android/ providers:

  • [applications]
  • [calendar]
  • [contacts]
  • [downloads]
  • [drm]
  • [media]
  • [settings]
  • [telephony]
  • [userdictionary]

本篇来解析一下telephony这个provider中的代码,首先来看一下它的目录结构:

android-2.2-froyo/ com/ android/ providers/ telephony:

  • MmsProvider.java
  • MmsSmsDatabaseHelper.java
  • MmsSmsProvider.java
  • SmsProvider.java
  • TelephonyProvider.java
  • Telephony.java (隐藏类,在Android 的source源代码中可以找到,如:sources\android-14\android\provider\Telephony.java)

以上6个类可以划分为3类:

第一类:数据库管理工具类 (A helper class to manage database),包括:MmsSmsDatabaseHelper.java

第二类:与电话操作相关数据类,包括:Telephony,它是个特殊的类,隐藏类

第三类:内容提供者 (ContentProvider),包括:MmsProvider.java、SmsProvider.java、MmsSmsProvider.java、TelephonyProvider.java,它们都继承于ContentProvider。

下面分别讲解一下以上三大类别的代码:

一、MmsSmsDatabaseHelper.java

由于它的代码有2828行,不宜贴出,这里抽取几个重要变量和方法来解析一下,

public class MmsSmsDatabaseHelper extends SQLiteOpenHelper 说明它是作为数据库管理工具类,

    static final String DATABASE_NAME = "mmssms.db";    /// M: Code analyze 006, unknown, for database upgrade.    static final int DATABASE_VERSION = 560000;

这里定义了数据库的名称和初始化版本。

/// M: Add for ip message @{    // this need be the first because it is used by later final consts.    private static final String UPDATE_THREAD_READ_COUNT =            "  UPDATE threads SET readcount = " +            "  (SELECT count(_id)FROM " +            "  (SELECT DISTINCT date * 1 AS normalized_date, _id, read FROM sms " +            "    WHERE ((read=1) AND thread_id = new.thread_id AND (type != 3)) " +            "  UNION SELECT DISTINCT date * 1000 AS normalized_date, pdu._id, read " +            "  FROM pdu LEFT JOIN pending_msgs ON pdu._id = pending_msgs.msg_id " +            "  WHERE ((read=1) AND thread_id = new.thread_id AND msg_box != 3 AND (msg_box != 3 " +            "        AND (m_type = 128 OR m_type = 132 OR m_type = 130)))" +            "   UNION SELECT DISTINCT date * 1 AS normalized_date, _id, read FROM cellbroadcast " +            "   WHERE ((read=1) AND thread_id = new.thread_id) ORDER BY normalized_date ASC))  " +            "  WHERE threads._id = new.thread_id; ";

其中还定义了类似的数据库语句的final型变量,如:UPDATE_THREAD_READ_COUNT_OLD、SMS_UPDATE_THREAD_READ_BODY、UPDATE_THREAD_COUNT_ON_NEW、UPDATE_THREAD_COUNT_ON_OLD、SMS_UPDATE_THREAD_DATE_SNIPPET_COUNT_ON_UPDATE等。

二、Telephony.java

The Telephony provider contains data related to phone operation.

该类的outline:

该类中定义了几个非常重要的内部类,在MmsProvider,SmsProvider,MmsSmsProvider中会用到。

1、接口 TextBasedSmsColumns:Base columns for tables that contain text based SMSs.

2、接口 BaseMmsColumns :Base columns for tables that contain MMSs.

public interface BaseMmsColumns extends BaseColumns 它继承BaseColumns这个接口。

3、接口 CanonicalAddressesColumns :Columns for the "canonical_addresses" table used by MMS and
* SMS."

public interface CanonicalAddressesColumns extends BaseColumns。

4、接口 ThreadsColumns :Columns for the "threads" table used by MMS and SMS.

public interface ThreadsColumns extends BaseColumns.

5、类 Sms:

类结构截图

Sms中定义了6个内部类,

代码:

/**     * Contains all text based SMS messages.     */    public static final class Sms implements BaseColumns, TextBasedSmsColumns {        public static final Cursor query(ContentResolver cr, String[] projection) {            return cr.query(CONTENT_URI, projection, null, null, DEFAULT_SORT_ORDER);        }        public static final Cursor query(ContentResolver cr, String[] projection,                String where, String orderBy) {            return cr.query(CONTENT_URI, projection, where,                                         null, orderBy == null ? DEFAULT_SORT_ORDER : orderBy);        }        /**         * The content:// style URL for this table         */        public static final Uri CONTENT_URI =            Uri.parse("content://sms");        /**         * The default sort order for this table         */        public static final String DEFAULT_SORT_ORDER = "date DESC";        /**         * Add an SMS to the given URI.         *         * @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 psuedo-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         * @return the URI for the new message         */        public static Uri addMessageToUri(ContentResolver resolver,                Uri uri, String address, String body, String subject,                Long date, boolean read, boolean deliveryReport) {            return addMessageToUri(resolver, uri, address, body, subject,                    date, read, deliveryReport, -1L);        }        /**         * Add an SMS to the given URI with thread_id specified.         *         * @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 psuedo-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         */        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(ADDRESS, address);            if (date != null) {                values.put(DATE, date);            }            values.put(READ, read ? Integer.valueOf(1) : Integer.valueOf(0));            values.put(SUBJECT, subject);            values.put(BODY, body);            if (deliveryReport) {                values.put(STATUS, STATUS_PENDING);            }            if (threadId != -1L) {                values.put(THREAD_ID, threadId);            }            return resolver.insert(uri, values);        }        /**         * Move a message to the given folder.         *         * @param context the context to use         * @param uri the message to move         * @param folder the folder to move to         * @return true if the operation succeeded         */        public static boolean moveMessageToFolder(Context context,                Uri uri, int folder, int error) {            if (uri == null) {                return false;            }            boolean markAsUnread = false;            boolean markAsRead = false;            switch(folder) {            case MESSAGE_TYPE_INBOX:            case MESSAGE_TYPE_DRAFT:                break;            case MESSAGE_TYPE_OUTBOX:            case MESSAGE_TYPE_SENT:                markAsRead = true;                break;            case MESSAGE_TYPE_FAILED:            case MESSAGE_TYPE_QUEUED:                markAsUnread = true;                break;            default:                return false;            }            ContentValues values = new ContentValues(3);            values.put(TYPE, folder);            if (markAsUnread) {                values.put(READ, Integer.valueOf(0));            } else if (markAsRead) {                values.put(READ, Integer.valueOf(1));            }            values.put(ERROR_CODE, error);            return 1 == SqliteWrapper.update(context, context.getContentResolver(),                            uri, values, null, null);        }        /**         * Returns true iff the folder (message type) identifies an         * outgoing message.         */        public static boolean isOutgoingFolder(int messageType) {            return  (messageType == MESSAGE_TYPE_FAILED)                    || (messageType == MESSAGE_TYPE_OUTBOX)                    || (messageType == MESSAGE_TYPE_SENT)                    || (messageType == MESSAGE_TYPE_QUEUED);        }        /**         * Contains all text based SMS messages in the SMS app's inbox.         */        public static final class Inbox implements BaseColumns, TextBasedSmsColumns {            /**             * The content:// style URL for this table             */            public static final Uri CONTENT_URI =                Uri.parse("content://sms/inbox");            /**             * The default sort order for this table             */            public static final String DEFAULT_SORT_ORDER = "date DESC";            /**             * Add an SMS to the Draft box.             *             * @param resolver the content resolver to use             * @param address the address of the sender             * @param body the body of the message             * @param subject the psuedo-subject of the message             * @param date the timestamp for the message             * @param read true if the message has been read, false if not             * @return the URI for the new message             */            public static Uri addMessage(ContentResolver resolver,                    String address, String body, String subject, Long date,                    boolean read) {                return addMessageToUri(resolver, CONTENT_URI, address, body,                        subject, date, read, false);            }        }        /**         * Contains all sent text based SMS messages in the SMS app's.         */        public static final class Sent implements BaseColumns, TextBasedSmsColumns {            /**             * The content:// style URL for this table             */            public static final Uri CONTENT_URI =                    Uri.parse("content://sms/sent");            /**             * The default sort order for this table             */            public static final String DEFAULT_SORT_ORDER = "date DESC";            /**             * Add an SMS to the Draft box.             *             * @param resolver the content resolver to use             * @param address the address of the sender             * @param body the body of the message             * @param subject the psuedo-subject of the message             * @param date the timestamp for the message             * @return the URI for the new message             */            public static Uri addMessage(ContentResolver resolver,                    String address, String body, String subject, Long date) {                return addMessageToUri(resolver, CONTENT_URI, address, body,                        subject, date, true, false);            }        }        /**         * Contains all sent text based SMS messages in the SMS app's.         */        public static final class Draft implements BaseColumns, TextBasedSmsColumns {            /**             * The content:// style URL for this table             */            public static final Uri CONTENT_URI =                    Uri.parse("content://sms/draft");            /**             * The default sort order for this table             */            public static final String DEFAULT_SORT_ORDER = "date DESC";            /**             * Add an SMS to the Draft box.             *             * @param resolver the content resolver to use             * @param address the address of the sender             * @param body the body of the message             * @param subject the psuedo-subject of the message             * @param date the timestamp for the message             * @return the URI for the new message             */            public static Uri addMessage(ContentResolver resolver,                    String address, String body, String subject, Long date) {                return addMessageToUri(resolver, CONTENT_URI, address, body,                        subject, date, true, false);            }            /**             * Save over an existing draft message.             *             * @param resolver the content resolver to use             * @param uri of existing message             * @param body the new body for the draft message             * @return true is successful, false otherwise             */            public static boolean saveMessage(ContentResolver resolver,                    Uri uri, String body) {                ContentValues values = new ContentValues(2);                values.put(BODY, body);                values.put(DATE, System.currentTimeMillis());                return resolver.update(uri, values, null, null) == 1;            }        }        /**         * Contains all pending outgoing text based SMS messages.         */        public static final class Outbox implements BaseColumns, TextBasedSmsColumns {            /**             * The content:// style URL for this table             */            public static final Uri CONTENT_URI =                Uri.parse("content://sms/outbox");            /**             * The default sort order for this table             */            public static final String DEFAULT_SORT_ORDER = "date DESC";            /**             * Add an SMS to the Out box.             *             * @param resolver the content resolver to use             * @param address the address of the sender             * @param body the body of the message             * @param subject the psuedo-subject of the message             * @param date the timestamp for the message             * @param deliveryReport whether a delivery report was requested for the message             * @return the URI for the new message             */            public static Uri addMessage(ContentResolver resolver,                    String address, String body, String subject, Long date,                    boolean deliveryReport, long threadId) {                return addMessageToUri(resolver, CONTENT_URI, address, body,                        subject, date, true, deliveryReport, threadId);            }        }        /**         * Contains all sent text-based SMS messages in the SMS app's.         */        public static final class Conversations                implements BaseColumns, TextBasedSmsColumns {            /**             * The content:// style URL for this table             */            public static final Uri CONTENT_URI =                Uri.parse("content://sms/conversations");            /**             * The default sort order for this table             */            public static final String DEFAULT_SORT_ORDER = "date DESC";            /**             * The first 45 characters of the body of the message             * <P>Type: TEXT</P>             */            public static final String SNIPPET = "snippet";            /**             * The number of messages in the conversation             * <P>Type: INTEGER</P>             */            public static final String MESSAGE_COUNT = "msg_count";        }        /**         * Contains info about SMS related Intents that are broadcast.         */        public static final class Intents {            /**             * Set by BroadcastReceiver. Indicates the message was handled             * successfully.             */            public static final int RESULT_SMS_HANDLED = 1;            /**             * Set by BroadcastReceiver. Indicates a generic error while             * processing the message.             */            public static final int RESULT_SMS_GENERIC_ERROR = 2;            /**             * Set by BroadcastReceiver. Indicates insufficient memory to store             * the message.             */            public static final int RESULT_SMS_OUT_OF_MEMORY = 3;            /**             * Set by BroadcastReceiver. Indicates the message, while             * possibly valid, is of a format or encoding that is not             * supported.             */            public static final int RESULT_SMS_UNSUPPORTED = 4;            /**             * Broadcast Action: A new text based SMS message has been received             * by the device. The intent will have the following extra             * values:</p>             *             * <ul>             *   <li><em>pdus</em> - An Object[] od byte[]s containing the PDUs             *   that make up the message.</li>             * </ul>             *             * <p>The extra values can be extracted using             * {@link #getMessagesFromIntent(Intent)}.</p>             *             * <p>If a BroadcastReceiver encounters an error while processing             * this intent it should set the result code appropriately.</p>             */            @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)            public static final String SMS_RECEIVED_ACTION =                    "android.provider.Telephony.SMS_RECEIVED";            /**             * Broadcast Action: A new data based SMS message has been received             * by the device. The intent will have the following extra             * values:</p>             *             * <ul>             *   <li><em>pdus</em> - An Object[] of byte[]s containing the PDUs             *   that make up the message.</li>             * </ul>             *             * <p>The extra values can be extracted using             * {@link #getMessagesFromIntent(Intent)}.</p>             *             * <p>If a BroadcastReceiver encounters an error while processing             * this intent it should set the result code appropriately.</p>             */            @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)            public static final String DATA_SMS_RECEIVED_ACTION =                    "android.intent.action.DATA_SMS_RECEIVED";            /**             * Broadcast Action: A new WAP PUSH message has been received by the             * device. The intent will have the following extra             * values:</p>             *             * <ul>             *   <li><em>transactionId (Integer)</em> - The WAP transaction ID</li>             *   <li><em>pduType (Integer)</em> - The WAP PDU type</li>             *   <li><em>header (byte[])</em> - The header of the message</li>             *   <li><em>data (byte[])</em> - The data payload of the message</li>             *   <li><em>contentTypeParameters (HashMap<String,String>)</em>             *   - Any parameters associated with the content type             *   (decoded from the WSP Content-Type header)</li>             * </ul>             *             * <p>If a BroadcastReceiver encounters an error while processing             * this intent it should set the result code appropriately.</p>             *             * <p>The contentTypeParameters extra value is map of content parameters keyed by             * their names.</p>             *             * <p>If any unassigned well-known parameters are encountered, the key of the map will             * be 'unassigned/0x...', where '...' is the hex value of the unassigned parameter.  If             * a parameter has No-Value the value in the map will be null.</p>             */            @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)            public static final String WAP_PUSH_RECEIVED_ACTION =                    "android.provider.Telephony.WAP_PUSH_RECEIVED";            /**             * Broadcast Action: A new Cell Broadcast message has been received             * by the device. The intent will have the following extra             * values:</p>             *             * <ul>             *   <li><em>pdus</em> - An Object[] of byte[]s containing the PDUs             *   that make up the message.</li>             * </ul>             *             * <p>The extra values can be extracted using             * {@link #getMessagesFromIntent(Intent)}.</p>             *             * <p>If a BroadcastReceiver encounters an error while processing             * this intent it should set the result code appropriately.</p>             */            @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)            public static final String SMS_CB_RECEIVED_ACTION =                    "android.provider.Telephony.SMS_CB_RECEIVED";            /**             * Broadcast Action: A new Emergency Broadcast message has been received             * by the device. The intent will have the following extra             * values:</p>             *             * <ul>             *   <li><em>pdus</em> - An Object[] of byte[]s containing the PDUs             *   that make up the message.</li>             * </ul>             *             * <p>The extra values can be extracted using             * {@link #getMessagesFromIntent(Intent)}.</p>             *             * <p>If a BroadcastReceiver encounters an error while processing             * this intent it should set the result code appropriately.</p>             */            @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)            public static final String SMS_EMERGENCY_CB_RECEIVED_ACTION =                    "android.provider.Telephony.SMS_EMERGENCY_CB_RECEIVED";            /**             * Broadcast Action: The SIM storage for SMS messages is full.  If             * space is not freed, messages targeted for the SIM (class 2) may             * not be saved.             */            @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)            public static final String SIM_FULL_ACTION =                    "android.provider.Telephony.SIM_FULL";            /**             * Broadcast Action: An incoming SMS has been rejected by the             * telephony framework.  This intent is sent in lieu of any             * of the RECEIVED_ACTION intents.  The intent will have the             * following extra value:</p>             *             * <ul>             *   <li><em>result</em> - An int result code, eg,             *   <code>{@link #RESULT_SMS_OUT_OF_MEMORY}</code>,             *   indicating the error returned to the network.</li>             * </ul>             */            @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)            public static final String SMS_REJECTED_ACTION =                "android.provider.Telephony.SMS_REJECTED";            /**             * Read the PDUs out of an {@link #SMS_RECEIVED_ACTION} or a             * {@link #DATA_SMS_RECEIVED_ACTION} intent.             *             * @param intent the intent to read from             * @return an array of SmsMessages for the PDUs             */            public static SmsMessage[] getMessagesFromIntent(                    Intent intent) {                Object[] messages = (Object[]) intent.getSerializableExtra("pdus");                String format = intent.getStringExtra("format");                byte[][] pduObjs = new byte[messages.length][];                for (int i = 0; i < messages.length; i++) {                    pduObjs[i] = (byte[]) messages[i];                }                byte[][] pdus = new byte[pduObjs.length][];                int pduCount = pdus.length;                SmsMessage[] msgs = new SmsMessage[pduCount];                for (int i = 0; i < pduCount; i++) {                    pdus[i] = pduObjs[i];                    msgs[i] = SmsMessage.createFromPdu(pdus[i], format);                }                return msgs;            }        }    }


Inbox类:

public static final class Inbox implements BaseColumns, TextBasedSmsColumns {            /**             * The content:// style URL for this table             */            public static final Uri CONTENT_URI =                Uri.parse("content://sms/inbox");
}

类似的还有Sent、Draft、Outbox、Conversations这几个都implements BaseMmsColumns,跟Inbox不一样。

BaseMmsColumns的代码:

public interface BaseMmsColumns extends BaseColumns {        public static final int MESSAGE_BOX_ALL    = 0;        public static final int MESSAGE_BOX_INBOX  = 1;        public static final int MESSAGE_BOX_SENT   = 2;        public static final int MESSAGE_BOX_DRAFTS = 3;        public static final int MESSAGE_BOX_OUTBOX = 4;


原来它是继承BaseColumns,在它基础上加了些变量。

1、Sms类:

/**     * Contains all MMS and SMS messages.     */    public static final class MmsSms implements BaseColumns {        /**         * The column to distinguish SMS & MMS messages in query results.         */        public static final String TYPE_DISCRIMINATOR_COLUMN =                "transport_type";        public static final Uri CONTENT_URI = Uri.parse("content://mms-sms/");        public static final Uri CONTENT_CONVERSATIONS_URI = Uri.parse(                "content://mms-sms/conversations");        public static final Uri CONTENT_FILTER_BYPHONE_URI = Uri.parse(                "content://mms-sms/messages/byphone");        public static final Uri CONTENT_UNDELIVERED_URI = Uri.parse(                "content://mms-sms/undelivered");        public static final Uri CONTENT_DRAFT_URI = Uri.parse(                "content://mms-sms/draft");        public static final Uri CONTENT_LOCKED_URI = Uri.parse(                "content://mms-sms/locked");        /***         * Pass in a query parameter called "pattern" which is the text         * to search for.         * The sort order is fixed to be thread_id ASC,date DESC.         */        public static final Uri SEARCH_URI = Uri.parse(                "content://mms-sms/search");        // Constants for message protocol types.        public static final int SMS_PROTO = 0;        public static final int MMS_PROTO = 1;        // Constants for error types of pending messages.        public static final int NO_ERROR                      = 0;        public static final int ERR_TYPE_GENERIC              = 1;        public static final int ERR_TYPE_SMS_PROTO_TRANSIENT  = 2;        public static final int ERR_TYPE_MMS_PROTO_TRANSIENT  = 3;        public static final int ERR_TYPE_TRANSPORT_FAILURE    = 4;        public static final int ERR_TYPE_GENERIC_PERMANENT    = 10;        public static final int ERR_TYPE_SMS_PROTO_PERMANENT  = 11;        public static final int ERR_TYPE_MMS_PROTO_PERMANENT  = 12;        public static final class PendingMessages implements BaseColumns {            public static final Uri CONTENT_URI = Uri.withAppendedPath(                    MmsSms.CONTENT_URI, "pending");            /**             * The type of transport protocol(MMS or SMS).             * <P>Type: INTEGER</P>             */            public static final String PROTO_TYPE = "proto_type";            /**             * The ID of the message to be sent or downloaded.             * <P>Type: INTEGER</P>             */            public static final String MSG_ID = "msg_id";            /**             * The type of the message to be sent or downloaded.             * This field is only valid for MM. For SM, its value is always             * set to 0.             */            public static final String MSG_TYPE = "msg_type";            /**             * The type of the error code.             * <P>Type: INTEGER</P>             */            public static final String ERROR_TYPE = "err_type";            /**             * The error code of sending/retrieving process.             * <P>Type:  INTEGER</P>             */            public static final String ERROR_CODE = "err_code";            /**             * How many times we tried to send or download the message.             * <P>Type:  INTEGER</P>             */            public static final String RETRY_INDEX = "retry_index";            /**             * The time to do next retry.             */            public static final String DUE_TIME = "due_time";            /**             * The time we last tried to send or download the message.             */            public static final String LAST_TRY = "last_try";        }        public static final class WordsTable {            public static final String ID = "_id";            public static final String SOURCE_ROW_ID = "source_id";            public static final String TABLE_ID = "table_to_use";            public static final String INDEXED_TEXT = "index_text";        }    }


2、Mms类:

/**     * Contains all MMS messages.     */    public static final class Mms implements BaseMmsColumns {        /**         * The content:// style URL for this table         */        public static final Uri CONTENT_URI = Uri.parse("content://mms");        public static final Uri REPORT_REQUEST_URI = Uri.withAppendedPath(                                            CONTENT_URI, "report-request");        public static final Uri REPORT_STATUS_URI = Uri.withAppendedPath(                                            CONTENT_URI, "report-status");        /**         * The default sort order for this table         */        public static final String DEFAULT_SORT_ORDER = "date DESC";        /**         * mailbox         =       name-addr         * name-addr       =       [display-name] angle-addr         * angle-addr      =       [CFWS] "<" addr-spec ">" [CFWS]         */        public static final Pattern NAME_ADDR_EMAIL_PATTERN =                Pattern.compile("\\s*(\"[^\"]*\"|[^<>\"]+)\\s*<([^<>]+)>\\s*");        /**         * quoted-string   =       [CFWS]         *                         DQUOTE *([FWS] qcontent) [FWS] DQUOTE         *                         [CFWS]         */        public static final Pattern QUOTED_STRING_PATTERN =                Pattern.compile("\\s*\"([^\"]*)\"\\s*");        public static final Cursor query(                ContentResolver cr, String[] projection) {            return cr.query(CONTENT_URI, projection, null, null, DEFAULT_SORT_ORDER);        }        public static final Cursor query(                ContentResolver cr, String[] projection,                String where, String orderBy) {            return cr.query(CONTENT_URI, projection,                    where, null, orderBy == null ? DEFAULT_SORT_ORDER : orderBy);        }        public static final String getMessageBoxName(int msgBox) {            switch (msgBox) {                case MESSAGE_BOX_ALL:                    return "all";                case MESSAGE_BOX_INBOX:                    return "inbox";                case MESSAGE_BOX_SENT:                    return "sent";                case MESSAGE_BOX_DRAFTS:                    return "drafts";                case MESSAGE_BOX_OUTBOX:                    return "outbox";                default:                    throw new IllegalArgumentException("Invalid message box: " + msgBox);            }        }        public static String extractAddrSpec(String address) {            Matcher match = NAME_ADDR_EMAIL_PATTERN.matcher(address);            if (match.matches()) {                return match.group(2);            }            return address;        }        /**         * Returns true if the address is an email address         *         * @param address the input address to be tested         * @return true if address is an email address         */        public static boolean isEmailAddress(String address) {            if (TextUtils.isEmpty(address)) {                return false;            }            String s = extractAddrSpec(address);            Matcher match = Patterns.EMAIL_ADDRESS.matcher(s);            return match.matches();        }        /**         * Returns true if the number is a Phone number         *         * @param number the input number to be tested         * @return true if number is a Phone number         */        public static boolean isPhoneNumber(String number) {            if (TextUtils.isEmpty(number)) {                return false;            }            Matcher match = Patterns.PHONE.matcher(number);            return match.matches();        }        /**         * Contains all MMS messages in the MMS app's inbox.         */        public static final class Inbox implements BaseMmsColumns {            /**             * The content:// style URL for this table             */            public static final Uri                    CONTENT_URI = Uri.parse("content://mms/inbox");            /**             * The default sort order for this table             */            public static final String DEFAULT_SORT_ORDER = "date DESC";        }        /**         * Contains all MMS messages in the MMS app's sent box.         */        public static final class Sent implements BaseMmsColumns {            /**             * The content:// style URL for this table             */            public static final Uri                    CONTENT_URI = Uri.parse("content://mms/sent");            /**             * The default sort order for this table             */            public static final String DEFAULT_SORT_ORDER = "date DESC";        }        /**         * Contains all MMS messages in the MMS app's drafts box.         */        public static final class Draft implements BaseMmsColumns {            /**             * The content:// style URL for this table             */            public static final Uri                    CONTENT_URI = Uri.parse("content://mms/drafts");            /**             * The default sort order for this table             */            public static final String DEFAULT_SORT_ORDER = "date DESC";        }        /**         * Contains all MMS messages in the MMS app's outbox.         */        public static final class Outbox implements BaseMmsColumns {            /**             * The content:// style URL for this table             */            public static final Uri                    CONTENT_URI = Uri.parse("content://mms/outbox");            /**             * The default sort order for this table             */            public static final String DEFAULT_SORT_ORDER = "date DESC";        }        public static final class Addr implements BaseColumns {            /**             * The ID of MM which this address entry belongs to.             */            public static final String MSG_ID = "msg_id";            /**             * The ID of contact entry in Phone Book.             */            public static final String CONTACT_ID = "contact_id";            /**             * The address text.             */            public static final String ADDRESS = "address";            /**             * Type of address, must be one of PduHeaders.BCC,             * PduHeaders.CC, PduHeaders.FROM, PduHeaders.TO.             */            public static final String TYPE = "type";            /**             * Character set of this entry.             */            public static final String CHARSET = "charset";        }        public static final class Part implements BaseColumns {            /**             * The identifier of the message which this part belongs to.             * <P>Type: INTEGER</P>             */            public static final String MSG_ID = "mid";            /**             * The order of the part.             * <P>Type: INTEGER</P>             */            public static final String SEQ = "seq";            /**             * The content type of the part.             * <P>Type: TEXT</P>             */            public static final String CONTENT_TYPE = "ct";            /**             * The name of the part.             * <P>Type: TEXT</P>             */            public static final String NAME = "name";            /**             * The charset of the part.             * <P>Type: TEXT</P>             */            public static final String CHARSET = "chset";            /**             * The file name of the part.             * <P>Type: TEXT</P>             */            public static final String FILENAME = "fn";            /**             * The content disposition of the part.             * <P>Type: TEXT</P>             */            public static final String CONTENT_DISPOSITION = "cd";            /**             * The content ID of the part.             * <P>Type: INTEGER</P>             */            public static final String CONTENT_ID = "cid";            /**             * The content location of the part.             * <P>Type: INTEGER</P>             */            public static final String CONTENT_LOCATION = "cl";            /**             * The start of content-type of the message.             * <P>Type: INTEGER</P>             */            public static final String CT_START = "ctt_s";            /**             * The type of content-type of the message.             * <P>Type: TEXT</P>             */            public static final String CT_TYPE = "ctt_t";            /**             * The location(on filesystem) of the binary data of the part.             * <P>Type: INTEGER</P>             */            public static final String _DATA = "_data";            public static final String TEXT = "text";        }        public static final class Rate {            public static final Uri CONTENT_URI = Uri.withAppendedPath(                    Mms.CONTENT_URI, "rate");            /**             * When a message was successfully sent.             * <P>Type: INTEGER</P>             */            public static final String SENT_TIME = "sent_time";        }        public static final class Intents {            private Intents() {                // Non-instantiatable.            }            /**             * The extra field to store the contents of the Intent,             * which should be an array of Uri.             */            public static final String EXTRA_CONTENTS = "contents";            /**             * The extra field to store the type of the contents,             * which should be an array of String.             */            public static final String EXTRA_TYPES    = "types";            /**             * The extra field to store the 'Cc' addresses.             */            public static final String EXTRA_CC       = "cc";            /**             * The extra field to store the 'Bcc' addresses;             */            public static final String EXTRA_BCC      = "bcc";            /**             * The extra field to store the 'Subject'.             */            public static final String EXTRA_SUBJECT  = "subject";            /**             * Indicates that the contents of specified URIs were changed.             * The application which is showing or caching these contents             * should be updated.             */            public static final String            CONTENT_CHANGED_ACTION = "android.intent.action.CONTENT_CHANGED";            /**             * An extra field which stores the URI of deleted contents.             */            public static final String DELETED_CONTENTS = "deleted_contents";        }    }



三、SmsProvider.java

The class to provide base facility to access MMS related content, which is stored in a SQLite database and in the file system.

短信的uri以content://sms开头。

可以使用Telephony中的Sms类提供的公共变量进行构造Uri,甚至使用其中提供的一些addMessage(将信息存入各个不同的信箱)、saveMessage(更新已存在的草稿)、addMessageToUri(插入数据到指定Uri)、moveMessageToFolder(将信息移到某一信箱)方法简化操作。

UriMatcher中配置了27种类型:

AUTHORITY

PATH

类型

说明

sms

SMS_ALL

所有短信

sms

#

SMS_ALL_ID

指定了_id的短信

sms

inbox

SMS_INBOX

位于收件箱的短信

sms

inbox/#

SMS_INBOX_ID

位于收件箱的指定了_id的短信

sms

sent

SMS_SENT

已成功发送出去的短信

sms

sent/#

SMS_SENT_ID

已成功发送出去的指定了_id的短信

sms

draft

SMS_DRAFT

位于草稿箱的短信

sms

draft

SMS_DRAFT_ID

位于草稿箱的指定了_id的短信

sms

outbox

SMS_OUTBOX

已从队列中取出进行处理但未成功发送出去的短信

sms

outbox/#

SMS_OUTBOX_ID

已从队列中取出进行处理但未成功发送出去的指定了_id的短信

sms

undelivered

SMS_UNDELIVERED

未成功发送出去的短信(包括发送失败、草稿、队列中的)

sms

failed

SMS_FAILED

发送失败的短信

sms

failed/#

SMS_FAILED_ID

发送失败的指定了_id的短信

sms

queued

SMS_QUEUED

队列中的短信

sms

conversations

SMS_CONVERSATIONS

所有会话包含的短信数量、内容、会话id

sms

conversations/*

SMS_CONVERSATIONS_ID

指定会话id的短信

sms

raw

SMS_RAW_MESSAGE

raw表中的短信(临时短信,用于接收长短信时使用)

sms

attachments

SMS_ATTACHMENT

往attachments表中插入或查询信息

sms

attachments/#

SMS_ATTACHMENT_ID

从attachments表中查询指定sms_id的信息

sms

threadID

SMS_NEW_THREAD_ID

往canonical_addresses表中插入信息

sms

threadID/*

SMS_QUERY_THREAD_ID

查询canonical_addresses中所有信息

sms

status/#

SMS_STATUS_ID

查询或更新指定id的短信(没有什么特殊功能,有可能没用上)

sms

sr_pending

SMS_STATUS_PENDING

对sr_pending表进行操作时用的

sms

icc

SMS_ALL_ICC

所有存在SIM/UIM卡上的短信

sms

icc/#

SMS_ICC

指定id的存在SIM/UIM卡上的短信

sms

sim

SMS_ALL_ICC

所有存在SIM/UIM卡上的短信

sms

sim/#

SMS_ICC

指定id的存在SIM/UIM卡上的短信

作者:wulianghuan 发表于2013-5-8 21:21:50 原文链接 阅读:20 评论:0 查看评论

更多相关文章

  1. android发送post请求出现问题
  2. Android在MTP模式下,只显示指定文件夹
  3. Android调用系统短信发送界面并预设接收号码、短信内容
  4. 关于android中shape的使用
  5. 'xlargeScreens' in package 'android'
  6. Android(安卓)bluetooth介绍(四): a2dp connect流程分析
  7. android打电话发短信
  8. Android(安卓)命令行编译、打包生成apk文件
  9. Android(安卓)开发中的倒计时

随机推荐

  1. Android 首选网络模式默认值的修改方法
  2. Android: 触屏fling/scroll/drag的区别及
  3. android studio每次启动都要在fetching A
  4. Android——四大组件、六大布局、五大存
  5. 自定义ListView分割线
  6. Android事件分发机制完全解析(二)
  7. Android基础学习【历史流程重走】 ---- A
  8. achartengine(Google给android提供的绘图
  9. Android添加自定义系统服务
  10. Android开发Tips(3)