Android开发-动态权限申请

目录

1.概述

1.1 Android 6.0之前版本权限

1.2 Android 6.0及更高版本权限

2.权限分类

2.1 正常权限

2.2 危险权限

3.权限组

3.1 权限组概念

3.2 权限组和危险权限列表

3.3 权限组和权限的表示

4.在运行时请求权限

4.1 原理

4.2 检查权限

4.3 解释权限

4.4 请求权限

4.5 处理结果


1.概述

1.1 Android 6.0之前版本权限

          Android 6.0(API23)之前应用的权限在安装程序时就全部授予,运行时应用不再需要询问用户。

1.2 Android 6.0及更高版本权限

         在Android 6.0和更高版本对权限进行了分类,对某些涉及到用户隐私的权限需要在运行时根据用户的需要进行动态的授予(对话框咨询用户是否授予权限),这样用户就不需要再安装时被迫同意某些权限。

2.权限分类

          Android系统权限分为几个保护级别,需要了解的两个最重要的保护级别是正常权限和危险权限。

2.1 正常权限

          指的是不会对直接威胁到用户的安全和隐私,或其他应用操作风险很小的权限。这些权限在应用安装时授予,运行时不再询问用户。例如:网络访问,WIFI状态,音量设置等

2.2 危险权限

         涵盖应用需要涉及用户隐私信息的数据或资源,或者可能对用户储存的数据或其他应用的操作产生影响的区域。例如:读取通讯录联系人信息,读写储存器数据,获取用户地理位置等。如果应用需要这些危险的权限,则必须在运行时明确的告诉用户,让用户手动的进行是否授予权限,如果不授权,则程序无法使用相应的功能。

3.权限组

3.1 权限组概念

        Android系统对所有的危险权限进行了分组,称之为权限组。属于同一组的危险权限将自动合并授予,用户授予应用某个权限组的权限,则应用将获得该权限组下的所有权限

3.2 权限组和危险权限列表

       权限组和危险权限列表如下:

CALENDAR

READ_CALENDAR      (read_calendar)

WRITE_CALENDAR    (write_calendar) 

 
CAMERACAMERA      (camera) 
CONTACTS

READ_CONTACTS     (read_contacts)

WRITE_CONTACTS   (write_contacts)

GET_ACCOUNTS      (get_accounts)

 
LOCATION

ACCESS_FINE_LOCATION         (access_fine_location)

ACCESS_COARSE_LOCATION   (access_coarse_loaction)

 
MICROPHONERECORD_AUTO     (record_aut0) 
PHONE

READ_PHONE_STATE  (read_phone_state)

CALL_PHONE               (call_phone)

READ_CALL_LOG        (read_call_log)

WRITE_CALL_LOG      (write_call_log)

ADD_VOICEMAIL         (add_voicemail)

USE_SIP                       (use_sip)

PROCESS_OUTGOING_CALLS   (process_outgoing_calls)
 
SENSORSBODY_SENDORS      (body_sendors) 
SMS

SEND_SMS               (send_sms)

RECEIVE_SMS         (receive_sms)

READ_SMS               (read_sms)

RECEIVE_WAP_PUSH    (receive_wap_push)

RECEIVE_MMS              (receive_mms)

 
STORAGE

READ_EXTERNAL_STORAGE   (read_external_storage)

WRITE_EXTERNAL_STORAGE  (write_external_storage)

 

3.3 权限组和权限的表示

         权限组和权限在Android代码中以字符串常量来表示,分别定义在以下两个静态内部类的字段中

android.Manifest.permission(权限):
Manifest.permission.READ_CALENDAR
Manifest.permission.READ_EXTERNAL_STORAGE

 

4.在运行时请求权限

4.1 原理

          设备系统是Android 6.0(API 23)或更高版本,并且应用的targetSdkVersion是23或更高版本,则针对在AndroidManifest中声明的危险权限,在运行时还需要动态请求用户进行授权。动态权限请求相关操作的API封装在android:support.v4包中,发起请求权限的Activity需要直接或间接继承android.support.v4.app.FragmentActivity,代码步骤中主要包含如下几个方法:

4.2 检查权限

          方法如下所示:

ContextCompat.checkSelfPermission(Context context,Permission permission)返回检查指定权限是否拥有的结果

         返回的值常量为:

有权限PackageManager.PERMISSION_GRANTED
 无权限PackageManager.PERMISSION_DENIED

         当应用需要到危险权限时,在执行权限相关代码前,使用该方法判断是否已经拥有指定的权限。如果有权限,则继续执行设计需要权限的代码;无权限,则向用户请求授予指定的权限。

4.3 解释权限

         方法如下所示:

ActivityCompat.shouldShowRequestPermissionRationale(Activity activity,String permission) 返回值为boolean

        该方法解释如下所示:        

1.此方法用于判断是否有必要向用户解释为什么要这项权限
2.如果应用第一次请求过此权限,但是被用户拒绝了,则之后调用该方法将会返回true,此时就有必要向用户详细说明需要此权限的原因。
3.如果应用第一次请求此权限被用户拒绝了,第二次再次请求此权限时,用户勾选了权限请求对话框的“不再询问”复选框,则此方法返回false。
4.如果设备规范禁止应用拥有该权限,则此方法也返回false。

4.4 请求权限

         方法如下所示:

ActivityCompat.requestPermission(Activity activity,String[] permissions,int requestCode)动态配置包含指定数组里面的权限

         该方法解释如下所示:

1.当检测到应用没有指定的权限时,调用此方法向用户请求权限,将弹出权限请求对话框询问用户,“允许”或“拒绝”指定的权限。
2.权限参数传入的是数组,可以调用该方法传入一次请求多个权限。传入的权限数组参数以单个具体权限为单位,但是当对话框询问用户授权时,属于同一个权限组的将自动合并询问权限一次。
3.请求的权限必须事先在AndroidManifest.xml中有声明,否则调用该方法请求时,将不弹出对话框,而是直接返回“拒绝”的结果。
4.第一次请求权限时,用户点击了“拒绝”,第二次再请求该权限时,对话框将出现“不再询问”的复选框,如果用户勾选了“不再询问”,并点击了“拒绝”,则之后再请求此权限组时将不在弹出对话框,而是直接返回“拒绝”的结果

4.5 处理结果

       请求权限的结果返回和接收一个Activity的返回类似,重写FragmentActivity或Fragment中的onRequestPermissionResult(...)方法,如下所示:

@Override
public void onRequestPermissionResult(int requestCode,String[] permissions,int[] grantResults){
    //处理结果
}

 

5.案例实现

       这里以打电话为案例,需要用户动态授予权限:打电话的权限为 CALL_PHONE

       布局文件:activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
   <Button
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="申请打电话"
       android:layout_centerInParent="true" />
</RelativeLayout>

        AndroidManifest,xml :添加权限

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.luckyliuqs.permission_getphonecontacts">

    <uses-permission android:name="android.permission.CALL_PHONE" />
   
    <application
        ......
    </application>
</manifest>

        java代码:MainActivity.java

public class MainActivity extends AppCompatActivity implements View.OnClickListener{

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button button = findViewById(R.id.button);
        button.setOnClickListener(this);
    }
    //执行打电话
    public void call(){
        try{
            //Intent.ACTION_CALL系统内置的打电话动作
            Intent intent = new Intent(Intent.ACTION_CALL);
            //指定协议为tel
            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) {
        switch (requestCode){
            case 1:
                //请求成功
                if(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
                    call();
                }else{
                    Toast.makeText(this,"你拒绝了权限",Toast.LENGTH_SHORT).show();
                }
                break;
            default:
                break;
        }
    }

    @Override
    public void onClick(View v) {
        //检查打电话权限是否已经被授予了
        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();
        }
    }

       效果图:

 

                                                                                                                                                   

                                                    

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Android是一个开放的移动操作系统,爱好者和开发者可以根据自己的需求进行定制和开发。在Android开发中,JavaPoet是一个非常有用的库,可以动态生成Java代码,简化一些重复的工作。而AOP(面向切面编程)则是一种编程范式,可以将横切关注点与业务逻辑分离,提高代码的可复用性和可维护性。 动态权限申请Android开发中经常遇到的一个问题。在Android系统中,一些敏感的操作和资源访问需要动态申请权限,以确保用户的隐私和安全。传统的权限申请方式是在每个需要权限的地方都进行判断和申请,这样会导致代码的冗余和可读性的下降。使用AOP结合JavaPoet可以实现动态权限申请的解决方案。 首先,我们可以通过AOP在需要权限的方法周围添加一个切面,用于检查和申请权限。通过AspectJ等AOP框架,我们可以定义一个切面,在方法执行之前和之后执行相应的逻辑。 然后,利用JavaPoet动态生成申请权限的代码。我们可以定义一个注解,用于标识需要权限的方法。在AOP切面中,当检测到方法上有该注解时,生成相应的权限申请代码。 最后,在代码编译阶段,通过JavaPoet生成的代码会自动插入到原始代码中。这样,我们就可以在运行时动态地进行权限申请了。 通过以上的实践,我们可以实现动态权限申请的功能,同时可以减少重复的代码,并提高代码的可维护性。使用JavaPoet和AOP相结合的方式,可以使我们的开发变得更加高效和便捷。它们为Android开发带来了更多的灵活性和扩展性,帮助我们更好地应对权限申请的问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

luckyliuqs

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值