Android 6.0应用权限请求

来源:互联网 发布:北京市历年人口数据 编辑:程序博客网 时间:2024/05/31 13:16

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


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


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


  • 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();    }}

0 0
原创粉丝点击