您的位置:首页 > 移动开发 > Android开发

Android 6.0应用权限请求

2016-10-13 15:58 351 查看
从API 23版本开始,Google修改了应用权限管理的模型。官方也说了这种方式简化了应用的安装过程,不需要在安装和更新应用的时候去给它们授权了;这种Runtime授权模型,把权力给了用户,让用户清楚的管理各个应用的权限。(Google的工程师的事少了,用户也高兴了,程序员苦逼了)

API 23之前,应用权限申请,将应用所需的权限使用<uses-permission>元素在manifest.xml中陈列后即可,系统在应用安装时自动授权。

API 23之后,应用所需的权限依然使用<uses-permission>元素在manifest.xml中陈列,不过,Android把Permission分成了Normal和Dangerous两类。

Normal permissions do not directly risk the user's privacy. If your app lists a normal permission in its manifest, the system grants the permission automatically.
Normal官方解释该类权限不涉及用户隐私。此类权限使用<uses-permission>元素在manifest.xml中陈列,在用户使用应用时系统自动授权。其中Normal类型包扩:

As of API level 23, the following permissions are classified as聽PROTECTION_NORMAL:

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_IGNORE_BATTERY_OPTIMIZATIONS
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 can give the app access to the user's confidential data. If your app lists a normal permission in its manifest, the system grants
the permission automatically. If you list a dangerous permission, the user has to explicitly give approval to your app.

Dangerous 这一类权限因为涉及用的隐私, 此类权限也要使用<uses-permission>元素在manifest.xml中陈列;在每次使用时还需要用户授权。

第一步:检查授权

// Assume thisActivity is the current activity
int permissionCheck=
ContextCompat.checkSelfPermission(thisActivity,

        Manifest.permission.WRITE_CALENDAR);

第二步:申请授权

// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(thisActivity,

                Manifest.permission.READ_CONTACTS)

        != PackageManager.PERMISSION_GRANTED){

    // Should we show an explanation?

    if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,

            Manifest.permission.READ_CONTACTS)){

        // Show an expanation to the user *asynchronously* -- don't block

        // this thread waiting for the user's response! After the user

        // sees the explanation, try again to request the permission.

    } else{

        // No explanation needed, we can request the permission.

        ActivityCompat.requestPermissions(thisActivity,

                new String[]{Manifest.permission.READ_CONTACTS},

                MY_PERMISSIONS_REQUEST_READ_CONTACTS);

        // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an

        // app-defined int constant. The callback method gets the

        // result of the request.

    }
}

第三步:核实授权结果

@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;

        }

        // other 'case' lines to check for other

        // permissions this app might request

    }
}

Dangerouspermissions and permission groups.
PermissionGroup
Permissions
CALENDAR
READ_CALENDAR

WRITE_CALENDAR

CAMERA
CAMERA

CONTACTS
READ_CONTACTS

WRITE_CONTACTS

GET_ACCOUNTS

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

综上来看,对于程序员来说,改变主要在 Dangerous这个类权限的处理,只不过每次都写这些重复的代码,就有点……因此有个想法写个工具类,来简化这个实现。下面不多说了,直接上码:

工具类:

/**
* 日   期:16/10/13 下午3:29
* 邮   箱:kexuan52@yeah.net
*/
public class PermissionTask {
static SparseArray<PermissionTask> permissionTasks = new SparseArray<>();
static final int FIRST = 0; //已获得授权
static final int SUCCESS = 1; //授权成功
static final int FAILED = 2; //授权失败
static final int DIALOG = 3; //可能上一次用户禁用了改授权

Params params;
public static class Params {
int resultCode = -1;
Activity activity;
String permission;
SparseArray<Task> mTask = new SparseArray();
}

/*public*/ PermissionTask(Params params) {
this.params = params;
}

public PermissionTask push () {
if (permissionTasks.indexOfKey(params.resultCode) < 0) {
permissionTasks.put(params.resultCode, this);
} else {
PermissionTask task = permissionTasks.get(params.resultCode);
if (task == null || !task.equals(this)) {
permissionTasks.put(params.resultCode, this);
}
}
return this;
}

public static void pull(int resultCode) {
if (permissionTasks.indexOfKey(resultCode) >= 0) {
permissionTasks.remove(resultCode);
}
}

public static void requestPermissions(int resultCode) {
if (permissionTasks.indexOfKey(resultCode) >= 0) {
PermissionTask task = permissionTasks.get(resultCode);
if (task != null) {
task.requestPermissions();
}
}
}

public static void checkResult(int requestCode, String[] permissions, int[] grantResults) {
if (permissionTasks.indexOfKey(requestCode) >= 0) {
PermissionTask permissionTask = permissionTasks.get(requestCode);
if (permissionTask == null) return;
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
permissionTask.execTask(SUCCESS);
} else {
permissionTask.execTask(FAILED);
}
}
}

boolean checkSelfPermission() {
return ActivityCompat.checkSelfPermission(params.activity, params.permission) == PackageManager.PERMISSION_GRANTED;
}

void requestPermissions() {
ActivityCompat.requestPermissions(params.activity,new String[]{params.permission}, params.resultCode);
}

boolean execTask(int key) {
Task task = params.mTask.get(key);
if (task != null) {
task.todo();
return true;
}
return false;
}

public void check() {
if (Build.VERSION.SDK_INT < 23) {
execTask(SUCCESS);
return;
}

if (!checkSelfPermission()) {
if (ActivityCompat.shouldShowRequestPermissionRationale(params.activity, params.permission)) {
if (!execTask(DIALOG)) {
requestPermissions();
}
} else {
requestPermissions();
}
} else {
execTask(FIRST);
}
}

public interface Task {
void todo();
}

public static class Builder {
Params params;
public Builder() {
params = new Params();
}
public Builder setActivity(Activity activity) {
params.activity = activity;
return this;
}

public Builder setPermission(String permission) {
params.permission = permission;
return this;
}

public Builder setResultCode(int resultCode) {
params.resultCode = resultCode;
return this;
}

public Builder setFirstTask(Task task) {
params.mTask.put(FIRST, task);
return this;
}

public Builder setSuccessTask(Task task) {
params.mTask.put(SUCCESS, task);
return this;
}

public Builder setDialogTask(Task task) {
params.mTask.put(DIALOG, task);
return this;
}

public Builder setFailedTask(Task task) {
params.mTask.put(FAILED, task);
return this;
}

public PermissionTask create() {
PermissionTask task = new PermissionTask(params);
return task;
}
}
}


Activity流程 

public class BaseActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
PermissionTask.checkResult(requestCode, permissions, grantResults);
}
}


测试demo

public class PermissionTestActivity extends BaseActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//        setContentView(R.layout.activity_main);
new PermissionTask.Builder()
.setActivity(this)
.setPermission(Manifest.permission.CAMERA)
.setResultCode(100)
.setFirstTask(()->{Log.e("task","First task");})
.setDialogTask(()->{
Log.e("task","Dialog task");
new AlertDialog.Builder(PermissionTestActivity.this)
.setTitle("权限申请")
.setMessage("申请使用摄像头")
.setPositiveButton("OK", (dialog, which) -> {
PermissionTask.requestPermissions(100);
})
.setNegativeButton("Cancel",null)
.create().show();
})
.setSuccessTask(()->{Log.e("task","SUCCESS task");})
.setFailedTask(()->{Log.e("task","FAILED task");})
.create().push().check();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android api