Android如何动态申请应用权限?

2019-10-23

关键字: APK申请权限、通过代码获取权限、定位权限、相机权限


这篇文章大部分的内容都搬自简书某位大神的博客: https://www.jianshu.com/p/e36f686588d6 。搬运的目的有二:一是方便自己后续查阅,二是添加一些自己的使用经验。感谢这位简书大神的奉献。

APK 开发中的权限主要有三种:

1、普通权限;

2、危险权限;

3、特殊权限;

这三种不同类型的权限都是单独针对APK用的。这些权限的背后代表着一款 APK 的功能完整性。越靠后的权限 Android 系统对其的把控就越严格。

1、普通权限

普通权限就是那些可以直接在 AndroidManifest.xml 中配置一下即可获得的权限。系统对它们的管理非常宽松。

常见的有使用网络、更改网络状态等。

2、危险权限

危险权限除了要在 AndroidManife.xml 中声明以外,还得额外通过代码或用户主动在系统权限管理设置中开启。下图是华为手机中某个应用的部分常用危险权限控制界面:

Android如何动态申请应用权限?

危险权限的各类如下表所示

权限组权限详情
CALENDAR

READ_CALENDAR

WRITE_CALENDAR

CAMERACAMERA
CONTACTS

READ_CONTACTS

WRIGE_CONTACTS

GET_ACCOUNTS

LOCATION

ACCESS_FINE_LOCATION

ACCESS_CONARSE_LOCATION

MICROPHONERECORD_AUDIO
PHONE

READ_PHONE_STATE

CALL_PHONE

READ_CALL_LOG

WRITE_CALL_LOG

ADD_VOICEMAIL

USE_SIP

PROCESS_OUTGOING_CALLS

SENSORSBODY_SENSORS
SMS

SEND_SMS

RECEIVE_SMS

READ_SMS

RECEIVE_WAP_PUSH

RECEIVE_MMS

STORAGE

READ_EXTERNAL_STORAGE

WRITE_EXTERNAL_STORAGE

关于危险权限的限制,不同的 ROM 有不同的做法,有的严格有的宽松。但在 APK 开发中,为了应用的兼容性,还是很有必要去检查这些权限的状态,并在有必要的情况下弹出申请弹窗。

1、权限状态检查

import androidx.core.content.ContextCompat;
int perm = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA);

以上代码用于检查当前 APK 是否拥有使用摄像头的权限。它的返回值是一个整型。这个整型有两个值:PackageManager.PERMISSION_GRANTED 与 PackageManager.PERMISSION_DENIED ,分别代表着有权限与无权限。通常我们会根据当前权限的状态来决定是否去申请相关权限。

2、申请危险权限

ActivityCompat.requestPermissions(this, new String[]{
        Manifest.permission.ACCESS_COARSE_LOCATION,
        Manifest.permission.ACCESS_FINE_LOCATION,
        Manifest.permission.CAMERA
    }, 0);

当执行了这段代码以后,会有两种情况:一种是所申请的权限在当前应用中确实没有。另一种是所申请的权限在当前应用中已拥有。

对于第一种情况,执行以后会发现系统将会弹出如下图所示的弹窗供用户选择:

Android如何动态申请应用权限?

对于第二种情况,执行以后系统不会有任何变化,一切就像没有发生过什么一样。

当权限申请结果出来以后,系统会通过回调 Activity 中的以下方法来回传结果:

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if(requestCode == 0) {
        try {
            for(int i = 0; i < permissions.length; i++) {
                Logger.d(TAG, permissions[i] + ":" + grantResults[i]);
            }

        }catch(Exception e){
            e.printStackTrace();
        }
    }

}

这段代码就遍历了所有申请的权限的结果,当然结果值仅会有值为数字 0 的 PackageManager.PERMISSION_GRANTED 以及值为数字 -1 的 PackageManager.PERMISSION_DENIED。

3、特殊权限

特殊权限主要包括:

1、通知栏;

2、自动启动;

3、悬浮窗;

4、无障碍辅助。

略。

4、注意事项

在申请危险权限时有一些注意事项必须要提一下。

由于权限申请结果是回调到 Activity 的 onRequestPermissionsResult 方法中的,所以我们通常都会直接在 Activity 里来做申请操作。

当你执行了权限申请代码以后,即执行了 ActivityCompat.requestPermissions(this, new String[]{}, 0); 以后,无论上面图片所示的权限弹窗是否弹出,当前 Activity 的状态都会进入到 onPause() 态。并且在权限申请结果出来以后,Activity 会回到 onResume() 态,即这一申请过程会导致 onPause() 与 onResume() 被执行一次。

如果你有在这两个方法中做一些逻辑操作的话,一定要注意处理一下这种额外的调用。

笔者就是因为将权限申请操作放在 onResume() 中做的,导致了这个权限申请一直在无限调用。


参考:https://www.jianshu.com/p/e36f686588d6  

相关推荐