1.原生申请权限案例:
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
public class MainActivity extends AppCompatActivity {
private AlertDialog dialog;
public static int PERMISSION_REQUEST = 1024;
public static int SETTING_REQUEST = 30;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
initAppData();
} else {
checkAndRequestPermission();
}
}
private void initAppData() {
Toast.makeText(this, "initData", Toast.LENGTH_SHORT).show();
}
@TargetApi(Build.VERSION_CODES.M)
private void checkAndRequestPermission() {
List<String> lackedPermission = new ArrayList<>();
if (!(checkSelfPermission(Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED)) {
lackedPermission.add(Manifest.permission.READ_PHONE_STATE);
}
if (!(checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED)) {
lackedPermission.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
if (!(checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED)) {
lackedPermission.add(Manifest.permission.ACCESS_FINE_LOCATION);
}
// 权限都已经有了,那么直接调用SDK
if (lackedPermission.size() == 0) {
initAppData();
} else {
// 请求所缺少的权限,在onRequestPermissionsResult中再看是否获得权限,如果获得权限就可以调用SDK,否则不要调用SDK。
String[] requestPermissions = new String[lackedPermission.size()];
lackedPermission.toArray(requestPermissions);
requestPermissions(requestPermissions, PERMISSION_REQUEST);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == PERMISSION_REQUEST) {
if (hasAllPermissionsGranted(grantResults)) {
initAppData();
} else {
// 如果用户没有授权,那么应该说明意图,引导用户去设置里面授权。
showPermission();
}
}
}
private boolean hasAllPermissionsGranted(int[] grantResults) {
for (int grantResult : grantResults) {
if (grantResult == PackageManager.PERMISSION_DENIED) {
return false;
}
}
return true;
}
private void showPermission() {
if (dialog == null || !dialog.isShowing()) {
dialog = new AlertDialog.Builder(this, R.style.Theme_AppCompat_Light_Dialog).setTitle("权限申请")
.setMessage("请在设置—应用—" + getString(R.string.app_name) + "—权限中开启相应权限").setCancelable(false)
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
finish();
}
})
.setPositiveButton("去设置", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
startAppSetting();
}
}).show();
}
}
private void startAppSetting() {
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", getPackageName(), null);
intent.setData(uri);
if (isIntentAvailable(this, intent)) {
startActivityForResult(intent, SETTING_REQUEST);
} else {
Toast.makeText(this, "请去设置开启权限", Toast.LENGTH_SHORT).show();
}
}
private static boolean isIntentAvailable(Context context, Intent intent) {
return intent != null && context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY).size() > 0;
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == SETTING_REQUEST) {
checkAndRequestPermission();
}
}
}
2.使用第三方库
implementation 'com.yanzhenjie:permission:1.1.2'
public class MainActivity extends AppCompatActivity {
private AlertDialog dialog;
public static final int PERMISSION_REQUEST = 1024;
public static final int SETTING_REQUEST = 30;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
initAppData();
} else {
requestPermission();
}
}
/**
* 请求权限
*/
private void requestPermission() {
// 如果你不想申请权限组,仅仅想申请某几个权限:
AndPermission.with(this)
.requestCode(PERMISSION_REQUEST)
.permission(
Manifest.permission.READ_PHONE_STATE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.ACCESS_FINE_LOCATION)
.callback(this)
.start();
}
// 成功回调的方法,用注解即可,这里的300就是请求时的requestCode。
@PermissionYes(PERMISSION_REQUEST)
private void getPermissionYes(List<String> grantedPermissions) {
if (AndPermission.hasPermission(MainActivity.this,
Manifest.permission.READ_PHONE_STATE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.ACCESS_FINE_LOCATION)) {
initAppData();
} else {
showPermission();
}
}
@PermissionNo(PERMISSION_REQUEST)
private void getPermissionNo(List<String> deniedPermissions) {
if (AndPermission.hasPermission(MainActivity.this,
Manifest.permission.READ_PHONE_STATE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.ACCESS_FINE_LOCATION)) {
initAppData();
} else {
showPermission();
}
}
private void showPermission() {
if (dialog == null || !dialog.isShowing()) {
dialog = new AlertDialog.Builder(this, R.style.Theme_AppCompat_Light_Dialog)
.setTitle(" 请允许打开您的权限")
.setMessage("因某某某需要相关权限,请允许打开相关权限,我们会保证您的数据安全")
.setCancelable(false)
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
finish();
}
})
.setPositiveButton("打开权限", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
startAppSetting();
}
}).show();
}
}
private void startAppSetting() {
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", getPackageName(), null);
intent.setData(uri);
if (isIntentAvailable(this, intent)) {
startActivityForResult(intent, SETTING_REQUEST);
} else {
Toast.makeText(this, "请去设置开启权限", Toast.LENGTH_SHORT).show();
}
}
private static boolean isIntentAvailable(Context context, Intent intent) {
if (intent == null) {
return false;
}
return context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY).size() > 0;
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == SETTING_REQUEST) {
requestPermission();
}
}
private void initAppData() {
Toast.makeText(this, "initData", Toast.LENGTH_SHORT).show();
}
}
3.通过RxPermission请求权限
项目build下:
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
App build下:
implementation 'com.github.tbruyelle:rxpermissions:0.10.2'
implementation 'io.reactivex.rxjava2:rxjava:2.1.9'
public class MainActivity extends AppCompatActivity {
private AlertDialog dialog;
public static int PERMISSION_REQUEST = 1024;
public static int SETTING_REQUEST = 30;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
initAppData();
} else {
requestPermission();
}
}
private void requestPermission() {
final RxPermissions rxPermissions = new RxPermissions(this);
//权限请求一次性处理,返回为Boolean granted表示是否全部通过
rxPermissions
.request(Manifest.permission.READ_PHONE_STATE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.ACCESS_FINE_LOCATION)
.subscribe(new Consumer<Boolean>() {
@Override
public void accept(Boolean granted) throws Exception {
if (granted) {
// All requested permissions are granted
initAppData();
} else {
// At least one permission is denied
// 如果用户没有授权,那么应该说明意图,引导用户去设置里面授权。
showPermission();
}
}
});
//处理每个权限请求结果
/*
rxPermissions
.requestEach(Manifest.permission.READ_PHONE_STATE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.ACCESS_FINE_LOCATION)
.subscribe(new Consumer<Permission>() {
@Override
public void accept(Permission permission) throws Exception {
if (permission.granted) {
// `permission.name` is granted !
} else if (permission.shouldShowRequestPermissionRationale) {
// Denied permission without ask never again
} else {
// Denied permission with ask never again
// Need to go to the settings
}
}
});
*/
//权限请求一次性处理,返回为Permission permission
/*
rxPermissions
.requestEachCombined(Manifest.permission.READ_PHONE_STATE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.ACCESS_FINE_LOCATION)
.subscribe(new Consumer<Permission>() { // will emit 1 Permission object
@Override
public void accept(Permission permission) throws Exception {
if (permission.granted) {//全部通过
// All permissions are granted !
} else if (permission.shouldShowRequestPermissionRationale){//有一项权限被拒绝,但是允许再次询问
// At least one denied permission without ask never again
} else {
//有一项权限被拒绝并且不允许再次询问,此时引导用户跳转设置
// At least one denied permission with ask never again
// Need to go to the settings
}
}
});
*/
}
private void initAppData() {
Toast.makeText(this, "initData", Toast.LENGTH_SHORT).show();
}
private void showPermission() {
if (dialog == null || !dialog.isShowing()) {
dialog = new AlertDialog.Builder(this, R.style.Theme_AppCompat_Light_Dialog).setTitle("权限申请")
.setMessage("请在设置—应用—" + getString(R.string.app_name) + "—权限中开启相应权限").setCancelable(false)
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
finish();
}
})
.setPositiveButton("去设置", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
startAppSetting();
}
}).show();
}
}
private void startAppSetting() {
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", getPackageName(), null);
intent.setData(uri);
if (isIntentAvailable(this, intent)) {
startActivityForResult(intent, SETTING_REQUEST);
} else {
Toast.makeText(this, "请去设置开启权限", Toast.LENGTH_SHORT).show();
}
}
private static boolean isIntentAvailable(Context context, Intent intent) {
return intent != null && context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY).size() > 0;
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == SETTING_REQUEST) {
requestPermission();
}
}
}
4.使用AOP实现
https://gitee.com/xydtest/aop-aspect-deom
5.其他
1)记录一次一加手机判断写入权限的坑。
//通过下面的方式,Android13一加手机测试,打开了安全中的所有文件访问权限,结果发现返回一直是false
ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED
//解决:通过下面的方式来判断
public static boolean isGranted(Context context, String permission) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R
&& (permission.equals(Manifest.permission.READ_EXTERNAL_STORAGE) || permission.equals(Manifest.permission.WRITE_EXTERNAL_STORAGE))) {
return Environment.isExternalStorageManager();
}
return Build.VERSION.SDK_INT < Build.VERSION_CODES.M || ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED;
}
1)Android11增加了所有文件访问权限,需要增加如下适配
1.AndroidManifest.xml中添加如下内容
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
2.权限申请相关代码
private static final int REQUEST_MANAGE_EXTERNAL_STORAGE_PERMISSION = 100;
public void requestPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
if (!Environment.isExternalStorageManager()) {
Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);
intent.setData(Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, REQUEST_MANAGE_EXTERNAL_STORAGE_PERMISSION );
} else {
//已有所有文件访问权限,可执行后续操作
}
} else {
//android11以下版本,还是按照之前的权限申请流程
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_MANAGE_EXTERNAL_STORAGE_PERMISSION) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
if (Environment.isExternalStorageManager()) {
//已有所有文件访问权限,可执行后续操作
} else {
//没有设置所有文件访问权限,可进行相关弹窗提示等操作
}
}
}
}