转载请注明原文出处:http://blog.csdn.net/yf210yf
这几天一直纠结于系统短信的界面,再查了n多资料后,终于自己写了个短信会话信息的界面,并仿照系统自带短信界面,得到了联络人与陌生人号码,还有最后接收的短信及其他信息。
关于短信的各种操作在我的另一篇博客里讲:
http://blog.csdn.net/yf210yf/article/details/7268904
这里略做补充点:
盗了别人两个图:
sms表,信息表
threads表
Threads的URI为:"content://mms-sms/conversations"
不过由于本人使用这个Uri查询出错,故使用content://sms/ 通过构造查询字段数组来查询Threads表。
ContentResolver cr = getContentResolver();
Cursor cursor = cr.query(Uri.parse("content://mms/"), new String[]
{ "* from threads--" }, null, null, null);
另一些补充的知识:
Android 中涉及数据库查询的地方一般都会有一个 query() 方法,而这些 query 中有大都(全部?)会有一个参数 selectionArgs,比如下面这个 android.database.sqlite.SQLiteDatabase.query():
public Cursor query (String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy)
public Cursor query (String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy)
selection 参数很好理解,就是 SQL 语句中 WHERE 后面的部分,即过滤条件, 比如可以为 id=3 AND name='Kevin Yuan' 表示只返回满足 id 为 3 且 name 为 "Kevin Yuan" 的记录。
再实际项目中像上面那样简单的“静态”的 selection 并不多见,更多的情况下要在运行时动态生成这个字符串,比如
public doQuery(long id, final String name)
{
mDb.query("some_table", // table name
null, // columns
"id=" + id + " AND name='" + name + "'", // selection
//...... 更多参数省略
);
}
public doQuery(long id, final String name)
{
mDb.query("some_table", // table name
null, // columns
"id=" + id + " AND name='" + name + "'", // selection
//...... 更多参数省略
);
}
在这种情况下就要考虑一个字符转义的问题,比如如果在上面代码中传进来的 name 参数的内容里面有单引号('),就会引发一个 "SQLiteException syntax error .... "。
手工处理转义的话,也不麻烦,就是 String.replace() 调用而已。但是 Android SDK 为我们准备了 selectionArgs 来专门处理这种问题:
public void doQuery(long id, final String name)
{
mDb.query("some_table", // table name
null, // columns
"id=" + id + " AND name=?", // selection
new String[] {name}, //selectionArgs
//...... 更多参数省略
);
// ...... 更多代码
}
public void doQuery(long id, final String name)
{
mDb.query("some_table", // table name
null, // columns
"id=" + id + " AND name=?", // selection
new String[] {name}, //selectionArgs
//...... 更多参数省略
);
// ...... 更多代码
}
也就是说我们在 selection 中需要嵌入字符串的地方用 ? 代替,然后在 selectionArgs 中依次提供各个用于替换的值就可以了。在 query() 执行时会对 selectionArgs 中的字符串正确转义并替换到对应的 ? 处以构成完整的 selection 字符串。 有点像 String.format()。
不过需要注意的是 ? 并不是“万金油”,只能用在原本应该是字符串出现的地方。比如下面的用法是错误的:
public void doQuery(long id, final String name)
{
mDb.query("some_table", // table name
null, // columns
"? = " + id + " AND name=?", // selection XXXX 错误!? 不能用来替换字段名
new String[]{"id", name}, //selectionArgs
//...... 更多参数省略
);
// ...... 更多代码
}
部分程序:
/**
* 从mms数据库中检索threads表
*/
public void getContacts_LastMessage()
{
ContentResolver cr = getContentResolver();
Cursor cursor = cr.query(Uri.parse("content://mms/"), new String[]
{ "* from threads--" }, null, null, null);
while (cursor.moveToNext())
{
int thread_id = cursor.getColumnIndex("_id");
int date = cursor.getColumnIndex("date");
int message_count = cursor.getColumnIndex("message_count");
int snippet = cursor.getColumnIndex("snippet");
//格式化短信日期显示
SimpleDateFormat sfd = new SimpleDateFormat("MM-dd hh:mm:ss");
Date date_format = new Date(Long.parseLong(cursor.getString(date)));
String time = sfd.format(date_format);
//获得短信的各项内容
String info[]=getPhoneNum(cursor.getString(thread_id));
String last_mms=cursor.getString(snippet);
String date_mms=time;
String count_mms=cursor.getString(message_count);
//判断是否联系人
String contact = getContactNameFromPhoneNum(this
.getApplicationContext(), info[0]);
//获得最后的未读短信与已读短信
String final_count="("+info[1]+"/"+count_mms+")";
//添加到list
if (contact.equals(""))
{
getData(
info[0],
last_mms,
final_count,
date_mms
);
}
else
{
getData(
contact,
last_mms,
final_count,
date_mms
);
}
}
}
/**
*
* @param 根据thread_id 检索sms库, 获得对应的号码
* @return
*/
public String[] getPhoneNum(String thread_id)
{
String PhoneNum="";
int noread_mms=0;
String[] info={"",""};
String[] projection = new String[]
{ "thread_id", "address", "person", "body", "date", "type","read" };
Uri uri = Uri.parse("content://sms/");
ContentResolver cr = getContentResolver();
Cursor cursor = cr.query
(
uri,
projection,
"thread_id=?",
new String[] { thread_id } ,
null
);
while (cursor.moveToNext())
{
int phoneNumber = cursor.getColumnIndex("address");
int isread =cursor.getColumnIndex("read");
if (cursor.getString(isread).equals("0"))
{
noread_mms++;
}
PhoneNum=cursor.getString(phoneNumber);
}
info[0]=PhoneNum;
info[1]=Integer.toString(noread_mms);
return info;
}
Cursor cursor = cr.query
(
uri,
projection,
"thread_id=?",
new String[] { thread_id } ,
"date asc" //按日期正序排 "date desc" //按日期倒序排
);