Android6.0(API 23)之后谷歌对权限的管理更加严格了。某些权限不但需要在AndroidManifest清单文件中添加,还需要在应用运行的时候动态申请。
1、权限使用说明
新的权限机制更好的保护了用户的隐私,Google将权限分为两类,一类是Normal Permissions,这类权限一般不涉及用户隐私,是不需要用户进行授权的,比如手机震动、访问网络等;另一类是Dangerous Permission,一般是涉及到用户隐私的,需要用户进行授权,比如读取sdcard、访问通讯录、电话、相机、日历、短信、麦克风、位置、传感器等。
2、动态申请权限的方法
a、在AndroidManifest文件中添加需要的权限。
<!-- 权限管理--> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.MOUNT_FORMAT_FILESYSTEMS"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"></uses-permission> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission> <uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.CAMERA" />
b、动态权限申请基类
package com.invt_iot_for_gm.app; import android.content.pm.PackageManager; import android.support.annotation.NonNull; import android.support.v4.app.ActivityCompat; import android.support.v4.content.ContextCompat; import android.support.v7.app.AppCompatActivity; /** * Created by xl on 2017/12/29. * 在android6.0之后,谷歌为了更进一步保护用户的手机安全及知情权,在权限管理方面做了改变。 * 在6.0之前,我们只需要在Manifest里增加对应的权限标签即可, * 但是现在就不同了,比如调用照相机。用户的系统设置默认不授予你的应用这个权限,而你此时没有进行动态授权, * 那不同产商就会有不同的问题(轻则不能调用,重则直接崩溃,小编的小米就是直接崩) */ public class PermissionsManagerActivity extends AppCompatActivity { /** * RequestCode是获取返回用的 */ protected final static int PERMISSION_REQUEST_CODE = 1; /** * 权限获取监听 */ private IPermissionListener mPermissionListener = null; /** * 判断是否拥有权限 * * @param permissions * @return */ public boolean hasPermission(String... permissions) { for (String permission : permissions) { if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) { return false; } } return true; } /** * 请求权限 */ protected void requestPermission(int code, String... permissions) { ActivityCompat.requestPermissions(this, permissions, code); } /** * 请求权限的回调 * * @param requestCode * @param permissions * @param grantResults */ @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { if(requestCode == PERMISSION_REQUEST_CODE){ for (int i = 0; i < grantResults.length; i++){ // 权限申请被拒绝 if (grantResults[i] != PackageManager.PERMISSION_GRANTED){ //权限拒绝 if (!ActivityCompat.shouldShowRequestPermissionRationale(this, permissions[i])) { // 用户直接拒绝了(勾选不再显示) } else { // 用户此次选择了禁止权限 } ToastUtils.showLongToast(this, R.string.msg_permissiondenied); return; } } //所有权限都被允许 doAfterHoldPermissions(); if(mPermissionListener != null){ mPermissionListener.doAfterHoldPermissions(); } } } /** * 获取权限之后执行逻辑 */ public void doAfterHoldPermissions(){ MyLogger.i(this.getClass().getSimpleName(), "permission granted, do your code"); } /** * 设置获取权限监听器 */ public void setPermissionListener(IPermissionListener listener){ this.mPermissionListener = listener; } }
c、继承基类PermissionsManagerActivity
public class SwipeActivity extends PermissionsManagerActivity {
//初始化handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.arg1) { case OPEN_SWIPE_ATY: //跳转到详细页,在主线程中 openSwipeAty((String) msg.obj); break; case EXIT_SWIPE_ATY: //关闭activity exit(); break; case CLEAR_WEBVIEW_CACHE: //清空缓存数据 clearWVCache(); break; case ALERT_DIALOG: //alert alertDlg((String) msg.obj); break; case OPEN_QR_SCAN: //动态申请权限 requestPermiss(); //扫描二维码 //startScanActivity(REQUSET_QRCODE); break; } } };
/** * 动态申请权限 */ private void requestPermiss() { //动态申请权限 if (hasPermission(Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.VIBRATE, Manifest.permission.CAMERA)) { doAfterHoldPermissions(); } else { requestPermission(PERMISSION_REQUEST_CODE, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.VIBRATE, Manifest.permission.CAMERA); } }
/** * 获得权限后执行 */ @Override public void doAfterHoldPermissions() { super.doAfterHoldPermissions(); //扫描二维码 startScanActivity(REQUSET_QRCODE); }
d、完