Android13调用Settings.ACTION_APPLICATION_DETAILS_SETTINGS触发SecurityException求助
Android 13中使用
Settings.ACTION_APPLICATION_DETAILS_SETTINGS触发SecurityException问题分析 问题场景
用户拒绝权限时,通过以下代码引导至应用详情设置页:
Intent intent = new Intent(); intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); Uri uri = Uri.fromParts("package", getActivity().getPackageName(), null); intent.setData(uri); getActivity().startActivity(intent);
该代码在Android 13以下系统运行正常,但在Android 13中触发如下SecurityException:
Bad call made by uid 1000. Package "package name" does not belong to uid -1. noteOperation java.lang.SecurityException: Specified package "package name" under uid -1 but it is not at com.android.server.appop.AppOpsService.verifyAndGetBypass(AppOpsService.java:4858) at com.android.server.appop.AppOpsService.noteOperationUnchecked(AppOpsService.java:3586) at com.android.server.appop.AppOpsService.noteOperationImpl(AppOpsService.java:3574) at com.android.server.appop.AppOpsService.-$$Nest$mnoteOperationImpl(Unknown Source:0) at com.android.server.appop.AppOpsService$CheckOpsDelegateDispatcher.lambda$noteOperation$4(AppOpsService.java:7928) at com.android.server.appop.AppOpsService$CheckOpsDelegateDispatcher.$r8$lambda$oOwUoG55BBmJ6yiwhp3OAq3tQ30(Unknown Source:0) at com.android.server.appop.AppOpsService$CheckOpsDelegateDispatcher$$ExternalSyntheticLambda4.apply(Unknown Source:32) at com.android.server.policy.AppOpsPolicy.noteOperation(AppOpsPolicy.java:225) at com.android.server.appop.AppOpsService$CheckOpsDelegateDispatcher.noteOperation(AppOpsService.java:7926) at com.android.server.appop.AppOpsService.noteOperation(AppOpsService.java:3558) at com.android.internal.app.IAppOpsService$Stub.onTransact(IAppOpsService.java:486) at android.os.Binder.execTransactInternal(Binder.java:1316) at android.os.Binder.execTransact(Binder.java:1280)
已在AndroidManifest.xml中设置android:exported="true",仍无法解决问题。
异常原因分析
从异常信息Specified package "package name" under uid -1 but it is not可以看出,系统在校验包名与UID的对应关系时,发现指定包名不属于UID -1(无效UID),核心原因如下:
- 上下文有效性问题:代码中使用
getActivity()获取上下文,若Fragment已脱离Activity(如onDestroyView之后调用),getActivity()可能返回失效实例,导致getPackageName()无法正确获取应用包名,进而系统解析时出现UID-1的错误。 - Uri构造的潜在问题:使用
Uri.fromParts("package", getActivity().getPackageName(), null)构造Uri时,若包名获取异常(如空值),可能导致Uri格式不符合系统预期,触发AppOps校验失败。 - 多进程场景下的上下文混淆:若代码运行在非主进程中,不同进程的上下文可能导致包名获取错误,系统校验时无法匹配正确的UID。
解决方案
针对上述原因,可通过以下方式修复:
1. 确保上下文有效
在Fragment中调用时,先判断Fragment是否已附加到Activity,使用requireActivity()替代getActivity()(若未附加会直接抛出异常,提前暴露问题):
if (isAdded()) { Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); Uri uri = Uri.parse("package:" + requireActivity().getPackageName()); intent.setData(uri); requireActivity().startActivity(intent); }
2. 改用更可靠的Uri构造方式
使用Uri.parse("package:" + 包名)替代Uri.fromParts,避免参数传递错误:
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); Uri uri = Uri.parse("package:" + getContext().getApplicationContext().getPackageName()); intent.setData(uri); // 若在非Activity上下文启动,需添加FLAG_ACTIVITY_NEW_TASK // intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); getContext().startActivity(intent);
3. 多进程场景下的处理
若代码运行在多进程环境,确保使用getApplicationContext().getPackageName()获取全局包名,避免进程间上下文差异导致的错误。
内容的提问来源于stack exchange,提问作者CodingBruceLee
相关产品推荐
相关产品推荐

