一般而言,android操作系统的应用程序所建立的数据只允许自己使用,应用程序彼此间无法借助公用存储器来共享数据,android系统提供了一个机制,即内容提供器(ContentProvider),来公开自己私有的数据到数据内容器,通过该机制,可以供其他应用程序来读取自己内部的数据,当然也可以访问其他应用程序的数据。通常,内容提供器背后都有SQLite数据库的支持,用以存储内容提供内部数据。
实现ContentProvider与实现SQLite的区别:
应用程序实现SQLite时,由应用程序直接与数据库进行对接,所以要在应用程序中实现SQLite的接口:db.onCreate()、db.insert()、db.update()、db.delete()、db.query()和db.close();
实现内容提供器时,在应用程序与数据库之间要实现一个ContentProvider程序,这个ContentProvider程序会直接与数据库进行对接,此时应用程序需要实现和ContentProvider程序接口的方法。
下面该说说如何建立内容提供器了:
首先,实现内容提供器接口:
实现该接口的5个重要方法;
其次,定义数据Uri:
提供器应用程序需要定义一个“基底”Uri,以供其他应用程序访问这一内容提供器,这一个Uri必须是唯一的,且必须是以“content://”开头,content: 表示内容提供器程序所控制数据的位置;在AndroidManifest.xml配置文件中添加如下代码以进行声明:
- <!-- 设置类名和授权 multiprocess属性是数据的同步性(同一时间可能有多个程序访问该内容提供器)-->
- <provider
- android:name="ContentProviderClass"
- android:multiprocess="true"
- android:authorities="com.example.data_contentprovider.ContentProviderClass" >
- </provider>
在应用程序中添加如下代码:
-
- getIntent().setData(Uri.parse("content://com.example.data_contentprovider.ContentProviderClass"));
- Uri uri = getIntent().getData();
定义一个Uri所在的位置,并设置一个变量来找到内容提供器程序的接口;
如下是一个完整的代码,功能是实现内容提供器的建立以及通过该内容提供器程序来添加和检索数据:
实现内容提供器接口的代码:
- package com.example.data_contentprovider;
-
- import com.example.data_contentprovider.DB.DBHelper;
-
- import android.net.Uri;
- import android.content.ContentProvider;
- import android.content.ContentValues;
- import android.database.Cursor;
- import android.database.sqlite.SQLiteDatabase;
- import android.database.sqlite.SQLiteQueryBuilder;
-
- public class ContentProviderClass extends ContentProvider {
-
- DBHelper dataBaseHelper;
-
-
- @Override
- public boolean onCreate() {
-
- dataBaseHelper = new DBHelper(getContext());
- return true;
- }
-
- @Override
- public Uri insert(Uri uri, ContentValues values) {
-
- SQLiteDatabase db = dataBaseHelper.getWritableDatabase();
- db.insert("test", null, values);
- return null;
- }
-
- @Override
- public Cursor query(Uri uri, String[] projection, String selection,
- String[] selectionArgs, String sortOrder) {
-
- SQLiteDatabase db = dataBaseHelper.getReadableDatabase();
- SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
- queryBuilder.setTables("test");
- Cursor cursor = queryBuilder.query(db, projection, selection,
- selectionArgs, null, null, null);
- return cursor;
- }
-
- @Override
- public int delete(Uri uri, String selection, String[] selectionArgs) {
-
- return 0;
- }
-
- @Override
- public String getType(Uri uri) {
-
- return null;
- }
-
- @Override
- public int update(Uri uri, ContentValues values, String selection,
- String[] selectionArgs) {
-
- return 0;
- }
-
- }
配置AndroidManifest.xml文件:
- <!-- 设置类名和授权 multiprocess属性是数据的同步性(同一时间可能有多个程序访问该内容提供器)-->
- <provider
- android:name="ContentProviderClass"
- android:multiprocess="true"
- android:authorities="com.example.data_contentprovider.ContentProviderClass" >
- </provider>
建立一个SQLite数据库系统来存储和管理数据,同时利用SQLiteOpenHilper类协助建立数据库和SQLiteDatabase类来管理数据库:
- package com.example.data_contentprovider.DB;
-
- import android.content.Context;
- import android.database.sqlite.SQLiteDatabase;
- import android.database.sqlite.SQLiteOpenHelper;
- import android.provider.BaseColumns;
-
- public class DBHelper extends SQLiteOpenHelper {
-
-
- public DBHelper(Context context) {
- super(context, "test.db", null, 1);
- }
-
-
- @Override
- public void onCreate(SQLiteDatabase db) {
- db.execSQL("create table test (" + BaseColumns._ID
- + "integer primary key," + "name text," + "description text"
- + ");");
- }
-
-
- @Override
- public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
- db.execSQL("DROP TABLE IF EXISTS test");
- onCreate(db);
- }
-
- }
下面就是provider的应用程序了:
- package com.example.data_contentprovider;
-
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.Map;
-
- import android.app.Activity;
- import android.content.ContentValues;
- import android.database.Cursor;
- import android.net.Uri;
- import android.os.Bundle;
- import android.widget.ListView;
- import android.widget.SimpleAdapter;
-
- public class ContentProviderActivity extends Activity {
-
- String [] from = {"column00","column01","column02"};
-
-
- @SuppressWarnings("deprecation")
- @Override
- protected void onCreate(Bundle savedInstanceState) {
-
- super.onCreate(savedInstanceState);
-
- <span style="background-color: rgb(192, 192, 192);">
- getIntent().setData(Uri.parse("content://com.example.data_contentprovider.ContentProviderClass"));
- Uri uri = getIntent().getData();</span>
-
-
- ContentValues values = new ContentValues();
- values.put("name", "marry");
- values.put("description", "123456");
- getContentResolver().insert(uri, values);
-
- values.put("name", "hello");
- values.put("description", "654321");
- getContentResolver().insert(uri, values);
-
-
- Cursor cursor = managedQuery(uri, null, null, null, null);
- cursor.moveToFirst();
-
-
- ArrayList<Map<String,Object>> data = new ArrayList<Map<String,Object>>();
- Map<String, Object> item;
-
- for (int i = 0; i < cursor.getCount(); i++) {
- item = new HashMap<String, Object>();
- item.put("column00", cursor.getString(0));
- item.put("column01", cursor.getString(1));
- item.put("column02", cursor.getString(2));
- data.add(item);
- cursor.moveToNext();
- }
-
- cursor.close();
-
- ListView listView = new ListView(this);
- SimpleAdapter adapter = new SimpleAdapter(this, data, R.layout.activity_content_provider, from, new int[]{R.id.text1,R.id.text2,R.id.text3});
- listView.setAdapter(adapter);
- setContentView(listView);
-
- }
-
- }
provider应用程序就可以通过该内容提供器检索数据库并向其添加数据了。
ContentProvider中重要的几个类:
UriMatcher:
要了解UriMatcher,首先需要了解android中的Uri表示方法,众所周知,Uri为通用资源标识符,它代表的是要操作的数据,Android中的每一种资源(比如文本,图像,视频等)都可以用Uri来表示。Android中的Uri由以下三部分组成:”content://”(即authory),数据的路径,资源标识ID(可选),其中如果存在ID,则表示某一个具体的资源,如果不存在ID,则表示路径下的整体。因此addUri()函数的3个参数也是对应上面的那3个。UriMatcher的匹配过程分为3步:初始化UriMatcher;注册需要用的Uri;与已经注册的Uri进行匹配。
ContentResolver :
当使用ContentProvider在不同的应用程序中共享数据时,其数据的暴露方式是采取类似数据库中表的方法。而ContentResolver 是恰好是采用类似数据库的方法来从ContentProvider中存取数据的,它是通过Uri来查询ContentProvider中提供的数据,查询时,还需知道目的数据库的名称,数据段的数据类型,或者说资源的ID。
SQLiteQueryBuilder:是一个用来生产SQL查询语句的辅助类,可以方便的去访问SQLiteDatabase. 在构造SQL查询语句时,它同样也需要指定表名,指定列名,指定where条件等。