Android解析短信信息

来源:互联网 发布:linux ip限制 编辑:程序博客网 时间:2024/06/04 08:31

最近做项目要解析手机中短信,获取短信有两种方式:一种是通过广播另一种就是通过数据库,由于项目需要我选择的是第二种方式,检索数据库来获取短信信息并且进行解析指定内容的短信。

在做任何一个新的功能的时候,我们首先查阅一下相关的知识,然后看看有没有相关的demo,最后建议反过来看Android应用层源码,看看它里面的一些常量的定义,建议使用高版本的api,你不一定能够使用它,但是它会给你指出一些思路,就拿短信这个功能为例:

既然我们要获取短信的信息,那就要只要它的各个组成部分,我们进入到android.jar里面中的android.provider.Telephony,我们可以看到Sms的相关的属性。如果你调用这里面的内容的话,会提示Field requires API level 19 (current min is ),但是这并不妨碍我们去模仿他, 我的需要是要检索收件箱,所以搜索数据库的时候,我只需要搜索收件箱里面的短信,在Telephony中TextBasedSmsColumns接口里面Message type根据需要我选择的是MESSAGE_TYPE_INBOX,接下来我们看一下Sms这个接口:

/**     * Contains all text-based SMS messages.     */    public static final class Sms implements BaseColumns, TextBasedSmsColumns {        /**         * Not instantiable.         * @hide         */        private Sms() {        }        /**         * Used to determine the currently configured default SMS package.         * @param context context of the requesting application         * @return package name for the default SMS package or null         */        public static String getDefaultSmsPackage(Context context) {            ComponentName component = SmsApplication.getDefaultSmsApplication(context, false);            if (component != null) {                return component.getPackageName();            }            return null;        }        /**         * Return cursor for table query.         * @hide         */        public static Cursor query(ContentResolver cr, String[] projection) {            return cr.query(CONTENT_URI, projection, null, null, DEFAULT_SORT_ORDER);        }        /**         * Return cursor for table query.         * @hide         */        public static 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 {@code 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 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         * @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) {            return addMessageToUri(resolver, uri, address, body, subject,                    date, read, deliveryReport, -1L);        }        /**         * 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(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         * @hide         */        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, 0);            } else if (markAsRead) {                values.put(READ, 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.         * @hide         */        public static boolean isOutgoingFolder(int messageType) {            return  (messageType == MESSAGE_TYPE_FAILED)                    || (messageType == MESSAGE_TYPE_OUTBOX)                    || (messageType == MESSAGE_TYPE_SENT)                    || (messageType == MESSAGE_TYPE_QUEUED);        }

里面给出了查询功能和添加功能,由于我只需要查询功能,但是里面public static final Uri CONTENT_URI = Uri.parse("content://sms");说明查询的是所有的短信,而我只要查询收件箱里面的,所以上面这就话改成public static final Uri CONTENT_URI = Uri.parse("content://sms/inbox");把Sms和TextBasedSmsColumns接口的内容拷贝出来分别放在两个接口里面命名自己设置,而Sms里面会有一些报错,有些我们引用了系统不开放的方法,把不相关的代码进行删除,整理后的代码如下:

package com.jwzhangjie.smarttv_client.support.sms1;import android.content.ContentResolver;import android.content.ContentValues;import android.database.Cursor;import android.net.Uri;import android.provider.BaseColumns;public final class Sms implements BaseColumns, TextBasedSmsColumns{ /**     * Not instantiable.     * @hide     */    private Sms() {    }    /**     * Return cursor for table query.     * @hide     */    public static Cursor query(ContentResolver cr, String[] projection) {        return cr.query(CONTENT_URI, projection, null, null, DEFAULT_SORT_ORDER);    }    /**     * Return cursor for table query.     * @hide     */    public static 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 {@code content://} style URL for this table.     *///    public static final Uri CONTENT_URI = Uri.parse("content://sms");    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 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 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     * @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) {        return addMessageToUri(resolver, uri, address, body, subject,                date, read, deliveryReport, -1L);    }    /**     * 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(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);    }    /**     * Returns true iff the folder (message type) identifies an     * outgoing message.     * @hide     */    public static boolean isOutgoingFolder(int messageType) {        return  (messageType == MESSAGE_TYPE_FAILED)                || (messageType == MESSAGE_TYPE_OUTBOX)                || (messageType == MESSAGE_TYPE_SENT)                || (messageType == MESSAGE_TYPE_QUEUED);}}


上面的代码不会有错误,查询功能有了之后,我们还要写一个保存查询出来的内容的类,根据自己的项目编写,例如:

package com.jwzhangjie.smarttv_client.support.sms1;/** * 数据库中sms相关的字段如下:    _id          一个自增字段,从1开始 thread_id    序号,同一发信人的id相同 address      发件人手机号码 person       联系人列表里的序号,陌生人为null date         发件日期 protocol     协议,分为: 0 SMS_RPOTO, 1 MMS_PROTO  read         是否阅读 0未读, 1已读  status       状态 -1接收,0 complete, 64 pending, 128 failed type     ALL    = 0;     INBOX  = 1;     SENT   = 2;     DRAFT  = 3;     OUTBOX = 4;     FAILED = 5;     QUEUED = 6; body                     短信内容 service_center     短信服务中心号码编号 subject                  短信的主题 reply_path_present     TP-Reply-Path locked */import android.os.Parcel;import android.os.Parcelable;/** * 保存短息信息 * @author jwzhangjie * */public class SMSInfo implements Parcelable{@Overridepublic int describeContents() {return 0;}/** * 短信序号 */private long id;/** * 协议 0:SMS_PROTO 短信 1:MMS_PROTO彩信 */private int protocol;/** * 短信内容 */private String smsBody;/** * 发送短息的电话号码 */private String smsPhoneNum;/** * 发送短信的日期和时间 */private String smsDateTime;/** * 发送短信人 */private String smsSender;/** * 短信类型:1是接收到的 2是已发送的 */private int smsType;public SMSInfo(){}private SMSInfo(Parcel source){readFromParcel(source);}public void readFromParcel(Parcel source){id = source.readLong();protocol = source.readInt();smsBody = source.readString();smsPhoneNum = source.readString();smsDateTime = source.readString();smsSender = source.readString();smsType = source.readInt();}@Overridepublic void writeToParcel(Parcel dest, int flags) {dest.writeLong(id);dest.writeInt(protocol);dest.writeString(smsBody);dest.writeString(smsPhoneNum);dest.writeString(smsDateTime);dest.writeString(smsSender);dest.writeInt(smsType);}public static Creator<SMSInfo> CREATOR = new Creator<SMSInfo>() {@Overridepublic SMSInfo createFromParcel(Parcel source) {return new SMSInfo(source);}@Overridepublic SMSInfo[] newArray(int size) {return new SMSInfo[size];}};@Overridepublic String toString() {StringBuilder builder = new StringBuilder();builder.append("id :"+id+"  协议:"+protocol+"  内容:"+smsBody);return builder.toString();}public long getId() {return id;}public void setId(long id) {this.id = id;}public int getProtocol() {return protocol;}public void setProtocol(int protocol) {this.protocol = protocol;}public String getSmsBody() {return smsBody;}public void setSmsBody(String smsBody) {this.smsBody = smsBody;}public String getSmsPhoneNum() {return smsPhoneNum;}public void setSmsPhoneNum(String smsPhoneNum) {this.smsPhoneNum = smsPhoneNum;}public String getSmsDateTime() {return smsDateTime;}public void setSmsDateTime(String smsDateTime) {this.smsDateTime = smsDateTime;}public String getSmsSender() {return smsSender;}public void setSmsSender(String smsSender) {this.smsSender = smsSender;}public int getSmsType() {return smsType;}public void setSmsType(int smsType) {this.smsType = smsType;}}


接下来就是获取数据库内容,我们先看一下查询数据库的方法:

 /**     * Return cursor for table query.     * @hide     */    public static Cursor query(ContentResolver cr, String[] projection,            String where, String orderBy) {        return cr.query(CONTENT_URI, projection, where,                null, orderBy == null ? DEFAULT_SORT_ORDER : orderBy);    }


CONTENT_URI:就是我们上面定义的public static final Uri CONTENT_URI = Uri.parse("content://sms/inbox");

projection:这个可以是null,那就是把所有的列都获取出来,不过不必,你需要什么就获取什么,不然既浪费时间又浪费内存

where:查询条件

orderBy:排序

package com.jwzhangjie.smarttv_client.support.sms1;import java.util.ArrayList;import java.util.List;import android.content.ContentResolver;import android.content.Context;import android.database.Cursor;public class GetSMSInfo {private ContentResolver mResolver;private Context context;private List<SMSInfo> infos;private static final String[] PROJECTION = new String[]{Sms._ID,//0:作为一个标志位,记录最后一个,作为下一次扫描的第一个Sms.TYPE,//1:收还是发Sms.ADDRESS,//2手机号Sms.BODY,//3内容Sms.DATE,//4日期Sms.PROTOCOL//5协议};public static final int COLUMN_INDEX_ID = 0;public static final int COLUMN_INDEX_TYPE  = 1;        public static final int COLUMN_INDEX_PHONE = 2;        public static final int COLUMN_INDEX_BODY  = 3;        public static final int COLUMN_INDEX_DATE = 4;        public static final int COLUMN_INDEX_PROTOCOL = 5;public GetSMSInfo(Context context){this.infos = new ArrayList<SMSInfo>();this.mResolver = context.getContentResolver();this.context = context;}/** * 获取短信各种信息 */public List<SMSInfo> getSmsInfo(){//获取上一次检索的最后一个IDlong last_sms_id = UPSharedPreferences.getLong(context, "card", "last_sms_id", 0);Cursor cursor = Sms.query(mResolver, PROJECTION, "_id >" + last_sms_id, "_id");int protocol;String body, date;if (cursor != null) {while (cursor.moveToNext()) {last_sms_id = cursor.getLong(COLUMN_INDEX_ID);body = cursor.getString(COLUMN_INDEX_BODY);date = cursor.getString(COLUMN_INDEX_DATE);protocol = cursor.getInt(COLUMN_INDEX_PROTOCOL);if (protocol == 0) {//收信息SMSInfo info = new SMSInfo();info.setId(last_sms_id);info.setSmsBody(body);info.setSmsDateTime(date);infos.add(info);}}cursor.close();}//保存当前最新的IDUPSharedPreferences.setLong(context, "card", "last_sms_id", last_sms_id);return infos;}}
读取得所有符合条件的短信都放在List<SMSInfo>里面,然后我们最后解析条件一个一个解析,这个涉及一些私人信息,就不显示效果了。


0 0
原创粉丝点击