Android 6.0 超级简单的权限申请2 (Permission)
写在前面
上次写了一个权限申请的例子Android 6.0 超级简单的权限申请 (Permission),原理是封装权限申请的代码到一个Helper类,然后重写onRequestPermissionsResult
方法处理。这已经是很简洁的权限申请方法了,但是还不够,因为这里还需要重写onRequestPermissionsResult
方法。所以研究了一番,再写了一个例子,不需要重写onRequestPermissionsResult
方法,真正做到一句代码搞定权限申请。
实现原理
封装权限申请的相关代码到一个Helper类中,在申请权限的时候,启动一个Fragment,但不显示,在Fragment中申请权限,也在Fragment中处理权限,最后回调给Helper。
实现过程
- 封装
PermissionHelper
类,定义对外开放的方法
/**
* @param permissions e.g. {@link Manifest.permission#CAMERA}
* @return true if all granted, false otherwise.
*/
public static boolean isGranted(Activity activity, String... permissions)
/**
* @param grantedListener run on all permission granted
* @param deniedListener run if one permission denied
*/
public static void requestPermissions(Activity activity,
OnPermissionGrantedListener grantedListener,
OnPermissionDeniedListener deniedListener,
String... permissions)
- 获取
AndroidManifest
中注册的权限
private static List<String> getRegisteredInManifestPermissions(Activity activity) {
List<String> list = new ArrayList<>();
try {
PackageInfo packageInfo = activity.getPackageManager().getPackageInfo(activity.getPackageName(), PackageManager.GET_PERMISSIONS);
String[] permissions = packageInfo.requestedPermissions;
if (permissions != null) {
list.addAll(Arrays.asList(permissions));
}
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return list;
}
- 检查权限是否已经注册
for (String permission : permissions) {
if (!mRegisteredInManifestPermissions.contains(permission)) {
throw new IllegalArgumentException("the permission \"" + permission + "\" is not registered in AndroidManifest.xml");
}
}
- 检查权限是否已经允许,AndroidM以下的设备直接判断为允许
public static boolean isGranted(Activity activity, String... permissions) {
checkPermissions(activity, permissions);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
for (String permission : permissions) {
if (activity.checkSelfPermission(permission) == PackageManager.PERMISSION_DENIED) {
return false;
}
}
}
return true;
}
- 初始化
Fragment
并添加到Activity
中
这里的PermissionHelper
直接继承Fragment
了,直接重写onRequestPermissionsResult
处理回调。new Fragment
之前先检查此Activity中是否已经存在一个,如果有则直接使用。
Fragment fragment = activity.getFragmentManager().findFragmentByTag(TAG);
if (fragment == null) {
fragment = new PermissionHelper();
FragmentManager fragmentManager = activity.getFragmentManager();
fragmentManager.beginTransaction().add(fragment, TAG).commitAllowingStateLoss();
fragmentManager.executePendingTransactions();
}
- 利用Fragment申请权限
fragment.requestPermissions(permissions, mRequestCode++);
- 处理
onRequestPermissionsResult
方法,并把结果正确的回调给用户
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (mOnGrantedListeners.containsKey(requestCode)) {
// 这里规定全部权限都通过才算通过
boolean granted = true;
// 在Activity A申请权限,然后马上跳转到Activity B,则grantResults.length=0
if (grantResults.length == 0) granted = false;
for (int result : grantResults) {
if (result == PackageManager.PERMISSION_DENIED) {
granted = false;
}
}
if (granted) {
OnPermissionGrantedListener listener = mOnGrantedListeners.get(requestCode);
if (listener != null) listener.onGranted();
} else {
OnPermissionDeniedListener listener = mOnDeniedListeners.get(requestCode);
if (listener != null) listener.onDenied();
}
mOnGrantedListeners.remove(mRequestCode);
mOnDeniedListeners.remove(mRequestCode);
}
}
使用方法
直接在Activity中调用下面代码既可,虽然很多行,但只是一句代码哈哈
PermissionHelper.requestPermissions(this, () -> {
// on granted
Toast.makeText(MainActivity.this, "onGranted", Toast.LENGTH_SHORT).show();
}, () -> {
// on denied
Toast.makeText(MainActivity.this, "onDenied", Toast.LENGTH_SHORT).show();
}, Manifest.permission.READ_CONTACTS, Manifest.permission.WRITE_EXTERNAL_STORAGE);
文件结构图
演示效果图
运行代码可能出现的问题
-
compileSdkVersion 27,可以改成你电脑中存在的SDK版本。
-
这里用的是 gradle-4.4-all.zip,如果你用的是其它版本,那么可能会下载超级慢,建议改成你电脑中存在的gradle版本,改文件PermissionHelper/gradle/wrapper/gradle-wrapper.properties即可。
-
其它问题可以直接联系我。
Android 6.0 超级简单的权限申请2 (Permission)
注:本文著作权归作者,由demo大师代发,拒绝转载,转载需要作者授权
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· Windows编程----内核对象竟然如此简单?