Content Provider 主要用于在不同应用程序间实现数据共享。
不同于文件存储和SharedPreferences存储中的两种全局可读写操作模式,Content Provider可以选择只对那一部分数据进行共享,从而保证我们的程序中的隐私数据不会由泄露的风险。
危险权限9组24项需要进行运行时权限处理。
权限组名 | 权限名 |
---|---|
CALENDAR | READ_CALENAR WRITE_CALENDAR |
CAMERA | CAMERA |
CONTACTS | READ_CONTACETS WRITE_CONTACTS GET_ACCOUNTS |
LOCATION | ACCESS_FINE_LOCATION ACCESS_COARSE_LOCATION |
MICROPHONE | RECORD_AUDIO |
PHONE | READ_PHONE_STATE CALL_PHONE READ_CALL_LOG WRITE_CALL_LOG ADD_VOICEMAIL USE_SIP PROCESS_OUTGOING_CALLS |
SENSORS | BODY_SENSORS |
SMS | SEND_SMS RECEIVE_SMS READ_SMS RECEIVE_WAP_PUSH RECEIVE_MMS |
STORAGE | READ_EXTERNAL_STORAGE WRITE_EXTERNAL_STORAGE |
普通权限,只需要在AndroidManifest.xml文件中添加权限声明就可以了。
举例,申请打电话权限 Manifest.permission.CALL_PHONE
1.先进行判断是否已经获得权限,有则直接打电话,无则申请权限
ContextCompat.checkSelfPermission(MainActivity.this, Manifest.
permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED
2.申请权限
ActivityCompat.requestPermissions(MainActivity.this, new
String[] {Manifest.permission.CALL_PHONE}, 1)
3.申请权限后,系统会弹出一个权限申请框,不管如何操作,最终会回调
onRequestPermissionsResult(int requestCode, String[] permissions,
int[] grantResult)
4.授权结果会封装在grantResult中,做最后判断是否授权成功。
int[0] grantResult == PackageManager.PERMISSION_GRANTED
Content Provider的用法由两种:
通过Context 中的getCOntentResolver()方法获得ContentResolver类的实例。
提供了方法用于对数据进行CRUD操作。(增加(Create)、读取(Read)、更新(Update)和删除(Delete))
content://com.example.app.provider/table1
内容URI字符串解析成Uri对象后,作为参数传入。
Uri uri = Uri.parse("content://com.example.app.provider/table1")
查询table1表数据,代码
Cursor cursor = getContentResolver().query(
uri,//指定查询某个应用程序下的某一张表
projection,//指定查询的列名
selection,//指定where的约束条件
selectionArgs,//为where的占位符提供具体符
sortOrder);//指定查询结果的排序方式
将数据从Cursor对象中逐个读取处理。通过移动游标来遍历Cursor所有行,在取出每一行相应列的数据。
if (cursor != null && cursor.moveToFirst()) {
do {
Stirng colum1 = cursor.getString(cursor.getColumnIndex("column1"));//根据 name的名称获得它的列索引
int colum2 = cursor.getInt(cursor.getColumnIndex("column2"));
}while(cursor.moveToNext());
cursor.close();
}
添加数据,先将待添加的数据组装子啊ContentValues 中,再调用ContentResolver的insert()方法。
ContentValues values = new ContentValues();
values.put("column1", "text");
values.put("column2", 1);
getContentResolver().insert(uri, values);
更新这条新添加的数据,把column1的值清空
ContentValues values = new ContentValues();
values.put("column1", "");
getContentResolver().update(uri, values, "column1 = ? and column2 = ?",
new String[] {"text", "1"});
删除数据
getContentResolver().delete(uri, "column2 = ?", new Stirng[] { "1" }
判断权限
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new
String[] {Manifest.permission.READ_CONTACTS}, 2);
} else {
readContacts();
}
回调返回值
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions,
int[] grantResults) {
case 2:
if (grantResults.length > 0 && grantResults[0] ==
PackageManager.PERMISSION_GRANTED) {
readContacts();
} else {
Toast.makeText(this, "You denied the permssion",
Toast.LENGTH_SHORT).show();
}
break;
default:
}
}
读取联系人
private void readContacts() {
Cursor cursor = null;
try {
cursor = getContentResolver().query(ContactsContract.CommonDataKinds.
Phone.CONTENT_URI, null, null, null, null);
if (cursor != null) {
while (cursor.moveToNext()) {
String displayName = cursor.getString(cursor.getColumnIndex
(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String number = cursor.getString(cursor.getColumnIndex
(ContactsContract.CommonDataKinds.Phone.NUMBER));
contactsList.add(displayName + "\n" + number);
}
adapter.notifyDataSetChanged();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (cursor != null) {
cursor.close();
}
}
}
AndroidManifest.xml声明权限
<uses-permission android:name="android.permission.READ_CONTACTS"/>
1.onCreate()
初始化ContentProvider时调用,完成对数据库的创建和升级。
只有当存在ContentResolver尝试访问我们程序中的数据时,ContentProvider才会被初始化。
2.query()
从ContentProvider中查询数据。查询结果存放在Cursor对象中返回。
3.insert()
向ContentProvider添加一条数据。使用uri参数确定要添加到的表,待添加的数据保持在values参数中。添加完成后,返回一个用于表示这条新纪录的URI。
4.update()
更新ContentProvider已有的数据。使用uri参数确定要更新到的表,新数据保持在values参数中,selection和selectionArgs参数用于约束更新哪些行,受影响的行数将作为返回值返回。
5.delete()
从ContentProvider中删除数据。使用uri参数确定要删除的表,selection和selectionArgs参数用于约束删除哪些行,被删除的行数将作为返回值返回。
6.getType()
根据传入的内容URI来返回相应的MIME类型。
标准的内容URI写法扩展:
原本:
content://com.example.app.provider/table1
内容URI后面添加id
content://com.example.app.provider/table1/1
表示访问/com.example.app这个应用的table1表中id为1的数据
通配符:
使用UriMatcher类匹配内容URI
该类提供addURI()方法,接受三个参数,分别把authority、path和一个自定义代码传进去。
该类提供match()方法,传入一个Uri对象,返回值是某个能够匹配这个URI对象的自定义代码。通过这个代码,可以判断期望访问哪一个表。
使用该类可以判断使用哪一个表,然后再进行CRUD操作。
getType()方法,用于获取Uri对象所对应的MIME类型。一个内容URI所对应的MIME字符串主要三部分组成。
<provider
android:name=".DatabaseProvider"
android:name="com.example.databasetest.provider"
android:enabled="true"
android:exported="true">
provider>