Android容许一个程序访问另外一个程序的数据,而且保证被访问数据的安全性。主要是经过Content Provider来实现的。java
Android6.0以前,权限在app安装的时候赋予,若是不一样意就没有办法安装,致使了不少店大欺客的行为。6.0之后,Android的权限变成了须要的时候进行申请,也就是运行时申请。可是并非全部的权限都须要申请,只有一些涉及到用户安全和隐私的权限才去申请,这一类权限叫作危险权限。其余的不须要运行时申请的权限叫作普通权限。android
权限组名安全 |
权限名app |
CALENDARide |
READ_CALENDARthis |
WRITE_CALENDARgoogle |
|
CAMERAurl |
CAMERAspa |
CONTACTScode |
READ_CONTACTS |
WRITE_CONTACTS |
|
GET_CONTACTS |
|
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 |
以上权限是以组的方式进行受权,就是说你受权了任意一个权限,那么app将会得到一组权限。
具体的代码以下:
public void call(View view){ if(ContextCompat.checkSelfPermission(RuntimePermissionActivity.this, Manifest.permission.CALL_PHONE)!= PackageManager.PERMISSION_GRANTED){//没有受权 ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.CALL_PHONE},1); }else{//有受权 callPhone(); } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { switch (requestCode){ case 1:{ if(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){ callPhone(); }else { Toast.makeText(this,"您拒绝了权限申请",Toast.LENGTH_SHORT).show(); } break; } } } private void callPhone(){ try { Intent intent = new Intent(Intent.ACTION_CALL); intent.setData(Uri.parse("tel:10086")); startActivity(intent); }catch (SecurityException e){ Log.e(TAG, "callPhone: "+e.getMessage()); } }
代码的讲解以下:
代码中直接打电话,会涉及到用户话费等隐私问题,因此须要获得用户的受权。会调用checkSelfPermission检验是否已经包含此权限,若是没有会调用系统的权限确认窗口进行确认。以后在onRequestPermissionsResult方法中回调。
android中完整的权限表:https://developer.android.google.cn/reference/android/Manifest.permission
注意:普通的权限在使用的时候,是须要在AndroidManifest.xml文件中进行申明的。
咱们能够调用Android系统的一些数据,例如用户的联系人,通话记录,等等内容。
URI用来表示须要得到哪一部分的数据,URI的格式为:<协议>://<authority>/<path>,其中authority通常为程序的包名。
一个标准的URI的表示方式为:content://com.example.app/table1
固然在查询数据的时候,主要用到的是URI的对象,因此以上String类型的参数,还须要经过
Uri uri = Uri.parse("content://com.example.app/table1")得到
使用getContentResolver()方法,得到ContentResolver对象
query( Uri uri,String[] projection, String selection,String[] selectionArgs, String sortOrder):Cursor
query()方法参数 |
对应Sql部分 |
uri |
from table_name |
projection |
select column1,column2 |
selection |
where column = ? |
selectionArgs |
where条件中占位符对应的数据 |
sortOrder |
order by column1,column2 |
insert(Uri url,ContentValues values):Uri//返回值为新建数据的uri
update( Uri uri,ContentValues values, String where,String[] selectionArgs):int //返回值为被更新的行数
delete( Uri url, String where,String[] selectionArgs):int//返回值被删除的行数
实现本身的ContentProvider直接extends ContentProvider,实现其中的onCreate(),query(),insert(),update(),delete(),getType()这几个方法。其中onCreate()返回值表示Provider是否已经建立成功。最后在AndroidManifest.xml文件中配置一下。其中getType()方法返回值是一个MIME类型。
URI的格式为:<协议>://<authority>/<path>
URL能够分为两种:一种是表示全部的的数据,还有一种是表示一条数据。例如:content://base.example.com/table1 表示得到全部数据,而后content://base.example.com/table1/1表示得到一条数据。
*表示匹配任意长度的字符。#表示匹配任意长度的数字。
因此一个可以匹配任意表的URI能够写成:content://base.example.com/ *
可以匹配table1表中的一条数据的URI能够写成:content://base.example.com/table1/#
.必须以vnd开头
.若是内容URI以路径结尾,则后接android.cursor.dir/,若是内容URI以id结尾,则后接android.cursor.item/
.最后接上vnd.<authority>.<path>
content://com.example.com/table1 所对应的MIME为:vnd.android.cursor.dir/vnd.com.example.com.table1
content://com.example.com/table1/1 所对应的MIME为:vnd.android.cursor.item/vnd.com.example.com.table1