安卓棉花糖:如何以编程方式允许运行时权限?

3
我正在开发一个需要一些系统权限的应用程序,但是在Android Marshmallow上安装时不再自动授予这些权限。
我想在运行时请求这些权限,并运行某种自动化程序,以便在系统权限对话框出现时无需用户点击“允许”按钮即可授予它们。
我该如何实现这一点? 在Marshmallow及更高版本中是否有任何方法可以做到这一点?
2个回答

3

对于Marshmallow或更高版本,权限不会在安装时授予,必须在运行时(如果之前未授予)请求所需的权限。

为此,您需要在用户执行需要额外系统权限的操作时,在Activity中运行ActivityCompat.requestPermissions()以弹出系统权限对话框。

例如,对于WRITE_EXTERNAL_STORAGE权限:

ActivityCompat.requestPermissions(
    this, 
    new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
    WRITE_EXTERNAL_STORAGE_REQUEST_CODE
);

注意:WRITE_EXTERNAL_STORAGE_REQUEST_CODE 是一个任意的整数常量,你应该在其他地方定义它。
你请求的权限也应该在你的 AndroidManifest.xml 中声明。在这个例子中,声明应该是:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> 

为了处理系统权限对话框的响应,您还需要在Activity中实现onRequestPermissionsResult()。对于此示例,代码类似于:
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) {
    if (grantResults.length == 0 || grantResults[0] == PackageManager.PERMISSION_DENIED) {
        return; //permission not granted, could also optionally log an error
    }
    if (requestCode == WRITE_EXTERNAL_STORAGE_REQUEST_CODE) {
        //Do whatever you needed the write permissions for            
    }
}

如果您正在通过Espresso, UIAutomator或其他UI测试框架自动化您的应用程序,那么您需要在测试期间预测并单击系统对话框,这可以通过以下测试代码实现:
private void allowPermissionsIfNeeded()  {
    if (Build.VERSION.SDK_INT >= 23) {
        UiObject allowPermissions = mDevice.findObject(new UiSelector().text("Allow"));
        if (allowPermissions.exists()) {
            try {
                allowPermissions.click();
            } catch (UiObjectNotFoundException e) {
                Timber.e(e, "There is no permissions dialog to interact with ");
            }
        }
    }
}

关于测试系统UI权限的更全面解释可以在这里找到。


感谢您的详细解释,尽管我只需要在“Espresso”之后的最后一部分。顺便说一下,我并没有通过“Espresso”自动化我的应用程序,我只是从应用程序内部点击按钮并控制应用程序流程。是否可能在不使用类似“Espresso”的任何东西的情况下这样做? - KayPee
不客气 :) 您究竟想要自动化什么以及出于什么目的?您目前是如何做到这一点的?从问题描述中,很难理解您想要实现什么(或者您所说的“点击”应用程序内的按钮意味着什么)。 - Nathan
简单来说,我想在内部授予权限,无需任何用户交互。 - KayPee
这样做将违背向用户请求权限的目的,并构成安全漏洞 - 自动化此类交互的唯一方法是通过控制应用程序之外的设备(通常使用某种仪器/ UI测试框架)。 - Nathan
是的,那肯定会打败运行时权限的目的。通常的做法是使用某种测试框架进行仪器化/UI测试。但我不知道那个,所以我决定采用内部点击事件。此外,我只需要很少的点击就能实现我的目标。所以我选择了这个方法。但是我在允许权限的部分卡住了。我想我必须去使用“仪器化/UI测试框架”了。 - KayPee
显示剩余4条评论

2

我发现在CI场景中,自动化权限接受的更简单的方法是通过adb预先安装apk,而不使用UIAutomator或espresso:

adb install -g {my_apk_file}

-g标记会自动将所有清单权限授予应用程序。之后,如果启动您的Espresso测试套件,则UI不会再次要求您授予权限。


这在超级用户模式下对我很有帮助。 - Dhruv Kaushal

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