在安卓中,我们可以使用内容提供器ContentResolver来获取其他应用程序的数据:

Cursor cursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,null,null,null,null);

public final @Nullable Cursor query(@RequiresPermission.Read @NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) { return query(uri, projection, selection, selectionArgs, sortOrder, null);}

类似上面的获取Cursor,其中的参数分别有以下含义:

uri:指定某一应用程序下的某一张表(l类似SQL中 from table_name),注意一点,使用时要提前申请访问数据权限

​ eg content://com.example.app.provider/table1

Uri uri = Uri.parse("content://com.example.app.provider/table1");

projection:指定查询的列名(类似SQL中 select column1,column2)

selection:指定where的约束条件(类似SQL中 where column = value)

selectionArgs:为以上条件指定具体的指(相当于SQL中where占位符提供的具体的值)

orderBy:指定查询结果的排序方式(类似SQL中 order by column1,column2)

用以上方法获取到指定的cursor后,可用以下方式获取:

if (cursor!=null){ while (cursor.moveToNext()){ //通过指定的列名获取相应的数据 String displayName = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)); }}

类似SQLite数据插入的方式,我们可以用以下的方式向指定表中添加数据:

ContentValues values = new ContentValues();values.put("column1","text");values.put("column2",1);getContentResolver().insert(uri,values);

更新数据:

ContentValues values1 = new ContentValues();values.put("column1","");//利用selection 和 selectionArgs参数来约束需要更新的条件getContentResolver().update(uri,values,"column1 = ? and column2 = ?",new String[]{"text",1});

删除数据:

//删除指定列column2中值为1的数据getContentResolver().delete(uri,"column2 = ?",new String[]{"1"});

实现自定义ContentProvider

先看一下ContentProvider中主要的几个方法:

onCreate():初始化内容提供器的时候调用。通常会在这里完成对数据库的创建和升级等操作,返回true表示内容提供器初始化成功,返回false则表示失败。注意,只有当存在ContentResolver尝试访问我们程序中的数据时,内容提供器才会被初始化

query():从内容提供器中查询数据。使用uri参数来确定查询哪张表,projection参数用于确定查询哪些列,selection和selectionArgs参数用于约束查询哪些行,sortOrder参数用于对结果进行排序,查询的结果存放在Cursor对象中返回

insert():向内容提供器中添加一条数据。使用uri参数来确定要添加到的表,待添加的数据保存在values参数中。添加完成后,返回一个用于表示这条记录的URI

update():更新内容提供器已有的数据。使用uri参数来确定更新哪一张表中的数据,新数据保存在values参数中,selection和selectionArgs参数用于约束更新哪些行,受影响的行数将作为返回值返回

delete():从内容提供器中删除数据。使用uri参数来确定删除哪一张表中的数据,selection和selectionArgs参数用于约束删除哪些行,被删除的行数将作为返回值返回

getType():根据传入的内容URI来返回相应的MIME类型。

URI写法:

content://com.example.app.provider/table1 表示访问com.example.app这个应用table1表中的数据。此外,我们可以在这个URI的后面加上一个id:

content://com.example.app.provider/table1/1 这就表示查询table1表中id为1的数据

此外我们可以使用通配符的方式来分别匹配这两种格式内容的URI:

* :表示匹配任意长度的任意字符

# :表示匹配任意长度的数字

所以,一个能够匹配任意表的内容URI格式就可以写成:

content://com.example.app.provider/*

而一个能够匹配任意一行数据的内容URI格式就可以写成:

content://com.example.app.provider/table1/#

接着,借助UriMatcher这个类可以实现匹配内容URI的功能。UriMatcher中提供了一个addURI()方法,这个方法接收三个参数,可以分别把authority、path和一个自定义代码传进去。这样,当调用UriMatcher的match()方法时,就可以将一个Uri对象传入,返回值是某个能够匹配这个Uri对象所对应的自定义代码,利用这个代码,我们就可以判断出调用方期望的是那张表中的数据了。

eg:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
public class MyContentProvider extends ContentProvider {

public static final int BOOK_DIR = 0; //表中所有数据
public static final int BOOK_ITEM = 1; //表中单条数据
public static final int CATEGORY_DIR = 2;
public static final int CATEGORY_ITEM = 3;
public static final String AUTHORITY = "com.example.ypp0623.decorator.provider";
public static UriMatcher uriMatcher;
private MyDataBaseHelper dbHelper;

static {
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI(AUTHORITY, "book", BOOK_DIR);
uriMatcher.addURI(AUTHORITY, "book/#", BOOK_ITEM);
uriMatcher.addURI(AUTHORITY, "category", CATEGORY_DIR);
uriMatcher.addURI(AUTHORITY, "catagory/#", CATEGORY_ITEM);
}

@Override
public int delete(@NonNull Uri uri, String selection, String[] selectionArgs) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
int deletedRows = 0;
switch (uriMatcher.match(uri)) {
case BOOK_DIR:
deletedRows = db.delete("Book", selection, selectionArgs);
break;
case BOOK_ITEM:
String bookId = uri.getPathSegments().get(1);
deletedRows = db.delete("Book", "id = ?", new String[]{bookId});
break;
case CATEGORY_DIR:
deletedRows = db.delete("Category", selection, selectionArgs);
break;
case CATEGORY_ITEM:
String categoryId = uri.getPathSegments().get(1);
deletedRows = db.delete("Category", "id = ?", new String[]{categoryId});
break;
default:
break;
}
return deletedRows;
}

@Override
public String getType(@NonNull Uri uri) {
switch (uriMatcher.match(uri)) {
case BOOK_DIR:
return "vnd.android.cursor.dir/vnd.com.example.ypp0623.decorator.provider.book";
case BOOK_ITEM:
return "vnd.android.cursor.item/vnd.com.example.ypp0623.decorator.provider.book";
case CATEGORY_DIR:
return "vnd.android.cursor.dir/vnd.com.example.ypp0623.decorator.provider.category";
case CATEGORY_ITEM:
return "vnd.android.cursor.item/vnd.com.example.ypp0623.decorator.provider.category";
}
return null;
}

@Override
public Uri insert(@NonNull Uri uri, ContentValues values) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
Uri uriReturn = null;
switch (uriMatcher.match(uri)) {
case BOOK_DIR:
case BOOK_ITEM:
long newBookId = db.insert("Book", null, values);
uriReturn = Uri.parse("content://" + AUTHORITY + "/book/" + newBookId);
break;
case CATEGORY_DIR:
case CATEGORY_ITEM:
long newCategoryId = db.insert("Category", null, values);
uriReturn = Uri.parse("content://" + AUTHORITY + "/catrgory/" + newCategoryId);
break;
default:
break;
}
return uriReturn;
}

@Override
public boolean onCreate() {
dbHelper = new MyDataBaseHelper(getContext(), "BookStore.db", null, 1);
return true;
}

@Override
public Cursor query(@NonNull Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
SQLiteDatabase db = dbHelper.getReadableDatabase();
Cursor cursor = null;
switch (uriMatcher.match(uri)) {
case BOOK_DIR:
cursor = db.query("Book", projection, selection, selectionArgs, null, null, sortOrder);
break;
case BOOK_ITEM:
String bookId = uri.getPathSegments().get(1);
cursor = db.query("Book", projection, "id = ?", new String[]{bookId}, null, null, sortOrder);
break;
case CATEGORY_DIR:
cursor = db.query("Category", projection, selection, selectionArgs, null, null, sortOrder);
break;
case CATEGORY_ITEM:
String categoryId = uri.getPathSegments().get(1);
cursor = db.query("Category", projection, "id = ?", new String[]{categoryId}, null, null, sortOrder);
break;
default:
break;
}
return cursor;
}

@Override
public int update(@NonNull Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
int updateRows = 0;
switch (uriMatcher.match(uri)) {
case BOOK_DIR:
updateRows = db.update("Book", values, selection, selectionArgs);
break;
case BOOK_ITEM:
String bookId = uri.getPathSegments().get(1);
updateRows = db.update("Book", values, "id = ?", new String[]{bookId});
break;
case CATEGORY_DIR:
updateRows = db.update("Category", values, selection, selectionArgs);
break;
case CATEGORY_ITEM:
String categoryId = uri.getPathSegments().get(1);
updateRows = db.update("Category", values, "id = ?", new String[]{categoryId});
break;
default:
break;
}
return updateRows;
}
}

MyDataBaseHelper如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class MyDataBaseHelper extends SQLiteOpenHelper {
private Context mContext;
public static final String CREATE_BOOK = "create table Book("
+"id integer primary key autoinCrement,"
+"author text,"
+"price real,"
+"pages integer,"
+"name text)";
public static final String CREATE_CATEGORY = "create table Category("
+"id integer primary key autoincrement,"
+"catrgory_name text,"
+"category_code integer)";

public MyDataBaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
mContext = context;
}

@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_BOOK);
db.execSQL(CREATE_CATEGORY);
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

}
}

在Manifest中注册:

1
2
3
4
5
6
<provider
android:authorities="com.example.ypp0623.decorator"
android:name=".MyContentProvider"
android:enabled="true"
android:exported="true">
</provider>

具体使用如下:

1
2
3
4
5
6
7
8
Uri uri1 = Uri.parse("content://com.example.ypp0623.decorator.MyContentProvider/book");
Cursor cursor1 = getContentResolver().query(uri1,null,null,null,null);
if (cursor1!=null){
while (cursor1.moveToNext()){
String name = cursor1.getString(cursor1.getColumnIndex("name"));
String author = cursor1.getString(cursor1.getColumnIndex("author"));
}
}

本文地址: http://www.yppcat.top/2019/03/09/ContentProvider用法详解/