Android手机短信,通话记录和通讯录的相关操作

ContentProvider简介:
(一)、引入:
         数据库在Android当中是私有的,不能将数据库设为WORLD_READABLE,每个数据库都只能创建它的包访问。这意味着只有创建这个数据库的应用程序才可访问它。也就是说不能跨越进程和包的边界,直接访问别的应用程序的数据库。那么如何在应用程序间交换数据呢? 如果需要在进程间传递数据,可以使用ContentProvider来实现。

(二)、ContentProvider的功能和意义:
        为了在应用程序之间交换数据,Android提供了ContentProvider,ContentProvider是不同应用程序之间进行数据交换的标准API。当一个应用程序需要把自己的数据暴露给其他应用程序使用时,该应用程序可以通过提供ContentProvider来实现;而其他应用程序需要使用这些数据时,可以通过ContentResolver来操作ContentProvider暴露的数据。
        一旦某个应用程序通过ContentProvider暴露了自己的数据操作接口,那么不管该应用程序是否启动,其他应用程序都可以通过该接口来操作被暴露的内部数据,包括增加数据、删除数据、修改数据、查询数据等。
        虽然大部分使用ContentProvider操作的数据都来自于数据库,但是也可以来自于文件、SharedPreferences、XML或网络等其他存储方式。

(三)、核心类:
    1、ContentProvider:(A应用暴露数据)
  •  一个程序可以通过实现一个ContentProvider的抽象接口将自己的数据暴露出去;
  •  外界根本看不到,也不用看到这个应用暴露的数据在应用当中是如何存储的,是用数据库存储还是用文件存储,还是通过网上获得,这些一切都不重要,重要的是外界可以通过这一套标准及统一的接口和程序里的数据打交道,可以读取程序的数据,也可以修改程序的数据。
    2、ContentResolver:(操作A应用所暴露的数据)
  •   外界的程序通过ContentResolver接口可以访问ContentProvider提供的数据
  •   ContentResolve可以理解成是HttpClient的作用。
    3、 Uri:Uri是ContentResolver和ContentProvider进行数据交换的标识。
  •   每个ContentProvider提供公共的URI来唯一标识其数据集。管理多个数据集的(多个表)的 ContentProvider 为每个数据集提供了单独的URI。
  •   Uri 的标准前缀:以“content://”作为前缀,这个是标准的前缀,表示该数据由 ContentProvider 管理。
  •   Uri 的authority部分:该部分是完整的类名。(使用小写形式)。
  •   Uri 的path部分(资源部分、数据部分): 用于决定哪类数据被请求。
  •   被请求的特定记录的id值。如果请求不仅限于某个单条数据,该部分及其前面的斜线应该删除。
  •   为了将一个字符串转换成Uri,Android中提供了Uri的parse()静态方法来实现。
        
【备注:】URI、URL、URN的区别:
  • 首先,URI,是uniform resource identifier,统一资源标识符,用来唯一的标识一个资源。
  • URL是uniform resource locator,统一资源定位器,它是一种具体的URI,即URL可以用来标识一个资源,而且还指明了如何locate这个资源。
  • URN,uniform resource name,统一资源命名,是通过名字来标识资源,比如mailto:[email protected]
        也就是说,URI是以一种抽象的,高层次概念定义统一资源标识,而URL和URN则是具体的资源标识的方式。URL和URN都是一种URI
        总结一下:URL是一种具体的URI,它不仅唯一标识资源,而且还提供了定位该资源的信息。URI是一种语义上的抽象概念,可以是绝对的,也可以是相对的,而URL则必须提供足够的信息来定位,所以,是绝对的。

(四)、系统内置的预定义ContentProvider:
1、Contacts:获取、修改、保存联系人的信息;
2、MediaStore:访问声音、视频、图片等多媒体文件;
3、CallLog :查看或更新通话记录;
4、Browser:读取或修改浏览历史、网络搜索、书签;
5、Setting:查看和获取蓝牙设置、铃声设置等设备首选项。


三、使用ContentResolver 管理联系人:
(一)、 使用ContentResolver 操作数据的步骤
1、调用Context的getContentResolver()方法获得ContentResolver 对象;
2、调用使用ContentResolver 的insert()、delete()、update()、query()方法操作数据。
  • Uri insert(Uri uri, ContentValues values)
  • int delete(Uri uri, String where, String[] whereArgs)
  • Cursor query(Uri uri, String[] projection, String where, String[] whereArgs, String sortOrder)
  • int update(Uri uri, ContentValues values, String where, String[] whereArgs)
参数解释:
String   where:表示带有占位符的where子句组成的字符串;
String[]   whereArgs:表示替换where参数中占位符后的数据组成的字符串数组;
String   sortOrder:表示select语句中的order by子句组成的字符串;
String[]   projection:表示select语句中需要查询的所有的字段组成的字符串数组。
ContentValues values:是由数据库中表字段和往该字段中放置的数据所组成的键值对对象。
【备注:】以上四个方法的参数分别是2、3、4、5个。

(二)、 联系人管理中ContentProvider的几个Uri
1、联系人的Uri==>      content://com.android.contacts/contacts 和 content://com.android.contacts/raw_contacts
2、电话号码的Uri==>  content://com.android.contacts/data/phones
3、EMAIL的URI==>     content://com.android.contacts/data/emails

不过为了方便记忆,系统中提供了以下常量来替代以上的Uri字符串。
  • Uri CONTACTS_URI = ContactsContract.Contacts.CONTENT_URI;
  • Uri PHONE_URI = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
  • Uri EMAIL_URI = ContactsContract.CommonDataKinds.Email.CONTENT_URI;
  • 短信的相关操作
     
  • package com.hht.android15_contentresolversms;
    
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.List;
    import java.util.Map;
    
    import android.app.Activity;
    import android.content.ContentResolver;
    import android.content.Context;
    import android.database.Cursor;
    import android.graphics.Color;
    import android.net.Uri;
    import android.os.Bundle;
    import android.view.LayoutInflater;
    import android.view.Menu;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.BaseAdapter;
    import android.widget.ListView;
    import android.widget.TextView;
    
    public class MainActivity extends Activity {
    
    	private ListView listView_main_sms;
    
    	private Cursor cursor = null;
    
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_main);
    		listView_main_sms = (ListView) findViewById(R.id.listView_main_sms);
    		ContentResolver contentResolver = getContentResolver();
    
    		String uri = "content://sms";
    
    		cursor = contentResolver.query(Uri.parse(uri), new String[] { "_id",
    				"address", "date", "type", "body" }, null, null, null);
    
    		MySQLiteOpenHelper helper = new MySQLiteOpenHelper(this);
    
    		List> list = helper.cursorToList(cursor);		
    
    		MyAdapter adapter = new MyAdapter(this, list);
    		listView_main_sms.setAdapter(adapter);
    	}
    
    	@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;
    	}
    
    	public String timeStampToDate(long timeStamp) {
    		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm");
    
    		return dateFormat.format(new Date(timeStamp));
    
    	}
    
    	class MyAdapter extends BaseAdapter {
    
    		private Context context;
    		private List> list = null;
    
    		public MyAdapter(Context context, List> list) {
    			super();
    			this.context = context;
    			this.list = list;
    		}
    
    		@Override
    		public int getCount() {
    			// TODO Auto-generated method stub
    			return list.size();
    		}
    
    		@Override
    		public Object getItem(int position) {
    			// TODO Auto-generated method stub
    			return list.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) {
    
    			ViewHolder holder = null;
    			if (convertView == null) {
    				holder = new ViewHolder();
    				convertView = LayoutInflater.from(context).inflate(
    						R.layout.item_list_main, null);
    
    				holder.textView_address = (TextView) convertView
    						.findViewById(R.id.textView_address);
    				holder.textView_type = (TextView) convertView
    						.findViewById(R.id.textView_type);
    				holder.textView_body = (TextView) convertView
    						.findViewById(R.id.textView_body);
    				holder.textView_date = (TextView) convertView
    						.findViewById(R.id.textView_date);
    				convertView.setTag(holder);
    			} else {
    				holder = (ViewHolder) convertView.getTag();
    			}
    
    			holder.textView_address.setText(list.get(position).get("address")
    					.toString());
    			holder.textView_type.setText(list.get(position).get("type")
    					.toString());
    			holder.textView_body.setText(list.get(position).get("body")
    					.toString());
    
    			holder.textView_date.setText(timeStampToDate((Long) list.get(
    					position).get("date")));
    			if (list.get(position).get("type").toString().equals("2")) {
    
    				convertView.setBackgroundColor(Color.GRAY);
    			}
    			return convertView;
    		}
    
    		class ViewHolder {
    			private TextView textView_address;
    			private TextView textView_type;
    			private TextView textView_body;
    			private TextView textView_date;
    		}
    
    	}
    
    }
    
    通话记录的相关操作
  • package com.hht.android15_contentcontacts;
    
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.List;
    import java.util.Map;
    
    import android.app.Activity;
    import android.content.ContentResolver;
    import android.content.Context;
    import android.database.Cursor;
    import android.graphics.Color;
    import android.net.Uri;
    import android.os.Bundle;
    import android.view.LayoutInflater;
    import android.view.Menu;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.BaseAdapter;
    import android.widget.ListView;
    import android.widget.TextView;
    
    public class MainActivity extends Activity {
    
    	private ListView listView_main_contacts;
    
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_main);
    		listView_main_contacts = (ListView) findViewById(R.id.listView_main_contacts);
    
    		ContentResolver contentResolver = getContentResolver();
    		String uri = "content://call_log/calls";
    		Cursor cursor = contentResolver.query(Uri.parse(uri), new String[] {
    				"_id", "number", "type", "date" }, null, null, null);
    
    		MySQLiteOpenHelper helper = new MySQLiteOpenHelper(this);
    
    		List> list = helper.cursorToList(cursor);
    		
    		MyAdapter adapter = new MyAdapter(this, list);
    		listView_main_contacts.setAdapter(adapter);
    	}
    
    	@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;
    	}
    
    	public String timeStampToDate(long timeStamp) {
    		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm");
    
    		return dateFormat.format(new Date(timeStamp));
    
    	}
    
    	class MyAdapter extends BaseAdapter {
    
    		private Context context;
    		private List> list = null;
    
    		public MyAdapter(Context context, List> list) {
    			super();
    			this.context = context;
    			this.list = list;
    		}
    
    		@Override
    		public int getCount() {
    			// TODO Auto-generated method stub
    			return list.size();
    		}
    
    		@Override
    		public Object getItem(int position) {
    			// TODO Auto-generated method stub
    			return list.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) {
    
    			ViewHolder holder = null;
    			if (convertView == null) {
    				holder = new ViewHolder();
    				convertView = LayoutInflater.from(context).inflate(
    						R.layout.item_list_main, null);
    
    				holder.textView_number = (TextView) convertView
    						.findViewById(R.id.textView_number);
    				holder.textView_type = (TextView) convertView
    						.findViewById(R.id.textView_type);
    				holder.textView_date = (TextView) convertView
    						.findViewById(R.id.textView_date);
    				convertView.setTag(holder);
    			} else {
    				holder = (ViewHolder) convertView.getTag();
    			}
    
    			holder.textView_number.setText(list.get(position).get("number")
    					.toString());
    			holder.textView_type.setText(list.get(position).get("type")
    					.toString());
    			holder.textView_date.setText(timeStampToDate((Long) list.get(
    					position).get("date")));
    			if (list.get(position).get("type").toString().equals("2")) {
    
    				convertView.setBackgroundColor(Color.GRAY);
    			}
    			return convertView;
    		}
    
    		class ViewHolder {
    			private TextView textView_number;
    			private TextView textView_type;
    			private TextView textView_date;
    		}
    
    	}
    
    }
    

    通讯录的相关操作
  • package com.hht.android15_contentcontacts;
    
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    import android.content.ContentResolver;
    import android.content.ContentUris;
    import android.content.ContentValues;
    import android.database.Cursor;
    import android.net.Uri;
    
    public class MyContactsHelper {
    	// 获取联系人信息
    	public static List> selectContactsMsg(
    
    	ContentResolver resolver) {
    
    		List> list = new ArrayList>();
    
    		String uri_contacts = "content://com.android.contacts/raw_contacts";
    
    		String uri_contacts_phones = "content://com.android.contacts/data/phones";
    
    		String uri_contacts_emails = "content://com.android.contacts/data/emails";
    
    		// 从raw_contacts表中或许联系人的id和联系人的姓名。
    
    		Cursor cursor_contacts = resolver.query(Uri.parse(uri_contacts),
    
    		new String[] { "_id", "display_name" }, null, null, null);
    
    		// 遍历所有的联系人的信息
    
    		while (cursor_contacts.moveToNext()) {
    
    			int contacts_id = cursor_contacts.getInt(cursor_contacts
    
    			.getColumnIndex("_id"));
    
    			String display_name = cursor_contacts.getString(cursor_contacts
    
    			.getColumnIndex("display_name"));
    
    			Map map = new HashMap();
    
    			map.put("_id", contacts_id);
    
    			map.put("display_name", display_name);
    
    			// 以下开始获取电话号码
    
    			// 根据每个联系人的id再去data表中查找相应的电话号码。
    
    			Cursor cursor_phones = resolver.query(
    
    			Uri.parse(uri_contacts_phones), new String[] {
    
    			"raw_contact_id", "data1" }, "raw_contact_id=?",
    
    			new String[] { contacts_id + "" }, null);
    
    			// 因为电话号码可能是多个,所以需要再遍历,组合在一起形成一个电话号码的字符串,放到StringBuilder中
    
    			StringBuilder sb = new StringBuilder();
    
    			while (cursor_phones.moveToNext()) {
    
    				sb.append(cursor_phones.getString(1));
    
    				sb.append(" | ");
    
    			}
    
    			// 将生成的电话号码放到map集合中
    
    			map.put("phones", sb.toString());
    
    			// 以下开始或许Email信息
    
    			Cursor cursor_emails = resolver.query(
    
    			Uri.parse(uri_contacts_emails), new String[] {
    
    			"raw_contact_id", "data1" }, "raw_contact_id=?",
    
    			new String[] { contacts_id + "" }, null);
    
    			StringBuilder sb2 = new StringBuilder();
    
    			while (cursor_emails.moveToNext()) {
    
    				sb2.append(cursor_emails.getString(1));
    
    				sb2.append(" | ");
    
    			}
    
    			map.put("emails", sb2.toString());
    
    			// 将包含有id、联系人姓名、手机号码、emails的map放到list集合中
    
    			list.add(map);
    
    		}
    
    		return list;
    	}
    
    	// 以下代码是更新联系人姓名的方法。
    
    	public static boolean updateContactsName(ContentResolver resolver,
    			Map map, int id) {
    
    		String uri_contacts = "content://com.android.contacts/raw_contacts";
    
    		String uri_contacts_data = "content://com.android.contacts/data";
    		ContentValues values = new ContentValues();
    
    		// 修改raw_contacts表中的数据
    		values.put("display_name", map.get("display_name").toString());
    
    		values.put("display_name_alt", map.get("display_name").toString());
    
    		values.put("sort_key", map.get("display_name").toString());
    
    		values.put("sort_key_alt", map.get("display_name").toString());
    
    		int count1 = resolver.update(Uri.parse(uri_contacts), values,
    
    		"_id=?", new String[] { id + "" });
    
    		// 修改data表姓名的数据
    
    		values.clear();
    
    		values.put("data1", map.get("display_name").toString());
    
    		values.put("data2", map.get("display_name").toString());
    
    		int count2 = resolver.update(Uri.parse(uri_contacts_data), values,
    
    		"raw_contact_id=? and mimetype_id=?", new String[] { id + "", "7" });
    
    		// 修改data表中phone的数据
    		values.clear();
    
    		values.put("data1", map.get("phone").toString());
    
    		values.put("data2", 2);
    
    		int count3 = resolver.update(Uri.parse(uri_contacts_data), values,
    
    		"raw_contact_id =? and mimetype_id=?", new String[] { id + "", "5" });
    
    		// 修改data表中email的数据
    		values.clear();
    
    		values.put("data1", map.get("email").toString());
    
    		values.put("data2", 1);
    
    		int count4 = resolver.update(Uri.parse(uri_contacts_data), values,
    
    		"raw_contact_id=? and mimetype_id=?", new String[] { id + "", "1" });
    		if (count1 > 0 && count2 > 0 && count3 > 0 && count4 > 0) {
    			return true;
    		} else {
    			return false;
    		}
    
    	}
    
    	public static void insertContacts(ContentResolver resolver,
    			List list) {
    		String uri_rawcontacts = "content://com.android.contacts/raw_contacts";
    		String uri_contacts_data = "content://com.android.contacts/data";
    		Uri uri = Uri.parse(uri_contacts_data);
    		// 首先向RawContacts.CONTENT_URI执行一个空值插入,目的是获取系统返回的rawContactId
    		ContentValues values = new ContentValues();
    		Uri rawContactUri = resolver.insert(Uri.parse(uri_rawcontacts), values);
    		long contact_id = ContentUris.parseId(rawContactUri);
    
    		// 向data表中添加用户名称信息
    		values.put("raw_contact_id", contact_id);
    		values.put("mimetype", "vnd.android.cursor.item/name");
    		values.put("data1", list.get(0));
    		values.put("data2", list.get(0));
    		resolver.insert(uri, values);
    		// 往data表中插入电话信息
    		values.clear();
    		values.put("raw_contact_id", contact_id);
    		values.put("mimetype", "vnd.android.cursor.item/phone_v2");
    		values.put("data1", list.get(1));
    		values.put("data2", 2);// 2,Phone.TYPE_MOBILE ,表示手机号码
    		resolver.insert(uri, values);
    
    		// 往data表中插入Email信息
    		values.clear();
    		values.put("raw_contact_id", contact_id);
    		values.put("mimetype", "vnd.android.cursor.item/email_v2");
    		values.put("data1", list.get(2));
    		values.put("data2", 2);// 2,Email.TYPE_WORK , 表示工作用Email号码
    		resolver.insert(uri, values);
    	}
    
    	// 以下代码是删除联系人信息的方法。
    	public static int deleteContacts(ContentResolver resolver, String where,
    			String[] whereArgs) {
    		String uri_contacts = "content://com.android.contacts/raw_contacts";
    		return resolver.delete(Uri.parse(uri_contacts), where, whereArgs);
    	}
    }
    

    四、系统自带ContentProvider的常用Uri地址:

    (一)、Android系统管理联系人的Uri如下:

    1. ContactsContract.Contacts.CONTENT_URI 管理联系人的Uri
    2. ContactsContract.CommonDataKinds.Phone.CONTENT_URI 管理联系人的电话的Uri
    3. ContactsContract.CommonDataKinds.Email.CONTENT_URI 管理联系人的Email的Uri
    【数据库中主要字段:】

    1. 联系人id字段名称为:ContactsContract.Contacts._ID
    2. 联系人name 字段为:ContactContract.Contracts.DISPLAY_NAME
    3. 电话信息表的外键id为:ContactsContract.CommonDataKinds.Phone.CONTACT_ID
    4. 电话号码 字段为:ContactsContract.CommonDataKinds.Phone.NUMBER.
    5. Email 字段为:ContactsContract.CommonDataKinds.Email.DATA
    6. 其外键为:ContactsContract.CommonDataKinds.Email.CONTACT_ID


    (二)、Android为多媒体提供的ContentProvider的Uri如下:

    1. MediaStore.Audio.Media.EXTERNAL_CONTENT_URI        存储在SD卡上的音频文件
    2. MediaStore.Audio.Video.EXTERNAL_CONTENT_URI         存储在 SD卡上的视频
    3. MediaStore.Audio.Images.EXTERNAL_CONTENT_URI       存储在 SD卡上的图片文件内容
    4. MediaStore.Audio.Media.INTERNAL_CONTENT_URI         手机内部存储器上的音频文件 
    5. MediaStore.Audio.Video.INTERNAL_CONTENT_URI          手机内部存储器上的视频
    6. MediaStore.Audio.Images.INTERNAL_CONTENT_URI        手机内部存储器上的图片

    【数据库中主要字段:】

    1. 图片名称字段:Media.DISPLAY_NAME
    2. 图片的详细描述字段:Media.DESCRIPTION  
    3. 图片的保存位置字段:Media.DATA

    (三)、短信Uri:

    1.  content://sms                所有短信
    2. content://sms/outbox      发送箱中的短信 
    3. content://sms/inbox       收件箱中短信
    【数据库中主要字段:】

    1. 短信手机号码 : address
    2. 短信标题:  subject
    3. 短信内容:body
    4.  短信发送时间戳:date

    (四)、通话记录Uri:

    1.  content://call_log/calls               所有通话记录

你可能感兴趣的:(Android技术)