android菜鸟学习笔记21----ContentProvider(一)ContentProvider的简单使用

ContentProvider是Android四大组件之一,它用来封装数据,并通过ContentResolver接口将数据提供给其他应用。只有当需要在多个应用之间共享数据时才会用到ContentProvider。

多个应用共享数据时,如何区分是哪个应用中的那部分数据呢?

ContentProvider通过Uri标识具体某个应用的某些数据。当一个应用提供了ContentProvider向其他应用共享数据时,该应用在其ContentProvider中添加标识自己特定数据的Uri,然后其他应用想要获得这些数据时,则可以通过向ContentResolver接口的方法传入标识要访问的数据的Uri即可。

如应用B和应用C都向外提供数据,他们就需要在自己提供的ContentProvider中分别指明自己所能解析的Uri。应用A要访问应用B和应用C提供的数据,就需要使用ContentResolver接口,要向该接口的访问数据的方法中传入特定的Uri以区分是要访问应用B的数据,还是要访问应用C的数据。

应用之间共享数据需要用到的类和接口有:ContentProvider、ContentResolver、Uri、UriMatcher、ContentUris等。

下面一一学习这几个类和接口的简单使用:

1)ContentProvider:

该类是一个抽象类,要在自己应用中使用ContentProvider对象,需要自定义类继承ContentProvider类,并实现几个主要的抽象方法:

onCreate()方法: 其它应用第一次访问该ContentProvider时被调。

insert()方法:外部应用使用此方法添加数据。

delete()方法:外部应用使用此方法删除数据。

update  ()方法:外部应用使用此方法更新数据。

query()方法:外部应用使用此方法查询数据。

getType()方法: 主要用于匹配数据类型,返回当前Uri所代表数据的MIME类型。如果操作的数据属于集合类型,那么MIME类型字符串应该以vnd.android.cursor.dir/自定义类型。数据属于非集合类型数据,应该返回vnd.android.cursor.item/自定义类型。

2)ContentResolver:

是一个接口,可以通过Context.getContentResolver()获取该接口的实例,当在自己应用中要访问别的应用ContentProvider提供的数据时,需要获取该接口的实例,然后调用该接口的insert()、update()、query()、delete()等方法,最终会调用对应ContentProvider中同名的方法,实现共享数据的增删改查操作。

3)Uri:

也是一个抽象类。

Uri标准的格式是:schema://主机名authority/path[/ID]

后面的ID部分根据访问需要,可能没有。

如:content://cn.csc.app1/student标识要访问的是cn.csc.app1所标识的应用中的student表。

ContentProvider中Uri的schema部分一般为content://

authority用来标识要访问的是哪个ContentProvider,通常用能唯一标识应用的包名作为authority。

path部分,则标识我们要访问的是哪些数据,如student表示我们要访问的是student表的数据。

若加上ID部分,如content://cn.csc.app1/student/10,一般被用来表示我们要访问的是student表中的id为10的那条数据。

uri中可以使用通配符:

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

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

如匹配任意表的uri可以表示为:content://cn.csc.app1/*

匹配student表中任意一条记录的uri:content://cn.csc.app1/student/#

常用到的是Uri中的一个静态方法:

parse()用来将字符串表示的uri解析为Uri对象。

4)UriMatcher:

Uri匹配的一个工具类,一般用在ContentProvider中:

一般使用常量NO_MATCH作为参数,构造UriMatcher对象,然后调用addURI()方法向该对象中添加URI,使用match()方法判断传入的Uri的匹配结果。

addURI()方法的参数说明:

authority:Uri中的authority用于标识是哪个ContentProvider

path:Uri中的path部分,标识要操作的是哪张表

code:用于设置当前添加的Uri的标识码,当使用match方法,传入一个Uri参数时,会将匹配到的Uri对应的code返回,以指明当前匹配到哪个Uri。

5)ContentUris:

一个实用的对Uri进行操作的工具类

parseId():用来获取传入的Uri中的Id部分

withAppendId():用于将传入的Uri和id拼接起来。

下面是实际编写ContentProvider的一个简单示例:

第一步:要先有一个数据库帮助类,以便于进行数据库增删改查操作

 1 package cn.csc.content_provider.db;
 2
 3
 4
 5 import android.content.Context;
 6
 7 import android.database.sqlite.SQLiteDatabase;
 8
 9 import android.database.sqlite.SQLiteOpenHelper;
10
11 import android.database.sqlite.SQLiteDatabase.CursorFactory;
12
13 import android.util.Log;
14
15
16
17 public class MySqliteHelper extends SQLiteOpenHelper {
18
19       public static final String TAG = "MYSQLITEHELPER";
20
21       public static final String CREATE_STUDENT = "create table t_student (" +
22
23                  "id integer primary key, name varchar(20), " +
24
25                  "gender varchar(10), age integer)";
26
27       public static final String CREATE_TEACHER = "create table t_teacher(" +
28
29                  "id integer primary key, name varchar(20))";
30
31       public MySqliteHelper(Context context, String name, CursorFactory factory,
32
33                  int version) {
34
35            super(context, name, factory, version);
36
37       }
38
39
40
41       @Override
42
43       public void onOpen(SQLiteDatabase db) {
44
45            Log.i(TAG,"open db");
46
47            super.onOpen(db);
48
49       }
50
51
52
53       @Override
54
55       public void onCreate(SQLiteDatabase db) {
56
57            db.execSQL(CREATE_STUDENT);
58
59            db.execSQL(CREATE_TEACHER);
60
61       }
62
63
64
65       @Override
66
67       public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
68
69
70
71       }
72
73 }

第二步:编写自己的ContentProvider类,继承自ContentProvider类,并实现主要的方法:

 1 1)编写MyContentProvider继承自ContentProvider类:
 2
 3 public class MyContentProvider extends ContentProvider {
 4
 5
 6
 7       @Override
 8
 9       public int delete (Uri uri, String selection, String[] selectionArgs) {
10
11            // TODO Auto-generated method stub
12
13            return 0;
14
15       }
16
17
18
19       @Override
20
21       public String getType(Uri uri) {
22
23            // TODO Auto-generated method stub
24
25            return null;
26
27       }
28
29
30
31       @Override
32
33       public Uri insert (Uri uri, ContentValues values){
34
35            // TODO Auto-generated method stub
36
37            return null;
38
39       }
40
41
42
43       @Override
44
45       public boolean onCreate() {
46
47            // TODO Auto-generated method stub
48
49            return false;
50
51       }
52
53
54
55       @Override
56
57       public Cursor query (Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
58
59            // TODO Auto-generated method stub
60
61            return null;
62
63       }
64
65
66
67       @Override
68
69       public int update (Uri uri, ContentValues values, String selection, String[] selectionArgs) {
70
71            // TODO Auto-generated method stub
72
73            return 0;
74
75       }
76
77 }

2)注意,四大组件都需要在Manifest.xml文件中注册:

在Application节点中添加:

1 <provider android:name="cn.csc.content_provider.MyContentProvider"
2
3             android:authorities="cn.csc.content_provider"></provider>

3)为该类添加一个静态UriMatcher字段,用于后续工作中Uri的匹配工作,并通过静态代码块,添加能够匹配的Uri:

 1 private static final UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
 2
 3       private static final int STUDENT_DIR = 0;
 4
 5       private static final int STUDENT_ITEM = 1;
 6
 7       private static final int TEACHER_DIR = 2;
 8
 9       private static final int TEACHER_ITEM = 3;
10
11       static{
12
13            matcher.addURI("cn.csc.content_provider", "t_student", STUDENT_DIR);
14
15            matcher.addURI("cn.csc.content_provider", "t_student/#", STUDENT_ITEM);
16
17            matcher.addURI("cn.csc.content_provider", "t_teacher", TEACHER_DIR);
18
19            matcher.addURI("cn.csc.content_provider", "t_teacher/#", TEACHER_ITEM);
20
21       }

4)实现父类中的几个抽象方法:

  1 @Override
  2
  3       public int delete (Uri uri, String selection, String[] selectionArgs) {
  4
  5            int cnt = -1;
  6
  7            switch(matcher.match(uri)){
  8
  9            case STUDENT_DIR:
 10
 11                  cnt = db.delete("t_student", selection, selectionArgs);
 12
 13                  break;
 14
 15            case STUDENT_ITEM:
 16
 17                  long id = ContentUris.parseId(uri);
 18
 19                  cnt = db.delete("t_student", "id = ?", new String[]{id+""});
 20
 21                  break;
 22
 23            case TEACHER_DIR:
 24
 25                  cnt = db.delete("t_teacher", selection, selectionArgs);
 26
 27                  break;
 28
 29            case TEACHER_ITEM:
 30
 31                  long id1 = ContentUris.parseId(uri);
 32
 33                  cnt = db.delete("t_teacher", "id = ?", new String[]{id1+""});
 34
 35                  break;
 36
 37            }
 38
 39            return cnt;
 40
 41       }
 42
 43
 44
 45       @Override
 46
 47       public String getType(Uri uri) {
 48
 49            switch(matcher.match(uri)){
 50
 51            case STUDENT_ITEM:
 52
 53                  return "vnd.android.cursor.item/student";
 54
 55            case TEACHER_ITEM:
 56
 57                  return "vnd.android.cursor.item/teacher";
 58
 59            case STUDENT_DIR:
 60
 61                  return "vnd.android.cursor.dir/student";
 62
 63            case TEACHER_DIR:
 64
 65                  return "vnd.android.cursor.dir/teacher";
 66
 67            }
 68
 69            return null;
 70
 71       }
 72
 73
 74
 75       @Override
 76
 77       public Uri insert (Uri uri, ContentValues values){
 78
 79
 80
 81            switch(matcher.match(uri)){
 82
 83            case STUDENT_DIR:
 84
 85                  long id = db.insert("t_student", null, values);
 86
 87                  return ContentUris.withAppendedId(uri, id);
 88
 89            case TEACHER_DIR:
 90
 91                  return ContentUris.withAppendedId(uri, db.insert("t_teacher", null, values));
 92
 93            }
 94
 95            return null;
 96
 97       }
 98
 99
100
101       @Override
102
103       public boolean onCreate() {
104
105            helper = new MySqliteHelper(getContext(), "students.db", null, 1);
106
107            db = helper.getWritableDatabase();
108
109            return true;
110
111       }
112
113
114
115       @Override
116
117       public Cursor query (Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
118
119            Cursor cursor = null;
120
121            switch (matcher.match(uri)) {
122
123            case STUDENT_ITEM:
124
125                  long id = ContentUris.parseId(uri);
126
127                  cursor = db.query("t_student", projection, "id = ?", new String[]{id+""}, null, null, sortOrder);
128
129                  break;
130
131            case TEACHER_ITEM:
132
133                  long id1 = ContentUris.parseId(uri);
134
135                  cursor = db.query("t_teacher", projection, "id = ?", new String[]{id1+""}, null, null, sortOrder);
136
137                  break;
138
139            case STUDENT_DIR:
140
141                  cursor = db.query("t_student", projection, selection, selectionArgs, null, null, sortOrder);
142
143                  break;
144
145            case TEACHER_DIR:
146
147                  cursor = db.query("t_teacher", projection, selection, selectionArgs, null, null, sortOrder);
148
149                  break;
150
151            }
152
153            return cursor;
154
155       }
156
157
158
159       @Override
160
161       public int update (Uri uri, ContentValues values, String selection, String[] selectionArgs) {
162
163            int cnt = -1;
164
165            switch (matcher.match(uri)) {
166
167            case STUDENT_ITEM:
168
169                  long id = ContentUris.parseId(uri);
170
171                  cnt = db.update("t_student", values, "id = ?", new String[]{id+""});
172
173                  break;
174
175            case TEACHER_ITEM:
176
177                  long id1 = ContentUris.parseId(uri);
178
179                  cnt = db.update("t_teacher", values, "id = ?", new String[]{id1+""});
180
181                  break;
182
183            case STUDENT_DIR:
184
185                  cnt = db.update("t_student", values, selection, selectionArgs);
186
187                  break;
188
189            case TEACHER_DIR:
190
191                  cnt = db.update("t_teacher", values, selection, selectionArgs);
192
193                  break;
194
195            }
196
197            return cnt;
198
199       }

5)新建一个项目,在其中通过ContentResolver访问该ContentProvider提供的数据:

 1 public class MyTest extends AndroidTestCase {
 2
 3       public void testInsert(){
 4
 5            Uri uri = Uri.parse("content://cn.csc.content_provider/t_student");
 6
 7            ContentValues values = new ContentValues();
 8
 9            values.put("name", "dqrcsc");
10
11            values.put("gender", "male");
12
13            values.put("age", 24);
14
15            Uri uri2 = getContext().getContentResolver().insert(uri, values);
16
17            Log.i("Test",uri2.toString());
18
19       }
20
21       public void testUpdate(){
22
23            Uri uri = Uri.parse("content://cn.csc.content_provider/t_student/2");
24
25            ContentValues values = new ContentValues();
26
27            values.put("name", "bbbb");
28
29            values.put("gender", "female");
30
31            values.put("age", 12);
32
33            int i = getContext().getContentResolver().update(uri, values, null, null);
34
35            Log.i("Test",i+"");
36
37       }
38
39       public void testQuery(){
40
41            Uri uri = Uri.parse("content://cn.csc.content_provider/t_student/3");
42
43            Cursor cursor = getContext().getContentResolver().query(uri, new String[]{"id","name","gender","age"}, null, null, null);
44
45            while(cursor != null && cursor.moveToNext()){
46
47                  Log.i("Test",cursor.getString(0)+","+cursor.getString(1)+","+cursor.getString(2)+","+cursor.getString(3));
48
49            }
50
51       }
52
53       public void testQueryAll(){
54
55            Uri uri = Uri.parse("content://cn.csc.content_provider/t_student");
56
57            Cursor cursor = getContext().getContentResolver().query(uri, new String[]{"id","name","gender","age"}, null, null, null);
58
59            while(cursor != null && cursor.moveToNext()){
60
61                  Log.i("Test",cursor.getString(0)+","+cursor.getString(1)+","+cursor.getString(2)+","+cursor.getString(3));
62
63            }
64
65       }
66
67       public void testDelete(){
68
69            Uri uri = Uri.parse("content://cn.csc.content_provider/t_student/6");
70
71            int i = getContext().getContentResolver().delete(uri, null, null);
72
73            Log.i("Test",i+"");
74
75       }
76
77 }

以上,就是ContentProvider的简单使用。

时间: 2024-10-27 13:39:20

android菜鸟学习笔记21----ContentProvider(一)ContentProvider的简单使用的相关文章

android菜鸟学习笔记22----ContentProvider(二)ContentObserver的简单使用

现在有这样一个应用A通过ContentProvider提供自己的数据给其他应用,应用B通过ContentResolver获取应用A中提供的数据,并将其展示在ListView中,而应用C通过ContentResolver修改应用A中的数据,或者添加新的数据.现在的问题是应用C修改A中数据后,应用B的ListView中显示的还是历史数据…… 具体程序如下: ContentProvider和插入数据的应用分别复用上一篇中的两个应用,然后新建一个应用,用于获取ContentProvider中的数据,并在

android菜鸟学习笔记7----Activity(一)

Activity是android应用程序中重要的组件之一,常听到的android四大组件是Activity.Service.BroadcastReceiver和ContentProvider.它间接继承自android.content.Context,因此,有些时候都直接把Activity实例当做Context的实例来使用. 如前面所提到的要在应用程序中使用Activity,必须在Android Manifest.xml中配置它. 新建一个Android工程,新建过程中勾选create acti

android菜鸟学习笔记24----与服务器端交互(一)使用HttpURLConnection和HttpClient请求服务端数据

主要是基于HTTP协议与服务端进行交互. 涉及到的类和接口有:URL.HttpURLConnection.HttpClient等 URL: 使用一个String类型的url构造一个URL对象,如: URL url = new URL(http://10.0.2.2/index.php); openConnection()方法返回一个对指定url的资源的连接.返回类型是URLConnection,但是,由于这里我们一般用的是http协议,所以返回的实际是HttpURLConnection对象,故一

android菜鸟学习笔记27----Fragment的简单使用

1.Fragment的生命周期: 简单在新建一个MyFragment继承自Fragment,重写各个生命周期回调方法,各个方法中直接输出标识相关函数被调用的信息. 重写MainActivity的各个生命周期回调方法,同样输出标识信息. MyFragment.java: 1 public class MyFragment extends Fragment { 2 3 @Override 4 5 public void onActivityCreated(Bundle savedInstanceSt

android菜鸟学习笔记30----Android使用百度地图API(一)准备工作及在应用中显示地图

1.准备工作: 百度地图API是免费开放的,但是需要申请API Key: 1)先注册一个百度开发者帐号 2)进入百度开放服务平台http://developer.baidu.com/ 3)进入LBS云 4)点击右上角的API控制台,没有登录的话会先跳转到登录页面,登录成功之后就进入应用控制台了: 5)点击创建应用: 应用类型选择Android SDK,注意下面的安全码,格式是数字签名+应用包名,中间用分号分隔.数字签名的获得: Eclipse中window->Preferences->Andr

android菜鸟学习笔记7----android布局(二)

3.FrameLayout:帧布局 如同Flash或者photoshop中图层的概念,在上面的图层遮盖下面的图层,没被遮到的地方仍然显示出来. 右击res/layout,然后在弹出的菜单中选择new,然后选择Android Xml File,要新建FrameLayout布局文件,就选择FrameLayout作为其根节点即可.文件名为frame_layout.xml. 代码如下: 1 <?xml version="1.0" encoding="utf-8"?&g

android菜鸟学习笔记6----android布局(一)

Android应用的UI组件都是继承自View类,View类表示的就是一个空白的矩形区域.常用的组件如TextView.Button.EditText等都直接或间接继承自View. 此外,View还有一个重要的子类ViewGroup,该类可以用来包含多个View组件,本身也可以当做一个View组件被其他的ViewGroup所包含,由此,可以构建出非常复杂的UI界面. 常用的布局管理器如FrameLayout.LinearLayout.RelativeLayout等都直接继承自ViewGroup.

android菜鸟学习笔记14----Android控件(三) ListView的简单使用

MVC模式: MVC的基本原理就是通过Controller连接View和Model.当View中所显示的数据发生变化时,会通知Controller,然后由Controller调用Model中的相关方法执行相应的数据修改操作.反之,当Model中的数据发生变化时,也会通知Controller,由Controller通知View更新显示内容.如此一来,就使得数据部分与视图部分相分离,任何一方发生改变都不会影响到另一方. 而在android中,MVC的一个常见应用就是ListView显示数据.V代表的

android菜鸟学习笔记31----Android使用百度地图API(二)获取地理位置及地图控制器的简单使用

1.获取当前地理位置: Android中提供了一个LocationManager的类,用于管理地理位置.不能通过构造函数获取该类的实例,而是通过Context的getSystemService(): LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE); 该类中有几个比较常用的方法: getLastKnownLocation(String provider)用于根据传入的provider