Android--6.0运行时权限处理

来源:互联网 发布:seo是做什么 编辑:程序博客网 时间:2024/06/05 02:20

一、概述

Andorid6.0版本自发布以来,相信不少开发者对于Android6.0版本来说,最大的手头工作无非就是做好6.0申请权限的工作,我们一旦没动态申请权限的话,那么将会报出一系列异常。当然有些权限的需要我们去动态申请的,而有些是不需要的,那么,这里估计会有人问:哪些需要或者哪些不需要?其实说白了,需要我们动态去申请的权限是属于危险权限,而我们不需要去动态申请的权限则是普通权限。下面我们将会介绍。所以,我们开发者有务必对6.0新版本sdk带来权限机制的变化。好的,那么今天我们将介绍Andorid6.0带来的运行时权限的一些处理。


二、运行时权限的变化

新的权限机制更好的保护了用户的隐私,Google将权限分为两类,一类是Normal Permissions正常的权限,这类权限一般不涉及用户隐私,是不需要用户进行授权的,比如手机震动、访问网络等,这类权限也是属于我们文章中概述介绍的非6.0该有申请的权限;另一类是Dangerous Permission危险的权限,一般是涉及到用户隐私的,需要用户进行授权,比如读取sdcard、访问通讯录等,这类权限正好是我们6.0新版本所需要申请的权限。


三、Normal Permissions权限和Dangerous Permissions列表

Normal Permissions:

ACCESS_LOCATION_EXTRA_COMMANDSACCESS_NETWORK_STATEACCESS_NOTIFICATION_POLICYACCESS_WIFI_STATEBLUETOOTHBLUETOOTH_ADMINBROADCAST_STICKYCHANGE_NETWORK_STATECHANGE_WIFI_MULTICAST_STATECHANGE_WIFI_STATEDISABLE_KEYGUARDEXPAND_STATUS_BARGET_PACKAGE_SIZEINSTALL_SHORTCUTINTERNETKILL_BACKGROUND_PROCESSESMODIFY_AUDIO_SETTINGSNFCREAD_SYNC_SETTINGSREAD_SYNC_STATSRECEIVE_BOOT_COMPLETEDREORDER_TASKSREQUEST_INSTALL_PACKAGESSET_ALARMSET_TIME_ZONESET_WALLPAPERSET_WALLPAPER_HINTSTRANSMIT_IRUNINSTALL_SHORTCUTUSE_FINGERPRINTVIBRATEWAKE_LOCKWRITE_SYNC_SETTINGS

Dangerous Permissions:

group:android.permission-group.CONTACTS  permission:android.permission.WRITE_CONTACTS  permission:android.permission.GET_ACCOUNTS  permission:android.permission.READ_CONTACTSgroup:android.permission-group.PHONE  permission:android.permission.READ_CALL_LOG  permission:android.permission.READ_PHONE_STATE  permission:android.permission.CALL_PHONE  permission:android.permission.WRITE_CALL_LOG  permission:android.permission.USE_SIP  permission:android.permission.PROCESS_OUTGOING_CALLS  permission:com.android.voicemail.permission.ADD_VOICEMAILgroup:android.permission-group.CALENDAR  permission:android.permission.READ_CALENDAR  permission:android.permission.WRITE_CALENDARgroup:android.permission-group.CAMERA  permission:android.permission.CAMERAgroup:android.permission-group.SENSORS  permission:android.permission.BODY_SENSORSgroup:android.permission-group.LOCATION  permission:android.permission.ACCESS_FINE_LOCATION  permission:android.permission.ACCESS_COARSE_LOCATIONgroup:android.permission-group.STORAGE  permission:android.permission.READ_EXTERNAL_STORAGE  permission:android.permission.WRITE_EXTERNAL_STORAGEgroup:android.permission-group.MICROPHONE  permission:android.permission.RECORD_AUDIOgroup:android.permission-group.SMS  permission:android.permission.READ_SMS  permission:android.permission.RECEIVE_WAP_PUSH  permission:android.permission.RECEIVE_MMS  permission:android.permission.RECEIVE_SMS  permission:android.permission.SEND_SMS  permission:android.permission.READ_CELL_BROADCASTS

PS:Normal Permissions普通权限是不需要我们在Andorid6.0去动态申请权限的,因为他属于普通权限,一般如果需要用到,我们直接在清单文件里面添加即可。Dangerous Permissions危险权限,则是需要我们在Android6.0中去动态申请权限的。看到Dangerous Permissions危险权限的时候,大家有没有发现都是一组一组的,没错,正是如此!其实之所以一组一组的,是因为Google故意设计的。

那么估计会有人问到,分组的权限机智对于我们开发者有影响吗,确实是有的,好比你现在拿一只安卓6.0版本的手机在运行程序,如果你申请某个危险的权限,假设你的app早已被用户授权了同一组的某个危险权限,那么系统会立即授权,而不需要用户去点击授权。比如你的app对READ_CONTACTS已经授权了,当你的app申请WRITE_CONTACTS时,系统会直接授权通过。此外,对于申请时弹出的dialog上面的文本说明也是对整个权限组的说明,而不是单个权限(ps:这个dialog是不能进行定制的)。

最后值得注意的是:我们在Android6.0申请危险权限的时候,我们要根据需求从而申请对应的权限列表,不能申请错误的权限列表哦!否则会出现一些错误,有关对应的权限名称,可自行上网百度。


四、相关的API以及动态申请权限的步骤

大概的步骤分为:检查权限--申请权限--处理申请权限的回调事件,其中,还有一个申请权限时的拒绝事件,也就是说点击了拒绝申请权限的事件,通常这个容易开开发者忽略,不过下面我们将会讲到。首先我们先来看看申请权限的几个基本步骤:


1、检查权限

if (ContextCompat.checkSelfPermission(MainActivity.this, CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {}
这里主要涉及到了一个API: ContextCompat.checkSelfPermission主要是用于检测当前某个权限是否已经被赋予了。如果当前权限不被PackageManager.PERMISSION_GRANTED所赋予了,我们就需要对他进行权限的申请。


2、申请权限

ActivityCompat.requestPermissions(MainActivity.this, new String[]{CALL_PHONE}, MY_PERMISSIONS_REQUEST_CALL_PHONE);
该方法是用来申请权限的,第一个参数是Context;第二个参数是需要申请的权限的字符串数组;第三个参数为requestCode,主要用于回调的时候检测。也就是我们自己定义的一个结果码,可以从方法名requestPermissions以及第二个参数看出,是支持一次性申请多个权限的,因为他是数组,系统会通过对话框逐一询问用户是否授权。


3、处于申请权限回调事件

@Override    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {        switch (requestCode) {            case MY_PERMISSIONS_REQUEST_CALL_PHONE: {                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {                    CallPhone();                } else {                    Toast.makeText(this, "授权失败!", Toast.LENGTH_LONG).show();                }                break;            }        }    }
对于申请权限的回调事件,我们首先先判断一个和我们申请权限的结果码是否一致,如果一致的话,才能对我们申请的结果进行处理,这里的CallPhone方法我们主要是模拟打电话。具体代码下面会给出。


4、最后有一个API值得提醒一下,就是文章中所说的拒绝回调事件,不知道大家记起来了没有,在文章中曾说过,没记得没关系,下面我将为大家隆重介绍。

if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, CALL_PHONE)) {}
该方法就是我们讲的拒绝权限申请回调事件,比如用户现在点击拒绝了,他会立刻执行到申请回调事件中的失败事件,在该事件中我们一般提示用户一下申请拒绝就可以了。然后等到第二次申请权限的时候,就会立刻执行 shouldShowRequestPermissionRationale方法体,在这个方法体中你需要给用户一个解释,为什么要授权,则使用该方法。一般在开发当中,我们可以在该方法体中用Toast提示用户说--请同意授权后,
才能拨打电话,这是常见的用法之一,但是还有一种比较流氓的手法,就是直接打开手机的设置面板,让用户手动开启该权限,这种做法确实比较流氓的,哈哈....下面最终案例里面会有涉及到这种用法,这么说一来,我确实也是流氓的大笑

好了,相关的API以及动态申请权限的步骤我已经介绍到这里。下面让我们一起来看看简单的例子。


五、简单的例子

这里我们将模拟打电话,大家也知道电话权限是属于危险权限的,在6.0版本中需要我们动态去申请该权限,所以我正好拿来这里做讲解,大家顺便看看6.0打电话是如何处理动态申请权限的。

当然我们这里代码也是非常简单的,无非就是检查权限,申请权限,处理权限回调事件。

MainActivity文件

import android.content.Intent;import android.content.pm.PackageManager;import android.net.Uri;import android.os.Bundle;import android.provider.Settings;import android.support.v4.app.ActivityCompat;import android.support.v4.content.ContextCompat;import android.support.v7.app.AppCompatActivity;import android.util.Log;import android.view.View;import android.widget.Button;import android.widget.Toast;import static android.Manifest.permission.CALL_PHONE;public class MainActivity extends AppCompatActivity {    //初始按钮控件和申请权限结果码    private Button call_phone;    private static final int MY_PERMISSIONS_REQUEST_CALL_PHONE = 0;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        call_phone = (Button) this.findViewById(R.id.call_phone);        call_phone.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                //这里我们将模拟申请打电话权限                TellPhone();            }        });    }    private void TellPhone() {        //检查当前是否有CALL_PHONE电话这个权限        if (ContextCompat.checkSelfPermission(MainActivity.this, CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {            //用户拒绝申请该权限的回调事件            if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, CALL_PHONE)) {                //提示该用户拒绝了权限信息                Toast.makeText(MainActivity.this, "请同意授权后,才能拨打电话", Toast.LENGTH_LONG).show();                // 帮跳转到该应用的设置界面,让用户手动同意打开电话授权(这里采用了流氓做法....)                Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);                Uri uri = Uri.fromParts("package", getPackageName(), null);                intent.setData(uri);                startActivity(intent);                Log.i("申请拒绝", "申请拒绝");            } else {                Log.i("正在申请", "正在申请");                ActivityCompat.requestPermissions(MainActivity.this, new String[]{CALL_PHONE}, MY_PERMISSIONS_REQUEST_CALL_PHONE);            }        } else {            Log.i("申请成功", "申请成功");            CallPhone();        }    }    //拨打电话    private void CallPhone() {        Intent intent = new Intent();        intent.setAction(Intent.ACTION_CALL); // 设置动作        Uri data = Uri.parse("tel:" + 10086); // 设置数据        intent.setData(data);        startActivity(intent);    }    //处理权限申请的回调事件    @Override    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {        switch (requestCode) {            //如果当前跟我们申请权限的结果码一致,则立刻执行            case MY_PERMISSIONS_REQUEST_CALL_PHONE: {                //申请权限成功                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {                    CallPhone();                } else {                    //申请权限失败                    Toast.makeText(this, "申请权限失败", Toast.LENGTH_LONG).show();                }                break;            }        }    }}
布局文件我就不贴了,没什么撒,就只有一个Button而已。

当我们在安卓6.0机器上运行的时候,点击按钮后会立刻弹出权限窗口,这时候你可以选择拒绝或者同意。

当你选择拒绝后会提示申请回调事件中的申请权限失败信息,此时我们还执行不到拒绝回调事件当中。拒绝回调事件会在拒绝后第二次打开时候才执行的。




当你选择同意后会立刻执行CallPhone方法拨打电话。



例子很简单,但是以后遇到6.0危险权限的时候,我们记得动态去申请对应的权限。好了,今天关于Andorid--6.0运行时权限的处理讲解到这里,希望对大家有所帮助!







原创粉丝点击