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

在做任何一个新的功能的时候,我们首先查阅一下相关的知识,然后看看有没有相关的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>里面,然后我们最后解析条件一个一个解析,这个涉及一些私人信息,就不显示效果了。



Android解析短信信息相关推荐

  1. Android 解决双卡双待手机解析短信异常

    开发中,难免会遇到各种各样的适配问题,尤其是经过深度修改定制过的系统,有的无论是软硬件上都有很大的区别,这里不得不提到一种奇葩的机型,没错,那就是双卡双待的手机(比如XT800, A60, S8600 ...

  2. Android 双卡双待手机解析短信异常分析及解决

    如有转载,请声明出处: 时之沙:http://blog.csdn.net/t12x3456 开发中,难免会遇到各种各样的适配问题,尤其是经过深度修改定制过的系统,有的无论是软硬件上都有很大的区别,这里 ...

  3. Android - xml动画,识别手势动作,代码抽取,获取手机SIM卡串号,获取联系人数据,开机广播,发送/解析短信,报警音乐

    转载请注明出处:https://blog.csdn.net/mythmayor/article/details/72878059 1.Activity的任务栈 1.类似一个木桶,每层只能放一个木块,我 ...

  4. 【Android】短信应用——短信信息实时获取

    我们知道,只需通过代码就可以读到收件箱中的短信,发件箱中的短信:但是却没办法在短信发来的瞬间获取:如果我们在短信发来的一瞬间能得到相应的信息内容,那么我们就可以依次来展开很多应用了--也就是通过短信去 ...

  5. Android中读取短信信息

    Android中读取的短信文件有 /*** 所有的短信*/public static final String SMS_URI_ALL = "content://sms/";/** ...

  6. Android之——短信的备份与还原

    转载请注明出处:http://blog.csdn.net/l1028386804/article/details/47091281 眼下,Android手机中的一些软件能够实现手机短信的备份与还原操作 ...

  7. Android:短信的接收

    短信的接收, 请先看一个 Demo private void initReceiverSms() {tv_content = (TextView) findViewById(R.id.tv_conte ...

  8. Android接收短信

    既然写了发送短信,那么接收短信肯定也是一定要写的了. 接收短信主要是广播的接收,每当Andorid接收到一条新短信时都会产生一个广播,我们的程序通过捕获这个广播,就能获取短信了. 依旧是权限问题:&l ...

  9. android sms 接收短信,Android SMS 短信操作

    android的短信保存在短信库里,但并提供类似Contacts的公开的Content Provider方便操作.这里简单的介绍下:android中的短信信息保存在/data/data/com.and ...

最新文章

  1. ECCV 2020 | PHOSA:一种基于单目图像的人-物重建方法
  2. C语言取字节的第n二进制,学C语言的看过来,最完整进制转换、整数和小数内存存储模型...
  3. (chap8 确认访问用户身份的认证) DIGES认证(摘要认证)
  4. Android keymaster的介绍和总结
  5. ___new__方法和__init__方法的区别
  6. Ubuntu配置静态IP
  7. oc 实例变量可见度、方法
  8. java随机抽题系统_什么样的考试场景需要使用随机试卷模式?
  9. Linux中Shell脚本教程学习
  10. Eclipse 优化
  11. 机甲大师s1 python编程_机甲大师RoboMaster S1教育机器人- DJI 大疆创新
  12. Scrapy爬虫框架,入门案例(非常详细)
  13. ICommand、ITool中调用要素闪烁/定位的方法
  14. 数据结构:串(String)【详解】
  15. 基于Tushare量化分析示例
  16. apk解包工具 安卓_MT管理器最新2.9.3版支持ROOT后安卓10安卓11文件修改替换
  17. Node rar压缩/解压文件
  18. 概论_第8章_假设检验的基本步骤__假设检验的类型
  19. [笔记] GPGPU-SIM的使用说明(一)
  20. 研究下身家1.28万亿的马斯克,只为浇灭你心中创业的小火苗

热门文章

  1. 智慧消防管理系统实现全民消防造福全社会
  2. 软件测试工程师的“薪情”如何
  3. Nginx-Rewrite
  4. 我为什么不是清华的学生
  5. 微软帝国踏上Windows7征途(图)
  6. 一个java面试题:一个农夫养了一头牛,三年后,这头牛每年会生出一头牛,生出来的牛三年后又可以每年生出一头牛,不考虑牛的性别和生死,问农夫10年后有多少头牛?
  7. 电子化时代到来,电子印章助力构建网络时代互信环境
  8. 全球10大B2B电子商务平台排行,这个网站只排第三!
  9. (四十三):Comprehensive Linguistic-Visual Composition Network for Image Retrieval
  10. 生物类实验室安全管理