基于Android的短信应用开发(五)——读取显示会话信息记录

         在上一次,我们读取显示了短信会话列表,接下来,要继续进行的工作就是点击每个短信会话后,显示该会话包含的所有信息记录,我们还是先来看一下运行效果吧,左图为短信会话列表,右图为点击其中第二个会话之后看到的该会话下的短信记录,蓝色背景的为发出的短信,灰色背景的为收到的短信。

基于Android的短信应用开发(五)——读取显示会话信息记录_第1张图片     基于Android的短信应用开发(五)——读取显示会话信息记录_第2张图片

     为了显示各个会话下所有的短信记录,需要取得短信会话的会话id,即sms表中的字段“thread_id”,而在上一篇文章中,我们已经在MessageListAdapter的getMessageSessions()方法中取得了每个短信会话的id,因此,我们还是先回去看一下吧,下面在getMessageSessions()中,红色代码部分执行了从threads表获取会话id的操作

  /** 
     * 从mms数据库中检索threads表  
     */  
    public void getMessageSessions(){  
        Cursor sessionCursor = null;
        ContentResolver resolver = null; 
        ContactData contact = null;
        
        try{
               Uri uri = Uri.parse(SMS_URI_ALL);
            resolver = mContext.getContentResolver();
            sessionCursor = resolver.query(uri, new String[]  
            { "* from threads--" }, null, null, null);  
            
            if (sessionCursor == null) {
                return;
            }    
            if (sessionCursor.getCount() == 0){
                sessionCursor.close();
                sessionCursor = null;
                return;
            }
              
            sessionCursor.moveToFirst();
            while (sessionCursor.isAfterLast() == false)  
            {  
                /*
                threads表各字段含义如下:
                1._id为会话id,他关联到sms表中的thread_id字段。
                2.recipient_ids为联系人ID,这个ID不是联系人表中的_id,而是指向表canonical_address里的id,
                canonical_address这个表同样位于mmssms.db,它映射了recipient_ids到一个电话号码,也就是说,
                最终获取联系人信息,还是得通过电话号码;
                3.mesage_count该会话的消息数量
                4.snippet为最后收到或发出的信息                
                */
                
                int thread_idColumn = sessionCursor.getColumnIndex("_id");  
                int dateColumn = sessionCursor.getColumnIndex("date");  
                int message_countColumn = sessionCursor.getColumnIndex("message_count");  
                int snippetColumn = sessionCursor.getColumnIndex("snippet");  
                int typeColumn = sessionCursor.getColumnIndex("type");
                              
                //格式化短信日期显示  
                //SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");  
                Date date = new Date(Long.parseLong(sessionCursor.getString(dateColumn)));    
                  
                //获得短信的各项内容  
                //phoneAndUnread[0]存放电话号码,phoneAndUnread[1]存放该会话中未读信息数
                String threadId = sessionCursor.getString(thread_idColumn);
                String phoneAndUnread[]=getPhoneNum(threadId);  
                String last_mms=sessionCursor.getString(snippetColumn);  
                //String date_mms=dateFormat.format(date);  
                String date_mms=date.toString();  
                String count_mms=sessionCursor.getString(message_countColumn);  
                String type = sessionCursor.getString(typeColumn);
                
                SMSInfo smsinfo = new SMSInfo();
                
                /*  
                phoneAndUnread[0]存放电话号码 
                */ 
                contact = getContactFromPhoneNum(mContext, phoneAndUnread[0]); 
                  
                //获得最后的未读短信与已读短信  
                //String final_count="("+phoneAndUnread[1]+"/"+count_mms+")";  
                  
                //将会话信息添加到信息列表中
                //判断是否联系人,若为联系人显示其名称,若不是则显示号码                                 
                if (contact.getContactName().equals("")){  
                    smsinfo.setContactMes(phoneAndUnread[0]);                                        
                }else{  
                    smsinfo.setContactMes(contact.getContactName());
                }  
                
                //如果有该信息会话人头像,则设置已有头像,如果没有则给他设置一个默认的头像
                if (contact.getPhotoUri() == null){ 
                    smsinfo.setContactPhoto(BitmapFactory.decodeResource(
                            mContext.getResources(), R.drawable.ic_launcher));                                    
               }else{  
                    Uri photoUri = contact.getPhotoUri();
                    InputStream input = ContactsContract.Contacts.
                            openContactPhotoInputStream(resolver, photoUri);  
                    smsinfo.setContactPhoto(BitmapFactory.decodeStream(input)); 
                }                
                
                smsinfo.setDate(date_mms);
                smsinfo.setSmsbody(last_mms);
                smsinfo.setType(type);
                smsinfo.setMessageCout(count_mms);
                smsinfo.setThreadId(threadId);
                infos.add(smsinfo);
                sessionCursor.moveToNext();
            } 
                sessionCursor.close();
        }catch(Exception e){
            Log.e(ThreadTAG,"E:" + e.toString());
        }finally{
            if (sessionCursor != null){
                sessionCursor.close();
                sessionCursor = null;
            }
        }
  
    } 

     接着,需要为每个短信会话列表项监听点击事件,但某个会话被点击时就跳转到显示该会话下所有短信记录的界面,具体做法为在MessageListAdaptergetView()方法中添加红色代码如下:

public View getView(final 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.index_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设置item中4个TextView的文本与联系人头像    
        //绘制短信联系人信息,内容为其名称或号码
        messageHolder.getTvTitle().setText(infos.get(position).getContactMes());
        //在信息正文区域绘制信息内容
        messageHolder.getTvDesc().setText(infos.get(position).getSmsbody());

        messageHolder.getTvCount().setText(""+infos.get(position).getMessageCout());
        messageHolder.getTvTime().setText(infos.get(position).getDate());
        messageHolder.getIvImage().setImageBitmap(infos.get(position).getContactPhoto());
        
        /*
         * 在短信主界面为每个短信会话设置监听事件,当选择点击某条会话时,跳转到显示该会话包含的所有信息记录的页面
         * */
        convertView.setOnClickListener(new OnClickListener(){
            @Override
            public void onClick(View v) {
                Intent intent = new Intent();
                //通过Intent向显示短信会话包含的信息的Activity传递会话id
                intent.putExtra("threadId",infos.get(position).getThreadId());
                intent.setClass(mContext, ShowSessionMessagesActivity.class);
                mContext.startActivity(intent);
            }            
        });    
        
        return convertView;
    }

       通过上面的代码,可以看到当会话列表项被点击时,通过Intent跳转到负责显示会话信息记录页面的ShowSessionMessagesActivity,并传递该会话的threadId,,我们一起来看一下这Activity是怎样定义的吧。

package com.example.mymessageproject;

import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.Menu;
import android.widget.ListView;
import android.widget.TextView;

public class ShowSessionMessagesActivity extends Activity {
    private ListView sessionMessagesListView;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_show_session_messages);
        
        //使用Intent对象得到短信会话的id
        Intent intent = getIntent();
        String threadId = intent.getStringExtra("threadId");
        
        sessionMessagesListView = (ListView)this.findViewById(R.id.SessionMessageListView);
        
        ShowSessionMessagesAdapter sessionMessagesAdapter = new ShowSessionMessagesAdapter(this);
        sessionMessagesAdapter.getSessionMessages(threadId);
        sessionMessagesListView.setAdapter(sessionMessagesAdapter);
        //实时通知数据已更新
        sessionMessagesAdapter.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.show_session_messages, menu);
        return true;
    }

}

      可以看到ShowSessionMessagesActivity的定义很简单,先通过Intent获取MessageListAdapter传过来的参数,即短信会话的threadId,然后获取用来显示会话记录的列表控件ListView,再将短信会话id传递给ListView的适配器ShowSessionMessagesAdapter,最后为ListView设置适配器,就大功告成了,而在ShowSessionMessagesAdapter中又执行了什么操作呢,还是来看一下其代码吧。

package com.example.mymessageproject;

import java.util.ArrayList;
import java.util.List;

import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

public class ShowSessionMessagesAdapter extends BaseAdapter{
    private LayoutInflater mInflater;
    private Context mContext = null;
    
     /**
      * 所有的短信
      */
     public static final String SMS_URI_ALL = "content://sms/";

     private static final String GetMessagesByThreadIdTAG = "Getting messages by thread id";
     
     //存储信息会话中所有来往短信的列表
    List infos = new ArrayList();

    
    //ShowSessionMessagesAdapter初始化构造方法
    public ShowSessionMessagesAdapter(Context context) {
        mContext = context;
        mInflater = LayoutInflater.from(mContext);
    }
    
    /** 
     *  
     * @param 根据thread_id 检索sms库, 获得该会话包含的信息
     * @return 
     */  
    public void getSessionMessages(String thread_id){      
        Cursor sessionMessagesCursor = null;    
        ContentResolver resolver = null;
        
         /**
         获取短信的各种信息 ,短信数据库sms表结构如下:
         _id:短信序号,如100  
        thread_id:对话的序号,如100,与同一个手机号互发的短信,其序号是相同的              
        address:发件人地址,即手机号,如+8613811810000              
        person:发件人,如果发件人在通讯录中则为具体姓名,陌生人为null              
        date:日期,long型,如1256539465022,可以对日期显示格式进行设置              
        protocol:协议0SMS_RPOTO短信,1MMS_PROTO彩信              
        read:是否阅读0未读,1已读              
        status:短信状态-1接收,0complete,64pending,128failed              
        type:短信类型1是接收到的,2是已发出              
        body:短信具体内容              
        service_center:短信服务中心号码编号,如+8613800755500
        */
        try{
        String[] projection = new String[]  
        { "thread_id", "address", "person", "body", "date", "type","read" };  
            
          
        //Uri uri = Uri.parse("content://sms/");  
        Uri uri = Uri.parse(SMS_URI_ALL);
        resolver = mContext.getContentResolver();            
          
        sessionMessagesCursor = resolver.query  
        (  
                uri,   
                projection,   
                "thread_id=?",  
                new String[] { thread_id } ,  
                null  
        );  
        
        if (sessionMessagesCursor == null) {
            return;
        }    
        if (sessionMessagesCursor.getCount() == 0){
            sessionMessagesCursor.close();
            sessionMessagesCursor = null;
            return;
        }
          
        int nameColumn = sessionMessagesCursor.getColumnIndex("person");
        int phoneNumberColumn = sessionMessagesCursor.getColumnIndex("address");
        int smsbodyColumn = sessionMessagesCursor.getColumnIndex("body");
        int dateColumn = sessionMessagesCursor.getColumnIndex("date");
        int typeColumn = sessionMessagesCursor.getColumnIndex("type");
        
        sessionMessagesCursor.moveToFirst();
        while (sessionMessagesCursor.isAfterLast() == false){  
            SMSInfo smsinfo = new SMSInfo();
            //将信息会话的信息内容和信息类型(收到或发出)存入infos中                    
            smsinfo.setSmsbody(sessionMessagesCursor.getString(smsbodyColumn));
            smsinfo.setType(sessionMessagesCursor.getString(typeColumn));
            infos.add(smsinfo);
            sessionMessagesCursor.moveToNext();
        }   
        
        sessionMessagesCursor.close();
        sessionMessagesCursor = null; 
        }catch(Exception e){
            Log.e(GetMessagesByThreadIdTAG,"E:" + e.toString());
        }finally{
            if (sessionMessagesCursor != null){
                sessionMessagesCursor.close();
                sessionMessagesCursor = null;
            }
        }
    }

    @Override
    public int getCount() {
        // TODO Auto-generated method stub
        return infos.size();
    }

    @Override
    public Object getItem(int position) {
        // TODO Auto-generated method stub
        return infos.get(position);
    }

    @Override
    public long getItemId(int position) {
        // TODO Auto-generated method stub
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        MessageHolder receivedMessageHolder = null; 
        MessageHolder sendMessageHolder = null; 
        
        //判断convertView是否已创建,若已存在则不必重新创建新视图,节省系统资源
        if (convertView == null) {        
            
            switch(Integer.parseInt(infos.get(position).getType())){
                //若从sms表提取的信息type为1,说明这是收到的信息
                case 1:
                //为收到的信息关联格式文件,设置显示格式
                convertView = mInflater.inflate(R.layout.message_session_list_received_item, null);
                receivedMessageHolder = new MessageHolder();
                receivedMessageHolder.setTvDesc((TextView) convertView.findViewById(
                        R.id.ReceivedSessionMessageTextView));                        
                //将联系人信息载体Holder放入convertView视图
                convertView.setTag(receivedMessageHolder);
                break;
                
                //若从sms表提取的信息type为其他,说明这是发出的信息
                default:
                //为发出的信息关联格式文件,设置显示格式
                convertView = mInflater.inflate(R.layout.message_session_list_send_item, null);
                sendMessageHolder = new MessageHolder();
                sendMessageHolder.setTvDesc((TextView) convertView.findViewById(
                        R.id.SendSessionMessageTextView));            
                convertView.setTag(sendMessageHolder);
                break;
            }                        
        }else{            
            //有convertView,按样式,从convertView视图取出联系人信息载体Holder
            switch(Integer.parseInt(infos.get(position).getType()))
            {
            case 1:
            receivedMessageHolder = (MessageHolder)convertView.getTag();
            break;
            
            default:
            sendMessageHolder = (MessageHolder)convertView.getTag();
            break;
            }
        }
        
        //设置资源
        switch(Integer.parseInt(infos.get(position).getType()))
        {
        case 1:
        receivedMessageHolder.getTvDesc().setText(infos.get(position).getSmsbody());
        break;
        
        default:
            sendMessageHolder.getTvDesc().setText(infos.get(position).getSmsbody());
        break;
        }        

        return convertView;
    }  
    
}

      简要分析一下上面的代码。在getSessionMessages()方法中,通过会话id查询得到该会话包含的所有短信记录,并将其存入infos列表中,接下来,值得一提的是在getView()方法中根据短信的类型,即收到的或发出的对其进行区分显示,通过分别加载不同的格式定义xml文件来使其显示为不同的格式,用留空和背景颜色的不同来加以区分,最后,给出文章中的xml文件代码。

1.显示会话包含的信息记录的ShowSessionMessagesActivity的格式定义文件activity_show_session_messages.xml


    
    

2.定义收到短信格式的message_session_list_received_item.xml

            
            
          
                                  
      

3.定义发出短信格式的message_session_list_send_item.xml

            
            
            
                         
      

4.颜色定义文件color.xml



#B0E0E6
#DCDCDC

参考文章链接:

http://www.eoeandroid.com/forum.php?mod=viewthread&tid=200168

http://blog.163.com/gis_warrior/blog/static/19361717320128149423856/




你可能感兴趣的:(基于Android的短信应用开发(五)——读取显示会话信息记录)