Android 6.0权限申请

 一、6.0发布权限变化

1.Android需要手动加入权限申请原因:

1)权限分为了两类:一类是Normal Permissions,这类权限一般不涉及用户隐私,是不需要用户进行授权的,比如手机震动、访问网络等;另一类是Dangerous Permission,一般是涉及到用户隐私的,需要用户进行授权,比如读取sdcard、访问通讯录等。

  • 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

2)权限不是所有的都自动允许给你的app的,默认是没有Dangerous Permission的,需要用户手动去申请,否则功能不能使用,例如:拍照、选取相册、下载、录音、打电话、发短信等等,可能会造成Crash崩溃。

3)6.0及之后系统不会自动去申请权限,也不会给提示,故需要手动自己添加申请。

二、Android程序内部加入6.0权限申请

1.确定自己App哪些地方需要申请?针对自己对应的地方去写权限请求。
例如:拍照、选取相册、下载、录音、打电话、发短信等等;
android.Manifest.permission.CAMERA;
android.Manifest.permission.READ_EXTERNAL_STORAGE
Manifest.permission.WRITE_EXTERNAL_STORAGE;
android.Manifest.permission.READ_PHONE_STATE
android.Manifest.permission.PROCESS_OUTGOING_CALLS;
android.Manifest.permission.RECORD_AUDIO;等等,注意:Manifests里边必须注册权限,低版本手机才能用,高版本手机才可以申请。

2.申请权限并处理
1)在AndroidManifest文件中添加需要的权限,例:
<uses-permission android:name="android.permission.CAMERA"/>
2)加入检查权限的判断,例:
  if (ContextCompat.checkSelfPermission(thisActivity, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {   }else{   //   }这里涉及到一个API,ContextCompat.checkSelfPermission,主要用于检测某个权限是否已经被授予,方法返回值
3)没有这个权限,去请求权限
 ActivityCompat.requestPermissions(thisActivity, new String[]{Manifest.permission.READ_CONTACTS}, MY_PERMISSIONS_REQUEST_READ_CONTACTS);
该方法是异步的,第一个参数是Context;第二个参数是需要申请的权限的字符串数组;第三个参数为requestCode,主要用于回调的时候检测。可以从方法名requestPermissions以及第二个参数看出,是支持一次性申请多个权限的,系统会通过对话框逐一询问用户是否授权。

4)处理权限申请回调
@Override
public void onRequestPermissionsResult(int requestCode,
        String permissions[], int[] grantResults) {
    switch (requestCode) {
        case MY_PERMISSIONS_REQUEST_READ_CONTACTS: {
            // If request is cancelled, the result arrays are empty.
            if (grantResults.length > 0
                && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                // permission was granted, yay! Do the
                // contacts-related task you need to do.

            } else {

                // permission denied, boo! Disable the
                // functionality that depends on this permission.
            }
            return;
        }
    }
}
对于权限的申请结果,首先验证requestCode定位到你的申请,然后验证grantResults对应于申请的结果,这里的数组对应于申请时的第二个权限字符串数组。如果你同时申请两个权限,那么grantResults的length就为2,分别记录你两个权限的申请结果。如果申请成功,就可以做你的事情了~

3.针对大部分权限申请封装

1)权限工具类:PermissionUtils

package com.up366.mobile.common.utils;

import android.Manifest;import android.app.Activity;import android.content.Context;import android.content.Intent;import android.content.pm.PackageManager;import android.net.Uri;import android.os.Build;import android.provider.Settings;import android.support.annotation.NonNull;import android.support.v4.app.ActivityCompat;import android.support.v4.content.ContextCompat;import android.view.View;

import com.up366.common.log.Logger;import com.up366.mobile.R;import com.up366.mobile.common.ui.baseui.BaseActivity;import com.up366.mobile.common.ui.baseui.BaseFragmentActivity;import com.up366.mobile.common.ui.baseui.IPermissionsCallback;

/** * @author 王静 * @description 权限申请公用类 * @date 2017年3月9日 下午1:55:37 */public class PermissionUtils {

public static int permisionIndexCount = 1;    public static final int PERMISSION_ALL = 0;    public static final int PERMISSION_CAMERA = 1;    public static final int PERMISSION_READ_EXTERNAL_STORAGE = 2;    public static final int PERMISSION_WRITE_EXTERNAL_STORAGE = 3;    public static final int PERMISSION_READ_PHONE_STATE = 4;    public static final int PERMISSION_RECORD_AUDIO = 5;

/**     * 检查权限     *     * @param context     * @param permissionsCallback:回调做后续操作     */    public static void requestToUserPermission(Context context, IPermissionsCallback permissionsCallback) {        //BaseActivity将PermissionsCallback传入,应用同一个callBack做同样的后续操作        if (context instanceof BaseActivity) {            ((BaseActivity) context).setPermissionsCallback(permissionsCallback);        } else if (context instanceof BaseFragmentActivity) {            ((BaseFragmentActivity) context).setPermissionsCallback(permissionsCallback);        } else {            throw new IllegalStateException("not Activity context");        }        //判断是哪种类型权限申请        switch (permisionIndexCount) {            case PERMISSION_ALL://所有的,针对小米6.0手机权限有问题,启动不了项目,故去掉刚刚进入app的MainVkActivity就调用申请,可写到内部的Fragment                int i = 0;                String[] permissionStr = new String[6];                if (ContextCompat.checkSelfPermission(context, android.Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {                    permissionStr[i++] = android.Manifest.permission.CAMERA;                }                if (ContextCompat.checkSelfPermission(context, android.Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {                    permissionStr[i++] = android.Manifest.permission.READ_EXTERNAL_STORAGE;                }                if (ContextCompat.checkSelfPermission(context, android.Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {                    permissionStr[i++] = Manifest.permission.WRITE_EXTERNAL_STORAGE;                }                if (ContextCompat.checkSelfPermission(context, android.Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {                    permissionStr[i++] = android.Manifest.permission.READ_PHONE_STATE;                    permissionStr[i++] = android.Manifest.permission.PROCESS_OUTGOING_CALLS;                }                if (ContextCompat.checkSelfPermission(context, android.Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {                    permissionStr[i++] = android.Manifest.permission.RECORD_AUDIO;                }                if (permissionStr.length != 0)                    ActivityCompat.requestPermissions((Activity) context, permissionStr, 100);//去请求所有权限                break;            case PERMISSION_CAMERA://相机权限也要有存储权限                if (ContextCompat.checkSelfPermission(context, android.Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED                        || ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {                    //没有此权限,去请求权限                    ActivityCompat.requestPermissions((Activity) context, new String[]{android.Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, 100);                } else {                    //有权限,直接回去做后续操作                    handleResult(context, permisionIndexCount);                }                break;            case PERMISSION_READ_EXTERNAL_STORAGE:                if (ContextCompat.checkSelfPermission(context, android.Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {                    ActivityCompat.requestPermissions((Activity) context, new String[]{android.Manifest.permission.READ_EXTERNAL_STORAGE}, 100);                } else {                    handleResult(context, permisionIndexCount);                }                break;            case PERMISSION_WRITE_EXTERNAL_STORAGE:                if (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {                    ActivityCompat.requestPermissions((Activity) context, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 100);                } else {                    handleResult(context, permisionIndexCount);                }                break;            case PERMISSION_READ_PHONE_STATE:                if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {                    ActivityCompat.requestPermissions((Activity) context, new String[]{Manifest.permission.READ_PHONE_STATE, Manifest.permission.PROCESS_OUTGOING_CALLS}, 100);                } else {                    handleResult(context, permisionIndexCount);                }                break;            case PERMISSION_RECORD_AUDIO:                if (ContextCompat.checkSelfPermission(context, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {                    ActivityCompat.requestPermissions((Activity) context, new String[]{Manifest.permission.RECORD_AUDIO}, 100);                } else {                    handleResult(context, permisionIndexCount);                }                break;        }    }

/**     * 有权限,直接去做后续操作     *     * @param context     * @param permisionIndexCount:权限类型index     */    private static void handleResult(Context context, int permisionIndexCount) {        IPermissionsCallback permissionsCallback = null;        if (context instanceof BaseActivity) {            permissionsCallback = ((BaseActivity) context).getPermissionsCallback();        } else if (context instanceof BaseFragmentActivity) {            permissionsCallback = ((BaseFragmentActivity) context).getPermissionsCallback();        } else {            throw new IllegalStateException("not Activity context");        }        if (permissionsCallback == null) {            Logger.warn("没有注册IPermissionsCallback");        } else {            permissionsCallback.onResult(permisionIndexCount);        }    }

/**     * 申请权限,回调     *     * @param requestCode:code码=100成功     * @param permissions:所请求的权限名称     * @param grantResults:请求结果:PackageManager.PERMISSION_DENIED申请被用户点禁用;PERMISSION_GRANTED申请成功     * @param context:上下文     * @param result:回调,回去做后续操作     */    public static void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults, final Context context, doSomethingResult result) {        if (requestCode == 100) {            if (grantResults.length > 0) {                for (int i = 0; i < grantResults.length; i++) {                    if (grantResults[i] == PackageManager.PERMISSION_DENIED) {//拒绝啦                        String msg = "";                        String permissionName = "";                        switch (permisionIndexCount) {//根据请求的类型,弹提示“您已禁用应用所需权限,有些功能将无法使用,请返回重新尝试,并选择允许权限。”                            case PERMISSION_ALL:                                msg = context.getString(R.string.permission_all);                                permissionName = "相关权限";                                break;                            case PERMISSION_CAMERA:                                msg = context.getString(R.string.permission_camera);                                permissionName = "相机权限";                                break;                            case PERMISSION_READ_EXTERNAL_STORAGE:                                msg = context.getString(R.string.permission_read_exteranal_storage);                                permissionName = "存储权限";                                break;                            case PERMISSION_WRITE_EXTERNAL_STORAGE:                                msg = context.getString(R.string.permission_write_exteranal_storage);                                permissionName = "存储权限";                                break;                            case PERMISSION_READ_PHONE_STATE:                                msg = context.getString(R.string.permission_read_phone_state);                                permissionName = "电话权限";                                break;                            case PERMISSION_RECORD_AUDIO:                                msg = context.getString(R.string.permission_read_exteranal_storage);                                permissionName = "录音权限";                                break;                        }                        //这个用户拒绝了权限请求,并且选择了不再提示!跳转至设置页面                        //shouldShowRequestPermissionRationale方法只能在23及以上版本调用                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !((Activity) context).shouldShowRequestPermissionRationale(permissions[i])) {

new CuDialog(context).create(R.layout.permission_denyed_forerer_to_setting)                                    .setText(R.id.dialog_msg, "无法获取" + permissionName + ",需要手动授权,否则该功能无法使用。")                                    .setOnClickListener(new int[]{R.id.dialog_leftbtn, R.id.dialog_rightbtn}, new View.OnClickListener() {                                        @Override                                        public void onClick(View v) {                                            if (v.getId() == R.id.dialog_rightbtn) {//去设置                                                Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);                                                Uri uri = Uri.fromParts("package", context.getPackageName(), null);                                                intent.setData(uri);                                                ((Activity) context).startActivityForResult(intent, 1024);                                                return;                                            } else if (v.getId() == R.id.dialog_leftbtn) {//取消

}                                        }                                    }).show();                        } else {                            CuDialog.showOkDialog((Activity) context, msg);                        }                        return;                    }                }                //权限被同意,做后续操作                result.onResult(permisionIndexCount);

}        }    }

/**     * 做后续操作接口     */    public interface doSomethingResult {        void onResult(int permisionIndexCount);    }}
PermissionUtils的gist链接:https://gist.github.com/wangjing0311/bf33938d2a762870d406a1b10ace75fe
2)所用接口:IPermissionsCallback
package com.up366.mobile.common.ui.baseui;

public interface IPermissionsCallback {

void onResult(int permisionIndexCount);}
3)BaseActivity与BaseFragmentActivity加入
onRequestPermissionsResult回调处理,还有IPermissionsCallback变量及get,set方法
@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {    super.onRequestPermissionsResult(requestCode, permissions, grantResults);    if (permissionsCallback != null)        PermissionUtils.onRequestPermissionsResult(requestCode, permissions, grantResults, this, new PermissionUtils.doSomethingResult() {            @Override            public void onResult(int permisionIndexCount) {                permissionsCallback.onResult(permisionIndexCount);            }        });}

private IPermissionsCallback permissionsCallback;

public void setPermissionsCallback(IPermissionsCallback permissionsCallback) {    this.permissionsCallback = permissionsCallback;}

public IPermissionsCallback getPermissionsCallback() {    return permissionsCallback;}
4)Activity中权限申请的调用:
PermissionUtils.permisionIndexCount = PermissionUtils.PERMISSION_CAMERA;PermissionUtils.requestToUserPermission(AlertUserInfoActivity.this, permissionsCallback);
及回调处理:

private IPermissionsCallback permissionsCallback = new IPermissionsCallback() {    @Override    public void onResult(int permisionIndexCount) {        switch (permisionIndexCount) {            case 1:                takePictureToPhoto();                break;            case 2:                getLocalPicToPhoto();                break;        }    }};
本人封装处理,已用感觉比较好用,敬请使用。
时间: 2024-08-06 02:14:56

Android 6.0权限申请的相关文章

【Android运行时权限申请快速学习教程】

1. Android权限介绍 Android权限是Android应用在设备上运行所需要的权力,义务就是为用户带来此Android应用的功能. 问题来源:在Android6.0版本之前,根据App在AndroidManifest申请的权限,在安装此App的时候进行提示权限允许,不允许就不给装不给用,那么我们只能默默的忍受这个APP对我们隐私的侵蚀(Eg.通讯录的读取权限). 解决办法:后来Google发现,诶,这样会导致Android用户们想用这个APP的某些功能而不能用.因此,在Android6

Android 6.0 权限管理

Android 6.0 权限管理 Android permission 运行时权限(Runtime permission) 旧版兼容 6.0权限弹框的两种模式 6.0之后的权限分类 Normal permissions(普通权限) Dangerous permissions(危险权限) 运行时权限请求的基本步骤 权限请求策略 运行时权限(Runtime permission) android的权限系统一直是首要的安全概念,因为这些权限只在安装的时候被询问一次.一旦安装了,app可以在用户毫不知晓

Android 6.0权限管理的解析与实战

一.引言 随着Android6.0发布,系统增加了一些新的特性和功能.这次的发布介绍了一种新的权限机制.用户可以在运行时直接管理应用程序的权限.这个功能提升了权限控制的可见性和可控性.同时简化了安装和自动升级过程,用户可以单独撤销或者授予应用程序某项权限,对应用拥有更多的控制权. 二.Android 6.0权限机制 当你应用程序target是Android 6.0及以上(API level 23),确保在运行时检查和请求权限.为了确定你的app是否授予某个权限,通过checkSelfPermis

android 6.0权限全面详细分析和解决方案

原文: http://www.2cto.com/kf/201512/455888.html http://blog.csdn.net/yangqingqo/article/details/48371123 http://inthecheesefactory.com/blog/things-you-need-to-know-about-Android-m-permission-developer-edition/en 一.Marshmallow版本权限简介 android的权限系统一直是首要的安全

Android 6.0 权限知识学习笔记

最近在项目上因为6.0运行时权限吃了亏,发现之前对运行时权限的理解不足,决定回炉重造,重新学习一下Android Permission. 进入正题: Android权限 在Android系统中,权限分为三种:正常权限.危险权限和特殊权限: 正常权限:不会直接给用户隐私权带来风险.如果您的应用在其清单中列出了正常权限,系统将自动授予该权限. 危险权限:涵盖应用需要涉及用户隐私信息的数据或资源,或者可能对用户存储的数据或其他应用的操作产生影响的区域.例如,能够读取用户的联系人属于危险权限.如果应用声

项目中处理android 6.0权限管理问题

android 6.0对于权限管理比较收紧,因此在适配android 6.0的时候就很有必要考虑一些权限管理的问题. 如果你没适配6.0的设备并且权限没给的话,就会出现类似如下的问题: java.lang.SecurityException: Permission Denial: starting Intent { act=android.intent.action.CALL dat=tel:xxxxxxxxxxx cmp=com.android.server.telecom/.componen

Android开发——Android 6.0权限管理机制详解

0.前言 最近在研究所实习,我负责维护Android手机取证项目的Android客户端,有客户反映我们的APP在Android6.0无响应,经过调试发现SD卡读写权限权限被拒绝.但明明是在AndroidManifest.xml文件中声明过的.查了很多资料才知道Android6.0的很多权限申请机制发生了改变,可以说是Android6.0在安全机制上更进了一步吧,因此写下这篇文章以记录. 注:在运行程序时,对于某些权限向用户询问申请(后面会详细地讲)时因为我们知道客户在我们APP中不会点"拒绝&q

Android6.0权限申请工具类

Android6.0以上,有部分权限是需要申请的.共9组,只要一个权限申请成功默认这一组的权限也申请成功,看下图: 权限申请工具类如下: 1 package com.example.android_lianshou_as.utils; 2 3 import android.Manifest; 4 import android.app.Activity; 5 import android.content.DialogInterface; 6 import android.content.Inten

关于Android的app权限申请问题

关于Android8.1的app权限申请问题 例如如何让普通app可以写/sdcard/Android/ 目录 / # cat /data/system/packages.xml | grep bluetooth<package name="com.mediatek.bluetooth.dtt" codePath="/system/app/BtTool" nativeLibraryPath="/system/app/BtTool/lib"