如何在Android 6.0(Marshmallow)上以编程方式打开特定应用程序的权限屏幕?

451

我有一个关于新的Android 6.0(Marshmallow)发布的问题。

是否可以通过Intent或类似的方式显示特定应用程序的“应用权限”屏幕?

Android M Permission Screen

可以使用以下代码在设置中显示应用程序的“应用信息”屏幕:

startActivity(
    new Intent(
        android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
        Uri.fromParts("package", getPackageName(), null)
    )
);

是否有类似的解决方案可以直接打开应用程序的“应用程序权限”屏幕?

我已经做了一些研究,但是我没有找到解决方案。


尝试一下,它可能有效。https://dev59.com/J1wX5IYBdhLWcg3w-Thv#41221852 - Bipin Bharti
请查看此链接:在Android中打开应用程序设置屏幕 - Ravi
请查看以下链接:https://dev59.com/lRP7s4cB2Jgan1znGgTj#71837394 - AllanRibas
15个回答

577
根据官方的Marshmallow权限视频(在4分43秒处),您必须打开应用程序“设置”页面(从那里单击一个按钮即可访问权限页面)。
要打开设置页面,您需要执行以下操作:
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", getPackageName(), null);
intent.setData(uri);
startActivity(intent);

34
它正在重定向到应用程序屏幕的常规细节。 如何直接进入应用程序权限屏幕。 我不想再多点击一次。 - Milind Mevada
12
目前您无法做到这一点。 - Martin Konecny
1
你能通过意图(intent)在“实时”中从设置活动向你的活动发送数据吗?我面临的问题是一旦从设置传输数据到你的活动中,如何处理这些数据。 - ThunderWiring
1
这在调试应用程序时有效,但在签署APK后无缘无故崩溃。logcat中也没有明显的原因。 - JCutting8

208

这是不可能的。我也试过这样做。我可以找出要启动的包名和活动名称。但最终你会因为缺少无法声明的权限而得到一个安全异常。


关于另一个答案,我也建议打开应用程序设置屏幕。我使用以下代码来实现这一点:
public static void startInstalledAppDetailsActivity(final Activity context) {
    if (context == null) {
        return;
    }
    final Intent i = new Intent();
    i.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
    i.addCategory(Intent.CATEGORY_DEFAULT);
    i.setData(Uri.parse("package:" + context.getPackageName()));
    i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    i.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
    i.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
    context.startActivity(i);
}

由于我不想在历史堆栈中保留它,所以我使用意图标志将其删除。

Kotlin版本:

val intent = Intent(ACTION_APPLICATION_DETAILS_SETTINGS)
with(intent) {
   data = Uri.fromParts("package", requireContext().packageName, null)
   addCategory(CATEGORY_DEFAULT)
   addFlags(FLAG_ACTIVITY_NEW_TASK)
   addFlags(FLAG_ACTIVITY_NO_HISTORY)
   addFlags(FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)
}

startActivity(intent)

我经历了相同的问题,认为可能有一种变通方法或另一种解决方案... :-/ - Frederik Schweiger
2
@Mulgard Whatsapp 必须使用 targetSdk="23"。这允许应用程序提示用户启用权限。如果您的目标 SDK < 23,则能够向用户显示应用程序权限屏幕非常有用,但似乎我们只能显示一般的应用程序设置屏幕。 - vman
6
在平板电脑上,当在设置屏幕中弹出一个窗口时,Intent.FLAG_ACTIVITY_NO_HISTORY有时会导致问题情况,它会关闭设置屏幕。去除该标志将解决此问题。 - Wirling
1
@Thomas R. 你说必须启动的活动是什么,但由于缺少无法声明的权限而生成了安全异常?我很好奇。 - Hugo Allexis Cardona
2
您可以同时显示一个 Toast,指示用户进入“权限”(即使应用程序的其余部分不可用于用户的语言,本地化此消息也是一个好主意)。 - vgergo
显示剩余6条评论

117
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Uri uri = Uri.fromParts("package", getPackageName(), null);
intent.setData(uri);
startActivity(intent);

描述

Settings.ACTION_APPLICATION_DETAILS_SETTINGS
   打开应用程序详细设置页面。在此页面上,用户必须手动分配所需的权限。

Intent.FLAG_ACTIVITY_NEW_TASK
   可选。如果设置,则打开新的Settings屏幕(Activity)作为新活动。否则,它将在当前正在运行的活动中打开。

Uri.fromParts("package", getPackageName(), null)
   准备或创建URI,其中getPackageName() - 返回您的应用程序包的名称。

intent.setData(uri)
   别忘了设置这个。否则,您将得到 android.content.ActivityNotFoundException因为你已经将你的意图设置为 Settings.ACTION_APPLICATION_DETAILS_SETTINGS而Android期望搜索一些名称。


8
这就是得票最高的答案的字面意思。为什么要重复而不是扩展原始答案呢?! - Thomas Keller
2
感谢您的深入解释。 - David Refoua
请注意使用FLAG_ACTIVITY_NEW_TASK标志,以避免将设置应用程序嵌入到您的应用程序任务中。 - Slion

46

如果你想在Kotlin中写更少的代码,你可以这样做:

fun Context.openAppSystemSettings() {
    startActivity(Intent().apply {
        action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS
        data = Uri.fromParts("package", packageName, null)
    })
}

基于 Martin Konecny 的回答


不错的Kotlin扩展使用 - David Jarvis
1
以下是较短的版本: fun Context.openAppSystemSettings() = startActivity(Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.fromParts("package", packageName, null))) - copolii
你需要留意,这只是应用程序的详细设置,但你必须点击"权限"按钮,然后再打开权限屏幕。 - user924

43

相反,您可以使用一行代码打开特定应用程序的常规设置:

 startActivity(new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.parse("package:" + BuildConfig.APPLICATION_ID)));

4
根据您的构建配置,您可能希望使用 getActivity().getPackageName() 获取包名。 - Cory Roy

30

Kotlin 风格。

startActivity(Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
    data = Uri.fromParts("package", packageName, null)
})

21

从Android 11开始,你可以使用以下代码直接打开应用程序特定的“位置权限”设置页面:requestPermissions(arrayOf(Manifest.permission.ACCESS_BACKGROUND_LOCATION), PERMISSION_REQUEST_BACKGROUND_LOCATION)

然而,以上方法只会生效一次。如果用户拒绝了权限或者意外地关闭了该屏幕,应用程序将无法再次触发该页面。

除此之外,Android 11之前的解决方法仍然适用——你只能打开应用程序特定的设置页面,并要求用户手动向下深入两个级别以启用适当的权限。

val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
val uri: Uri = Uri.fromParts("package", packageName, null)
intent.data = uri
// This will take the user to a page where they have to click twice to drill down to grant the permission
startActivity(intent)

查看我相关的问题: Android 11用户无法授予后台位置权限?


如果题外话,问题与位置背景权限无关! - user924

18

无法通过编程方式打开权限屏幕。相反,我们可以打开应用程序设置屏幕。

代码

Intent i = new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.parse("package:" + BuildConfig.APPLICATION_ID));
startActivity(i);

样例输出

在此输入图片描述


2
他正在请求许可页面。 - Maveňツ

7

Xamarin Forms Android:

//---------------------------------------------------------
public void OpenSettings()
//---------------------------------------------------------
{
    var intent = new Intent(Android.Provider.Settings.ActionApplicationDetailsSettings,
        Android.Net.Uri.Parse("package:" + Forms.Context.PackageName));
    Forms.Context.StartActivity(intent);
}

6
在Kotlin中
    /*
*
* To open app notification permission screen instead of setting
* */
fun Context.openAppNotificationSettings() {
    val intent = Intent().apply {
        when {
            Build.VERSION.SDK_INT >= Build.VERSION_CODES.O -> {
                action = Settings.ACTION_APP_NOTIFICATION_SETTINGS
                putExtra(Settings.EXTRA_APP_PACKAGE, packageName)
            }
            else -> {
                action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS
                addCategory(Intent.CATEGORY_DEFAULT)
                data = Uri.parse("package:" + packageName)
            }
        }
    }
    startActivity(intent)
}

以上代码已测试并可行,希望它能帮到您。


是的,它能够工作,但是我需要将ACTION_APP_NOTIFICATION_SETTINGS更改为ACTION_APPLICATION_SETTINGS,因为在ACTION_APP_NOTIFICATION_SETTINGS中无法做任何操作。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接