基于Android的短信应用开发(三)——读取手机短信

         在上一次的学习中,我们读取了手机联系人并将其显示在短信界面上,而接下来,我们将开始读取手机短信了,下面先来看一下最终运行效果图吧。

基于Android的短信应用开发(三)——读取手机短信_第1张图片

       首先看一下手机短信数据库,访问路径是:/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
基于Android的短信应用开发(三)——读取手机短信_第2张图片
2.threads表
recipient_ids:指向canonical_addresses表的_id字段,通过canonical_addresses表的address字段
可获取联系人号码
snippest:最后收到/发出的信息
message_count:该会话的消息数量
基于Android的短信应用开发(三)——读取手机短信_第3张图片
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


    
    
    

    

        好了,今天就到到这里吧,在上一篇和这一篇文章中,我们分别读取了手机联系人和手机短信,在下一次,将开始联结查询两个数据库,进一步完善在短信会话主界面联系人头像等信息的展示。

参考文章链接:http://www.cnblogs.com/kakafra/archive/2012/09/28/2707790.html










你可能感兴趣的:(基于Android的短信应用开发(三)——读取手机短信)