转自:
今天将项目中需要授权的地方,增加了判断 -----------关于6.0权限的封装。
大家知道,在android6.0之后,谷歌为了更进一步保护用户的手机安全及知情权,在权限管理方面做了改变。
在6.0之前,我们只需要在Manifest里增加对应的权限标签即可,
如:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CAMERA" />
但是现在就不同了,比如调用照相机。用户的系统设置默认不授予你的应用这个权限,而你此时没有进行动态授权,
那不同产商就会有不同的问题(轻则不能调用,重则直接崩溃,小编的小米就是直接崩)
说了这么多,让我们看看代码。
在BaseActivity做好封装,具体的子类只要进行调用,去实现具体的逻辑就好
四部曲:
第一步,先判断是否有权限
/**
* 判断是否拥有权限
*
* @param permissions
* @return
*/
public boolean hasPermission(String... permissions) {
for (String permission : permissions) {
if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED)
return false;
}
return true;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
第二步:如果没有权限,就进行请求
/**
* 请求权限
*/
protected void requestPermission(int code, String... permissions) {
ActivityCompat.requestPermissions(this, permissions, code);
ToastUtil.showMessage(this, "如果拒绝授权,会导致应用无法正常使用", Toast.Length_SHORT);
}
第三步:请求授权后的回调
/**
* 请求权限的回调
*
* @param requestCode
* @param permissions
* @param grantResults
*/
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case Constants.CODE_CAMERA:
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
ToastUtil.showMessage(this, "现在您拥有了权限");
doYourNeedDo();
} else {
ToastUtil.showMessage(this, "您拒绝授权,会导致应用无法正常使用,可以在系统设置中重新开启权限", Toast.Length_SHORT);
}
break;
case Constants.CODE_READ_EXTERNAL_STORAGE:
break;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
最后,第四步,留一个方法,给子类重写,实现你所需要的业务逻辑(比如 拍照)
public void doYourNeedDo() {
}
OK,封装完成
接下来,在需要进行授权的Activity中 extends 这个封装了权限请求的BaseActvity
在需要调用的地方进行判断
//判断是否有权限
if (hasPermission(Manifest.permission.CAMERA,Manifest.permission.CAMERA)) {
//有权限,则写你的业务逻辑
doYourNeedDo()
}else {
//没权限,进行权限请求
requestPermission(Constants.CODE_CAMERA, Manifest.permission.CAMERA)
}
@Override
public void doYourNeedDo() {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
String cameraPath = LocalImageHelper.getInstance().setCameraImgPath();
File file = new File(cameraPath);
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file));
startActivityForResult(intent, ImageUtils.REQUEST_CODE_GETIMAGE_BYCAMERA);
}
OK,这样就搞定了。
写到这里,总结一下上面的思路,
就是,
一,判断权限、
二、有权限,执行 / 没权限,请求权限
三、请求后的权限回调(这里注意CODE,要匹配)
四、业务逻辑(有权限则直接从第二步跳到这步,没权限则在第三步的回调中调用)
上面的封装方法,最好在Manifest里还是像原先一样,将需要的权限先添加上,这样就可以兼容6.0以上和6.0以下的版本。
6.0以下不会有任何影响。
再说一说友盟的实现逻辑
//如想让你的app在android 6.0系统上也能运行的话,需要动态获取权限,没有权限的话分享sdk会出错,
//参考一下代码做动态获取权限,适配安卓6.0系统
//你需要最新的android.support.v4包,或者v13的包可也以
if(Build.VERSION.SDK_INT>=23){
String[] mPermissionList = new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.ACCESS_FINE_LOCATION,Manifest.permission.CALL_PHONE,Manifest.permission.READ_LOGS,Manifest.permission.READ_PHONE_STATE, Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.SET_DEBUG_APP,Manifest.permission.SYSTEM_ALERT_WINDOW,Manifest.permission.GET_ACCOUNTS,Manifest.permission.WRITE_APN_SETTINGS}
ActivityCompat.requestPermissions(this,mPermissionList,123)
}
其实思路大抵相同,只是友盟是通过判断版本号,是否大于23,。
上面这段代码是直接从友盟分享中拷出来的,mPermissionList 这个数组用在我们第一种封装的方法上也是一样的。