Android中的权限申请

一、权限的基本使用

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);
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值