Android 权限之 Android 6.0 权限机制
Android 6.0 有新的权限机制,这个权限机制主要是在运行时提示给用户是否可以访问系统的某些资源。在6.0 之前,用户在安装应用程序的时候,系统就默认给应用程序相应的权限(当然了5.*的短信权限除外),这样的结果就是 一些不老实的应用会使用一些额外的权限,从而做一些不干净的事情。
在Android 6.0 的时候,系统多出一个dangerous 级别的权限,在这个权限的级别里面包含着用户隐私数据的访问权限。尽管在安装的时候,获得了提示要使用这些权限,但是在使用过程中,仍然需要判断和请求,如果得不到权限 就会奔溃,或者无反馈结果。
具体的dangerous级别的权限包括以下这些:
1 CALENDAR 日历
android.permission.READ_CALENDAR
android.permission.WRITE_CALENDAR
2 CAMERA 相机拍照(相机拍摄过的照片)
android.permission.CAMERA
3 联系人
android.permission.READ_CONTACTS
android.permission.WRITE_CONTACTS
android.permission.GET_ACCOUNTS
4 定位
android.permission.ACCESS_FINE_LOCATION
android.permission.ACCESS_COARSE_LOCATION
5 MICROPHONE 麦克风(录音)
android.permission.RECORD_AUDIO
6 PHONE 手机的信息,IMEI号等。以及通话记录等等
android.permission.READ_PHONE_STATE
android.permission.CALL_PHONE
android.permission.READ_CALL_LOG
android.permission.WRITE_CALL_LOG
android.permission.USE_SIP
android.permission.PROCESS_OUTGOING_CALLS
7 传感器(通过传感器获得的数据)
android.permission.BODY_SENSORS
8 SMS 读取,发送短息
android.permission.SEND_SMS
android.permission.RECEIVE_SMS
android.permission.READ_SMS
android.permission.RECEIVE_WAP_PUSH
android.permission.RECEIVE_MMS
9 STORAGE 存储 读写扩展分区
android.permission.READ_EXTERNAL_STORAGE
android.permission.WRITE_EXTERNAL_STORAGE
10 其他
android.permission.WRITE_SETTINGS
android.permission.SYSTEM_ALERT_WINDOW
当然了这些权限必须在AndroidMainfest文件里面应用。当然了你如果想避免在运行时申请。你可以将编译目标降低到23之下。(android:targetSdkVersion="23")
下面针对 Android 6.0 ,应用程序在运行的时候,主动申请权限相关的一些实现做一简单的介绍
1 判断应用有无权限
ContextCompat.checkSelfPermission(context, "android.permission.READ_CONTACTS") == PackageManager.PERMISSION_GRANTED; 如果是对外提供的jar之类的则调用 checkCallingOrSelfPermission(context, "android.permission.READ_CONTACTS") == PackageManager.PERMISSION_GRANTED;
2 如果上一个步骤返回的是ture,则表示权限存在,如果不是,则需要申请权限。
ActivityCompat.requestPermissions(Activity activity, String[] permissions, int requestCode); //其中permissions 是要请求的数组,requestCode是定义了一个本次请求的请求码
3 然后界面会出现你要求情的权限弹框。如果用户点击是,则表示需要这个权限,如果用户点击否,则表示用户不要这个权限。
4 返回权限请求结果
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults){ if(requestCode == 200){ // 如果和原来的权限请求码相同 int length = grantResults.length; for(int i = 0; i < length; i++){ if (PackageManager.PERMISSION_GRANTED == grantResults[i]){ //表示permissions[i] 这项权限申请成功 } } } }
5 以上是针对1 到 9 这些的权限修改的问题。针对最后两项,应用置顶和修改设置属性的修改和其他9项不同。具体如下:
//针对android.permission.WRITE_SETTINGS 读写系统设置 if (!Settings.System.canWrite(this.getApplicationContext())) { Intent intent = new Intent(android.provider.Settings.ACTION_MANAGE_WRITE_SETTINGS); intent.setData(Uri.parse("package:" + getPackageName())); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); }
//针对android.permission.SYSTEM_ALERT_WINDOW 允许一个程序打开窗口使用TYPE_SYSTEM_ALERT,显示在其他所有程序的顶层 if (!Settings.canDrawOverlays(this)) { Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName())); startActivityForResult(intent, requestcode); }
这两种方法的权限检测与1到9项都是一样的。
6 如果第一次请求权限的时候,被拒绝。第二次在弹出该权限请求的时候,会出现“不在提醒”的选择框。如果用户选择了不在提醒。则永远不会弹出该权限框请求。针对这样的场景,处理如下:
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults){ if(requestCode == 200){ // 如果和原来的权限请求码相同 int length = grantResults.length; for(int i = 0; i < length; i++){ if (PackageManager.PERMISSION_GRANTED == grantResults[i]){ //表示permissions[i] 这项权限申请成功 }else if(!ActivityCompat.shouldShowRequestPermissionRationale(activity, grantResults[i])){ //表示权限被拒绝,而且用户选择了“不在提醒”的复选框。此时一般的做法是弹出对话框,提醒用户。 } } } }
最后的提示就是如果需要这样的处理,需要添加入V4 jar。