ContentProvider实现数据共享-->【好处:统一了数据的访问方式】
一、ContentProvider的作用与常用方法
Uri简介


ContentResolver
Context提供了getContentResolver()来获得ContentResolver对象。
调用ContentResolver的如下方法来操作数据:
<1>、insert(Uri url, ContentValues values):向Uri对应的ContentProvider中插入values对应的数据;
<2>、delete(Uri url, String where, String[] selectionArgs):删除Uri对应的ContentProvider中where提交匹配的数据;
<3>、update(Uri uri, ContentValues values, String where, String[] selectionArgs):更新Uri对应的ContentProvider中where提交匹配的数据;
<4>、query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder):查询Uri对应的ContentResolver中where提交匹配的数据;

ContentResolver与ContentProvider关系
以指定Uri为标识,ContentResolver可以实现“间接调用”ContentProvider的CRUD方法。

开发ContentProvider
(1)、开发一个ContentProvider的子类,该子类需要实现query()、insert()、update()、delete()等方法;
(2)、在清单文件中注册该ContentProvider,指定android:authorities属性;

配置ContentProvider
<!-- 注册一个ContentProvider -->
<provider 
	android:name=".DictProvider" //类名
	android:authorities="com.android.providers.dictprovider"  //指定Uri
	android:exported="true"  //是否允许其他程序调用
/>

创建ContentProvider
ContentProvider只有一个生命周期方法:onCreate()方法,第一次访问ContentProvider时,onCreate()方法会被回调。
UriMatcher工具类提供了2个方法用来确定内容提供者实际能处理的Uri:
	1>.void addRUI(String authority,String path,int code):用于向UriMathcher对象注册Uri.authority和path组合成一个Uri,而code则代表该Uri对应的标识符。
	2>.int match(Uri uri):根据前面注册的Uri来判断指定uri对应的标识符,如果找不到匹配的标识码就返回-1.

二、使用ContentProvider操作数据
public class zouyongprovider extends ContentProvider 
{
	private DBOpenHelper dbhelper;
	private static final UriMatcher MARCHER=new UriMatcher(UriMatcher.NO_MATCH);
	private static final int USERS=1;
	private static final int USER=2;
	static
	{
		MARCHER.addURI("com.zouyong.provider.zouyongprovider", "user", USERS);
		MARCHER.addURI("com.zouyong.provider.zouyongprovider", "user/#", USER);//#代表数字
	}
	public boolean onCreate() //对象被创建时调用,调用1次
	{
		this.dbhelper=new DBOpenHelper(getContext());
		return true;
	}
	
	public Uri insert(Uri uri, ContentValues values) //插入数据
	{
		SQLiteDatabase db=dbhelper.getWritableDatabase();
		switch (MARCHER.match(uri)) {
		case USERS:
			long rawid=db.insert("userinfo", "user", values);
			Uri insertUri=ContentUris.withAppendedId(uri, rawid);
			this.getContext().getContentResolver().notifyChange(insertUri, null);//发出数据变化通知
			return insertUri;
		default:
			throw new IllegalArgumentException("Wrong Uri!");
		}
	}
	
	public int delete(Uri uri, String selection, String[] selectionArgs) //删除数据
	{
		SQLiteDatabase db=dbhelper.getWritableDatabase();
		int num=0;
		switch (MARCHER.match(uri)) {
		case USERS:
			num=db.delete("userinfo", selection, selectionArgs);
			break;
		case USER:
			long userid=ContentUris.parseId(uri);
			String whereClause="_id="+userid;
			if(selection!=null && !"".equals(selection.trim()))
				whereClause=whereClause+" and "+selection;
			num=db.delete("userinfo", whereClause, selectionArgs);
			break;
		default:
			throw new IllegalArgumentException("Wrong Uri!");
		}
		return num;
	}

	public int update(Uri uri, ContentValues values, String selection,String[] selectionArgs) //更新数据
	{
		SQLiteDatabase db=dbhelper.getWritableDatabase();
		int num=0;
		switch (MARCHER.match(uri)) {
		case USERS:
			num=db.update("userinfo", values, selection, selectionArgs);
			break;
		case USER:
			long userid=ContentUris.parseId(uri);
			String whereClause="_id="+userid;
			if(selection!=null && !"".equals(selection.trim()))
				whereClause=whereClause+" and "+selection;
			num=db.update("userinfo", values, whereClause, selectionArgs);
			break;
		default:
			throw new IllegalArgumentException("Wrong Uri!");
		}
		return num;
	}

	public Cursor query(Uri uri, String[] projection, String selection,String[] selectionArgs, String sortOrder)//外部应用查询 
	{
		SQLiteDatabase db=dbhelper.getReadableDatabase();
		switch (MARCHER.match(uri)) {
		case USERS:
			return db.query("userinfo", projection, selection, selectionArgs, null, null, sortOrder);//返回Cursor对象
		case USER:
			long userid=ContentUris.parseId(uri);
			String whereClause="_id="+userid;
			if(selection!=null && !"".equals(selection.trim()))
				whereClause=whereClause+" and "+selection;
			return db.query("userinfo", projection, whereClause, selectionArgs, null, null, sortOrder);//返回Cursor对象
		default:
			throw new IllegalArgumentException("Wrong Uri!");
		}
	}

	public String getType(Uri uri) 
	//该方法用于返回当前Uri所代表数据的MIME类型,如果操作的数据数据集合类型,MIME类型字符串应该以vnd.android.cursor.dir/开头;如果要操作的数据属于非集合类型数据,那么MIME类型字符串应该以vnd.android.cursor.item/开头
	{
		switch (MARCHER.match(uri)) {
		case USERS:
			return "vnd.android.cursor.dir/user";
		case USER:
			return "vnd.android.cursor.item/user";
		default:
			throw new IllegalArgumentException("Wrong Uri!");
			}
	}
}

其他应用使用内容提供者的数据
public class ContentProviderTest extends AndroidTestCase 
{
	private static final String TAG="ContentProviderTest";
	
	public void testInsert() throws Exception
	{
		Uri uri=Uri.parse("content://com.zouyong.provider.zouyongprovider/user");
		ContentResolver resolver=this.getContext().getContentResolver();
		ContentValues values=new ContentValues();
		values.put("name", "zhangsan");
		values.put("phone", "123456");
		values.put("amount", "1222222");
		resolver.insert(uri, values);
	}
	
	public void testDelete() throws Exception
	{
		Uri uri=Uri.parse("content://com.zouyong.provider.zouyongprovider/user/89");
		ContentResolver resolver=this.getContext().getContentResolver();
		resolver.delete(uri, null, null);
	}
	
	public void testUpdate() throws Exception
	{
		Uri uri=Uri.parse("content://com.zouyong.provider.zouyongprovider/user/89");
		ContentResolver resolver=this.getContext().getContentResolver();
		ContentValues values=new ContentValues();
		values.put("name", "wangwu");
		resolver.update(uri, values, null, null);
	}
	
	public void testQuery() throws Exception
	{
		Uri uri=Uri.parse("content://com.zouyong.provider.zouyongprovider/user/89");
		ContentResolver resolver=this.getContext().getContentResolver();
		Cursor cursor=resolver.query(uri, null, null, null, "_id asc");
		while(cursor.moveToNext())
		{
			String name=cursor.getString(cursor.getColumnIndex("name"));
			Log.i(TAG, name);
		}
		cursor.close();
	}
}

三、监听ContentProvider中的数据变化
ContentProvider中:
public Uri insert(Uri uri, ContentValues values) //插入数据
{
	......
	this.getContext().getContentResolver().notifyChange(insertUri, null);
	......
}
A应用插入数据:
public void insert(View view)
{
	Uri uri=Uri.parse("content://com.zouyong.provider.zouyongprovider/user");
	ContentResolver resolver=this.getContentResolver();
	ContentValues values=new ContentValues();
	values.put("name", "zhangsan");
	values.put("phone", "8888888");
	values.put("amount", "9999999");
	resolver.insert(uri, values);
}
B应用中监听数据变化:
Uri uri=Uri.parse("content://com.zouyong.provider.zouyongprovider/user");
this.getContentResolver().registerContentObserver(uri, true, new UserContentObserver(new Handler()));
private class UserContentObserver extends ContentObserver
{
	public UserContentObserver(Handler handler) 
	{
		super(handler);
	}


	public void onChange(boolean selfChange) 
	{
		Uri uri=Uri.parse("content://com.zouyong.provider.zouyongprovider/user");
		ContentResolver resolver=getContentResolver();
		Cursor cursor=resolver.query(uri, null, null, null, "_id desc limit 1");
		if(cursor.moveToFirst())
		{
			String name=cursor.getString(cursor.getColumnIndex("name"));
			Log.i(TAG, name);
		}
		cursor.close();
	}
}

/***********监听用户发出的短信**************/
/****Uri为content://sms的数据改变即可监听到用户短信的数据变化,并在监听器的onChange(boolean selfChange)方法里查询Uri为content://sms/outbox的数据,这样即可获取用户正在发送的短信****************/
public class MonitorSms extends Activity
{
	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		// 为content://sms的数据改变注册监听器
		getContentResolver().registerContentObserver(
			Uri.parse("content://sms"), true,
			new SmsObserver(new Handler()));
	}

	// 提供自定义的ContentObserver监听器类
	private final class SmsObserver extends ContentObserver
	{
		public SmsObserver(Handler handler)
		{
			super(handler);
		}


		public void onChange(boolean selfChange)
		{
			// 查询发送箱中的短信(处于正在发送状态的短信放在发送箱)
			Cursor cursor = getContentResolver().query(
				Uri.parse("content://sms/outbox")
				, null, null, null, null);
			// 遍历查询得到的结果集,即可获取用户正在发送的短信
			while (cursor.moveToNext())
			{
				StringBuilder sb = new StringBuilder();
				// 获取短信的发送地址
				sb.append("address=").append(cursor
					.getString(cursor.getColumnIndex("address")));
				// 获取短信的标题
				sb.append(";subject=").append(cursor
					.getString(cursor.getColumnIndex("subject")));
				// 获取短信的内容
				sb.append(";body=").append(cursor
					.getString(cursor.getColumnIndex("body")));
				// 获取短信的发送时间
				sb.append(";time=").append(cursor
					.getLong(cursor.getColumnIndex("date")));
				Toast.makeText(getApplicationContext(), sb.toString(), 1).show();
			}
		}
	}
}

四、调用系统的ContentProvider
访问通讯录中的联系人和添加联系人
Android系统对联系人管理ContentProvider的几个Uri如下:
ContactsContract.Contacts.CONTENT_URI:管理联系人的Uri
ContactsContract.CommonDataKinds.Phone.CONTENT_URI:管理联系人电话的Uri
ContactsContract.CommonDataKinds.Email.CONTENT_URI:管理联系人Email的Uri

/**********书籍中的例子******************/
public class ContactProviderTest extends Activity
{
	Button search;
	Button add;


	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		// 获取系统界面中查找、添加两个按钮
		search = (Button) findViewById(R.id.search);
		add = (Button) findViewById(R.id.add);
		search.setOnClickListener(new OnClickListener()
		{
			@Override
			public void onClick(View source)
			{
				// 定义两个List来封装系统的联系人信息、指定联系人的电话号码、Email等详情
				final ArrayList<String> names = new ArrayList<String>();
				final ArrayList<ArrayList<String>> details 
					= new ArrayList<ArrayList<String>>();
				// 使用ContentResolver查找联系人数据
				Cursor cursor = getContentResolver().query(
					ContactsContract.Contacts.CONTENT_URI, null, null,
					null, null);
				// 遍历查询结果,获取系统中所有联系人
				while (cursor.moveToNext())
				{
					// 获取联系人ID
					String contactId = cursor.getString(cursor
						.getColumnIndex(ContactsContract.Contacts._ID));
					// 获取联系人的名字
					String name = cursor.getString(cursor.getColumnIndex(
						ContactsContract.Contacts.DISPLAY_NAME));
					names.add(name);
					// 使用ContentResolver查找联系人的电话号码
					Cursor phones = getContentResolver().query(
						ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
						null,
						ContactsContract.CommonDataKinds.Phone.CONTACT_ID
							+ " = " + contactId, null, null);
					ArrayList<String> detail = new ArrayList<String>();
					// 遍历查询结果,获取该联系人的多个电话号码
					while (phones.moveToNext())
					{
						// 获取查询结果中电话号码列中数据。
						String phoneNumber = phones.getString(phones
							.getColumnIndex(ContactsContract
							.CommonDataKinds.Phone.NUMBER));
						detail.add("电话号码:" + phoneNumber);
					}
					phones.close();
					// 使用ContentResolver查找联系人的Email地址
					Cursor emails = getContentResolver().query(
						ContactsContract.CommonDataKinds.Email.CONTENT_URI,
						null,
						ContactsContract.CommonDataKinds.Email.CONTACT_ID
						+ " = " + contactId, null, null);
					// 遍历查询结果,获取该联系人的多个Email地址
					while (emails.moveToNext())
					{
						// 获取查询结果中Email地址列中数据。
						String emailAddress = emails.getString(emails
							.getColumnIndex(ContactsContract
							.CommonDataKinds.Email.DATA));
						detail.add("邮件地址:" + emailAddress);
					}
					emails.close();
					details.add(detail);
				}
				cursor.close();
				// 加载result.xml界面布局代表的视图
				View resultDialog = getLayoutInflater().inflate(
					R.layout.result, null);
				// 获取resultDialog中ID为list的ExpandableListView
				ExpandableListView list = (ExpandableListView) resultDialog
					.findViewById(R.id.list);
				// 创建一个ExpandableListAdapter对象
				ExpandableListAdapter adapter = 
					new BaseExpandableListAdapter()
				{
					// 获取指定组位置、指定子列表项处的子列表项数据
					@Override
					public Object getChild(int groupPosition,
						int childPosition)
					{
						return details.get(groupPosition).get(
							childPosition);
					}
		
					@Override
					public long getChildId(int groupPosition,
						int childPosition)
					{
						return childPosition;
					}
		
					@Override
					public int getChildrenCount(int groupPosition)
					{
						return details.get(groupPosition).size();
					}
		
					private TextView getTextView()
					{
						AbsListView.LayoutParams lp = new AbsListView
							.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT
							, 64);
						TextView textView = new TextView(
							ContactProviderTest.this);
						textView.setLayoutParams(lp);
						textView.setGravity(Gravity.CENTER_VERTICAL
							| Gravity.LEFT);
						textView.setPadding(36, 0, 0, 0);
						textView.setTextSize(20);
						return textView;
					}
		
					// 该方法决定每个子选项的外观
					@Override
					public View getChildView(int groupPosition,
						int childPosition, boolean isLastChild,
						View convertView, ViewGroup parent)
					{
						TextView textView = getTextView();
						textView.setText(getChild(groupPosition,
							childPosition).toString());
						return textView;
					}
		
					// 获取指定组位置处的组数据
					@Override
					public Object getGroup(int groupPosition)
					{
						return names.get(groupPosition);
					}
		
					@Override
					public int getGroupCount()
					{
						return names.size();
					}
		
					@Override
					public long getGroupId(int groupPosition)
					{
						return groupPosition;
					}
		
					// 该方法决定每个组选项的外观
					@Override
					public View getGroupView(int groupPosition,
						boolean isExpanded, View convertView,
						ViewGroup parent)
					{
						TextView textView = getTextView();
						textView.setText(getGroup(groupPosition)
							.toString());
						return textView;
					}
		
					@Override
					public boolean isChildSelectable(int groupPosition,
						int childPosition)
					{
						return true;
					}
		
					@Override
					public boolean hasStableIds()
					{
						return true;
					}
				};
				// 为ExpandableListView设置Adapter对象
				list.setAdapter(adapter);
				// 使用对话框来显示查询结果。
				new AlertDialog.Builder(ContactProviderTest.this)
					.setView(resultDialog).setPositiveButton("确定", null)
					.show();
			}
		});
		// 为add按钮的单击事件绑定监听器
		add.setOnClickListener(new OnClickListener()
		{
			@Override
			public void onClick(View v)
			{
				// 获取程序界面中的3个文本框
				String name = ((EditText) findViewById(R.id.name))
					.getText().toString();
				String phone = ((EditText) findViewById(R.id.phone))
					.getText().toString();
				String email = ((EditText) findViewById(R.id.email))
					.getText().toString();
				// 创建一个空的ContentValues
				ContentValues values = new ContentValues();
				// 向RawContacts.CONTENT_URI执行一个空值插入,
				// 目的是获取系统返回的rawContactId
				Uri rawContactUri = getContentResolver().insert(
					RawContacts.CONTENT_URI, values);
				long rawContactId = ContentUris.parseId(rawContactUri);
				values.clear();
				values.put(Data.RAW_CONTACT_ID, rawContactId);
				// 设置内容类型
				values
					.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);
				// 设置联系人名字
				values.put(StructuredName.GIVEN_NAME, name);
				// 向联系人URI添加联系人名字
				getContentResolver().insert(
					android.provider.ContactsContract.Data.CONTENT_URI,
					values);
				values.clear();
				values.put(Data.RAW_CONTACT_ID, rawContactId);
				values.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
				// 设置联系人的电话号码
				values.put(Phone.NUMBER, phone);
				// 设置电话类型
				values.put(Phone.TYPE, Phone.TYPE_MOBILE);
				// 向联系人电话号码URI添加电话号码
				getContentResolver().insert(
					android.provider.ContactsContract.Data.CONTENT_URI,
					values);
				values.clear();
				values.put(Data.RAW_CONTACT_ID, rawContactId);
				values.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE);
				// 设置联系人的Email地址
				values.put(Email.DATA, email);
				// 设置该电子邮件的类型
				values.put(Email.TYPE, Email.TYPE_WORK);
				// 向联系人Email URI添加Email数据
				getContentResolver().insert(
					android.provider.ContactsContract.Data.CONTENT_URI,
					values);
				Toast.makeText(ContactProviderTest.this, "联系人数据添加成功",
					Toast.LENGTH_LONG).show();
			}
		});
	}
}

/**********视频教程中例子******************/
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<uses-permission android:name="android.permission.WRITE_CONTACTS"/>
//往通信录中添加联系人
public void testAddContact()
{
	Uri uri=Uri.parse("content://com.android.contacts/raw_contacts");
	ContentResolver resolver=this.getContext().getContentResolver();
	ContentValues values=new ContentValues();
	long contactid=ContentUris.parseId(resolver.insert(uri, values));
	uri=Uri.parse("content://com.android.contacts/data");
	//添加姓名
	values.put("raw_contact_id", contactid);
	values.put("mimetype", "vnd.android.cursor.item/name");
	values.put("data2", "zhangsan");
	resolver.insert(uri, values);
	//添加电话
	values.clear();
	values.put("raw_contact_id", contactid);
	values.put("mimetype", "vnd.android.cursor.item/phone_v2");
	values.put("data2", "2");
	values.put("data1", "999");
	resolver.insert(uri, values);
	//添加E-Mail
	values.clear();
	values.put("raw_contact_id", contactid);
	values.put("mimetype", "vnd.android.cursor.item/email_v2");
	values.put("data2", "2");
	values.put("data1", "hello@126.com");
	resolver.insert(uri, values);
}
//在同一个事务中完成联系人各项数据的添加
public void testSaveContact() throws RemoteException, OperationApplicationException
{
	Uri uri=Uri.parse("content://com.android.contacts/raw_contacts");
	ContentResolver resolver=this.getContext().getContentResolver();
	ArrayList<ContentProviderOperation> operations=new ArrayList<ContentProviderOperation>();
	ContentProviderOperation op1=ContentProviderOperation.newInsert(uri)
	.withValue("account_name", null)//Gmail帐号
	.build();
	operations.add(op1);
	uri=Uri.parse("content://com.android.contacts/data");
	ContentProviderOperation op2=ContentProviderOperation.newInsert(uri)
	.withValueBackReference("raw_contact_id", 0)
	.withValue("mimetype", "vnd.android.cursor.item/name")
	.withValue("data2", "lisi")
	.build();
	operations.add(op2);
	
	ContentProviderOperation op3=ContentProviderOperation.newInsert(uri)
	.withValueBackReference("raw_contact_id", 0)
	.withValue("mimetype", "vnd.android.cursor.item/phone_v2")
	.withValue("data2", "2")
	.withValue("data1", "911")
	.build();
	operations.add(op3);
	
	ContentProviderOperation op4=ContentProviderOperation.newInsert(uri)
	.withValueBackReference("raw_contact_id", 0)
	.withValue("mimetype", "vnd.android.cursor.item/email_v2")
	.withValue("data2", "2")
	.withValue("data1", "world@126.com")
	.build();
	operations.add(op4);


	resolver.applyBatch("com.android.contacts", operations);
}
//查询所有联系人
public void testContacts()
{
	Uri uri=Uri.parse("content://com.android.contacts/contacts");
	ContentResolver resolver=this.getContext().getContentResolver();
	Cursor cursor=resolver.query(uri, new String[]{"_id"}, null, null, null);
	while(cursor.moveToNext())
	{
		StringBuilder sb=new StringBuilder();
		long contactid=cursor.getInt(0);
		sb.append("contactid:"+contactid+";");
		uri=Uri.parse("content://com.android.contacts/contacts/"+contactid+"/data");
		Cursor datacursor=resolver.query(uri, new String[]{"mimetype","data1","data2"},  null, null, null);
		while(datacursor.moveToNext())
		{
			String data=datacursor.getString(datacursor.getColumnIndex("data1"));
			String type=datacursor.getString(datacursor.getColumnIndex("mimetype"));
			if(type.equals("vnd.android.cursor.item/name"))
			{
				sb.append("name:"+data+";");
			}
			if(type.equals("vnd.android.cursor.item/phone_v2"))
			{
				sb.append("phonenumer:"+data+";");
			}
			if(type.equals("vnd.android.cursor.item/email_v2"))
			{
				sb.append("email:"+data+".");
			}
		}
		Log.i(TAG, sb.toString());
	}
}
//根据号码查询联系人姓名
public void testContactByNumber()
{
	String mobilenumber="999";
	Uri uri=Uri.parse("content://com.android.contacts/data/phones/filter/"+mobilenumber);
	ContentResolver resolver=this.getContext().getContentResolver();
	Cursor cursor=resolver.query(uri, new String[]{"display_name"}, null, null, null);
	if(cursor.moveToFirst())
	{
		String contactname="Name:"+cursor.getString(0);
		Log.i(TAG, contactname);
	}
	cursor.close();
}

Android为多媒体提供的ContentProvider的Uri如下:
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI:存储在外置SD卡上音频内容的URI
MediaStore.Audio.Media.INTERNAL_CONTENT_URI:存储在内置SD卡上音频内容的URI
MediaStore.Images.Media.EXTERNAL_CONTENT_URI:存储在外置SD卡上图片文件的URI
MediaStore.Images.Media.INTERNAL_CONTENT_URI:存储在内置SD卡上图片文件的URI
MediaStore.Video.Media.EXTERNAL_CONTENT_URI:存储在外置SD卡上视频内容的URI
MediaStore.Video.Media.INTERNAL_CONTENT_URI:存储在内置SD卡上视频内容的URI

public class MediaProviderTest extends Activity
{
	Button add;
	Button view;
	ListView show;
	ArrayList<String> names = new ArrayList<String>();
	ArrayList<String> descs = new ArrayList<String>();
	ArrayList<String> fileNames = new ArrayList<String>();


	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		add = (Button) findViewById(R.id.add);
		view = (Button) findViewById(R.id.view);
		show = (ListView) findViewById(R.id.show);
		// 为add按钮的单击事件绑定监听器
		add.setOnClickListener(new OnClickListener()
		{
			@Override
			public void onClick(View v)
			{
				// 创建ContentValues对象,准备插入数据
				ContentValues values = new ContentValues();
				values.put(Media.DISPLAY_NAME, "jinta");
				values.put(Media.DESCRIPTION, "金塔");
				values.put(Media.MIME_TYPE, "image/jpeg");
				// 插入数据,返回所插入数据对应的Uri
				Uri uri = getContentResolver().insert(
					Media.EXTERNAL_CONTENT_URI, values);
				// 加载应用程序下的jinta图片
				Bitmap bitmap = BitmapFactory.decodeResource(
					MediaProviderTest.this.getResources(),
					R.drawable.jinta);
				OutputStream os = null;
				try
				{
					// 获取刚插入的数据的Uri对应的输出流
					os = getContentResolver().openOutputStream(uri); //①
					// 将bitmap图片保存到Uri对应的数据节点中
					bitmap.compress(Bitmap.CompressFormat.JPEG, 100, os);
					os.close();
				}
				catch (IOException e)
				{
					e.printStackTrace();
				}
			}
		});
		// 为view按钮的单击事件绑定监听器
		view.setOnClickListener(new OnClickListener()
		{
			@Override
			public void onClick(View v)
			{
				// 清空names、descs、fileNames集合里原有的数据。
				names.clear();
				descs.clear();
				fileNames.clear();
				// 通过ContentResolver查询所有图片信息
				Cursor cursor = getContentResolver().query(
					Media.EXTERNAL_CONTENT_URI, null, null, null, null);
				while (cursor.moveToNext())
				{
					// 获取图片的显示名
					String name = cursor.getString(cursor
						.getColumnIndex(Media.DISPLAY_NAME));
					// 获取图片的详细描述
					String desc = cursor.getString(cursor
						.getColumnIndex(Media.DESCRIPTION));
					// 获取图片的保存位置的数据
					byte[] data = cursor.getBlob(cursor
						.getColumnIndex(Media.DATA));
					// 将图片名添加到names集合中
					names.add(name);
					// 将图片描述添加到descs集合中
					descs.add(desc);
					// 将图片保存路径添加到fileNames集合中
					fileNames.add(new String(data, 0, data.length - 1));
				}
				// 创建一个List集合,List集合的元素是Map
				List<Map<String, Object>> listItems =
					new ArrayList<Map<String, Object>>();
				// 将names、descs两个集合对象的数据转换到Map集合中
				for (int i = 0; i < names.size(); i++)
				{
					Map<String, Object> listItem =
						new HashMap<String, Object>();
					listItem.put("name", names.get(i));
					listItem.put("desc", descs.get(i));
					listItems.add(listItem);
				}
				// 创建一个SimpleAdapter
				SimpleAdapter simpleAdapter = new SimpleAdapter(
					MediaProviderTest.this, listItems
					, R.layout.line,
					new String[] { "name", "desc" }
					, new int[] {R.id.name, R.id.desc });
				// 为show ListView组件设置Adapter
				show.setAdapter(simpleAdapter);
			}
		});
		// 为show ListView的列表项单击事件添加监听器
		show.setOnItemClickListener(new OnItemClickListener()
		{
			@Override
			public void onItemClick(AdapterView<?> parent
				, View source, int position, long id)
			{
				// 加载view.xml界面布局代表的视图
				View viewDialog = getLayoutInflater().inflate(
					R.layout.view, null);
				// 获取viewDialog中ID为image的组件
				ImageView image = (ImageView) viewDialog
					.findViewById(R.id.image);
				// 设置image显示指定图片
				image.setImageBitmap(BitmapFactory.decodeFile(
					fileNames.get(position)));
				// 使用对话框显示用户单击的图片
				new AlertDialog.Builder(MediaProviderTest.this)
					.setView(viewDialog).setPositiveButton("确定", null)
					.show();
			}
		});
	}
}