这一篇记录下安卓的组件之一ContentProvider,这个组件的主要作用有两个,一个是通过该组件访问其他应用暴露出来的数据,另一个作用就是将自己应用中的数据选择性的暴露给其他的应用。下面就讲解一下该组件的一些基本概念,以及基本的使用方式。
- ContentProvider 概念详解
内容提供者将数据作为一个或多个与关系数据库中的表相似的表提供给外部应用程序。 行代表提供程序收集的某种类型数据的实例,行中的每一列代表针对实例收集的单个数据片段。
如果app需要将自己的数据共享出去,那么就可以在app中实现ContentProvider,同时注册一个Uri,然后在其他的应用中使用ContentResolver根据Uri取得app中的数据。
上面提到了Uri,那么什么是Uri呢?
在计算机术语中,统一资源标识符(Uniform Resource Identifier,或URI)是一个用于标识某一互联网资源名称的字符串。 该种标识允许用户对任何(包括本地和互联网)的资源通过特定的协议进行交互操作。URI由包括确定语法和相关协议的方案所定义。
URI的格式在Intent那一篇中介绍过了,这里赘述一遍:
URI的格式通常为:scheme://host:port/path,参数的意义依次为:协议头,主机。端口,路径。 -
ContentProvider 简单使用
-
Query
下面讲解一下如何提取系统提供的一些数据,最常用的就是获取系统中的联系人信息。
需要注意的一点是,读取联系人信息,需要添加权限:<uses-permission android:name="android.permission.READ_CONTACTS"/>
private void getContacts(){ ContentResolver resolver = getContentResolver(); Uri uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI; Cursor cursor = resolver.query(uri, null, null, null, null); assert cursor != null; while(cursor.moveToNext()) { String cName = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)); String cNum = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)); Log.d(TAG,"姓名:" + cName); Log.d(TAG,"号码:" + cNum); } cursor.close(); }
上面这一段代码,就是一个最基础的用法,利用了resolver获取数据。只是调用了query方法,这个方法的参数如下:
- @param uri The URI, using the content:// scheme, for the content to retrieve.
- @param projection A list of which columns to return. Passing null will return all columns, which is inefficient.
- @param selection A filter declaring which rows to return, formatted as an SQL WHERE clause (excluding the WHERE itself). Passing null will return all rows for the given URI.
- @param selectionArgs You may include ?s in selection, which will be replaced by the values from selectionArgs, in the order that they appear in the selection. The values will be bound as Strings.
- @param sortOrder How to order the rows, formatted as an SQL ORDER BY clause (excluding the ORDER BY itself). Passing null will use the default sort order, which may be unordered.
- @return A Cursor object, which is positioned before the first entry, or null
- @see Cursor
这一段是安卓sdk中的注释,uri是一个资源标识字符串;projection就是定义的数据库中的列名,为空时代表返回所有列;selection A就是相当于sql中的where语句(ps:学习安卓的开发是需要一些sql的知识的,这里就不详解了,有时间的话,我在把sql的基本用法记录一下,方便自己的查阅,也为初学者提供一些便利);selectionArgs 就是相当于selectionA中的占位数据,selectionA中如果包含?占位符,那么占位的数据就在这个地方填写;sortOrder,顾名思义,就是代表了排序的语句,将取出的数据按照这个地方的规则进行排序。
-
Insert
插入这一块也利用联系人进行信息进行展示,同样的需要添加一些权限控制,<uses-permission android:name="android.permission.WRITE_CONTACTS" />
下面直接给出代码:private void insertContact() throws RemoteException, OperationApplicationException { //使用事务添加联系人 Uri uri = Uri.parse("content://com.android.contacts/raw_contacts"); Uri dataUri = Uri.parse("content://com.android.contacts/data"); ContentResolver resolver = getContentResolver(); ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>(); ContentProviderOperation op1 = ContentProviderOperation.newInsert(uri) .withValue("account_name", null) .build(); operations.add(op1); //依次是姓名,号码,邮箱 ContentProviderOperation op2 = ContentProviderOperation.newInsert(dataUri) .withValueBackReference("raw_contact_id", 0) .withValue("mimetype", "vnd.android.cursor.item/name") .withValue("data2", "zorpan") .build(); operations.add(op2); ContentProviderOperation op3 = ContentProviderOperation.newInsert(dataUri) .withValueBackReference("raw_contact_id", 0) .withValue("mimetype", "vnd.android.cursor.item/phone_v2") .withValue("data1", "17806236835") .withValue("data2", "2") .build(); operations.add(op3); ContentProviderOperation op4 = ContentProviderOperation.newInsert(dataUri) .withValueBackReference("raw_contact_id", 0) .withValue("mimetype", "vnd.android.cursor.item/email_v2") .withValue("data1", "728606401@qq.com") .withValue("data2", "2") .build(); operations.add(op4); //将上述内容添加到手机联系人中 resolver.applyBatch("com.android.contacts", operations); Toast.makeText(getApplicationContext(), "添加成功", Toast.LENGTH_SHORT).show(); }
代码就是这样,很简单,涉及到的就是一个数据类ContentProviderOperation ,这个类是用来存储Content数据,具体的细节就不多说了,这个类在sdk可以直接查看。每个字段都有详细的解释。
-