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

Fre*_*ger 306 android android-permissions android-6.0-marshmallow

我对新的Android Marshmallow版本有疑问:

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

Android M权限屏幕

可以使用以下代码显示应用程序设置 - 是否有直接打开权限屏幕的模拟解决方案?

startActivity(new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
Uri.fromParts("package", getPackageName(), null)));
Run Code Online (Sandbox Code Playgroud)

我已经对此做过一些研究,但我无法找到合适的解决方案 - 我将非常感谢您的帮助!

Mar*_*cny 410

根据官方的Marshmallow权限视频(在4m 43s标记处),您必须打开应用程序"设置"页面(从那里只需单击一次"权限"页面).

要打开设置页面,您可以这样做

Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", getPackageName(), null);
intent.setData(uri);
startActivity(intent);
Run Code Online (Sandbox Code Playgroud)

  • 它重定向到应用程序屏幕的一般细节.怎么可以去专门的App Permissions屏幕.我不希望剩下一次点击, (6认同)
  • @MilindMevada - 你现在不能这样做. (4认同)

Tho*_* R. 176

这是不可能的.我也试过这样做.我可以找出包名称和将要启动的活动.但最终您将获得一个安全例外,因为您无法声明您缺少的权限.

更新:

关于其他答案,我还建议打开应用程序设置屏幕.我使用以下代码执行此操作:

    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);
}
Run Code Online (Sandbox Code Playgroud)

因为我不希望在我的历史堆栈中有这个,所以我使用intent标记删除它.

  • 当设置屏幕中显示弹出窗口时,Intent.FLAG_ACTIVITY_NO_HISTORY有时可能会导致平板电脑出现问题,它将关闭设置屏幕.只需删除该标志即可解决此问题. (4认同)
  • @Mulgard Whatsapp 必须使用 targetSdk="23"。这允许应用程序提示用户启用权限。如果您的目标 SDK < 23,能够向用户显示应用程序权限屏幕很有用,但似乎我们只能显示常规应用程序设置屏幕。 (2认同)
  • 您可以同时显示Toast,指示用户进入“权限”(即使您的应用程序的其余部分无法以用户的语言显示,本地化此消息的好主意) (2认同)

sin*_*eep 69

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);
Run Code Online (Sandbox Code Playgroud)

说明 打开App的详细信息设置页面.从这里用户必须手动分配所需的权限.

Settings.ACTION_APPLICATION_DETAILS_SETTINGS
  

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

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

intent.setData(uri)
   别忘了设置它.否则,你会得到 android.content.ActivityNotFoundException.因为你已经设置了你的意图, Settings.ACTION_APPLICATION_DETAILS_SETTINGS 并且android期望一些名字来搜索.

  • 这实际上就是最高投票的答案。为什么要复制这个而不是扩展原来的答案?! (3认同)
  • 感谢您的深入解释。 (2认同)

dgn*_*can 32

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

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

  • 您可能希望使用 getActivity().getPackageName() 来获取包名称,具体取决于您的构建配置方式。 (3认同)

Sai*_*Sai 19

科特林风格。

    startActivity(Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
        data = Uri.fromParts("package", packageName, null)
    })
Run Code Online (Sandbox Code Playgroud)


小智 10

无法以实用方式打开权限屏幕.相反,我们可以打开应用程序设置屏幕.

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

样本输出

在此输入图像描述

  • 他正在请求权限页面 (2认同)

dav*_*ung 8

从 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)

Run Code Online (Sandbox Code Playgroud)

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


Yog*_*dra 7

在科特林中

    /*
*
* 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)
}
Run Code Online (Sandbox Code Playgroud)

以上是经过测试和工作的代码,希望对您有所帮助。


Ult*_*o_m 5

如果您想编写更少的代码,Kotlin可以这样做:

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

根据Martin Konecny的回答

  • 这是一个较短的版本:`fun Context.openAppSystemSettings() = startActivity(Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.fromParts("package", packageName, null)))` (2认同)

Nic*_*sky 5

Xamarin 表单 Android:

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


小智 5

可能这会帮助你

private void openSettings() {
    Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
    Uri uri = Uri.fromParts("package", getPackageName(), null);
    intent.setData(uri);
    startActivityForResult(intent, 101);
}
Run Code Online (Sandbox Code Playgroud)