一、Android 6.0权限的简单介绍
在Android6.0以前的设备上,android的权限只在安装的时候被询问一次。一旦安装了,app可以在用户毫不知晓的情况下访问权限内的所有东西,而且用户通常不会去查看app的权限列表,更不会去深入了解这些权限的作用以及可能带来的相关危害。所以在android 6.0 Marshmallow版本之后,系统不会在软件安装的时候就赋予该app所有其申请的权限,对于一些危险级别的权限,app需要在运行时一个一个询问用户授予权限,先看看6.0的危险级别的权限有哪些。
Permission Group | 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 |
二、第三方库PermissionsDispatcher的使用
PermissionsDispatcher是通过提供简单的注释来处理运行在Android 6.0上的运行时权限。
github地址:https://github.com/hotchemi/PermissionsDispatcher
1、使用PermissionsDispatcher首先搜索下载PermissionsDispatcher的插件,如图:
2、先在module gradle里面添加
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.1.2'
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
3、在app gradle里面添加依赖包,${latest.version}填写最新的版本号,目前为 2.2.0。
apply plugin: 'android-apt'
dependencies {
compile 'com.github.hotchemi:permissionsdispatcher:${latest.version}'
apt 'com.github.hotchemi:permissionsdispatcher-processor:${latest.version}'
}
4、进行动态权限处理代码的生成,在Android Studio中选择Code、Generate、Generate Runtime Permissions,如下图所示:
/**
* @NeedsPermission 当申请的权限被用户允许后,调用此方法。
* @OnShowRationale 当第一次申请权限时,用户选择拒绝,再次申请时调用此方法,在此方法中提示用户为什么需要这个权限。
* @OnPermissionDenied 当申请的权限被用户拒绝后,调用此方法
* @OnNeverAskAgain 当用户点击不再询问后,调用此方法。
*/
@RuntimePermissions
public class PermissionsDispatcherActivity extends AppCompatActivity {
TextView mTxt;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_permissions_dispatcher);
mTxt = (TextView) findViewById(R.id.pd_txt);
}
void onClick(View view) {
PermissionsDispatcherActivityPermissionsDispatcher.needsPermissionWithCheck(this);
}
@NeedsPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
void needsPermission() {
mTxt.setTextColor(Color.GREEN);
mTxt.setText("存储空间权限已申请成功");
}
@OnShowRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)
void showRationale(final PermissionRequest request) {
new AlertDialog.Builder(this)
.setMessage("申请存储空间权限")
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//再次执行请求
request.proceed();
}
}).show();
}
@OnPermissionDenied(Manifest.permission.WRITE_EXTERNAL_STORAGE)
void permissionDenied() {
mTxt.setTextColor(Color.RED);
mTxt.setText("权限被拒绝");
}
@OnNeverAskAgain(Manifest.permission.WRITE_EXTERNAL_STORAGE)
void neverAskAgain() {
mTxt.setTextColor(Color.YELLOW);
mTxt.setText("不再询问");
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
PermissionsDispatcherActivityPermissionsDispatcher.onRequestPermissionsResult(this, requestCode, grantResults);
}
}
看看效果:
三、最后再来自己实现以下,就不多说了,直接上代码
public class RuntimePermisionActivity extends AppCompatActivity {
TextView mTxt;
private final int CAMERA_REQUEST_CODE = 0x001;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_runtime_permision);
mTxt = (TextView) findViewById(R.id.rp_txt);
}
void onClick(View view) {
requestPermissions();
}
private void requestPermissions() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
// 第一次请求权限时,向用户解释为什么需要这个权限,用户如果拒绝,下一次请求shouldShowRequestPermissionRationale()返回true
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
new AlertDialog.Builder(this)
.setMessage("申请存储空间权限")
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//申请存储空间权限
ActivityCompat.requestPermissions(RuntimePermisionActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, CAMERA_REQUEST_CODE);
}
}) .show();
} else {
//申请存储空间权限
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, CAMERA_REQUEST_CODE);
}
} else {
mTxt.setTextColor(Color.GREEN);
mTxt.setText("存储空间权限已申请");
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == CAMERA_REQUEST_CODE) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
mTxt.setTextColor(Color.GREEN);
mTxt.setText("存储空间权限已申请");
} else {
//用户勾选了不再询问
//提示用户手动打开权限
if (!ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
mTxt.setTextColor(Color.RED);
mTxt.setText("存储空间权限已被禁止");
}
}
}
}
}
效果和使用PermissionsDispatcher是一样的
最后再来个最简单的权限判断请求方法
private final static int REQUEST_CODE_ASK_PERMISSIONS = 100;
public static boolean requestPermission(Activity activity, String... premission) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
for (int i = 0; i < premission.length; i++) {
int hasPermission = activity.checkSelfPermission(premission[i]);
if (hasPermission != PackageManager.PERMISSION_GRANTED) {
activity.requestPermissions(premission,
REQUEST_CODE_ASK_PERMISSIONS);
return false;
}
}
}
return true;
}
if (Utils.requestPermission(this,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.CAMERA,
Manifest.permission.RECORD_AUDIO)) {
//请求后的操作
}
github地址:https://github.com/JerryLong/Android/tree/master/app/src/main/java/com/dralong/demo/ui