Content Provider 属于 Android 应用程序的组件之一,作为应用程序之间惟一的共享数据的路径,Content Provider 次要的性能就是存储并检索数据以及向其余应用程序提供拜访数据的借口。
Android 零碎为一些常见的数据类型 (如音乐、视频、图像、手机通信录联系人信息等) 内置了一系列的 Content Provider, 这些都位于 android.provider 包下。持有特定的许可,能够在本人开发的应用程序中拜访这些 Content Provider。
让本人的数据和其余应用程序共享有两种形式:创立本人的 Content Provier(即继承自 ContentProvider 的子类) 或者是将本人的数据增加到已有的 Content Provider 中去,后者须要保障现有的 Content Provider 和本人的数据类型雷同且具备该 Content Provider 的写入权限。对于 Content Provider,最重要的就是数据模型(data model) 和 URI。
1. 数据模型
Content Provider 将其存储的数据以数据表的模式提供给访问者,在数据表中每一行为一条记录,每一列为具备特定类型和意义的数据。每一条数据记录都包含一个 “_ID” 数值字段,改字段惟一标识一条数据。
2.URI
URI,每一个 Content Provider 都对外提供一个可能惟一标识本人数据集 (data set) 的公开 URI, 如果一个 Content Provider 治理多个数据集,其将会为每个数据集调配一个独立的 URI。所有的 Content Provider 的 URI 都以 ”content://” 结尾,其中 ”content:” 是用来标识数据是由 Content Provider 治理的 schema。
在简直所有的 Content Provider 的操作中都会用到 URI,因而一般来讲,如果是本人开发的 Content Provider,最好将 URI 定义为常量,这样在简化开发的同时也进步了代码的可维护性。
首先来介绍如何拜访 Content Provider 中的数据,拜访 Content Provider 中的数据次要通过 ContentResolver 对象,ContentResolver 类提供了成员办法能够用来对 Content Provider 中的数据进行查问、插入、批改和删除等操作。以查问为例,查问一个 Content Provider 须要把握如下的信息。
惟一标识 Content Provider 的 URI
须要拜访的数据字段名称。
该数据字段的数据类型
提醒:如果须要拜访特定的某条数据记录,只需该记录的 ID 即可。
查问 Content Provider 的办法有两个:ContentResolver 的 query() 和 Activity 对象的 managedQuery(), 二者接管的参数均雷同,返回的都是 Cursor 对象,惟一不同的是 应用 managedQuery 办法能够让 Activity 来治理 Cursor 的生命周期。
被治理的 Cursor 会在 Activity 进入暂停状态的时候调用本人的 deactivate 办法自行卸载,而在 Activity 回到运行状态时会调用本人的 requery 办法从新查问生成的 Cursor 对象。如果一个未被治理的 Cursor 对象想被 Activity 治理,能够调用 Activity 的 startManagingCursor 办法来实现。
Android 应用程序能够应用文件或 SqlLite 数据库来存储数据。Content Provider 提供了一种多利用间数据共享的形式,比方:联系人信息能够被多个应用程序拜访。Content Provider 是个实现了一组用于提供其余应用程序存取数据的规范办法的类。
应用程序能够在 Content Provider 中执行如下操作:
查问数据
批改数据
增加数据
删除数据
/Chapter10_ContentProvider_01_Test02/src/com/amaker/ch10/app/MainActivity.java
package com.amaker.ch10.app;
import android.app.Activity;
import android.content.ContentUris;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import com.amaker.ch10.app.Employees.Employee;
public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 增加
insert();
// 查问
query();
// 更新
update();
// 查问
query();
// 删除
del();
// 查问
query();}
// 删除办法
private void del(){
// 删除 ID 为 1 的记录
Uri uri = ContentUris.withAppendedId(Employee.CONTENT_URI, 1);
// 取得 ContentResolver,并删除
getContentResolver().delete(uri, null, null);
}
// 更新
private void update(){
// 更新 ID 为 1 的记录
Uri uri = ContentUris.withAppendedId(Employee.CONTENT_URI, 1);
ContentValues values = new ContentValues();
// 增加员工信息
values.put(Employee.NAME, "hz.guo");
values.put(Employee.GENDER, "male");
values.put(Employee.AGE,31);
// 取得 ContentResolver,并更新
getContentResolver().update(uri, values, null, null);
}
// 查问
private void query(){
// 查问列数组
String[] PROJECTION = new String[] {
Employee._ID, // 0
Employee.NAME, // 1
Employee.GENDER, // 2
Employee.AGE // 3
};
// 查问所有备忘录信息
Cursor c = managedQuery(Employee.CONTENT_URI, PROJECTION, null,
null, Employee.DEFAULT_SORT_ORDER);
// 判断游标是否为空
if (c.moveToFirst()) {
// 遍历游标
for (int i = 0; i < c.getCount(); i++) {c.moveToPosition(i);
// 取得姓名
String name = c.getString(1);
String gender = c.getString(2);
int age = c.getInt(3);
// 输入日志
Log.i("emp", name+":"+gender+":"+age);
}
}
}
// 插入
private void insert(){
// 申明 Uri
Uri uri = Employee.CONTENT_URI;
// 实例化 ContentValues
ContentValues values = new ContentValues();
// 增加员工信息
values.put(Employee.NAME, "amaker");
values.put(Employee.GENDER, "male");
values.put(Employee.AGE,30);
// 取得 ContentResolver,并插入
getContentResolver().insert(uri, values);
}
}
/Chapter10_ContentProvider_01_Test02/src/com/amaker/ch10/app/Employees.java
package com.amaker.ch10.app;
import android.net.Uri;
import android.provider.BaseColumns;
/**
- 通讯录常量类
*/
public final class Employees {
// 受权常量
public static final String AUTHORITY = "com.amaker.provider.Employees";
private Employees() {}
// 外部类
public static final class Employee implements BaseColumns {
// 构造方法
private Employee() {}
// 拜访 Uri
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/employee");
// 内容类型
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.amaker.employees";
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.amaker.employees";
// 默认排序常量
public static final String DEFAULT_SORT_ORDER = "name DESC";// 按姓名排序
// 表字段常量
public static final String NAME = "name"; // 姓名
public static final String GENDER= "gender"; // 性别
public static final String AGE = "age"; // 年龄
}
}
/Chapter10_ContentProvider_01_Test02/src/com/amaker/ch10/app/EmployeeProvider.java
package com.amaker.ch10.app;
import java.util.HashMap;
import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.text.TextUtils;
import com.amaker.ch10.app.Employees.Employee;
public class EmployeeProvider extends ContentProvider{
// 数据库帮忙类
private DBHelper dbHelper;
// Uri 工具类
private static final UriMatcher sUriMatcher;
// 查问、更新条件
private static final int EMPLOYEE = 1;
private static final int EMPLOYEE_ID = 2;
// 查问列汇合
private static HashMap<String, String> empProjectionMap;
static {
// Uri 匹配工具类
sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
sUriMatcher.addURI(Employees.AUTHORITY, "employee", EMPLOYEE);
sUriMatcher.addURI(Employees.AUTHORITY, "employee/#", EMPLOYEE_ID);
// 实例化查问列汇合
empProjectionMap = new HashMap<String, String>();
// 增加查问列
empProjectionMap.put(Employee._ID, Employee._ID);
empProjectionMap.put(Employee.NAME, Employee.NAME);
empProjectionMap.put(Employee.GENDER, Employee.GENDER);
empProjectionMap.put(Employee.AGE, Employee.AGE);
}
// 创立是调用
public boolean onCreate() {
// 实例化数据库帮忙类
dbHelper = new DBHelper(getContext());
return true;
}
// 增加办法
public Uri insert(Uri uri, ContentValues values) {
// 取得数据库实例
SQLiteDatabase db = dbHelper.getWritableDatabase();
// 插入数据,返回行 ID
long rowId = db.insert(DBHelper.EMPLOYEES_TABLE_NAME, Employee.NAME, values);
// 如果插入胜利返回 uri
if (rowId > 0) {Uri empUri = ContentUris.withAppendedId(Employee.CONTENT_URI, rowId);
getContext().getContentResolver().notifyChange(empUri, null);
return empUri;
}
return null;
}
// 删除办法
public int delete(Uri uri, String selection, String[] selectionArgs) {
// 取得数据库实例
SQLiteDatabase db = dbHelper.getWritableDatabase();
// 取得数据库实例
int count;
switch (sUriMatcher.match(uri)) {
// 依据指定条件删除
case EMPLOYEE:
count = db.delete(DBHelper.EMPLOYEES_TABLE_NAME, selection, selectionArgs);
break;
// 依据指定条件和 ID 删除
case EMPLOYEE_ID:
String noteId = uri.getPathSegments().get(1);
count = db.delete(DBHelper.EMPLOYEES_TABLE_NAME, Employee._ID + "=" + noteId
+ (!TextUtils.isEmpty(selection) ? "AND (" + selection + ')' : ""), selectionArgs);
break;
default:
throw new IllegalArgumentException("谬误的 URI" + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return count;
}
// 取得类型
public String getType(Uri uri) {return null;}
// 查询方法
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
switch (sUriMatcher.match(uri)) {
// 查问所有
case EMPLOYEE:
qb.setTables(DBHelper.EMPLOYEES_TABLE_NAME);
qb.setProjectionMap(empProjectionMap);
break;
// 依据 ID 查问
case EMPLOYEE_ID:
qb.setTables(DBHelper.EMPLOYEES_TABLE_NAME);
qb.setProjectionMap(empProjectionMap);
qb.appendWhere(Employee._ID + "=" + uri.getPathSegments().get(1));
break;
default:
throw new IllegalArgumentException("Uri 谬误!" + uri);
}
// 应用默认排序
String orderBy;
if (TextUtils.isEmpty(sortOrder)) {orderBy = Employee.DEFAULT_SORT_ORDER;} else {orderBy = sortOrder;}
// 取得数据库实例
SQLiteDatabase db = dbHelper.getReadableDatabase();
// 返回游标汇合
Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, orderBy);
c.setNotificationUri(getContext().getContentResolver(), uri);
return c;
}
// 更新办法
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
// 取得数据库实例
SQLiteDatabase db = dbHelper.getWritableDatabase();
int count;
switch (sUriMatcher.match(uri)) {
// 依据指定条件更新
case EMPLOYEE:
count = db.update(DBHelper.EMPLOYEES_TABLE_NAME, values, selection, selectionArgs);
break;
// 依据指定条件和 ID 更新
case EMPLOYEE_ID:
String noteId = uri.getPathSegments().get(1);
count = db.update(DBHelper.EMPLOYEES_TABLE_NAME, values, Employee._ID + "=" + noteId
+ (!TextUtils.isEmpty(selection) ? "AND (" + selection + ')' : ""), selectionArgs);
break;
default:
throw new IllegalArgumentException("谬误的 URI" + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return count;
}
}
/Chapter10_ContentProvider_01_Test02/src/com/amaker/ch10/app/DBHelper.java
package com.amaker.ch10.app;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import com.amaker.ch10.app.Employees.Employee;
/**
- 数据库工具类
*/
public class DBHelper extends SQLiteOpenHelper{
// 数据库名称常量
private static final String DATABASE_NAME = "Employees.db";
// 数据库版本常量
private static final int DATABASE_VERSION = 1;
// 表名称常量
public static final String EMPLOYEES_TABLE_NAME = "employee";
// 构造方法
public DBHelper(Context context) {
// 创立数据库
super(context, DATABASE_NAME,null, DATABASE_VERSION);
}
// 创立时调用
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE" + EMPLOYEES_TABLE_NAME + "("
+ Employee._ID + "INTEGER PRIMARY KEY,"
+ Employee.NAME + "TEXT,"
+ Employee.GENDER + "TEXT,"
+ Employee.AGE + "INTEGER"
+ ");");
}
// 版本更新时调用
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// 删除表
db.execSQL("DROP TABLE IF EXISTS employee");
onCreate(db);
}
}
/Chapter10_ContentProvider_01_Test02/AndroidManifest.xml
<?xml version=”1.0″ encoding=”utf-8″?>
<manifest xmlns:android=”http://schemas.android.com/apk/res/android”
package="com.amaker.ch10.app"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<provider android:name="EmployeeProvider"
android:authorities="com.amaker.provider.Employees"/>
<activity android:name=".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>
</application>
<uses-sdk android:minSdkVersion="3" />
</manifest>