【安卓开发——运行时权限】

Android 6.0之后,加入了运行时权限功能,参考郭神这里是一个运行时权限的封装。在这之前需要了解到如下相关信息:

  • 运行时权限也必须在AndroidManifest.xml中申明,否则申请时不提示用户,直接回调开发者权限被拒绝。
  • 同一个权限组的任何一个权限被授权了,这个权限组的其他权限也自动被授权。例如一旦WRITE_CONTACTS被授权了,App也有READ_CONTACTS和GET_ACCOUNTS了。
  • 申请某一个权限的时候系统弹出的Dialog是对整个权限组的说明,而不是单个权限。例如我申请READ_EXTERNAL_STORAGE,系统会提示"允许xxx访问设备上的照片、媒体内容和文件吗?"
  • 权限一旦允许,之后运行程序就是默认允许,不会再提示权限申请对话框,不过可在系统提供的程序权限管理中更改。

需要用到运行时权限的危险权限包括如下,当要使用一个权限时,查看属于这张表中的权限时,就需要进行运行时权限处理:

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

OK,接下来开始运行时权限的代码处理。这里为了能够在非Activity中使用,使用Activity管理器提供栈顶Activity,将运行时权限检测写入到BaseActivity中:

public class BaseActivity extends AppCompatActivity {
    private static PermissionListener mListener;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityCollector.addActivity(this);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        ActivityCollector.removeActivity(this);
    }

    /**
     * 请求运行时权限
     *
     * @param permissions
     * @param listener
     */
    public static void requestRuntimePermission(String[] permissions, PermissionListener listener) {
        try {
            Activity topActivity = ActivityCollector.getTopActivity();
            if (topActivity == null) {
                return;
            }
            mListener = listener;
            List permissionList = new ArrayList<>();
            for (String permission : permissions) {
                if (ContextCompat.checkSelfPermission(topActivity, permission) != PackageManager.PERMISSION_GRANTED) {
                    permissionList.add(permission);
                }
            }

            if (!permissionList.isEmpty()) {
                ActivityCompat.requestPermissions(topActivity, permissionList.toArray(new String[permissionList.size()]), 1);
            } else {
                //授权成功
                mListener.onGranted();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode) {
            case 1:
                //有权限被拒绝
                if (grantResults.length > 0) {
                    List deniedPermissions = new ArrayList<>();
                    for (int i = 0; i < grantResults.length; i++) {
                        int grantResult = grantResults[i];
                        String permission = permissions[i];
                        if (grantResult != PackageManager.PERMISSION_GRANTED) {
                            deniedPermissions.add(permission);
                        }
                    }
                    //全部授权成功
                    if (deniedPermissions.isEmpty()) {
                        mListener.onGranted();
                    } else {
                        mListener.onDenied(deniedPermissions);
                    }
                }
                break;
            default:
                break;
        }
    }
}

授权回调接口及使用:

//申明
public interface PermissionListener {
    //授权,同意
    void onGranted();
    //拒绝
    void onDenied(List deniedPermission);
}

//具体调用示例,未继承自BaseActivity的类调用前需要添加BaseActivity.,否则不加。另外,下面的Manifest类是安卓SDK的类,打包时会自动进行引用编译,试着查看该类定义便可知道
BaseActivity.requestRuntimePermission(new String[]{Manifest.permission.CALL_PHONE, Manifest.permission.WRITE_EXTERNAL_STORAGE},new PermissionListener(){
    @Override
    public void onGranted() {
        //真正想要执行的代码逻辑
    }

    @Override
    public void onDenied(List deniedPermission) {
        //此处可进行提示信息
    }
});

常用的ActivityCollector控制器:

public class ActivityCollector {

    private static List activityList = new ArrayList<>();

    public static void addActivity(Activity activity){
        activityList.add(activity);
    }

    public static void removeActivity(Activity activity){
        activityList.remove(activity);
    }

    //获取当前栈顶activity
    public static Activity getTopActivity(){
        if (activityList.isEmpty()){
            return null;
        }else {
            return activityList.get(activityList.size()-1);
        }
    }

    public static void finishAll(){
        for (Activity activity : activityList) {
            if (!activity.isFinishing()){
                activity.finish();
            }
        }
    }
}

 

你可能感兴趣的:(Android)