版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Android应用程序开发技术第8章ContentProvider数据共享为了更加安全便捷的在不同应用之间共享数据,Android提供了ContentProvider组件,它是不同应用程序之间进行数据交换的标准API,当一个应用中的数据被其他应用所需要的时候,该应用就可以提供ContentProvider暴露自己的数据,其他应用程序可以通过ContentResolver来操作ContentProvider暴露的数据,包括增加数据、删除数据、修改数据、查询数据等。Android内置的许多数据都是使用ContentProvider形式,供开发者调用(如视频,音频,图片,通讯录等)。章节概述8.1ContentProvider简介8.2
开发ContentProvider程序8.3
本章总结8.4
习题8.5上机目
录ContentProvider可以选择对部分数据进行分享,保证数据安全,是Android提供的四大组件之一,主要用于不同应用程序之间实现数据共享。ContentProvider以Uri的形式对外提供数据,允许其他应用访问和修改数据;其它应用使用ContentResolver根据Uri进行访问操作指定的数据。ContentProvider内部保存数据的方式由其设计者决定。所有的ContentProvider都实现一组通用的方法用来提供数据的增、删、改、查功能。客户端通常不会直接使用这些方法,大多数是通过ContentResolver对象实现对ContentProvider的操作。开发人员可以通过调用Activity或者其它应用程序组件的实现类中,getContentResolver()方法来获得ContentResolver对象,例如:ContentResolvercr=getContentResolver();使用ContentResolver提供的方法可以获得ContentProvider中任何感兴趣的数据。8.1ContentProvider简介
8.1.1ContentProvider基本概念组织数据方式ContentProvider向其它应用提供数据有两种基本形式:文件形式和表格形式。在需要对大量的数据进行修改和查询操作时,将数据以一个表或多个表(与在关系型数据库中的表类似)的形式呈现给外部应用更加便于操作。其中,每一行表示一条记录,而每一列代表特定类型和含义的数据,并且其中每一条数据记录都包含一个名为“_ID”的字段类标识每条数据。【例】联系人的信息可以如下表所示。每条记录包含一个数值型的_ID字段,用于在表格中唯一标识该记录。ID能用于匹配相关表格中的记录,例如,在一个表格中查询联系人的电话,在另一表格中查询其照片。_IDNAMENUMBEREMAIL001张××123*****123**@002王××134*****134**@003李××145*****145***@004赵××156*****156***@8.1.1ContentProvider基本概念组织数据方式8.1.1ContentProvider基本概念URI统一资源标识符(UniformResourceIdentifier,URI)是一个用于标识某一互联网资源名称的字符串。该种标识允许用户对任何(包括本地和互联网)的资源通过特定的协议进行交互操作。ContentProvider提供公共的URI来唯一标识其数据集。管理多个数据集的ContentProvider为每个数据集提供了单独的URI。URI主要包含两部分信息:需要操作的ContentProvider和ContentProvider中需要进行操作的数据。8.1.1ContentProvider基本概念URI一个URI由以下几部分组成:自定义URI=content://vider/User/ID主题名授权信息表名记录主题名(Schema):用于标识该数据由ContentProvider管理,无需修改。授权信息(authority):URI的authority部分,ContentProvider的唯一标识符,外部调用者可以根据这个标识来找到它。表名(Path):ContentProvider的路径部分,用于决定哪类数据被请求。如果ContentProvider提供一种数据类型,可以省略该部分;如果提供几种类型,包括子类型,这部分可以由几部分组成。记录(ID):被请求记录的ID值。若无指定,则返回全部记录。8.1.1ContentProvider基本概念URI【例】
1.//设置URI2.Uriuri=Uri.parse("content://vider/User/1")3.//上述URI指向的资源是:名为`vider`的`ContentProvider`中表名
为`User`中的`id`为1的数据4.//特别注意:URI模式存在匹配通配符*&#5.//*:匹配任意长度的任何有效字符的字符串6.//以下的URI表示
匹配provider的任何内容7.content://vider/*8.//#:匹配任意长度的数字字符的字符串9.//以下的URI表示
匹配provider中的table表的所有行10.content://vider/table/#8.1.1ContentProvider基本概念URI通常解析URI使用Android系统提供的操作URI工具类:UriMatcher。UriMatcher类用来匹配URI,对匹配结果返回对应的匹配码。UriMatcher使用addURI()方法注册需要匹配的URI。addURI()方法原型是:publicvoidaddURI(Stringauthority,Stringpath,intcode)注册完成之后可以使用UriMatcher类的match()方法匹配URI,如果匹配成功就返回相应的匹配码,匹配码是使用addURI()注册URI时传入的第3个参数,注册时传入的匹配码需要唯一。8.1.1ContentProvider基本概念URI【例】1.publicstaticfinalintBOOK_DIR=0;2.publicstaticfinalintBOOK_ITEM=1;3.//第一步,初始化4.UriMatchermatcher=newUriMatcher(UriMatcher.NO_MATCH);5.//第二步,注册待匹配的Uri6.matcher.addURI(AUTHORITY,"book",BOOK_DIR);7.matcher.addURI(AUTHORITY,"book/#",BOOK_ITEM);8.//第三步,进行匹配9.Uriuri=Uri.parse("content://"+"com.example.yy"+"/book");10.intmatch=matcher.match(uri);11.switch(match){12.caseBOOK_DIR:13.return"vnd.android.cursor.dir/book";14.caseBOOK_ITEM:15.return"vnd.android.cursor.item/book";16.default:17.returnnull;18.}//上面返回的是Uri对应的MIME8.1.1ContentProvider基本概念URI操作URI的工具类还有一个ContentUris类,用于操作UriURI路径后面的Id。ContentUris处理URI有两个作用:为路径加上ID和从URI路径中获取ID。8.1.1ContentProvider基本概念URI具体代码如下。为URI路径加上ID:withAppendedId(uri,id);19.//比如有这样一个URI20.Uriuri=Uri.parse("content://com.example.yy/book");21.22.//通过ContentUris的withAppendedId()方法,为该Uri加上ID23.UriresultUri=ContentUris.withAppendedId(uri,10);24.//最后resultUri为:25.//content://com.example.yy/book/1026.从Uri路径中获取ID—parseId(uri);27.Uriuri=Uri.parse("content://com.example.yy/book/10")28.longbookId=ContentUris.parseId(uri);
8.1.1ContentProvider基本概念URIAndroid系统提供了一些定义好的URI。例如,手机短信的信息、图库数据、联系人信息等操作系统均提供相应的URI。知道对应的URI后,就可以通过ContentResolver对象,根据URI进行数据访问。Android系统用于管理联系人的ContentProvider的几个URI如下:ContactsContract.Contacts.CONTENT_URI:管理联系人的URI。ContactsContract.CommonDataKinds.Phone.CONTENT_URI:管理联系人电话的URI。ContactsContract.CommonDataKinds.Email.CONTENT_URI:管理联系人E-mail的URI。8.1.1ContentProvider基本概念URIAndroid系统用于管理多媒体的ContentProvider的几个URI如下:MediaStore.Audio.Media.EXTERNAL_CONTENT_URI:存储在外部存储器(SD卡)上的音频文件内容的ContentProvider的URI。MediaStore.Audio.Media.INTERNAL_CONTENT_URI:存储在手机内部存储器上的音频文件内容的ContentProvider的URI。MediaStore.Images.Media.EXTERNAL_CONTENT_URI:存储在外部存储器(SD卡)上的图片文件内容的ContentProvider的URI。MediaStore.Images.Media.INTERNAL_CONTENT_URI:存储在手机内部存储器上的图片文件内容的ContentProvider的URI。MediaStore.Video.Media.EXTERNAL_CONTENT_URI:存储在外部存储器(SD卡)上的视频文件内容的ContentProvider的URI。MediaStore.Video.Media.INTERNAL_CONTENT_URI:存储在手机内部存储器上的视频文件内容的ContentProvider的URI。8.1.1ContentProvider基本概念.MIME数据类型多功能Internet邮件扩充服务(MIME:MultipurposeInternetMailExtensions)是一种多用途网际邮件扩充协议。该服务于1992年最早应用于电子邮件系统,后来也应用到浏览器。MIME类型就是设定某种扩展名的文件用一种应用程序来打开的方式类型。当该扩展名文件被访问的时候,浏览器会自动使用指定应用程序打开,多用于指定一些客户端自定义的文件名,以及一些媒体文件打开方式。在Android中MIME数据类型的作用是指定应用程序打开特定扩展名的文件。URI里面提供给provider所支持的MIME数据类型,provider根据web中MIME标准返回一个由两个字符串组成的MIME类型识别。8.1.1ContentProvider基本概念.MIME数据类型每种MIME数据类型由两部分组成:一个类型和一个子类型。MIME类型是一个包含两部分的字符串。这里有些熟知的MIME类型对:text/htmltext/csstext/xmltext/vnd.curl8.1.1ContentProvider基本概念.MIME数据类型MIME类型在Android里面得到了大规模的应用,特别是在intent里,系统根据MIME数据的类型来决定调用哪个activity。MIME类型始终通过contentproviders继承自它们的URIs。在使用MIME类型的时候要记住三点:基本类型和子类型代表的东西要唯一。如果是非标准的,专有的类型和子类型,前面需要加vnd。对于特定的需求,注意名字空间。在ContentProvider中使用getType()方法返回当前Uri所代表数据的MIME类型。8.1.2ContentProvider常用操作ContentProvider类提供了以下六个方法:onCreate()方法:用来执行一些初始化的工作query()方法:用来返回数据给调用者Insert()方法:用来插入新的数据update()方法:用来更新已有的数据delete()方法:用来删除数据getType()方法:用来返回数据的MIME类型8.1.2ContentProvider常用操作onCreate()方法用来执行一些初始化的工作。其函数原型为:publicbooleanonCreate()该方法在ContentProvider创建后被调用。onCreate()方法返回一个boolean类型的值,初始化操作成功时返回true,否则返回false,具体代码如下所示。
1.onCreate()方法1.@Override
2.public
boolean
onCreate()
{
3.
//初始化数据库
4.
String
sql
=
"create
table
if
not
exists
t1("
+
"id
integer
primary
key,
name
text,
phone
text);";5.//在content.db数据库中创建t1表
6.
SQLiteDatabase
db
=
getContext().openOrCreateDatabase("content.db",
0,
null);
7.
db.execSQL(sql);
8.
db.close();
9.
return
true;
10.}
8.1.2ContentProvider常用操作2.query()方法query()方法用来返回数据给调用者。其函数原型为:publicCursorquery(Uriuri,String[]projection,Stringselection,String[]
selectionArgs,StringsortOrder)该方法用于供外部应用从ContentProvider中获取数据。根据Uri查询出selection条件所匹配的全部记录,其中projection表明选择出指定的数据列,最终查询结果保存在Cursor对象中并返回,具体代码如下所示。1.@Override
2.public
Cursor
query(Uri
uri,
String[]
projection,
String
selection,
String[]
selectionArgs,
String
sortOrder)
{
3.
Cursor
result
=
null;
4.
SQLiteDatabase
db
=
getContext().openOrCreateDatabase("content.db",
0,
null);
5.
int
matchResult
=
matcher.match(uri);
6.
if
(matchReuslt
==
T1_DIR)
{
7.
result
=
db.query("t1",
projection,
selection,
selectionArgs,
null,
null,
sortOrder);
8.
}
9.
else
if(matchResult
==
T1_ITEM)
{
10.
String
id
=
uri.getPathSegments().get(1);
11.
result
=
db.query("t1",
projection,
"id
=
"
+
id,
null,
null,
null,
sortOrder);
12.
}
13.
return
result;
14.}
8.1.2ContentProvider常用操作3.Insert()方法Insert()方法用来插入新的数据。其函数原型为:publicUriinsert(Uri
uri,
ContenrValues
values)该方法用于供外部应用往ContentProvider添加数据。该方法需要两个参数,第一个参数是使用资源的Uri对象,第二个参数为需要添加的数据。添加成功则返回新数据的Uri对象;操作失败则返回null,具体代码如下所示。1.@Override
2.public
Uri
insert(Uri
uri,
ContenrValues
values)
{
3.
int
matchResult
=
matcher.match(uri);
4.
if(matchResult
==
T1_DIR
||
matchResult
==
T1_ITEM)
{
5.
//插入数据并返回Uri
6.
SQLiteDatabase
db
=
getContext().openOrCreateDatabase("content.db",
0,
null);
7.
long
newId
=
db.insert("t1",
null,
values);
8.
db.close();
9.
return
Uri.parse("content://vider/t1/"
+
newId);
10.
}
11.
else
{
12.
return
null;
13.
}
14.}
8.1.2ContentProvider常用操作4.update()方法update()方法用来更新已有的数据。其函数原型为:publicintupdate(Uriuri,ContentValuesvalues,Stringselection,String[]selectionArgs)该方法用于供外部应用更新ContentProvider中的数据。根据Uri修改selection条件所匹配的全部记录,最终返回值表示更新操作影响的记录数量,具体代码如下所示。1.@Override
2.public
int
update(Uri
uri,
ContentValues
values,
String
selection,
String[]
selectionArgs)
{
3.
SQLiteDatabase
db
=
getContext().openOrCreateDatabase("content.db",
0,
null);
4.
int
result
=
0;
5.
int
matchResult
=
matcher.match(uri);
6.
if
(matchResult
==
T1_DIR)
{
7.
result
=
db.update("t1",
values,
selection,
selectionArgs);
8.
}
9.
else
if
(matchResult
==
T1_ITEM)
{
10.
String
id
=
uri.getPathSegments().get(1);
11.
result
=
db.update("t1",
values,
"id
=
"
+
id,
null);
12.
}
13.
db.close();
14.
return
result;
15.}
8.1.2ContentProvider常用操作5.delete()方法delete()方法用来删除数据。其函数原型为:publicintdelete(Uri
uri,
String
selection,
String[]
selectionArgs)该方法用于供外部应用从ContentProvider删除数据。根据Uri删除selection条件所匹配的全部记录,具体代码如下所示。1.@Override
2.public
int
delete(Uri
uri,
String
selection,
String[]
selectionArgs)
{
3.
SQLiteDatabase
db
=
getContext().openOrCreateDatabase("content.db",
0,
null);
4.
int
result
=
0;
5.
int
matchResult
=
matcher.match(uri);
6.
if
(matchResult
==
T1_DIR)
{
7.
result
=
db.delete("t1",
selection,
selectionArgs);
8.
}
9.
else
if
(matchResult
==
T1_ITEM)
{
10.
String
id
=
uri.getPathSegments().get(1);
11.
result
=
db.delete("t1",
"id
=
"
+
id,
null);
12.
}
13.
db.close();
14.
return
result;
15.}
8.1.2ContentProvider常用操作6.getType()方法getType()方法用来返回数据的MIME类型。其函数原型为:publicStringgetType(Uriuri)该方法用于返回当前Uri所代表数据的MIME类型。如果该Uri对应的数据可能包含多条记录,那么MIME类型字符串应该以vnd.android.cursor.dir/开头;如果该Uri对应的数据只包含一条记录,那么MIME类型字符串应该以vnd.android.cursor.item/开头,具体代码如下所示。1.@Override
2.public
String
getType(Uri
uri)
{
3.
int
matchResult
=
matcher.match(uri);
4.
if
(matchResult
==
T1_DIR)
{
5.
return
"vnd.android.cursor.dir/vider.t1";
6.
}
7.
else
if
(matchResult
==
T1_ITEM)
{
8.
return
"vnd.android.cursor.item/vider.t1";
9.
}
10.
else
{
11.
return
null;
12.
}
13.}
8.1.3ContentResolver常用操作如果访问内容提供器ContentProvider中的数据,则需要使用ContentResolver类。ContentResolver类的功能就是通过标准接口统一管理不同
ContentProvider间的操作。该类实例可以通过Context的getContentResolver()方法获得ContentResolver中提供了insert()、update()、delete()、query()等方法对数据进行CRUD操作。常见的,ContentProvider是单例模式的,当多个应用程序通过ContentResolver来操作ContentProvider提供的数据时,ContentResolver调用的数据操作将会委托给同一个ContentProvider处理。8.1.2ContentProvider常用操作1.insert()方法insert()方法用于向Uri对应ContentProvider中插入对应的数据。其函数原型为:publicUriinsert(Uriuri,ContentValuesvalues)1.//添加一条记录2.ContentValuesvalues=newContentValues();3.values.put("name","itcast");4.values.put("age",25);5.resolver.insert(uri,values);13.
db.close();
14.
return
result;
15.}
8.1.2ContentProvider常用操作2.delete()方法delete()方法用于删除Uri对应的ContentProvider中的数据。其函数原型为:publicintupdate(Uriuri,ContentValuesvalues,Stringselection,String[]selectionArgs)8.//删除id为2的记录9.UrideleteIdUri=ContentUris.withAppendedId(uri,2);10.resolver.delete(deleteIdUri,null,null);8.1.2ContentProvider常用操作3.update()方法update()方法用于更新Uri对应的ContentProvider中的数据。其函数原型为:publicintupdate(Uriuri,ContentValuesvalues,Stringselection,String[]selectionArgs)13.//把id为1的记录的name字段值更改新为liming14.ContentValuesupdateValues=newContentValues();15.updateValues.put("name","liming");16.UriupdateIdUri=ContentUris.withAppendedId(uri,2);17.resolver.update(updateIdUri,updateValues,null,null);8.1.2ContentProvider常用操作4.query()方法query()方法用于查询Uri对应的ContentProvider中的数据。其函数原型为:publicCursorquery(Uriuri,String[]projection,Stringselection,String[]selectionArgs,StringsortOrder)18.//获取person表中所有记录19.Cursorcursor=resolver.query(uri,null,null,null,"personiddesc");20.while(cursor.moveToNext()){21.Log.i("ContentTest","personid="+cursor.getInt(0)+",name="+cursor.getString(1));22.}8.1ContentProvider简介8.2开发ContentProvider程序8.3
本章总结8.4
习题8.5上机目
录8.2开发ContentProvider程序8.2.1派生ContentProvider子类定义自己的ContentProvider类,该类需要继承Android提供的ContentProvider基类。该子类需要实现query()、insert()、update()和delete()等方法。这些方法并不是给该应用本身调用的,而是供其它应用来调用。当其它应用通过ContentResolver调用query()、insert()、update()和delete()方法执行数据访问时,实际上就是调用指定URI对应的ContentProvider中的这些方法。8.2开发ContentProvider程序8.2.1派生ContentProvider子类以【例8-1】共享单词数据存储为例。派生的ContentProvider子类示例代码如下。1.import
android.content.ContentProvider;
2.import
android.content.ContentUris;
3.import
android.content.ContentValues;
4.import
android.content.UriMatcher;
5.import
android.database.Cursor;
6.import
android.database.sqlite.SQLiteDatabase;
7.import
.Uri;
8.import
androidx.annotation.NonNull;
9.import
androidx.annotation.Nullable;
10.
11.public
class
DictProvider
extends
ContentProvider
{
12.
private
static
UriMatcher
matcher
=
new
UriMatcher(UriMatcher.NO_MATCH);
13.
private
static
final
int
WORDS
=
1;
14.
private
static
final
int
WORD
=
2;
15.
private
MyDatabaseHelper
dbOpenHelper;
16.
17.
static
{
18.
//为UriMatcher注册两个Uri
19.
matcher.addURI(Words.AUTHORITY,
"words",
WORDS);
20.
matcher.addURI(Words.AUTHORITY,
"word/#",
WORD);
21.
}
22.
23.
@Override
24.
public
boolean
onCreate()
{
25.
dbOpenHelper
=
new
MyDatabaseHelper(this.getContext(),
"myDict.db3",
1);
26.
return
true;
27.
}
28.
8.2开发ContentProvider程序8.2.1派生ContentProvider子类29.
//执行查询方法,该方法返回查询得到的cursor的值
30.
@Nullable
31.
@Override
32.
public
Cursor
query(@NonNull
Uri
uri,
@Nullable
String[]
projection,
@Nullable
String
selection,
@Nullable
String[]
selectionArgs,
@Nullable
String
sortOrder)
{
33.
SQLiteDatabase
db
=
dbOpenHelper.getReadableDatabase();
34.
switch
(matcher.match(uri))
{
35.
//如果URI参数代表操作全部数据项
36.
case
WORDS:
37.
//执行查询
38.
return
db.query("dict",
projection,
selection,
selectionArgs,
null,
null,
sortOrder);
39.
//如果URI参数代表操作指定数据项
40.
case
WORD:
41.
//解析出想查询的记录ID
42.
long
id
=
ContentUris.parseId(uri);
43.
String
whereClause
=
Words.Word._ID
+
"="
+
id;
44.
//如果原来的where子句存在,拼接where子句
45.
if
(selection
!=
null
&&
!"".equals(selection))
{
46.
whereClause
=
whereClause
+
"and"
+
selection;
47.
}
48.
return
db.query("dict",
projection,
whereClause,
selectionArgs,
null,
null,
sortOrder);
49.
default:
50.
try
{
51.
throw
new
IllegalAccessException("未知uri:"
+
uri);
52.
}
catch
(IllegalAccessException
e)
{
53.
e.printStackTrace();
54.
}
55.
}
56.
return
null;
57.
}
58.
8.2开发ContentProvider程序8.2.1派生ContentProvider子类59.
@Nullable
60.
//该方法的返回值代表了该contentProvider所提供数据的MIME类型
61.
@Override
62.
public
String
getType(@NonNull
Uri
uri)
{
63.
switch
(matcher.match(uri))
{
64.
//如果操作的数据为多项记录
65.
case
WORDS:
66.
return
"vnd:android.cursor.dir/org.crazyit.dict";
67.
//如果操作的数据为单项记录
68.
case
WORD:
69.
return
"vnd:android.cursor.item/org.crazyit.dict";
70.
default:
71.
try
{
72.
throw
new
IllegalAccessException("未知URI:"
+
uri);
73.
}
catch
(IllegalAccessException
e)
{
74.
e.printStackTrace();
75.
}
76.
}
77.
return
null;
78.
}
79.
8.2开发ContentProvider程序8.2.1派生ContentProvider子类80.
//实现插入的方法,该方法返回新插入的记录的uri
81.
@Nullable
82.
@Override
83.
public
Uri
insert(@NonNull
Uri
uri,
@Nullable
ContentValues
values)
{
84.
//获得数据库实例
85.
SQLiteDatabase
db
=
dbOpenHelper.getReadableDatabase();
86.
switch
(matcher.match(uri))
{
87.
case
WORDS:
88.
long
rowId
=
db.insert("dict",
Words.Word._ID,
values);
89.
//如果成功插入返回uri
90.
if
(rowId
>
0)
{
91.
//在已有的uri后面追加id
92.
Uri
wordUri
=
ContentUris.withAppendedId(uri,
rowId);
93.
//通知数据已经改变
94.
getContext().getContentResolver().notifyChange(wordUri,
null);
95.
return
wordUri;
96.
}
97.
break;
98.
default:
99.
try
{
100.
throw
new
IllegalAccessException("未知URI:"
+
uri);
101.
}
catch
(IllegalAccessException
e)
{
102.
e.printStackTrace();
103.
}
104.
}
105.
return
null;
106.
}
107.
8.2开发ContentProvider程序8.2.1派生ContentProvider子类108.
//实现删除方法,该方法返回被删除的记录条数
109.
@Override
110.
public
int
delete(@NonNull
Uri
uri,
@Nullable
String
selection,
@Nullable
String[]
selectionArgs)
{
111.
SQLiteDatabase
db
=
dbOpenHelper.getReadableDatabase();
112.
//记录删除的数据行数
113.
int
num
=
0;
114.
switch
(matcher.match(uri))
{
115.
case
WORDS:
116.
num
=
db.delete("dict",
selection,
selectionArgs);
117.
break;
118.
case
WORD:
119.
long
id
=
ContentUris.parseId(uri);
120.
String
whereClause
=
Words.Word._ID
+
"="
+
id;
121.
//如果原来的where子句存在,拼接where子句
122.
if
(selection
!=
null
&&
!"".equals(selection))
{
123.
whereClause
=
whereClause
+
"and"
+
selection;
124.
}
125.
num
=
db.delete("dict",
whereClause,
selectionArgs);
126.
break;
127.
default:
128.
try
{
129.
throw
new
IllegalAccessException("未知URI:"
+
uri);
130.
}
catch
(IllegalAccessException
e)
{
131.
e.printStackTrace();
132.
}
133.
}
134.
getContext().getContentResolver().notifyChange(uri,
null);
135.
return
num;
136.
}
137.
8.2开发ContentProvider程序8.2.1派生ContentProvider子类138.
//实现更新方法,该方法应该返回被更新的记录条数
139.
@Override
140.
public
int
update(@NonNull
Uri
uri,
@Nullable
ContentValues
values,
@Nullable
String
selection,
@Nullable
String[]
selectionArgs)
{
141.
SQLiteDatabase
db
=
dbOpenHelper.getReadableDatabase();
142.
//记录修改的数据数
143.
int
num
=
0;
144.
switch
(matcher.match(uri))
{
145.
case
WORDS:
146.
num
=
db.update("dict",
values,
selection,
selectionArgs);
147.
break;
148.
case
WORD:
149.
long
id
=
ContentUris.parseId(uri);
150.
String
whereClause
=
Words.Word._ID
+
"="
+
id;
151.
//如果原来的where子句存在,拼接where子句
152.
if
(selection
!=
null
&&
!"".equals(selection))
{
153.
whereClause
=
whereClause
+
"and"
+
selection;
154.
}
155.
num
=
db.update("dict",
values,
whereClause,
selectionArgs);
156.
break;
157.
default:
158.
try
{
159.
throw
new
IllegalAccessException("未知URI:"
+
uri);
160.
}
catch
(IllegalAccessException
e)
{
161.
e.printStackTrace();
162.
}
163.
}
164.
//通知数据已经改变
165.
getContext().getContentResolver().notifyChange(uri,
null);
166.
return
num;
167.
}
168.}
8.2开发ContentProvider程序8.2.2注册ContentProviderAndroidManifest.xml使用<provider>对该ContentProvider进行配置。为便于其它应用查找该ContentProvider,ContentProvider采用了authorities(主机名/域名)对它进行唯一标识。可以把ContentProvider看作是一个网站,authorities就是它的域名,配置ContentProvider时通常指定如下属性:name:指定该ContentProvider的实现类的类名。authorities:指定该ContentProvider对应的Uri(相当于为该ContentProvider分配一个域名)。android:exported:指定该ContentProvider是否允许其它应用调用。如果将该属性设为false,那么该ContentProvider将不允许其他应用调用。8.2开发ContentProvider程序8.2.2注册ContentProvider以【例8-1】共享单词数据存储为例。注册ContentProvider示例代码如下。
1.<provider
2.
android:authorities="com.myapplication.dictprovider"
3.
android:name=".DictProvider"
4.
android:exported="true"/>
8.2开发ContentProvider程序8.2.3使用ContentProvider当外部应用需要对ContentProvider中的数据进行添加、删除、修改和查询操作时,可以使用ContentResolver类来完成。要获取ContentResolver对象,可以使用Context提供的getContentResolver()方法。ContentResolver调用方法时参数将会传给该ContentProvider的query()、insert()、update()和delete()方法,同时ContentResolver调用方法的返回值,也就是ContentProvider执行这些方法的返回值。ContentResolver类提供了与ContentProvider类相同的四个方法。以【例8-1】共享单词数据存储为例。使用ContentResolver的insert()方法示例代码如下。1.import
android.app.Activity;
2.import
android.content.ContentResolver;
3.import
android.content.ContentValues;
4.import
android.content.Intent;
5.import
android.database.Cursor;
6.import
android.os.Bundle;
7.import
android.view.View;
8.import
android.widget.Button;
9.import
android.widget.EditText;
10.import
android.widget.Toast;
11.import
androidx.annotation.Nullable;
12.import
java.util.ArrayList;
13.import
java.util.HashMap;
14.import
java.util.Map;
15.
16.public
class
DictResolver
extends
Activity
{
17.
ContentResolver
contentResolver;
18.
Button
insert=null;
19.
Button
search=null;
20.
21.
@Override
22.
protected
void
onCreate(@Nullable
Bundle
savedInstanceState)
{
23.
super.onCreate(savedInstanceState);
24.
setContentView(R.layout.dict);
25.
contentResolver=getContentResolver();
26.
insert=(Button)
findViewById(R.id.insert);
27.
search=(Button)
findViewById(R.id.search);
28.
insert.setOnClickListener(new
View.OnClickListener()
{
29.
@Override
30.
public
void
onClick(View
v)
{
31.
String
word=((EditText)findViewById(R.id.word)).getText().toString();
32.
String
detail=((EditText)findViewById(R.id.detail)).getText().toString();
33.
//插入生词记录
34.
ContentValues
values=new
ContentValues();
35.
values.put(Words.Word.WORD,word);
36.
values.put(Words.Word.DETAIL,detail);
37.
contentResolver.insert(Words.Word.DICT_CONTENT_URI,values);
8.2开发ContentProvider程序8.2.4使用ContentProvider实现共享单词数据存储示例【例8-1】创建Android项目,使用ContentProvider实现共享单词数据存储。在res/layout包中创建dict.xml、result.xml及line.xml文件,代码如下:以下为dict.xml1.<?xml
version="1.0"
encoding="utf-8"?>
2.<LinearLayout
xmlns:android="/apk/res/android"
3.
android:layout_width="match_parent"
4.
android:layout_height="match_parent"
5.
android:orientation="vertical">
6.
<EditText
7.
android:id="@+id/word"
8.
android:layout_width="match_parent"
9.
android:layout_height="wrap_content"
/>
10.
<EditText
11.
android:id="@+id/detail"
12.
android:layout_width="match_parent"
13.
android:layout_height="wrap_content"
/>
14.
<Button
15.
android:id="@+id/insert"
16.
android:layout_width="wrap_content"
17.
android:layout_height="wrap_content"
18.
android:text="插入"
/>
19.
<EditText
20.
android:id="@+id/key"
21.
android:layout_width="match_parent"
22.
android:layout_height="wrap_content"
/>
23.
<Button
24.
android:id="@+id/search"
25.
android:layout_width="wrap_content"
26.
android:layout_height="wrap_content"
27.
android:text="查询"
/>
28.</LinearLayout>8.2开发ContentProvider程序8.2.4使用ContentProvider实现共享单词数据存储示例以下为result.xml1.<?xml
version="1.0"
encoding="utf-8"?>
2.<LinearLayout
xmlns:android="/apk/res/android"
3.
android:orientation="vertical"
android:layout_width="match_parent"
4.
android:layout_height="match_parent">
5.
<ListView
6.
android:layout_width="wrap_content"
7.
android:layout_height="wrap_content"
8.
android:id="@+id/show"/>
9.</LinearLayout>
8.2开发ContentProvider程序8.2.4使用ContentProvider实现共享单词数据存储示例以下为line.xml1.<?xml
version="1.0"
encoding="utf-8"?>
2.<LinearLayout
xmlns:android="/apk/res/android"
3.
android:layout_width="match_parent"
4.
android:layout_height="match_parent"
5.
android:orientation="vertical">
6.
<EditText
7.
android:id="@+id/my_title"
8.
android:layout_width="wrap_content"
9.
android:layout_height="wrap_content"
/>
10.
<EditText
11.
android:id="@+id/my_content"
12.
android:layout_width="wrap_content"
13.
android:layout_height="wrap_content"
/>
14.</LinearLayout>8.2开发ContentProvider程序8.2.4使用ContentProvider实现共享单词数据存储示例定义ContentProvider所需的Uri及常量。代码如下:1.import
.Uri;
2.import
vider.BaseColumns;
3.
4.public
final
class
Words
{
5.
//定义该ContentProvider的Authorities
6.
public
static
final
String
AUTHORITY
=
"com.myapplication.dictprovider";
7.
8.
//定义一个静态类,定义该ContentProvider所包含数据列的列名
9.
public
static
final
class
Word
implements
BaseColumns
{
10.
//定义Content所允许操作的三个数据列
11.
public
final
static
String
_ID
=
"_id";
12.
public
final
static
String
WORD
=
"word";
13.
public
final
static
String
DETAILL
=
"detaill";
14.
//定义该Content提供服务的两个uri
15.
public
final
static
Uri
DICT_CONTENT_URI
=
Uri.parse("content://"
+
AUTHORITY
+
"/words");
16.
public
final
static
Uri
WORD_CONTENT_URI
=
Uri.parse("content://"
+
AUTHORITY
+
"/word");
17.
}
18.}
8.2开发ContentProvider程序8.2.4使用ContentProvider实现共享单词数据存储示例继承ContentProvider基类DictProvider提供词典,重写其中的增、删、改、查等方法,以下为代码实现:1.import
android.content.ContentProvider;
2.import
android.content.ContentUris;
3.import
android.content.ContentValues;
4.import
android.content.UriMatcher;
5.import
android.database.Cursor;
6.import
android.database.sqlite.SQLiteDatabase;
7.import
.Uri;
8.import
androidx.annotation.NonNull;
9.import
androidx.annotation.Nullable;
10.
11.public
class
DictProvider
extends
ContentProvider
{
12.
private
static
UriMatcher
matcher
=
new
UriMatcher(UriMatcher.NO_MATCH);
13.
private
static
final
int
WORDS
=
1;
14.
private
static
final
int
WORD
=
2;
15.
private
MyDatabaseHelper
dbOpenHelper;
16.
17.
static
{
18.
//为UriMatcher注册两个Uri
19.
matcher.addURI(Words.AUTHORITY,
"words",
WORDS);
20.
matcher.addURI(Words.AUTHORITY,
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 物业小区节约用电管理制度及管控流程
- 教师校本培训实施细则
- 机械设备租赁 GPS 定位与监控管理手册
- 路灯清洁与外观维护手册
- 矿山开采与安全生产管理手册
- 工业电器设备防爆安全操作手册
- 病退条件符合申请
- 饲料生产工艺流程优化与效率手册
- 餐厅监控区域提示标识手册
- 海事管理与船舶安全操作规范手册
- 《研学旅行课程设计》课件-研学课程设计原则
- DB11T 1197-2024住宅全装修设计标准
- 领导干部个人有关事项报告制度
- 大连啤酒节策划方案
- 成人高考《专科起点本科》生态学基础复习资料
- TCSAE 261-2022 自主代客泊车 地图与定位技术要求
- 脊髓损伤的治疗及研究进展
- 合成实验室安全培训
- YY/T 1833.1-2022人工智能医疗器械质量要求和评价第1部分:术语
- GB/T 17947-2008拟再循环、再利用或作非放射性废物处置的固体物质的放射性活度测量
- GB/T 16895.15-2002建筑物电气装置第5部分:电气设备的选择和安装第523节:布线系统载流量
评论
0/150
提交评论