在上一次的学习中,我们读取了手机联系人并将其显示在短信界面上,而接下来,我们将开始读取手机短信了,下面先来看一下最终运行效果图吧。
首先看一下手机短信数据库,访问路径是:/data/data/com.android.providers.telephony/databases/mmssms.db,用SQLiteExpertPers打开后可以看到数据库中的表,下面我们来看一下其中的sms表,threads表和canonical_addresses表。
1.sms表:
thread_id:与threads表的_id相对应
address:短信会话人号码
body:短信内容
person:通过SQLiteExpert工具查看,发现无论是否是联系人该列都为null
contact_name:通过SQLiteExpert工具查看,结果为:号码+空格+联系人名称(若为联系人)
status:-1表示短信已接受
read:0为未读,1为已读
type:1表示收到的短信,通过SQLiteExpert工具查看此数据库时发出的信息type值为6
2.threads表
recipient_ids:指向canonical_addresses表的_id字段,通过canonical_addresses表的address字段
可获取联系人号码
snippest:最后收到/发出的信息
message_count:该会话的消息数量
3.canonical_addresses表
_id:与thread表的recipient_ids相对应
address:电话号码
相对于上一个版本,这次工程新增了SMSInfo类作为短信数据库表对应的实体类,在适配器类MessageListAdapter 中,定义新方法getSMSInfo()来获取sms表中的短信记录,并在 MainActivity中调用该方法。另外,在实际读取短信记录时,发现之前的页面布局显示有问题,如在短信列表页面,当某条短信内容较长时,应该采用单行显示,超过一行的部分应该被隐藏,因此对主布局文件activity_main.xml和列表项布局文件list_item.xml也做了修改,如下文所示。另外,与读取联系人一样,读取短信同样需要AndroidManifest.xml文件中配置手机短信读取权限,在文件中增加如下声明:
在MessageListAdapter中进行查询时,使用了query方法,我们来看一下这个方法的用法中各参数含义。
query(Uri uri,String[] project,String selection,String selectionArgs,String sortOrder):
uri:要读取数据对应的Uri
projection:需要读取的字段
selection:数据检索的条件
selectionArgs:数据检索条件的参数
sortOrder:对查询结果排序所依据的字段
最后给出程序代码如下:
1.MainActivity.java
package com.example.mymessageproject;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.widget.ListView;
public class MainActivity extends Activity {
private ListView messageListView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
messageListView = (ListView)this.findViewById(R.id.messageListView);
MessageListAdapter adapter = new MessageListAdapter(this);
//获取短信记录
adapter.getSMSInfo();
messageListView.setAdapter(adapter);
//实时通知数据已更新
adapter.notifyDataSetChanged();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
2.MessageListAdapter.java
package com.example.mymessageproject;
import java.io.InputStream;
import java.sql.Date;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.database.Cursor;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.CommonDataKinds.Photo;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
public class MessageListAdapter extends BaseAdapter {
private LayoutInflater mInflater;
private Context mContext = null;
/**
* 可读取所有的短信的Uri
*/
public static final String SMS_URI_ALL = "content://sms/";
private static final String MesTAG = "Reading Messages";
private static final String ThreadTAG = "Reading from Thread Table";
private static final String GetPhoneNumberTAG = "Getting phone number";
private static final String GetContactByPhoneTAG = "Getting contact by phone number";
//存储所有短信信息的列表
List infos = new ArrayList();
//MessageListAdapter初始化构造方法
public MessageListAdapter(Context context) {
mContext = context;
mInflater = LayoutInflater.from(mContext);
}
/*获取手机中的信息,并将其存入信息列表infos中*/
public void getSMSInfo() {
Uri uri = Uri.parse(SMS_URI_ALL);
Cursor messageCursor = null;
ContentResolver resolver = null;
try{
/**
获取短信的各种信息 ,短信数据库sms表结构如下:
_id:短信序号,如100
thread_id:对话的序号,如100,与同一个手机号互发的短信,其序号是相同的
address:发件人地址,即手机号,如+8613811810000
date:日期,long型,如1256539465022,可以对日期显示格式进行设置
read:是否阅读0为未读
status:短信状态-1表示短信已被接收
type:短信类型1表示接收到的短信
body:短信具体内容
service_center:短信服务中心号码编号,如+8613800755500
*/
resolver = mContext.getContentResolver();
String[] projection = new String[] {"_id", "address","body",
"date", "type"};
uri = Uri.parse(SMS_URI_ALL);
/*
* query(Uri uri,String[] project,String selection,
* String selectionArgs,String sortOrder)方法各参数含义
* uri:要读取数据对应的Uri
* projection:需要读取的字段
* selection:数据检索的条件
* selectionArgs:数据检索条件的参数
* sortOrder:对查询结果排序所依据的字段
* */
messageCursor = resolver.query(uri, projection, null, null, "date desc");
if (messageCursor == null) {
return;
}
if (messageCursor.getCount() == 0){
messageCursor.close();
messageCursor = null;
return;
}
int phoneNumberColumn = messageCursor.getColumnIndex("address");
int smsbodyColumn = messageCursor.getColumnIndex("body");
int dateColumn = messageCursor.getColumnIndex("date");
int typeColumn = messageCursor.getColumnIndex("type");
if (messageCursor != null) {
while (messageCursor.moveToNext()) {
//设置日期显示格式
SimpleDateFormat dateFormat = new SimpleDateFormat(
"yyyy-MM-dd");
Date date = new Date(Long.parseLong(messageCursor.getString(dateColumn)));
SMSInfo smsinfo = new SMSInfo();
//此处contactMes为电话号码
smsinfo.setContactMes(messageCursor.getString(phoneNumberColumn));
smsinfo.setDate(dateFormat.format(date));
smsinfo.setSmsbody(messageCursor.getString(smsbodyColumn));
smsinfo.setType(messageCursor.getString(typeColumn));
infos.add(smsinfo);
}
}
messageCursor.close();
}catch(Exception e){
Log.e(MesTAG,"E:" + e.toString());
}finally{
if (messageCursor != null){
messageCursor.close();
messageCursor = null;
}
}
}
public Object getItem(int arg0) {
// TODO Auto-generated method stub
return infos.get(arg0);
}
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
public int getCount() {
// TODO Auto-generated method stub
//return contactDataList.size();
return infos.size();
}
public View getView(int position, View convertView,android.view.ViewGroup parent) {
MessageHolder messageHolder = null;
//判断convertView是否已创建,若已存在则不必重新创建新视图,节省系统资源
if (convertView == null) {
// 和item_custom.xml脚本关联
convertView = mInflater.inflate(R.layout.list_item, null);
messageHolder = new MessageHolder();
//加载控件到信息载体中
messageHolder.setIvImage((ImageView) convertView.findViewById(R.id.contact_image));
messageHolder.setTvTitle((TextView) convertView.findViewById(R.id.titleTextView));
messageHolder.setTvDesc((TextView) convertView.findViewById(R.id.descTextView));
messageHolder.setTvCount((TextView) convertView.findViewById(R.id.countTextView));
messageHolder.setTvTime((TextView) convertView.findViewById(R.id.timeTextView));
//将联系人信息载体Holder放入convertView视图
convertView.setTag(messageHolder);
}else{
//从convertView视图取出联系人信息载体Holder
messageHolder = (MessageHolder)convertView.getTag();
}
// 通过短信Holder设置list_item中4个TextView的文本与联系人头像
//绘制短信联系人信息,内容为其号码
messageHolder.getTvTitle().setText(infos.get(position).getContactMes());
//绘制信息内容
messageHolder.getTvDesc().setText(infos.get(position).getSmsbody());
//此处显示的是当前所有短信数量
messageHolder.getTvCount().setText(""+infos.size());
//绘制时间
messageHolder.getTvTime().setText(infos.get(position).getDate());
// 设置显示在每条短信左边的图片
messageHolder.getIvImage().setBackgroundResource(R.drawable.ic_launcher);
return convertView;
}
}
3.SMSInfo.java
package com.example.mymessageproject;
import android.graphics.Bitmap;
public class SMSInfo {
/**
* 短信内容
*/
private String smsbody;
/**
*
* 发送短信的日期和时间
*/
private String date;
/**
* 短信类型1是接收到的,通过SQLiteExpertPers查看发出信息类型为6
*/
private String type;
/**
* 与同一个联系人的会话包含的消息数
*/
private String messageCout;
/**
* 会话人的信息,属于联系人则为名称,否则为其号码
*/
private String contactMes;
/**
* 该会话对应的联系人头像
*/
private Bitmap contactPhoto;
public String getContactMes() {
return contactMes;
}
public void setContactMes(String contactMes) {
this.contactMes = contactMes;
}
public Bitmap getContactPhoto() {
return contactPhoto;
}
public void setContactPhoto(Bitmap contactPhoto) {
this.contactPhoto = contactPhoto;
}
public String getMessageCout() {
return messageCout;
}
public void setMessageCout(String messageCout) {
this.messageCout = messageCout;
}
public String getSmsbody() {
return smsbody;
}
public void setSmsbody(String smsbody) {
this.smsbody = smsbody;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
4.activity_main.xml
5.list_item.xml
好了,今天就到到这里吧,在上一篇和这一篇文章中,我们分别读取了手机联系人和手机短信,在下一次,将开始联结查询两个数据库,进一步完善在短信会话主界面联系人头像等信息的展示。
参考文章链接:http://www.cnblogs.com/kakafra/archive/2012/09/28/2707790.html