Android组件系列----ContentProvider内容提供者

【声明】

欢迎转载,但请保留文章原始出处→_→

生命壹号:http://www.cnblogs.com/smyhvae/

文章来源:http://www.cnblogs.com/smyhvae/p/4108017.html

联系方式:[email protected]

【正文】


一、ContentProvider简介:

ContentProvider内容提供者(四大组件之一)主要用于在不同的应用程序之间实现数据共享的功能

ContentProvider可以理解为一个Android应用对外开放的接口,只要是符合它所定义的Uri格式的请求,均可以正常访问执行操作。其他的Android应用可以使用ContentResolver对象通过与ContentProvider同名的方法请求执行,被执行的就是ContentProvider中的同名方法。所以ContentProvider有很多对外可以访问的方法,在ContentResolver中均有同名的方法,是一一对应的,来看 下面这一张图:

Android附带了许多有用的ContentProvider,但是本文暂时不涉及到这么多。Android附带的ContentProvider包括:

  • Browser:存储如浏览器的信息。
  • CallLog:存储通话记录等信息。
  • Contacts:存储联系人等信息。
  • MediaStore:存储媒体文件的信息。
  • Settings:存储设备的设置和首选项信息。

ContentProvider的方法:

如果要创建自己的内容提供者,需要新建一个类继承抽象类ContentProvider,并重写其中的抽象方法。抽象方法如下:

boolean onCreate()   初始化提供者

Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)
查询数据,返回一个数据Cursor对象。其中参数selection和selectionArgs是外部程序提供的查询条件

Uri insert(Uri uri, ContentValues values) 插入一条数据。参数values是需要插入的值

int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) 根据条件更新数据

int delete(Uri uri, String selection, String[] selectionArgs)  根据条件删除数据

String getType(Uri uri)   返回MIME类型对应内容的URI

除了onCreate()和getType()方法外,其他的均为CRUD操作,这些方法中,Uri参数为与ContentProvider匹配的请求Uri,剩下的参数可以参见SQLite的CRUD操作,基本一致。 

备注:还有两个非常有意思的方法,必须要提一下,call()和bulkInsert()方法,使用call,理论上可以在ContentResolver中执行ContentProvider暴露出来的任何方法,而bulkInsert()方法用于插入多条数据。

Uri:

在Android中,Uri是一种比较常见的资源访问方式。而对于ContentProvider而言,Uri也是有固定格式的:<srandard_prefix>://<authority>/<data_path>/<id>

  • <srandard_prefix>:ContentProvider的srandard_prefix始终是content://。
  • <authority>:ContentProvider的名称。
  • <data_path>:请求的数据类型。
  • <id>:指定请求的特定数据。

在ContentProvider的CRUD操作,均会传递一个Uri对象,通过这个对象来匹配对应的请求。那么如何确定一个Uri执行哪项操作呢?需要用到一个UriMatcher对象,这个对象用来帮助内容提供者匹配Uri。它所提供的方法非常简单,仅有两个:

  • void addURI(String authority,String path,int code):添加一个Uri匹配项,authority为AndroidManifest.xml中注册的ContentProvider中的authority属性;path为一个路径,可以设置通配符,#表示任意数字,*表示任意字符;code为自定义的一个Uri代码。
  • int match(Uri uri):匹配传递的Uri,返回addURI()传递的code参数。

二、代码举例:

最终所有工程文件的目录结构如下:

PersonDao是增删改查数据库的工具类,并在PersonContentProvider中得到调用。DBHelper用于初始化SQLite数据库。

PersonContentProvider用于向外提供增删改查的接口。并最终在ContentResolverTest的Test.java中进行单元测试,实现CRUD。

下面来看一下具体的实现步骤。

新建工程文件ContetProviderTest01。

(1)新建类PersonDao:用于进行对SQLite的CRUD操作。代码如下:

PersonDao.java:

 1 package com.example.contentprovidertest01.dao;
 2
 3 import android.content.ContentValues;
 4 import android.content.Context;
 5 import android.database.Cursor;
 6 import android.database.sqlite.SQLiteDatabase;
 7
 8 import com.example.contentprovidertest01.db.DBHelper;
 9
10 public class PersonDao {
11     private DBHelper helper = null;
12
13     public PersonDao(Context context) {
14         helper = new DBHelper(context);
15     }
16
17     //方法:插入操作,返回的long类型为:插入当前行的行号
18     public long insertPerson(ContentValues values) {
19         long id = -1;
20         SQLiteDatabase database = null;
21         try {
22             database = helper.getWritableDatabase();
23             id = database.insert("person", null, values);
24         } catch (Exception e) {
25             e.printStackTrace();
26         } finally {
27             if (database != null) {
28                 database.close();
29             }
30         }
31         return id;
32     }
33
34     public int deletePerson(String whereClause, String[] whereArgs) {
35         int count = -1;
36         SQLiteDatabase database = null;
37         try {
38             database = helper.getWritableDatabase();
39             count = database.delete("person", whereClause, whereArgs);
40         } catch (Exception e) {
41             e.printStackTrace();
42         } finally {
43             if (database != null) {
44                 database.close();
45             }
46         }
47         return count;
48     }
49
50     public int updatePerson(ContentValues values, String whereClause,
51             String[] whereArgs) {
52         SQLiteDatabase database = null;
53         int count = -1;
54         try {
55             database = helper.getWritableDatabase();
56             count = database.update("person", values, whereClause, whereArgs);
57         } catch (Exception e) {
58             e.printStackTrace();
59         } finally {
60             if (null != database) {
61                 database.close();
62             }
63         }
64         return count;
65     }
66
67     public Cursor queryPersons(String selection, String[] selectionArgs) {
68         SQLiteDatabase database = null;
69         Cursor cursor = null;
70         try {
71             database = helper.getReadableDatabase();
72             cursor = database.query(true, "person", null, selection,
73                     selectionArgs, null, null, null, null);
74         } catch (Exception e) {
75             e.printStackTrace();
76         } finally {
77             if (null != database) {
78                 // database.close();
79             }
80         }
81         return cursor;
82     }
83
84 }

(2)新建类DBHelper:用于初始化SQLiate数据库

DBHelper.java:

 1 package com.example.contentprovidertest01.db;
 2
 3 import android.content.Context;
 4 import android.database.sqlite.SQLiteDatabase;
 5 import android.database.sqlite.SQLiteOpenHelper;
 6
 7 public class DBHelper extends SQLiteOpenHelper {
 8
 9     private static String name = "mydb.db"; // 数据库的名字
10     private static int version = 1; // 数据库的版本
11
12     public DBHelper(Context context) {
13         super(context, name, null, version);
14     }
15
16     @Override
17     public void onCreate(SQLiteDatabase db) {
18         // 只能支持基本数据类型:varchar int long float boolean text blob clob
19         // 建表语句执行
20         String sql = "create table person(id integer primary key autoincrement,name varchar(64),address varchar(64))";
21         db.execSQL(sql);
22     }
23
24     @Override
25     public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
26         // TODO Auto-generated method stub
27         String sql = "alter table person add sex varchar(8)";
28         db.execSQL(sql);
29     }
30
31 }

(3)【核心】新建类PersonContentProvider,继承ContetProvider

PersonContentProvider.java:

  1 package com.example.contentprovidertest01;
  2
  3 import com.example.contentprovidertest01.dao.PersonDao;
  4
  5 import android.content.ContentProvider;
  6 import android.content.ContentUris;
  7 import android.content.ContentValues;
  8 import android.content.UriMatcher;
  9 import android.database.Cursor;
 10 import android.net.Uri;
 11 import android.os.Bundle;
 12 import android.util.Log;
 13
 14 public class PersonContentProvider extends ContentProvider {
 15
 16     private final String TAG = "PersonContentProvider";
 17     private PersonDao personDao = null;
 18     private static final UriMatcher URI_MATCHER = new UriMatcher(
 19             UriMatcher.NO_MATCH);// 默认的规则是不匹配的
 20     private static final int PERSON = 1; // 操作单行记录
 21     private static final int PERSONS = 2; // 操作多行记录
 22     // 往UriMatcher中添加匹配规则。注意,这里面的url不要写错了,我就是因为写错了,半天没调试出来。哎···
 23     static {
 24         // 添加两个URI筛选
 25         URI_MATCHER.addURI("com.example.contentprovidertest01.PersonContentProvider",
 26                 "person", PERSONS);
 27         // 使用通配符#,匹配任意数字
 28         URI_MATCHER.addURI("com.example.contentprovidertest01.PersonContentProvider",
 29                 "person/#", PERSON);
 30     }
 31
 32     public PersonContentProvider() {
 33
 34     }
 35
 36     @Override
 37     public boolean onCreate() {
 38         // 初始化一个数据持久层
 39         personDao = new PersonDao(getContext());
 40         //Log.i(TAG, "--->>onCreate()被调用");
 41         return true;
 42     }
 43
 44     @Override
 45     public Uri insert(Uri uri, ContentValues values) {
 46         Uri resultUri = null;
 47         // 解析Uri,返回Code
 48         int flag = URI_MATCHER.match(uri);
 49         switch (flag) {
 50         case PERSONS:
 51             //调用数据库的访问方法
 52             long id = personDao.insertPerson(values); //执行插入操作的方法,返回插入当前行的行号
 53             resultUri = ContentUris.withAppendedId(uri, id);
 54             Log.i(TAG,"--->>插入成功, id=" + id);
 55             Log.i(TAG,"--->>插入成功, resultUri=" + resultUri.toString());
 56             System.out.println("insert success");
 57             break;
 58         }
 59         return resultUri;
 60     }
 61
 62     //方法:删除记录。注:参数:selection和selectionArgs是查询的条件,是由外部(另一个应用程序)传进来的
 63     @Override
 64     public int delete(Uri uri, String selection, String[] selectionArgs) {
 65         int count = -1;
 66         try {
 67             int flag = URI_MATCHER.match(uri);
 68             switch (flag) {
 69             case PERSON:
 70                 // delete from student where id=?
 71                 // 单条数据,使用ContentUris工具类解析出结尾的Id
 72                 long id = ContentUris.parseId(uri);
 73                 String where_value = "id = ?";
 74                 String[] args = { String.valueOf(id) };
 75                 count = personDao.deletePerson(where_value, args);
 76                 break;
 77             case PERSONS:
 78                 count = personDao.deletePerson(selection, selectionArgs);
 79                 break;
 80             }
 81         } catch (Exception e) {
 82             e.printStackTrace();
 83         }
 84         Log.i(TAG, "--->>删除成功,count=" + count);
 85         return count;
 86     }
 87
 88     @Override
 89     public int update(Uri uri, ContentValues values, String selection,
 90             String[] selectionArgs) {
 91         int count = -1;
 92         try {
 93             int flag = URI_MATCHER.match(uri);
 94             switch (flag) {
 95             case PERSON:
 96                 long id = ContentUris.parseId(uri);
 97                 String where_value = " id = ?";
 98                 String[] args = { String.valueOf(id) };
 99                 count = personDao.updatePerson(values, where_value, args);
100                 break;
101             case PERSONS:
102                 count = personDao
103                         .updatePerson(values, selection, selectionArgs);
104                 break;
105             }
106         } catch (Exception e) {
107             e.printStackTrace();
108         }
109         Log.i(TAG, "--->>更新成功,count=" + count);
110         return count;
111     }
112
113     @Override
114     public Cursor query(Uri uri, String[] projection, String selection,
115             String[] selectionArgs, String sortOrder) {
116         Cursor cursor = null;
117         try {
118             int flag = URI_MATCHER.match(uri);
119             switch (flag) {
120             case PERSON:
121                 long id = ContentUris.parseId(uri);
122                 String where_value = " id = ?";
123                 String[] args = { String.valueOf(id) };
124                 cursor = personDao.queryPersons(where_value, args);
125                 break;
126             case PERSONS:
127                 cursor = personDao.queryPersons(selection, selectionArgs);
128                 break;
129             }
130         } catch (Exception e) {
131             e.printStackTrace();
132         }
133         Log.i(TAG, "--->>查询成功,Count=" + cursor.getCount());
134         return cursor;
135     }
136
137     @Override
138     public String getType(Uri uri) {
139         int flag = URI_MATCHER.match(uri);
140         switch (flag) {
141         case PERSON:
142             return "vnd.android.cursor.item/person"; // 如果是单条记录,则为vnd.android.cursor.item/
143                                                         // + path
144
145         case PERSONS:
146             return "vnd.android.cursor.dir/persons"; // 如果是多条记录,则为vnd.android.cursor.dir/
147                                                         // + path
148         }
149         return null;
150     }
151
152     @Override
153     public Bundle call(String method, String arg, Bundle extras) {
154         Log.i(TAG, "--->>" + method);
155         Bundle bundle = new Bundle();
156         bundle.putString("returnCall", "call被执行了");
157         return bundle;
158     }
159 }

18行的UriMatcher类的作用是:匹配内容uri,默认的规则是不匹配的。UriMatcher提供了一个addURI方法:

  • void android.content.UriMatcher.addURI(String authority, String path, int code)

这三个参数分别代表:权限、路径、和一个自定义代码。一般第一个参数是uri(包名.内容提供者的类名),第二个参数一般是数据库的表名。

27行:匹配规则的解释:*表示匹配任意字符,#表示匹配任意数字。注:如果内部的匹配规则越多,越容易访问。

138行的getType(Uri uri)方法:所有的内容提供者都必须提供的一个方法。用于获取uri对象所对应的MIME类型。

然后,每编写一个内容提供者,都必须在清单文件中进行声明。在AndroidManifest.xml中<application>节点中增加,格式如下:

<provider
    android:name=".内容提供者的类名"
    android:authorities="包名.内容提供者的类名" >
</provider>

第3行表示的是uri路径,毕竟Contet Provider是通过路径来访问的。

所以在本程序中,在AndroidManifest.xml的<application>节点中增加如下代码:

<provider
  android:name=".PersonContentProvider"
  android:authorities="com.example.contentprovidertest01.PersonContentProvider" >
</provider>

(4)单元测试类:

这里需要涉及到另外一个知识:ContentResolver内容访问者

要想访问ContentProvider,则必须使用ContentResolver。可以通过ContentResolver来操作ContentProvider所暴露处理的接口。一般使用Content.getContentResolver()方法获取ContentResolver对象。第一段中已经提到:ContentProvider有很多对外可以访问的方法,在ContentResolver中均有同名的方法,是一一对应的。所以它也存在insert、query、update、delete等方法。于是单元测试类可以这样写:(注:单元测试如果不清楚,可以参考另外一篇文章:JUnit单元测试的使用

MyTest.java:

  1 package com.example.contentresolvertest;
  2
  3 import android.content.ContentResolver;
  4 import android.content.ContentValues;
  5 import android.database.Cursor;
  6 import android.net.Uri;
  7 import android.os.Bundle;
  8 import android.test.AndroidTestCase;
  9 import android.util.Log;
 10
 11 public class MyTest extends AndroidTestCase {
 12
 13     public MyTest() {
 14         // TODO Auto-generated constructor stub
 15
 16     }
 17
 18     public void calltest() {
 19         ContentResolver contentResolver = getContext().getContentResolver();
 20         Uri uri = Uri
 21                 .parse("content://com.example.contentprovidertest01.PersonContentProvider/person");
 22         Bundle bundle = contentResolver.call(uri, "method", null, null);
 23         String returnCall = bundle.getString("returnCall");
 24         Log.i("main", "-------------->" + returnCall);
 25     }
 26
 27     //测试方法:向数据库中添加记录。如果之前没有数据库,则会自动创建
 28     public void insert() {
 29         // 使用内容解析者ContentResolver访问内容提供者ContentProvider
 30         ContentResolver contentResolver = getContext().getContentResolver();
 31         ContentValues values = new ContentValues();
 32         values.put("name", "生命贰号");
 33         values.put("address", "湖北");
 34         // content://authorities/person
 35         // http://
 36         Uri uri = Uri
 37                 .parse("content://com.example.contentprovidertest01.PersonContentProvider/person");
 38         contentResolver.insert(uri, values);
 39     }
 40
 41     //测试方法:删除单条记录。如果要删除所有记录:content://com.example.contentprovidertest01.PersonContentProvider/person
 42     public void delete() {
 43         ContentResolver contentResolver = getContext().getContentResolver();
 44         Uri uri = Uri
 45                 .parse("content://com.example.contentprovidertest01.PersonContentProvider/person/2");//删除id为1的记录
 46         contentResolver.delete(uri, null, null);
 47     }
 48
 49     //测试方法:根据条件删除记录。
 50     public void deletes() {
 51         ContentResolver contentResolver = getContext().getContentResolver();
 52         Uri uri = Uri
 53                 .parse("content://com.example.contentprovidertest01.PersonContentProvider/person");
 54         String where = "address=?";
 55         String[] where_args = { "HK" };
 56         contentResolver.delete(uri, where, where_args);  //第二个参数表示查询的条件"address=?",第三个参数表示占位符中的具体内容
 57     }
 58
 59     //方法:根据id修改记录。注:很少有批量修改的情况。
 60     public void update() {
 61         ContentResolver contentResolver = getContext().getContentResolver();
 62         Uri uri = Uri
 63                 .parse("content://com.example.contentprovidertest01.PersonContentProvider/person/2");
 64         ContentValues values = new ContentValues();
 65         values.put("name", "李四");
 66         values.put("address", "上海");
 67         contentResolver.update(uri, values, null, null);
 68     }
 69
 70     //方法:根据条件来修改记录。
 71     public void updates() {
 72         ContentResolver contentResolver = getContext().getContentResolver();
 73         Uri uri = Uri
 74                 .parse("content://com.example.contentprovidertest01.PersonContentProvider/person/student");
 75         ContentValues values = new ContentValues();
 76         values.put("name", "王五");
 77         values.put("address", "深圳");
 78         String where = "address=?";
 79         String[] where_args = { "beijing" };
 80         contentResolver.update(uri, values, where, where_args);
 81     }
 82
 83     //测试方法:查询所有记录。如果要查询单条记录:content://com.example.contentprovidertest01.PersonContentProvider/person/1
 84     public void query() {
 85         ContentResolver contentResolver = getContext().getContentResolver();
 86         Uri uri = Uri
 87                 .parse("content://com.example.contentprovidertest01.PersonContentProvider/person");
 88         Cursor cursor = contentResolver.query(uri, null, null, null, null);
 89         while (cursor.moveToNext()) {
 90             Log.i("MyTest",
 91                     "--->>"
 92                             + cursor.getString(cursor.getColumnIndex("name")));
 93         }
 94     }
 95
 96     //测试方法:根据条件查询所有记录。
 97     public void querys() {
 98         ContentResolver contentResolver = getContext().getContentResolver();
 99         Uri uri = Uri
100                 .parse("content://com.example.contentprovidertest01.PersonContentProvider/person");
101         String where = "address=?";
102         String[] where_args = { "深圳" };
103         Cursor cursor = contentResolver.query(uri, null, where, where_args,
104                 null);
105         while (cursor.moveToNext()) {
106             Log.i("main",
107                     "-------------->"
108                             + cursor.getString(cursor.getColumnIndex("name")));
109         }
110     }
111
112 }

既然ContetProvider实现的是跨应用访问数据,那这个测试类Test.java就应该写在另一个应用程序中才行。于是,我们新建另外一个工程文件ContentResolverTest,在里面添加单元测试,里面的代码其实和上方的Test.java的代码是一模一样的。运行单元测试,依然能在ContentResolverTest中实现对ContentProviderTest01中的CRUD.核心在于:使用应用1中的内容解析者ContentResolver访问应用2中的内容提供者ContentProvider

现在运行ContentProviderTest01中的单元测试类:

1、运行insert()方法,实现插入操作。后台打印如下:

上图中红框部分表明,这个uri就是代表内容提供者中,person表中,id为1的数据。

此时,打开file Explorer,进行查看,发现确实多了个文件:

注意:如果SQLite中之前没有mydb.db这个数据库,当实现插入操作时,会自动创建mydb.db这个数据库,并自动创建person表(因为在PersonDao类中执行了getWritableDatabase()方法)。

现在将上图中的mydb.db导出,然后用SQLiteExpert软件打开,输入sql查询语句,就可以看到person表中的数据了:

如果再执行insert()方法,又会继续添加一条记录(id是自动增长的)。

2、运行query()方法,查询所有记录(目前一共两条记录)。后台输出效果如下:

经测试,其他方法也都是可以执行的。

事实证明,新建的另外一个工程文件ContentResolverTest中,在里面运行单元测试,也是可以执行的(单元测试的代码不变,实现的CRUD功能也一模一样),也就是说,能够对ContentProviderTest01中的SQLite进行CRUD操作。例如,运行query()方法,后台输出如下:

这样,我们的目的也就达到了。

【特别注意】

需要特别注意的是,代码中uri不要写错了,这些错误一旦发生,很难被发现。具体表现在:

1、清单文件中:

<provider
    android:name=".内容提供者的类名"
    android:authorities="包名.内容提供者的类名" >
</provider>

如:

        <provider
            android:name=".PersonContentProvider"
            android:authorities="com.example.contentprovidertest01.PersonContentProvider" >
        </provider>

2、ContentProvider类中的UriMatcher中的uri:

 1     private static final UriMatcher URI_MATCHER = new UriMatcher(
 2             UriMatcher.NO_MATCH);// 默认的规则是不匹配的
 3     private static final int PERSON = 1; // 操作单行记录
 4     private static final int PERSONS = 2; // 操作多行记录
 5     // 往UriMatcher中添加匹配规则。注意,这里面的url不要写错了,我就是因为写错了,半天没调试出来。哎···
 6     static {
 7         // 添加两个URI筛选
 8         URI_MATCHER.addURI("com.example.contentprovidertest01.PersonContentProvider",
 9                 "person", PERSONS);
10         // 使用通配符#,匹配任意数字
11         URI_MATCHER.addURI("com.example.contentprovidertest01.PersonContentProvider",
12                 "person/#", PERSON);
13     }

3、ContentProvider类中的getType()方法里面的代码:

 1     @Override
 2     public String getType(Uri uri) {
 3         int flag = URI_MATCHER.match(uri);
 4         switch (flag) {
 5         case PERSON:
 6             return "vnd.android.cursor.item/person"; // 如果是单条记录,则为vnd.android.cursor.item/
 7                                                         // + path
 8         case PERSONS:
 9             return "vnd.android.cursor.dir/persons"; // 如果是多条记录,则为vnd.android.cursor.dir/
10                                                         // + path
11         }
12         return null;
13     }

4、ContentResolver类中的uri:(以insert()方法为例)

 1     //测试方法:向数据库中添加记录。如果之前没有数据库,则会自动创建
 2     public void insert() {
 3         // 使用内容解析者ContentResolver访问内容提供者ContentProvider
 4         ContentResolver contentResolver = getContext().getContentResolver();
 5         ContentValues values = new ContentValues();
 6         values.put("name", "生命贰号");
 7         values.put("address", "湖北");
 8         // content://authorities/person
 9         // http://
10         Uri uri = Uri
11                 .parse("content://com.example.contentprovidertest01.PersonContentProvider/person");
12         contentResolver.insert(uri, values);
13     }

【工程文件】

链接:http://pan.baidu.com/s/1hq7VO12

密码:0a49

时间: 2024-08-05 02:13:02

Android组件系列----ContentProvider内容提供者的相关文章

Android组件系列----ContentProvider内容提供者【4】

(4)单元測试类: 这里须要涉及到另外一个知识:ContentResolver内容訪问者. 要想訪问ContentProvider.则必须使用ContentResolver. 能够通过ContentResolver来操作ContentProvider所暴露处理的接口.一般使用Content.getContentResolver()方法获取ContentResolver对象.第一段中已经提到:ContentProvider有非常多对外能够訪问的方法,在ContentResolver中均有同名的方法

Android组件系列----ContentProvider内容提供者【2】

二.代码举例: 终于全部project文件的文件夹结构例如以下: PersonDao是增删改查数据库的工具类,并在PersonContentProvider中得到调用.DBHelper用于初始化SQLite数据库. PersonContentProvider用于向外提供增删改查的接口.并终于在ContentResolverTest的Test.java中进行单元測试,实现CRUD. 以下来看一下详细的实现步骤. 新建project文件ContetProviderTest01. (1)新建类Pers

入门篇:9.组件4:ContentProvider(内容提供者)

android 四大基本组件 的ContentProvider(内容提供者) 这个组件其实就是一个应用进行数据或数据库提供.共享其他应用获取数据的组件,其大致的结构图如下: 其中uri是一个重要的中间媒介. 联系到我们平时用的安卓程序,最常见的就是通讯录.在我们的安卓手机里,通讯录的设计其实是两个程序,其中有一个程序没有用户界面,单纯的存储着联系人信息,并且数据库结构复杂,这也是为了保证数据的安全.另外一个程序就是我们可以看见的通讯录程序.那么第一个程序就是一个ContentProvider,用

android 53 ContentProvider内容提供者

ContentProvider内容提供者:像是一个中间件一样,一个媒介一样,可以以标准的增删改差操作对手机的文件.数据库进行增删改差.通过ContentProvider查找sd卡的音频文件,可以提供标准的方法而且不用知道音频文件在那个文件夹里面,只要设置条件就可以找到. 安卓系统把音视频.图片存在系统内部的数据库里面,ContentProvider操作的是数据库不是去文件夹里面去找.sd卡和内存卡的文件安卓系统都会登记,登记文件类型.路径,文件名,文件大小都保存在数据库里.ContentProv

android contentprovider内容提供者

contentprovider内容提供者:让其他app可以访问私有数据库(文件) 1.AndroidManifest.xml 配置provider <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.dbtest&q

[Android Pro] 监听内容提供者ContentProvider的数据变化

转载自:http://blog.csdn.net/woshixuye/article/details/8281385 一.提出需求 有A,B,C三个应用,B中的数据需要被共享,所以B中定义了内容提供者ContentProvider:A应用修改了B应用的数据,插入了一条数据.有这样一个需求,此时C应用需要得到数据被修改的通知并处理相应操作. 二.示例代码 A应用 /** * 对内容提供者进行操作 * * @author XY * */ public class MainActivity exten

contentProvider 内容提供者

http://blog.csdn.net/woshixuye/article/details/8280879 实例代码当数据需要在应用程序间共享时,我们就可以利用ContentProvider为数据定义一个URI.之后其他应用程序对数据进行查询或者修改时,只需要从当前上下文对象获得一个ContentResolver(内容解析器)传入相应的URI就可以了.contentProvider和Activity一样是Android的组件,故使用前需要在AndroidManifest.xml中注册,必须放在

Android组件系列----Activity组件详解

[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/3924567.html 联系方式:[email protected] [正文] 注:四大组件指的是应用组件:Activity.Service.BroadcastReceiver.ContentProvider:之前的控件指的是UI组件. 博文目录: 一.Activity简介 二.Activity的状

(转)ContentProvider 内容提供者

1.1.  什么是内容提供者 内容提供者是Android中的四大组件之一,可以将应用中的数据对外进行共享 内容提供者将数据的访问方式统一,不必针对不同数据类型采取不同的访问策略 内容提供者将数据封装,只暴露出我们希望提供给其他程序的数据 内容提供者中数据更改可被监听 1.2.  创建内容提供者 定义类继承ContentProvider,根据需要重写内部方法    在清单文件的<application>节点下进行配置,<provider>标签中需要指定name和authorities