关闭

Android四大组件之ConentProvider.

241人阅读 评论(0) 收藏 举报
分类:

Android中的四大组件有一个叫做ContentProvider的东西,这货是用来干什么的呢?

下面听小弟给你细细道来:

基本介绍:

           Android中有四大组件分别是Activity,ContentProvider,Service,BroadcastReceiver,它们都需要在AndroidManifest.xml文件中进行配置.

           ContentProvider组件主要用于Android系统中应用程序之间交换数据,当一个应用程序需要把自己的数据暴露给其他程序使用时,该应用程序就可以通过ContentProvider来实现;其他应用程序就可以通过ContentResolver来操作ContentProvider暴露的数据.

           当一个应用程序通过ContentProvider暴露了自己的数据操作接口,那么不管该应用程序是否启动,其他应用程序都可以通过该接口操作该应用程序内部的数据,包括增加,删除,修改,查询数据等.

大概思路:

            

ContentProvider以某种Uri的形式对外提供数据,允许其他应用访问或修改数据;其他应用程序使用ContentResolver根据Uri去访问操作指定数据;

开发ContentProvider步骤:

         1.定义自己的ContentProvider类,该类需要继承Android提供的ContentProvider基类.

         2.向Android系统注册这个ContentProvider,也就是在AndroidManifest.xml文件中注册这个ContentProvider,就和注册Activity一样,注册ContentProvider时需要为它绑定一个Uri;

         注:向Android中注册ContentProvider,只需在AndroidManifest.xml配置文件中<application.../>元素下添加如下子元素即可:

<!- -下面配置中name属性指定为ContentProvider类,
       authorities就相当于为该ContentProvider指定域名,exported设置为true就是允许其他应用访问该应用内部
- ->
<provider
          android:name="com.xiyou.MProvider"
          android:authorities="com.xiyou.provider.mprovider"
          android:exported="true"/>

 通过注册上面的provider别的应用就可以通过这个Uri访问MProvider所暴露的数据.


 继承ContentProvider的这个MProvider类通常要提供以下几种方法,以让外部应用访问:

                 public boolean onCreate():该方法在ContentProvider创建后会被调用,当其他应用程序第一次访问ContentProvider,该ContentProvider会被创建出来,并立即回调该onCreate()方法.

                 public Uri insert(Uri uri,  ContentValues values):根据该Uri插入values对应的数据.

                 public int delete(Uri uri, String selection, String[] selectionArgs):根据Uri删除select条件所匹配的全部数据.

                 public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs):根据Uri修改select条件所匹配的全部记录.

                 public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder):根据Uri查询出select条件所匹配的全部记录,其中projection就是一个列名列表,表明只选择出指定的数据列. 

                 public String getType(Uri uri):该方法用于返回当前Uri所代表的数据的MIME类型.如果该Uri对应数据可能包括多条记录,那么MIME类型字符串应该以vnd.android.cursor.dir/开头;如果该Uri对应的数据只包含一条记录,那么返回MIME类型字符串应该以vnd.android.cursor.item/开头.


从每一个方法的参数中我们可以看出Uri是一个非常重要的参数,那么下面我们来了解了解Uri:


                我们先来给出一个简单的URL:http://www.xiyou.edu.cn/test.php

                分解开来看:

                http://:URL的协议部分;只要通过HTTP协议访问网站,这个部分是固定的.

                www.xiyou.edu.cn:域名部分.只要访问指定的网站,这个部分总是固定的.

                test.php:网站资源部分.当访问者需要访问不同资源时,这个部分根据资源的不同而改变.


                ContentProvider要求的Uri与此类似,例如如下Uri:content://com.xiyou.provider.mprovider/test

                分解开来看:

                content://:此部分是Android的ContentProvider规定的,就想网上的协议默认是http://一样.暴露ContentProvider,访问ContentProvider的协议默认是content://.

                com.xiyou.provider.mprovider:这个部分是就是ContentProvider的authority.系统就是由这个部分来找到操作哪个ContentProvider只要访问指定的ContentProvider,这个部分总是固定的.

                test:资源部分,当访问者需要访问不同的资源时,这个部分是动态改变的 


使用ContentResolver操作数据如下方法:

               通过getContentResolver()方法获取ContentResolver对象,获得ContentResolver对象后通过调用ContentResolver的如下方法操作ContentProvider中的数据.

               insert(Uri uri, ContentValues values):向对应的ContentProvider中插入values对应的数据.

               delete(Uri uri, String where, String[] selectionArgs):删除Uri对应的ContentProvider中where提交匹配的数据.

               update(Uri uri, ContentValues values, String where, String[] selectionArgs):更新Uri对应的ContentProvider中where提交匹配的数据.

               query(Uri uri, String[] projection, String selection,String[] selectionArgs, String sortOrder):查询Uri对应的ContentProvider中select提交的匹配的数据.

               

                    ContentProvider,Uri,COntentResolver三者之间有着某些关系:

                    

     下面开发一个ContentProvider和ContentResolver的例子来给大家看看:

     ContentProvider程序:

     

package com.example.firstprovider;

import android.net.Uri;
import android.os.Bundle;
import android.app.Activity;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.database.Cursor;
import android.view.Menu;

public class MainActivity extends ContentProvider {

	// 第一次创建该ContentProvider时调用该方法
	@Override
	public boolean onCreate() {

		System.out.println("==onCreate()方法被调用==");

		return true;
	}

	// 实现查询方法,该方法应该返回查询得到的Cursor
	@Override
	public Cursor query(Uri uri, String[] projection, String selection,
			String[] selectionArgs, String sortOrder) {

		System.out.println(uri + "==query()方法被调用==");
		System.out.println("selection参数为:" + selection);

		return null;
	}

	// 该方法的返回值代表了该ContentProvider所提供的数据的MIME类型.
	@Override
	public String getType(Uri uri) {
		return null;
	}

	// 实现插入的方法,该方法应该返回新插入的记录的Uri
	@Override
	public Uri insert(Uri uri, ContentValues values) {

		System.out.println(uri + "==insert()方法被调用==");
		System.out.println("values参数为:" + values);
		return null;
	}

	// 实现删除方法,该方法应该返回被更新的记录条数
	@Override
	public int delete(Uri uri, String selection, String[] selectionArgs) {

		System.out.println(uri + "==deletet()方法被调用==");
		System.out.println("selection参数为:" + selection);

		return 0;
	}

	// 实现更新方法,该方法应该返回被更新的记录条数
	@Override
	public int update(Uri uri, ContentValues values, String selection,
			String[] selectionArgs) {

		System.out.println(uri + "==update()方法被调用==");
		System.out
				.println("selection参数为:" + selection + ",values参数为:" + values);
		return 0;
	}

}

ContentProvider程序的AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.firstprovider"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="18" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.firstprovider.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <provider 
            android:name=".MainActivity"
            android:authorities="com.xiyou.provider.firstprovider"
            android:exported="true"
            ></provider>
    </application>

</manifest>


ContentResolver程序:

布局代码中只有四个button所以未给出:

package com.example.firstresolver;

import android.net.Uri;
import android.os.Bundle;
import android.R.integer;
import android.app.Activity;
import android.app.DownloadManager.Query;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.database.Cursor;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends Activity {

	Button query, insert, update, delete;
	Uri uri = Uri.parse("content://com.xiyou.provider.firstprovider/");
	ContentResolver contentResolver;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		contentResolver = this.getContentResolver();
		query = (Button) findViewById(R.id.query);
		update = (Button) findViewById(R.id.update);
		insert = (Button) findViewById(R.id.insert);
		delete = (Button) findViewById(R.id.delete);
		query.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				query(v);
			}
		});
		insert.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				insert(v);
			}
		});
		delete.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				delete(v);
			}
		});
		update.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				update(v);
			}
		});

	}

	@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 void query(View source) {
		// 调用ContentResolver的query()方法
		// 实际返回的是该Uri对应的ContentProvider的query()的返回值
		Cursor c = contentResolver.query(uri, null, "query_where", null, null);
		Toast.makeText(this, "远程ContentProvider返回的Cursor为:" + c,
				Toast.LENGTH_SHORT).show();
	}

	public void insert(View source) {
		ContentValues contentValues = new ContentValues();
		contentValues.put("name", "xiyoucx");
		// 调用ContentResolver的insert()方法
		// 实际返回的是该Uri对应ContentProvider的insert()方法返回值
		Uri newUri = contentResolver.insert(uri, contentValues);
		Toast.makeText(this, "远程ContentProvider返回的新插入记录的Uri为:" + newUri,
				Toast.LENGTH_SHORT).show();
	}

	public void update(View source) {
		ContentValues contentValues = new ContentValues();
		contentValues.put("name", "xiyoucx");
		// 调用ContentResolver的update()方法
		// 实际返回的是该Uri对应的contentp的update()返回值
		int count = contentResolver.update(uri, contentValues, "update_values",
				null);
		Toast.makeText(this, "远程ContentProvider返回的新插入记录数为:" + count,
				Toast.LENGTH_SHORT).show();
	}

	public void delete(View source) {
		// 调用ContentResolver的delete()方法
		// 实际返回的是该Uri对应的contentp的delete()的返回值
		int count = contentResolver.delete(uri, "delete_where", null);
		Toast.makeText(this, "远程ContentProvider返回的删除记录数为:" + count,
				Toast.LENGTH_SHORT).show();
	}

}

运行结果:



这奏是两个程序之间的数据交换.


下面我们再来看看应用程序如何获取系统内部数据:

以联系人为例:


               未完待续~~

               



0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:39322次
    • 积分:710
    • 等级:
    • 排名:千里之外
    • 原创:26篇
    • 转载:35篇
    • 译文:0篇
    • 评论:12条
    文章分类
    最新评论