`
ssrc0604hx
  • 浏览: 8904 次
文章分类
社区版块
存档分类
最新评论

android 中管理短信

 
阅读更多
为了看代码方便,一边在网上google资料,一边看Android java 源代码。

偶然发现了一个类MmsSmsDatabaseHelper.java,原来android将所有的短信信息都存入了mmssms.db中。

公开的SDK中没有这个类,不能直接使用。于是自己写了一个SQLiteOpenHelper,但是查询的时候发生SQL异常。

看来不能为所欲为了,不过据网上资料介绍可以拷贝db文件来实现短信数据备份。

既然每个db跟package名相关,建立了一个package为com.android.providers.telephony的工程去试一试,看看能不能成功。

结果输出Please execute 'adb uninstall com.android.providers.telephony' in a shell,android的安全做得很强大啊。

不能直接访问数据库,只能通过协议来访问数据库了,
先贴出相关的协议:
content://sms/inbox 收件箱
content://sms/sent 已发送
content://sms/draft 草稿
content://sms/outbox 发件箱
content://sms/failed 发送失败
content://sms/queued 待发送列表

在模拟器上Outbox没有查询到数据,在模拟器上找了老半天也没找到发件箱,很郁闷。
数据库中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

检索数据方法很简单:

Uri uri = Uri.parse("content://sms/inbox");         
Cursor cur = this.managedQuery(uri, null, null, null, null);         
if (cur.moveToFirst()) {         
    do{     
    for(int j = 0; j < cur.getColumnCount(); j++){     
            info = "name:" + cur.getColumnName(j) + "=" + cur.getString(j); 
            Log.i("====>", info); 
        } 
    }while(cur.moveToNext());      
}
managedQuery最终也要将参数转换为SQL语句向SQLite发送消息,因此参数跟SQL语句很类似,所以可以在查询字段中加入SQL函数,

比如new String[] projection = new String[]{"count(*) as count"}等等。
managedQuery中的参数依次为uri,
查询字段 查询字段数组,也可以将所有需要查询的字段放入一个字符内
比如new projection[]{"_id", "thread_id"}和new projection[]{"_id,thread_id"}是一致的。
跟SQL一样,字段名不区分大小写
条件 不带Where的SQL 条件字符,如果有参数则用?替代,比如"_id=? And thread_id = ? Or type = '1'"
条件中的参数 参数字符数组,跟上述的条件一一对应
排序 不带Order by排序字符串,比如_id desc, type
如果参数为null,SQL中查询字段为“*”,相关的条件为空白

还可以用getContentResolver()获得一个ContentResolver,
getContentResolver().query()同样返回一个Cursor对象,参数跟managedQuery一致。
不过用ContentResolver对象去更新、删除和插入一条数据时报SecurityException。看来没有权限,在Manifest.xml中加入权限:
<uses-permission android:name="android.permission.WRITE_SMS"></uses-permission>
然后删除短信:
this.getContentResolver().delete(Uri.parse("content://sms"), "_id=?", new String[]{"3"});
删除成功。

Url中content://sms 替换成content://sms/ 也成功,但是其它url时程序报错,比如content://sms/inbox

看了一下android的源代码,sms支持的协议有:

sURLMatcher.addURI("sms", null, SMS_ALL); 
sURLMatcher.addURI("sms", "#", SMS_ALL_ID); 
sURLMatcher.addURI("sms", "inbox", SMS_INBOX); 
sURLMatcher.addURI("sms", "inbox/#", SMS_INBOX_ID); 
sURLMatcher.addURI("sms", "sent", SMS_SENT); 
sURLMatcher.addURI("sms", "sent/#", SMS_SENT_ID); 
sURLMatcher.addURI("sms", "draft", SMS_DRAFT); 
sURLMatcher.addURI("sms", "draft/#", SMS_DRAFT_ID); 
sURLMatcher.addURI("sms", "outbox", SMS_OUTBOX); 
sURLMatcher.addURI("sms", "outbox/#", SMS_OUTBOX_ID); 
sURLMatcher.addURI("sms", "undelivered", SMS_UNDELIVERED); 
sURLMatcher.addURI("sms", "failed", SMS_FAILED); 
sURLMatcher.addURI("sms", "failed/#", SMS_FAILED_ID); 
sURLMatcher.addURI("sms", "queued", SMS_QUEUED); 
sURLMatcher.addURI("sms", "conversations", SMS_CONVERSATIONS); 
sURLMatcher.addURI("sms", "conversations/*", SMS_CONVERSATIONS_ID); 
sURLMatcher.addURI("sms", "raw", SMS_RAW_MESSAGE); 
sURLMatcher.addURI("sms", "attachments", SMS_ATTACHMENT); 
sURLMatcher.addURI("sms", "attachments/#", SMS_ATTACHMENT_ID); 
sURLMatcher.addURI("sms", "threadID", SMS_NEW_THREAD_ID); 
sURLMatcher.addURI("sms", "threadID/*", SMS_QUERY_THREAD_ID); 
sURLMatcher.addURI("sms", "status/#", SMS_STATUS_ID); 
sURLMatcher.addURI("sms", "sr_pending", SMS_STATUS_PENDING); 
sURLMatcher.addURI("sms", "sim", SMS_ALL_SIM); 
sURLMatcher.addURI("sms", "sim/#", SMS_SIM);

其中,delete方法中支持的协议为:

SMS_ALL 根据参数中的条件删除sms表数据
SMS_ALL_ID 根据_id删除sms表数据
SMS_CONVERSATIONS_ID 根据thread_id删除sms表数据,可以带其它条件
SMS_RAW_MESSAGE 根据参数中的条件删除 raw表
SMS_STATUS_PENDING 根据参数中的条件删除 sr_pending表
SMS_SIM 从Sim卡上删除数据

试一下SMS_CONVERSATIONS_ID:"content://sms/conversations/3 ",删除thread_id="3", _id="5"的数据
在eclipse中的Emulator Control中,以13800给模拟器发送三条数据,然后以13900发送一条
this.getContentResolver().delete(Uri.parse("content://sms/conversations/3"), "_id=?", new String[]{"5"});
成功删除一条数据。

在数据库中每个发送者的thread_id虽然一样,但不是固定的,如果把一个发送者的全部数据删除掉,
然后换一个新号码发送短信时,thread_id是以数据库中最大的id+1赋值的。

update支持的协议有很多:

SMS_RAW_MESSAGE
SMS_STATUS_PENDING
SMS_ALL
SMS_FAILED
SMS_QUEUED
SMS_INBOX
SMS_SENT
SMS_DRAFT
SMS_OUTBOX
SMS_CONVERSATIONS
SMS_ALL_ID
SMS_INBOX_ID
SMS_FAILED_ID
SMS_SENT_ID
SMS_DRAFT_ID
SMS_OUTBOX_ID
SMS_CONVERSATIONS_ID
SMS_STATUS_ID

以SMS_INBOX_ID测试一下:


ContentValues cv = new ContentValues();    
cv.put("thread_id", "2");    
cv.put("address", "00000");    
cv.put("person", "11");    
cv.put("date", "11111111");    
this.getContentResolver().update(Uri.parse("content://sms/inbox/4"), cv, null, null);   
太强了,连thread_id都可以修改。

insert支持的协议:

SMS_ALL
SMS_INBOX
SMS_FAILED
SMS_QUEUED
SMS_SENT
SMS_DRAFT
SMS_OUTBOX
SMS_RAW_MESSAGE
SMS_STATUS_PENDING
SMS_ATTACHMENT
SMS_NEW_THREAD_ID

向sms表插入数据时,type是根据协议来自动设置,
如果传入的数据中没有设置date时,自动设置为当前系统时间;非SMS_INBOX协议时,read标志设置为1
SMS_INBOX协议时,系统会自动查询并设置PERSON
threadId为null或者0时,系统也会自动设置

一直为造不了"发送失败"的邮件而发愁,现在来做一个:

content://sms/failed    

ContentValues cv = new ContentValues();    
cv.put("_id", "99");    
cv.put("thread_id", "0");    
cv.put("address", "9999");    
cv.put("person", "888");    
cv.put("date", "9999"); 
cv.put("protocol", "0"); 
cv.put("read", "1"); 
cv.put("status", "-1"); 
//cv.put("type", "0"); 
cv.put("body", "@@@@@@@@@"); 
this.getContentResolver().insert(Uri.parse("content://sms/failed"), cv);
type被设置成了5,thread_id设置为1

系统连最起码的数据校验都没有做啊,google对程序员也太仁慈了。

看看能不能再挖掘一下sms的功能。先来做一个错误的查询:

getContentResolver().query( Uri.parse("content://sms/") , new String[]{"a"}, "b", null, null);

log输出错误的SQL语句:

SELECT a FROM sms WHERE (b) ORDER BY date DESC

query方法中没有Group by,如果想对短信做统计,对Cursor进行遍历再统计也太慢了。

在SQL语言中group by在Where后面,那就在条件参数中想想办法:

Android组织SQL语句时将条件两端加(),那就拼一个group by出来吧:

getContentResolver().query( Uri.parse("content://sms/") , new String[]{"count(*) as count, thread_id"}, "1=1) group by (thread_id", null, null);

那么输出的SQL= SELECT count(*) as count, thread_id FROM sms WHERE ( 1=1) group by (thread_id ) ORDER BY date DESC

如果想查询URI没有对应的表怎么办呢,比如想知道 mmssms.db数据库中有哪些表,

查询的表是URI定的,再在条件参数中拼凑肯定是不行。

那我们把目光往前移,看看在字段参数中能不能凑出来。

要查询其它表,关键要去掉系统固定添加的FROM sms,

用用SQL中的注释吧,

getContentResolver().query(Uri.parse("content://sms/"), new String[]{" * from sqlite_master WHERE type = 'table' -- "}, null, null, null);

那么输出的SQL=SELECT * from sqlite_master WHERE type = 'table' -- FROM sms ORDER BY date DESC

居然能够运行。

得寸进尺,再进一步,如果加入“;”也能运行的话,哈哈,那么建表、删除表、更新表也能为所欲为咯。

getContentResolver().query(Uri.parse("content://sms/"), new String[]{" * from sms;select * from thrreads;-- "}, null, null, null);

很可惜,只运行了第一条SQL语句,看来在关键问题上,android还是有所控制的。

不过支持--也很不错了,这样可以查询数据库中所有的表,而且还可以多表联查



分享到:
评论

相关推荐

    Android管理手机短信

    本文将深入探讨如何实现“Android管理手机短信”这一主题,包括显示未读短信、ListView下拉刷新、发送短信以及自动刷新和异步处理等关键知识点。 首先,显示未读短信是Android短信应用的基础。这需要访问Android...

    Android获取手机短信

    在Android平台上,获取手机短信是一项常见的功能,尤其在开发与短信相关的应用时,如验证码接收、备份或管理短信等。Android系统提供了丰富的API接口供开发者使用,使得我们能够方便地读取、操作甚至监听短信的变化...

    简易的android短信管理器代码

    在Android平台上,开发一个简易的短信管理器是常见的任务,涉及到的主要知识点包括Android系统的权限管理、BroadcastReceiver(广播接收者)、SMSManager类以及UI设计。下面将详细解释这些概念及其在实现短信管理器...

    Android智能短信管理器

    在Android平台上,智能短信管理器是一款非常实用的应用程序,它为用户提供了全面的短信管理和组织功能,极大地提升了处理日常通信的效率。以下是该应用的主要特点和相关知识点的详细解释: 1. **对话形式展示**:...

    android手机短信管理系统论文 完整版

    4.2 短信管理软件程序中各类组件 21 4.2.1 Package Explorer中的组件 22 4.2.2 应用程序的资源 22 4.2.3 布局文件main.xml 22 4.2.4 AndroidManifest.xml 23 4.3 手机短信软件设计实现 24 4.3.1 系统主界面的实现 24...

    Android4.4+短信拦截删除

    在Android系统中,短信服务是核心功能之一,它允许用户接收、发送和管理短信。在Android 4.4(KitKat)及更高版本中,为了增强用户体验和安全性,系统提供了更高级别的API来处理短信,包括拦截和删除短信。本文将...

    基于android手机短信管理系统设计

    ### 基于Android手机短信管理系统设计 #### 一、课题背景与研究意义 随着智能手机在日常生活中的普及,其已成为获取信息的重要工具。本研究针对当前市场上流行的多种移动操作系统(如Symbian、Windows Mobile、Mac...

    Android代码-安卓短信管理

    在Android平台上,短信管理涉及到的是对手机中短信的读取、发送、接收和删除等操作。这个名为“Android代码-安卓短信管理”的压缩包文件,很可能是包含了一个名为smsmanager-master的项目源码,用于演示或教学如何在...

    Android SMSNotify Android 短信通知源码

    【Android SMSNotify】是一款专为Android平台设计的短信通知组件,其源码提供了一套完整的解决方案,用于帮助开发者实现应用程序中的短信提醒功能。这个组件的核心是利用Android系统的短信API,结合自定义的通知机制...

    发短信小例子(Android)

    首先,Android系统提供了一个名为`SmsManager`的类,它是用来管理短信发送的核心接口。在AndroidManifest.xml文件中,我们需要添加必要的权限,特别是`SEND_SMS`权限,因为发送短信涉及到用户的隐私和费用,因此系统...

    android 短信管理

    通过这个类,我们可以实现发送短信、接收短信以及管理短信存储等功能。例如,要发送一条短信,可以使用`SmsManager.getDefault().sendTextMessage()`方法,传入目标电话号码和短信内容。 在描述中提到的“随机生成...

    基于android短信平台的管理

    2. **SMS APIs**: Android系统提供了SMS相关的API,允许应用程序发送、接收、读取和管理短信。开发者可能使用SmsManager类进行短信操作,如sendTextMessage()方法用于发送文本短信,以及registerReceiver()用于监听...

    Android通讯录管理(获取联系人、通话记录、短信消息)

    在Android系统中,通讯录管理是一项重要的功能,它涉及到用户个人信息的存储和访问。这篇教程将深入探讨如何在Android应用中获取联系人信息、通话记录以及短信消息。首先,我们来了解一下基本概念。 1. **获取联系...

    读取android手机内所有短信

    本文将详细介绍如何在Android中读取短信,以及涉及到的相关知识点。 首先,为了读取短信,我们需要使用Android提供的`Telephony.Sms`内容提供者。这个内容提供者允许应用程序访问手机中的短信数据库。以下是一些...

    android 信息(短信)管理器源码

    在Android系统中,信息(短信)管理器是一个关键组件,它负责处理短信的接收、发送、存储和查询等操作。本源码库提供了一个学习和理解Android短信管理器功能的实例,适合Android开发者进行深入研究。以下是关于...

    Android拦截接收短信

    在Android开发中,"Android拦截接收短信"涉及到的是BroadcastReceiver(广播接收器)的使用,以及对系统短信服务的监听。BroadcastReceiver是Android四大组件之一,用于接收系统或应用广播事件,比如接收到短信、...

    获取Android手机中所有短信的实现代码

    在Android平台上,获取手机中所有短信的实现代码涉及到对Android系统的Content Provider的使用。Content Provider是Android系统中数据共享和交换的重要机制,它允许应用程序访问其他应用的数据,比如短信存储在系统...

    android实战 查看短信的猫(android studio源程序工程)

    在Android平台上,开发一款应用程序来查看手机中的短信是一项常见的任务,尤其对于初学者而言,它是一个很好的实践项目。本文将详细解析"查看短信的猫"这个Android Studio源代码工程,帮助你理解Android移动开发的...

Global site tag (gtag.js) - Google Analytics