Android6.0后,对于权限有了更严格的管控,在6.0之前只要AndroidManifest中注册即可,但是6.0之后,还是沿用之前的方法,就会出现一系列的问题。一旦用到需要用到权限方面的问题的时候,只要你没有运行时的去检测权限是否开启,就很有可能crash。
其中有一种偷懒的手段,便是将AndroidManifest的targetSdkVersion设置在小于23的范围内,这样仅仅只要和以前一样,在AndroidMainfest中注册即可。但是随着Android快速的发展,将targetSdkVersion局限在23以下,这绝对不是一个好的开发人员,仅仅是为了完成工作的话,可是会被同行鄙视的哦=。=
所以我们就来探索一下这个必须要学会的技能,以及进一步的封装后,方便使用,也是作为程序员必要的手段吧!
首先我们可以看下原汁原味的写法:
@Override
public void onClick(View v) {
if (!(checkSelfPermission(Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED)) {
requestCameraPermission();
}
}
private static final int REQUEST_PERMISSION_CAMERA_CODE = 1;
private void requestCameraPermission() {
requestPermissions(new String[]{Manifest.permission.CAMERA}, REQUEST_PERMISSION_CAMERA_CODE);
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_PERMISSION_CAMERA_CODE) {
int grantResult = grantResults[0];
boolean granted = grantResult == PackageManager.PERMISSION_GRANTED;
Log.i(LOGTAG, "onRequestPermissionsResult granted=" + granted);
}
}
这是一个请求相机权限的代码,首先请求对相机权限,用户进行权限选择后,通过回调判断用户是否授此功能,来进行不同的操作。
乍一看 ,代码并不是很多,但若是每个activity都需要进行授权功能,就会觉得代码开始冗余了。java中提到,相同的代码,不要超过2次,这也是封装思想。你也可以当cv战士,但这对你今后的成长,有害无益。思想不提神,写10年的代码,也不会进步。
所以接下来我们来封装一下吧,先贴一下整个代码:
public class BaseActivity extends AppCompatActivity {
/**
* (23以及之后需要运行时动态监测的权限)
* 身体传感器
* 日历
* 摄像头
* 通讯录
* 地理位置
* 麦克风
* 电话
* 短信
* 存储空间
*/
public static final int REQUEST_CODE = 0;
private String[] permissions;
public interface PermissionCallBackListening {
void permissionGranted();
void permissionDenied();
}
//回调接口,暴露接口给用户操作
public PermissionCallBackListening listening;
//PermissionCallBackListening的实现类,本身也是一个抽象类,可进行部分操作
abstract class SimplepermiassionCallBackListening implements PermissionCallBackListening {
@Override
public void permissionDenied() {
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
/**
* 设置有多少权限需要加入提示(大于sdk23可用)
*/
public void setPermissions(String[] permissions, PermissionCallBackListening listening) {
this.permissions = permissions;
this.listening = listening;
if(permissions.length==0)
return;
requestPermissions();
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_CODE) {
if (userGrantedAllPermissions(grantResults)) {
// 授权成功、
listening.permissionGranted();
} else {
// 授权失败
listening.permissionDenied();
}
}
}
/**
* 对用户进行授权请求
*/
public void requestPermissions() {
ActivityCompat.requestPermissions(this, permissions,
REQUEST_CODE);
}
/**
* 判断用户是否全都点击了授权
*/
public boolean userGrantedAllPermissions(@NonNull int[] grantResults) {
int length = grantResults.length;
for (int i = 0; i < length; i++) {
// TODO: 2016/10/14
if (!(grantResults[i] == PackageManager.PERMISSION_GRANTED)) {
return false;
}
}
return true;
}
}
这里介绍下2个对象,PermissionCallBackListening和SimplepermiassionCallBackListening,一个用户暴露给用户操作,一个是对PermissionCallBackListening的二次封装。主要介绍下第二个对象,Simple类的诞生主要是为了开发者对于权限失败后进行统一处理,不需要在activity内在进行一次重写。这个看需求,若是要统一处理,就用;单一处理,直接用第一个。代码如下:
//没有Simple类实现时,必须要重写2个方法
findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
setPermissions(permissions, new PermissionCallBackListening() {
@Override
public void permissionGranted() {
Toast.makeText(MainActivity.this, "授权成功", Toast.LENGTH_SHORT).show();
//拍照存储操作
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, 2);
}
@Override
public void permissionDenied() {
Toast.makeText(MainActivity.this, "未授权成功", Toast.LENGTH_SHORT).show();
}
});
}
});
//有Simple类实现时,只需要重写一个方法。当申请权限失败的时候,可以在simple类进行统一处理
setPermissions(permissions, new SimplepermiassionCallBackListening() {
@Override
public void permissionGranted() {
}
});
一旦将上述封装到基类,对于后面继承此基类的子Activity或者也可以写到fragment的基类中,用起来都是非常方便的。