一、权限的基本使用
Android开发中,运行时申请权限的场景会经常遇到,随手记一下,方便下次查阅,如有错误,多谢指出.
1.引入时机:
Android中的 运行时权限 是在Android6.0时引入的,主要用于保护用户安全与隐私;
2.运行时权限:
用户不需要在安装软件的时候一次性授权所有申请的权限,而是在软件使用的过程中再对某一项权限申请进行授权
3.Android权限分类:
并非每种权限都需要申请,Android中将权限分为两类:普通权限和危险权限;
普通权限:不会直接影响用户安全和隐私的权限,对于这部分权限,系统会自动申请,无需用户手动操作
危险权限:触及用户隐私,或者对设备安全性造成影响的权限,这部分权限必须要用户手动点击授权才可以,否则程序就无法使用对应的功能;
危险权限共9组,分别为:CALENDAR / CAMERA /CONTACTS / LOCATION / MICROPHONE / PHONE / SENSORS / SMS / STORAGE
4.不同种类权限的处理方案:
普通权限:只需要在AndroidManifest文件中,在application标签之外,使用uses-permission标签声明对应的权限即可;
危险权限:运行时手动申请权限,并且申请的权限在AndroidManifest中也要加入;
5.运行时权限申请–Demo (以CALL_PHONE权限为例)
public void doClick(View view) {
checkCallPhonePermission();
}
private void checkCallPhonePermission() {
if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(MainActivity.this, new String[{Manifest.permission.CALL_PHONE},1);
} else {
call();
}
}
private void call() {
try {
Intent intent = new Intent(Intent.ACTION_CALL);
intent.setData(Uri.parse("tel:10086"));
startActivity(intent);
} catch (SecurityException e) {
e.printStackTrace();
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if (requestCode == CALL_PHONE_REQUEST_CODE) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
call();
} else {
Toast.makeText(MainActivity.this, "权限被手动禁止", Toast.LENGTH_SHORT).show();
}
}
}
**
二、使用开源框架–permissionsdispatcher申请权限
1.优点:permissionsdispatcher框架基于注解,可以避免书写大量繁琐的样板代码
2.框架支持的注释:
@RuntimePermissions : 注册Activity 或Fragment(此框架两者都支持)来处理权限
@NeedsPermission : 注释执行需要一个或者多个权限的操作的方法
@OnShowRationale : 注释一个解释为什么需要权限的方法,它传入一个PermissionRequest对象,该对象可用于在用户输入时继续或中止当前的权限请求;
@OnPermissionDenied : 注释如果用户未授予权限则调用的方法 ;
@OnNeverAskAgain : 如果用户选择让设备“永不再询问”权限,则注释一个被调用的方法
3.使用步骤:
1) AndroidManifest增加需要申请的权限
2) 在build.gradle(project)的allProjects标签中添加maven仓库依赖,例如:
allprojects {
repositories {
jcenter()
mavenCentral()
}
}
3) 导入依赖:build.gradle(app):
implementation("com.github.hotchemi:permissionsdispatcher:3.1.0") {
//if you don't use android.app.Fragment you can exclude support for them
exclude module: "support-v13"
}
annotationProcessor 'com.github.hotchemi:permissionsdispatcher-processor:3.1.0'
4) 在onCreate方法中或者在需要申请权限的地方,加入:
StartupActivity(Activity名称)PermissionsDispatcher.showMainViewWithPermissionCheck(this); //报红就make
5) 重写onRequestPermissionsResult方法
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
StartupActivity(Activity名称)PermissionsDispatcher.onRequestPermissionsResult(this, requestCode, grantResults);
}
6) 使用各个注释对权限进行申请
@RuntimePermissions (加入此注释,必须加入此注释)
public class MainActivity extends AppCompatActivity{ }
@NeedsPermission(Manifest.permission.CAMERA) (假如当前需要申请相机权限,程序需要请求什么权限都在此添加,可申请多个)
void showCamera() {
三秒后跳转
}
@OnPermissionDenied(Manifest.permission.CAMERA) (用户未授予权限,则此时再次申请权限)
void showDeniedForCamera() {
用户未授予权限,则此时再次申请权限
}
@OnNeverAskAgain(Manifest.permission.CAMERA) (上次选择禁止并勾选:下次不在询问)
void showNeverAskForCamera() {
弹出对话框,取消则退出程序(APP),确定则跳转到 权限设置页面,进行权限设置
}
7) 跳转到设置页面
链接:跳转到指定app权限设置页面,代码如下(可以将其封装到工具类中,使用的时候直接调用):
public static void gotoAppSettingPage(Context context) {
Intent localIntent = new Intent();
localIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
localIntent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
localIntent.setData(Uri.fromParts("package", context.getPackageName(), null));
context.startActivity(localIntent);
}
三、具体案例—Activity中使用permissionsdispatcher框架申请权限
此框架在Activity与Fragment中用法是一致的,这里就不写fragment中使用的代码了,需要源码评论私信我;
具体场景模拟:
1.App启动页跳转到主页面, 进入启动页面进行存储权限申请
2.同意存储权限则3秒后跳转到主页面,不同意则再次申请
3.如果点击了不再提示且拒绝的话,弹出提示框,显示 进入权限设置 或者 退出APP两个选项;
4.点击权限设置进入app对应的权限设置页面,点击退出则退出程序
代码如下:
@RuntimePermissions
public class StartActivity extends FragmentActivity {
private Handler mHandler = new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_start);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
} else {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
}
@Override
protected void onStart() {
super.onStart();
StartActivityPermissionsDispatcher.allowPermissionsWithPermissionCheck(this);
}
private void skipMainActivity() {
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
startActivity(new Intent(StartActivity.this, MainActivity.class));
finish();
}
}, 3000);
}
@NeedsPermission({Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.CAMERA})
void allowPermissions() {
skipMainActivity();
}
@OnPermissionDenied({Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.CAMERA})
void denyPermission() {
StartActivityPermissionsDispatcher.allowPermissionsWithPermissionCheck(this);
}
@OnNeverAskAgain({Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.CAMERA})
void neverAskAgain() {
showNeverAskAgainDialog();
}
private void showNeverAskAgainDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(StartActivity.this);
builder.setMessage("权限被禁止,无法进入app")
.setCancelable(false)
.setNegativeButton("退出程序", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
})
.setPositiveButton("进入权限设置页面", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
gotoAppSetting();
}
})
.create().show();
}
private void gotoAppSetting() {
Intent intent = new Intent();
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
intent.setData(Uri.fromParts("package", getPackageName(), null));
startActivity(intent);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
StartActivityPermissionsDispatcher.onRequestPermissionsResult(this, requestCode, grantResults);
}
}