Android 6.0+ 运行时权限 处理

smartbetter · · 122 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

尽管Android正在被不断开发,但Android 6.0是完全不同的,对于Android 6.0的几个主要的变化,查看查看官网的这篇文章:
https://developer.android.google.cn/about/versions/marshmallow/android-6.0-changes.html
其中当然包含Runtime Permissions。

本篇文章目的就是让开发者能轻松解决一些运行时权限的问题。

Android M 运行时权限

新的权限获取方式除了要求像之前版本一样在AndroidManifest文件中静态申请之外,应用还需根据需要请求权限,方式采用向用户显示一个请求权限的对话框。这些被动态申请的权限可以在系统设置中被手动关闭。另外,对于类别为NORMAL(正常)的权限,仍然只需要在AndroidManifest文件中静态申请,系统安装时会直接获取,对于Dangerous(危险)权限则需要在Java代码中作处理。

Normal Permissions如下:

ACCESS_LOCATION_EXTRA_COMMANDS
ACCESS_NETWORK_STATE
ACCESS_NOTIFICATION_POLICY
ACCESS_WIFI_STATE
BLUETOOTH
BLUETOOTH_ADMIN
BROADCAST_STICKY
CHANGE_NETWORK_STATE
CHANGE_WIFI_MULTICAST_STATE
CHANGE_WIFI_STATE
DISABLE_KEYGUARD
EXPAND_STATUS_BAR
GET_PACKAGE_SIZE
INSTALL_SHORTCUT
INTERNET
KILL_BACKGROUND_PROCESSES
MODIFY_AUDIO_SETTINGS
NFC
READ_SYNC_SETTINGS
READ_SYNC_STATS
RECEIVE_BOOT_COMPLETED
REORDER_TASKS
REQUEST_INSTALL_PACKAGES
SET_ALARM
SET_TIME_ZONE
SET_WALLPAPER
SET_WALLPAPER_HINTS
TRANSMIT_IR
UNINSTALL_SHORTCUT
USE_FINGERPRINT
VIBRATE
WAKE_LOCK
WRITE_SYNC_SETTINGS

Dangerous Permissions如下(权限组的形式):

group:android.permission-group.CONTACTS
    permission:android.permission.WRITE_CONTACTS
    permission:android.permission.GET_ACCOUNTS
    permission:android.permission.READ_CONTACTS

group: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_VOICEMAIL

group:android.permission-group.CALENDAR
    permission:android.permission.READ_CALENDAR
    permission:android.permission.WRITE_CALENDAR

group:android.permission-group.CAMERA
    permission:android.permission.CAMERA

group:android.permission-group.SENSORS
    permission:android.permission.BODY_SENSORS

group:android.permission-group.LOCATION
    permission:android.permission.ACCESS_FINE_LOCATION
    permission:android.permission.ACCESS_COARSE_LOCATION

group:android.permission-group.STORAGE
    permission:android.permission.READ_EXTERNAL_STORAGE
    permission:android.permission.WRITE_EXTERNAL_STORAGE

group:android.permission-group.MICROPHONE
    permission:android.permission.RECORD_AUDIO

group: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

注:如果你申请某个Dangerous Permissions,假设你的app早已被用户授权了同一组的某个危险权限,那么系统会立即授权,而不需要用户去点击授权。开发的时候不要对权限组有过多依赖,尽可能对每个危险权限都进行正常的权限申请。

1.Android 6.0 运行时权限新增 API

// 检查某个权限是否授权
ContextCompat.checkSelfPermission(Context context, String permission);

// 申请一个或多个权限
ActivityCompat.requestPermissions(Activity activity, String[] permissions, int requestCode);

// 是否显示请求权限的说明
ActivityCompat.shouldShowRequestPermissionRationale(Activity activity, String permission);

处理权限结果回调:

@Override
public void onRequestPermissionsResult(int permsRequestCode, String[] permissions, int[] grantResults){
    switch(permsRequestCode){
        case REQUEST_XX_PERMISSION:
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                //授权成功
            } else {
                //授权拒绝
            }
            break;
    }
}

2.Android 6.0 运行时权限处理

(1)在AndroidManifest文件中添加需要的权限(我们假设权限xx);

<uses-permission android:name="android.permission.xx" />

(2)在Java代码中进行动态授权:

private static final int REQUEST_XX_PERMISSION=10;

/**
 * 这个方法在需要进行授权的地方调用
 */
private void requestXxPermission(){
    //判断系统版本
    if (Build.VERSION.SDK_INT >= 23) {
        //检测当前app是否拥有某个权限
        int checkCallPhonePermission = ContextCompat.checkSelfPermission(this, Manifest.permission.xx);
        //判断这个权限是否已经授权过
        if(checkCallPhonePermission != PackageManager.PERMISSION_GRANTED){
            //判断是否需要 向用户解释,为什么要申请该权限,该方法只有在用户在上一次已经拒绝过你的这个权限申请才会调用。
            if(ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.xx))
                Toast.makeText(this,"Need xx permission.",Toast.LENGTH_SHORT).show();
            /**
             * 参数1 Context
             * 参数2 需要申请权限的字符串数组,支持一次性申请多个权限,对话框逐一询问
             * 参数3 requestCode 主要用于回调的时候检测
             */
            ActivityCompat.requestPermissions(this ,new String[]{Manifest.permission.xx},REQUEST_BLUETOOTH_PERMISSION);
            return;
        }else{
        }
    } else {
    }
}

(3)授权回调处理

@Override
public void onRequestPermissionsResult(int permsRequestCode, String[] permissions, int[] grantResults){
    switch(permsRequestCode){
        case REQUEST_XX_PERMISSION:
            if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                //授权成功
            } else {
                //授权拒绝
            }
            break;
    }
}

对于权限的申请结果,首先验证requestCode定位到你的申请,然后验证grantResults对应于申请的结果,这里的数组对应于申请时的第二个权限字符串数组。如果你同时申请两个权限,那么grantResults的length就为2,分别记录你两个权限的申请结果。如果申请成功,就可以做你的事情了。

3.案例一 适配Android 6.0 蓝牙

(1)在AndroidManifest文件中添加需要的权限;

<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />  
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />  
<uses-feature
    android:name="android.hardware.bluetooth_le"
    android:required="true" />

(2)在Java代码中进行动态授权(这里以蓝牙权限为例):

private static final int REQUEST_BLUETOOTH_PERMISSION=10;

private void requestBluetoothPermission(){
    //判断系统版本
    if (Build.VERSION.SDK_INT >= 23) {
        //检测当前app是否拥有某个权限
        int checkCallPhonePermission = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION);
        //判断这个权限是否已经授权过
        if(checkCallPhonePermission != PackageManager.PERMISSION_GRANTED){
            //判断是否需要 向用户解释,为什么要申请该权限
            if(ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_COARSE_LOCATION))
                Toast.makeText(this,"Need bluetooth permission.",Toast.LENGTH_SHORT).show();
            ActivityCompat.requestPermissions(this ,new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},REQUEST_BLUETOOTH_PERMISSION);
            return;
        }else{
        }
    } else {
    }
}

(3)此处为简化处理就不作授权回调处理了。

本文来自:博客园

感谢作者:smartbetter

查看原文:Android 6.0+ 运行时权限 处理

122 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet