前两篇博客并分别讲了获取联系人和通话记录的知识,这篇主要介绍短信获取知识,短信在通讯管理中应该说是一个难点,因为短信涉及到短息会话和短信详情两个部分,并且短信的数据量比较大,可以采用AsyncQueryHandler框架来查询,同时采用CursorAdapter来绑定数据
其中短信中可以来获取联系人的头像和姓名。这个在代码工具类中有实现,如果联系人存在,则显示姓名,否则显示号码,如果联系人头像存在则显示头像,否则显示默认头像,如图片所示。这两部分功能在联系人和通话记录中均可以实现,有兴趣的童鞋可以修改。
查询框架
package cn.zxw.contact.utils; import android.content.AsyncQueryHandler; import android.content.ContentResolver; import android.database.Cursor; import android.support.v4.widget.CursorAdapter; import android.util.Log; /** * QueryHandler框架 * @author zhan * */ public class QueryHandler extends AsyncQueryHandler { private static final String TAG = "QueryHandler"; public QueryHandler(ContentResolver cr) { super(cr); } @Override protected void onQueryComplete(int token, Object cookie, Cursor cursor) { super.onQueryComplete(token, cookie, cursor); String names[] = cursor.getColumnNames(); for (String name : names) { Log.i(TAG, name); } // 查询完成 // if (cookie != null && cookie instanceof CursorAdapter) { // 把查询出来的cursor结果设置给adapter CursorAdapter adapter = (CursorAdapter) cookie; adapter.changeCursor(cursor); } } }短信会话获取
package cn.zxw.contact; import cn.zxw.contact.utils.ContactsUtils; import cn.zxw.contact.utils.QueryHandler; import cn.zxw.contact.utils.TimeUtils; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.database.Cursor; import android.graphics.Bitmap; import android.net.Uri; import android.os.Bundle; import android.support.v4.widget.CursorAdapter; import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; /** * 短信列表 * 点击短息列表中的条目会进入条目对应的短信详情页面 * @author zhan * */ public class MsgActivity extends Activity implements OnItemClickListener { private ListView lv; public MyCursorAdapter adapter; // 查询的结果集 private String[] projection = new String[] { "snippet", "sms.thread_id as _id", "msg_count", "sms.address as address", "sms.date as date" }; private final static int SINPPET_COLUMN_INDEX = 0; private final static int THREAD_ID_COLUMN_INDEX = 1; private final static int MSG_COUNT_COLUMN_INDEX = 2; private final static int ADDRESS_COLUMN_INDEX = 3; private final static int DATE_COLUMN_INDEX = 4; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_contacts_msg_calllog); lv = (ListView) findViewById(R.id.lv); adapter=new MyCursorAdapter(this, null);//初始化Adapter lv.setAdapter(adapter); startQuery(); lv.setOnItemClickListener(this); } /** * 执行查询 */ private void startQuery() { QueryHandler mQueryHandler = new QueryHandler(getContentResolver()); // 执行查询 /** * token唯一标识 cookie可以用来传递数据 上面的参数会传递给一个方法 onQueryComplete */ Uri uri = Uri.parse("content://sms/conversations"); // mQueryHandler.startQuery(0, null, uri, projection, null, // null,"date desc"); mQueryHandler.startQuery(0, adapter, uri, projection, null, null, "date desc"); } // 自定义CursorAdapter private class MyCursorAdapter extends CursorAdapter { private LayoutInflater mInflater; public MyCursorAdapter(Context context, Cursor c) { super(context, c); mInflater = LayoutInflater.from(context); } // 创建条目 @Override public View newView(Context context, Cursor cursor, ViewGroup parent) { View view = mInflater.inflate(R.layout.activity_msg_list_item, null); return view; } // 绑定条目 @Override public void bindView(View view, Context context, Cursor cursor) { // 1.获取条目 // 2.获取数据 // 3.绑定数据 ImageView iv_header = (ImageView) view.findViewById(R.id.iv_header); TextView tv_number = (TextView) view.findViewById(R.id.tv_number); TextView tv_body = (TextView) view.findViewById(R.id.tv_body); TextView tv_date = (TextView) view.findViewById(R.id.tv_date); // 由于Listview的数据显示是通过适配器来控制的,所以到bindView方法中来控制checkbox 的显示 // 获取数据 int id = cursor.getInt(THREAD_ID_COLUMN_INDEX); String address = cursor.getString(ADDRESS_COLUMN_INDEX); int msg_count = cursor.getInt(MSG_COUNT_COLUMN_INDEX); long date = cursor.getLong(DATE_COLUMN_INDEX); String body = cursor.getString(SINPPET_COLUMN_INDEX); System.out.println(address); // 绑定数据 String displayName = ContactsUtils.getContactNameByAddress( getApplicationContext(), address); if (TextUtils.isEmpty(displayName)) { // 未知联系人 iv_header.setImageResource(R.drawable.ic_launcher); tv_number.setText(address + "(" + msg_count + ")"); } else { // 已知联系人 tv_number.setText(displayName + "(" + msg_count + ")"); Bitmap bitmap = ContactsUtils.getContactPhotoByAddress( getApplicationContext(), address); if (bitmap == null) { iv_header.setImageResource(R.drawable.ic_launcher); } else { iv_header.setImageBitmap(bitmap); } } tv_body.setText(body); String dataStr = TimeUtils .formatDate(getApplicationContext(), date); tv_date.setText(dataStr); } } @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { //传递数据 Cursor cursor = (Cursor) adapter.getItem(position); int _id = cursor.getInt(THREAD_ID_COLUMN_INDEX); String address=cursor.getString(ADDRESS_COLUMN_INDEX); String displayName=ContactsUtils.getContactNameByAddress(getApplicationContext(), address); //进入列表详情页面 Intent intent=new Intent(this, MsgDetailActivity.class); intent.putExtra("_id", _id); intent.putExtra("address", address); intent.putExtra("displayName", displayName); startActivity(intent); } }短信详情页面,可以实现发送短息
package cn.zxw.contact; import cn.zxw.contact.utils.Constants; import cn.zxw.contact.utils.ContactsMsgUtils; import cn.zxw.contact.utils.QueryHandler; import cn.zxw.contact.utils.TimeUtils; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.database.Cursor; import android.os.Bundle; import android.support.v4.widget.CursorAdapter; import android.text.TextUtils; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.Button; import android.widget.EditText; import android.widget.ListView; import android.widget.TextView; import android.widget.Toast; public class MsgDetailActivity extends Activity implements OnClickListener { private Button bt_back; private TextView tv_number; private ListView lv; private EditText et_msg_content; private Button bt_send; private int _id; private String address; private MyCursorAdapter adapter; private String[] projection=new String[]{ "_id","type","body","date" }; private final static int ID_COLUMN_INDEX=0; private final static int TYPE_COLUMN_INDEX=1; private final static int BODY_COLUMN_INDEX=2; private final static int DATE_COLUMN_INDEX=3; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_msg_list_detail); initView(); startQuery(); } public void initView() { bt_back = (Button) findViewById(R.id.bt_back); tv_number = (TextView) findViewById(R.id.tv_number); lv = (ListView) findViewById(R.id.lv); et_msg_content = (EditText) findViewById(R.id.et_msg_content); bt_send = (Button) findViewById(R.id.bt_send); bt_back.setOnClickListener(this); bt_send.setOnClickListener(this); Intent intent=getIntent(); _id = intent.getIntExtra("_id", 0); address = intent.getStringExtra("address"); String displayName=intent.getStringExtra("displayName"); if (TextUtils.isEmpty(displayName)) { tv_number.setText(address); }else{ tv_number.setText(displayName); } adapter = new MyCursorAdapter(this, null); lv.setAdapter(adapter); } public void startQuery() { //查询 QueryHandler mHandler=new QueryHandler(getContentResolver()); //查询指定会话id里面的所有短信 String selection="thread_id=?"; String[] selectionArgs=new String[]{_id+""}; mHandler.startQuery(0, adapter, Constants.SMS_URI, projection, selection, selectionArgs, "date asc"); } private class MyCursorAdapter extends CursorAdapter{ public MyCursorAdapter(Context context, Cursor c) { super(context, c); } @Override public View newView(Context context, Cursor cursor, ViewGroup viewGroup) { View view=getLayoutInflater().inflate(R.layout.activity_msg_detial_item, null); return view; } @Override public void bindView(View view, Context context, Cursor cursor) { TextView tv_date=(TextView) view.findViewById(R.id.tv_date); TextView tv_send=(TextView) view.findViewById(R.id.tv_send); TextView tv_receive=(TextView) view.findViewById(R.id.tv_receive); long date=cursor.getLong(DATE_COLUMN_INDEX); String body=cursor.getString(BODY_COLUMN_INDEX); int type=cursor.getInt(TYPE_COLUMN_INDEX); String str=TimeUtils.formatDate(getApplicationContext(), date); tv_date.setText(str); if (type==Constants.RECEIVE_TYPE) { //1表示接收 tv_date.setVisibility(View.VISIBLE); tv_receive.setText(body); tv_send.setVisibility(View.GONE); }else if (type==Constants.SEND_TYPE) { //2表示发送 tv_date.setVisibility(View.VISIBLE); tv_send.setVisibility(View.VISIBLE); tv_send.setText(body); tv_receive.setVisibility(View.GONE); } } /** * 该方法一定会被系统调用 */ @Override public void notifyDataSetChanged() { super.notifyDataSetChanged(); //让Listview滚动到最后面 lv.setSelection(adapter.getCount()-1); } } @Override public void onClick(View v) { switch (v.getId()) { case R.id.bt_back: finish();//关闭当前activity break; case R.id.bt_send: // 获取短息内容 String content=et_msg_content.getText().toString().trim(); if (TextUtils.isEmpty(content)) { //发送内容为空 Toast.makeText(getApplicationContext(), "短信为空", 0).show(); }else{ ContactsMsgUtils.sendMsg(getApplicationContext(), address, content); //清空 et_msg_content.setText(""); //短息发送成功后自动滚动到最后 } break; default: break; } } }短信发送方法:
/** * 发送短信 * @param address * @param content */ public static void sendMsg(Context context,String address,String content){ SmsManager smsManager=SmsManager.getDefault();//如果短信太长,拆分短信 ArrayList<String> parts=smsManager.divideMessage(content); smsManager.sendMultipartTextMessage(address, null, parts, null, null); //手动存储短信 ContentResolver resolver=context.getContentResolver(); Uri uri=Constants.SMS_URI; ContentValues values=new ContentValues(); values.put("address", address); values.put("body", content); values.put("type", Constants.SEND_TYPE); values.put("date", System.currentTimeMillis()); resolver.insert(uri, values); }关于AsyncQueryHandler和CursorAdapter可以参考http://blog.csdn.net/yuzhiboyi/article/details/8093408和http://blog.csdn.net/yuzhiboyi/article/details/7654840来学习
原文地址:http://blog.csdn.net/waniu123/article/details/44809793