6.0版本以后Android权限成为问题需要手动去授权,长期下来积累了一些解决权限的方法,在这里总结两套工具类以后长期使用。
1、权限介绍
Android开发权限汇总:https://blog.csdn.net/ufo00001/article/details/69397256
申请权限时:
1、在清单文件中声明权限(如果不在这张表中,声明完就可以了)
2、如果在这张表中的权限需要手动来申请
这些权限6.0以后需要手动申请,,每一个权限组中的权限只要有一个权限同意授权了,整个权限组中的权限就不用重复申请了。
Android O 8.0对于权限更加严格
对于针对Android O的应用,此行为已被纠正。系统只会授予应用明确请求的权限。然而一旦用户为应用授予某个权限,则所有后续对该权限组中权限的请求都将被自动批准。
例如,假设某个应用在其清单中列出READ_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAGE。应用请求READ_EXTERNAL_STORAGE,并且用户授予了该权限,如果该应用针对的是API级别24或更低级别,系统还会同时授予WRITE_EXTERNAL_STORAGE,因为该权限也属于STORAGE权限组并且也在清单中注册过。如果该应用针对的是Android O,则系统此时仅会授予READ_EXTERNAL_STORAGE,不过在该应用以后申请WRITE_EXTERNAL_STORAGE权限时,系统会立即授予该权限,而不会提示用户。
注意:如果使用了没有授权的权限,会崩溃的
所以对于8.0权限,我们要做的处理,是尽量把所用到的危险权限全部申请。但是有的权限在不同版本出现,所以要兼容不同的版本,所以要加一个版本的判断。
归根结底:android M (6.0)以后,申请权限组一个,即表示整个权限组可以用,所以我们干脆,只要api 版本大于23(6.0),我们申请的权限就是申请整个权限组。这样就兼容了android8.0-------------------为了省事的话可以用AndPermission这个第三方框架,或者自己封装一个。
2.开源框架EasyPermissionDemo
https://github.com/googlesamples/easypermissions
框架案例
直接调用:
public class TestActivity extends Activity implements EasyPermissions.PermissionCallbacks {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestCodeQRCodePermissions();
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
}
@Override
public void onPermissionsGranted(int requestCode, List perms) {
}
@Override
public void onPermissionsDenied(int requestCode, List perms) {
}
@AfterPermissionGranted(REQUEST_CODE_QRCODE_PERMISSIONS)
private void requestCodeQRCodePermissions() {
String[] perms = {Manifest.permission.CAMERA, Manifest.permission.READ_EXTERNAL_STORAGE
};
if (!EasyPermissions.hasPermissions(this, perms)) {
EasyPermissions.requestPermissions(this, "扫描二维码需要打开相机和散光灯的权限", REQUEST_CODE_QRCODE_PERMISSIONS, perms);
}
}
封装成工具类调用:
import pub.devrel.easypermissions.EasyPermissions;
public class PermissionManager {
/**
* 写入权限的请求code,提示语,和权限码
*/
public final static int WRITE_PERMISSION_CODE=110;
public final static String WRITE_PERMISSION_TIP ="为了正常使用,请允许读写权限!";
public final static String[] PERMS_WRITE ={Manifest.permission.WRITE_EXTERNAL_STORAGE};
/**
*
* @param context
* return true:已经获取权限
* return false: 未获取权限,主动请求权限
*/
// @AfterPermissionGranted 是可选的
public static boolean checkPermission(Activity context, String[] perms) {
return EasyPermissions.hasPermissions(context, perms);
}
/**
* 检查添加权限
*/
public void checkBasePermission(Activity context,String[] perms) {
boolean result = PermissionManager.checkPermission(context,perms);
if (!result) {
PermissionManager.requestPermission(context, PermissionManager.WRITE_PERMISSION_TIP, PermissionManager.WRITE_PERMISSION_CODE, perms);
}
}
/**
* 检查基础权限
*/
public void checkBasePermission(Activity context) {
boolean result = PermissionManager.checkPermission(context,PERMS_WRITE);
if (!result) {
PermissionManager.requestPermission(context, PermissionManager.WRITE_PERMISSION_TIP, PermissionManager.WRITE_PERMISSION_CODE, PermissionManager.PERMS_WRITE);
}
}
/**
* 请求权限
* @param context
*/
public static void requestPermission(Activity context, String tip, int requestCode, String[] perms) {
EasyPermissions.requestPermissions(context, tip,requestCode,perms);
}
}
调用:
PermissionManager permissionManager = new PermissionManager();
permissionManager.checkBasePermission(LoadingActivity.this);
public class MainActivity extends AppCompatActivity implements EasyPermissions.PermissionCallbacks {
public final static String[] PERMS_WRITE = {Manifest.permission.WRITE_EXTERNAL_STORAGE};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// recoverState(savedInstanceState);
PermissionManager permissionManager = new PermissionManager();
permissionManager.checkBasePermission(MainActivity.this,PERMS_WRITE);
}
/**
* 重写onRequestPermissionsResult,用于接受请求结果
*
* @param requestCode
* @param permissions
* @param grantResults
*/
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
//将请求结果传递EasyPermission库处理
EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
}
/**
* 请求权限成功
*
* @param requestCode
* @param perms
*/
@Override
public void onPermissionsGranted(int requestCode, List perms) {
// ToastUtils.showToast(getApplicationContext(), "用户授权成功");
}
/**
* 请求权限失败
*
* @param requestCode
* @param perms
*/
@Override
public void onPermissionsDenied(int requestCode, List perms) {
// ToastUtils.showToast(getApplicationContext(), "用户授权失败");
/**
* 若是在权限弹窗中,用户勾选了'NEVER ASK AGAIN.'或者'不在提示',且拒绝权限。
* 这时候,需要跳转到设置界面去,让用户手动开启。
*/
if (EasyPermissions.somePermissionPermanentlyDenied(this, perms)) {
new AppSettingsDialog.Builder(this).build().show();
}
}
}
框架介绍:
EasyPermissions是谷歌封装的一个运行时权限申请的库,简化了操作的过程。
使用过程: 没有什么先后顺序,下面没有按这个顺序。这么做是可以的,当然还有其他的使用方法
框架使用方法:
首先,引用库
dependencies {
implementation ‘pub.devrel:easypermissions:2.0.0’
}
easypermissions处理权限分为3步。
1 检查权限
String[] perms = {Manifest.permission.CAMERA, Manifest.permission.CHANGE_WIFI_STATE};
if (EasyPermissions.hasPermissions(this, perms)) {
//...
} else {
//...
}
2 申请权限
EasyPermissions.requestPermissions(this, "拍照需要摄像头权限",
RC_CAMERA_AND_WIFI, perms);
3 实现EasyPermissions.PermissionCallbacks接口,直接处理权限是否成功申请
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
// Forward results to EasyPermissions
EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
}
//成功
@Override
public void onPermissionsGranted(int requestCode, List list) {
// Some permissions have been granted
// ...
}
//失败
@Override
public void onPermissionsDenied(int requestCode, List list) {
// Some permissions have been denied
// ...
}
3.自己写的获取权限方法
1.
@TargetApi(23)
private void getPersimmions() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
ArrayList permissions = new ArrayList();
/***
* 定位权限为必须权限,用户如果禁止,则每次进入都会申请
*/
// 定位精确位置
if(checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED){
permissions.add(Manifest.permission.ACCESS_FINE_LOCATION);
}
if(checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED){
permissions.add(Manifest.permission.ACCESS_COARSE_LOCATION);
}
if(checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED){
permissions.add(Manifest.permission.CAMERA);
}
if(checkSelfPermission(Manifest.permission.WRITE_SETTINGS) != PackageManager.PERMISSION_GRANTED){
permissions.add(Manifest.permission.WRITE_SETTINGS);
}
/*
* 读写权限和电话状态权限非必要权限(建议授予)只会申请一次,用户同意或者禁止,只会弹一次
*/
// 读写权限
if (addPermission(permissions, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
permissionInfo += "Manifest.permission.WRITE_EXTERNAL_STORAGE Deny \n";
}
// 读取电话状态权限
// if (addPermission(permissions, Manifest.permission.READ_PHONE_STATE)) {
// permissionInfo += "Manifest.permission.READ_PHONE_STATE Deny \n";
// }
if (permissions.size() > 0) {
requestPermissions(permissions.toArray(new String[permissions.size()]), SDK_PERMISSION_REQUEST);
}
}
}
@TargetApi(23)
private boolean addPermission(ArrayList permissionsList, String permission) {
if (checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) { // 如果应用没有获得对应权限,则添加到列表中,准备批量申请
if (shouldShowRequestPermissionRationale(permission)){
return true;
}else{
permissionsList.add(permission);
return false;
}
}else{
return true;
}
}
//6.0以上才能调用
@TargetApi(23)
void checkPermission(){
if(!Settings.System.canWrite(this)){
Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS,
Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, REQUEST_CODE);
}
}
调用:
getPersimmions();
if (Build.VERSION.SDK_INT >= 23) {
checkPermission();
}
/**
* android 6.0 以上需要动态申请权限
*/
private void initPermission() {
String[] permissions = {
Manifest.permission.INTERNET,
Manifest.permission.ACCESS_NETWORK_STATE,
Manifest.permission.MODIFY_AUDIO_SETTINGS,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.WRITE_SETTINGS,
Manifest.permission.READ_PHONE_STATE,
Manifest.permission.ACCESS_WIFI_STATE,
Manifest.permission.CHANGE_WIFI_STATE
};
ArrayList toApplyList = new ArrayList();
for (String perm : permissions) {
if (PackageManager.PERMISSION_GRANTED != ContextCompat.checkSelfPermission(this, perm)) {
toApplyList.add(perm);
// 进入到这里代表没有权限.
}
}
String[] tmpList = new String[toApplyList.size()];
if (!toApplyList.isEmpty()) {
ActivityCompat.requestPermissions(this, toApplyList.toArray(tmpList), 123);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
// 此处为android 6.0以上动态授权的回调,用户自行实现。
}
调用:
initPermission(); // android 6.0以上动态权限申请