Android如何动态申请应用权限?
2019-10-23
关键字: APK申请权限、通过代码获取权限、定位权限、相机权限
这篇文章大部分的内容都搬自简书某位大神的博客: https://www.jianshu.com/p/e36f686588d6 。搬运的目的有二:一是方便自己后续查阅,二是添加一些自己的使用经验。感谢这位简书大神的奉献。
APK 开发中的权限主要有三种:
1、普通权限;
2、危险权限;
3、特殊权限;
这三种不同类型的权限都是单独针对APK用的。这些权限的背后代表着一款 APK 的功能完整性。越靠后的权限 Android 系统对其的把控就越严格。
1、普通权限
普通权限就是那些可以直接在 AndroidManifest.xml 中配置一下即可获得的权限。系统对它们的管理非常宽松。
常见的有使用网络、更改网络状态等。
2、危险权限
危险权限除了要在 AndroidManife.xml 中声明以外,还得额外通过代码或用户主动在系统权限管理设置中开启。下图是华为手机中某个应用的部分常用危险权限控制界面:
危险权限的各类如下表所示
权限组 | 权限详情 |
CALENDAR | READ_CALENDAR WRITE_CALENDAR |
CAMERA | CAMERA |
CONTACTS | READ_CONTACTS WRIGE_CONTACTS GET_ACCOUNTS |
LOCATION | ACCESS_FINE_LOCATION ACCESS_CONARSE_LOCATION |
MICROPHONE | RECORD_AUDIO |
PHONE | READ_PHONE_STATE CALL_PHONE READ_CALL_LOG WRITE_CALL_LOG ADD_VOICEMAIL USE_SIP PROCESS_OUTGOING_CALLS |
SENSORS | BODY_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);
当执行了这段代码以后,会有两种情况:一种是所申请的权限在当前应用中确实没有。另一种是所申请的权限在当前应用中已拥有。
对于第一种情况,执行以后会发现系统将会弹出如下图所示的弹窗供用户选择:
对于第二种情况,执行以后系统不会有任何变化,一切就像没有发生过什么一样。
当权限申请结果出来以后,系统会通过回调 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
相关推荐
adb shell cd system/app rm *.apk21. 获取管理员权限: adb root22. 启动Activity: adb shell am start -n 包名/包名+类名。