无法测试需要棉花糖 CHANGE_NETWORK_STATE / WRITE_SETTINGS 权限的代码

Unable to test code requiring CHANGE_NETWORK_STATE / WRITE_SETTINGS permission on Marshmallow

我正在尝试将我的应用程序的 targetSDK 升级到 23 以上,但 运行 遇到了一个小问题。我有一个 activity 将流量绑定到 Wifi(以测量路由器的网络速度,即使路由器未连接到互联网)。为了实现这一点,我的应用需要 CHANGE_NETWORK_STATE 权限。如果在清单中声明,通常会直接授予该权限。在 Android 6.0 上(确切地说,这已在 6.0.1 IIRC 中修复)CHANGE_NETWORK_STATE 已损坏且不会被授予,因此您需要 WRITE_SETTINGS 权限。我已经为 Android 6.0 用户实施了一种授予该权限的方法,但是当我想使用浓缩咖啡测试我的 Activity 时,我无法这样做。通过添加类似

的内容授予测试权限

@Rule public GrantPermissionRule runtimePermissionRule = GrantPermissionRule.grant(Manifest.permission.CHANGE_NETWORK_STATE);

到测试用例。这在应用程序的其他地方有效,但为此我得到了 junit.framework.AssertionFailedError: Failed to grant permissions, see logcat for details 在我的测试结果中。在 logcat 中,我发现 E/GrantPermissionCallable: Permission: android.permission.WRITE_SETTINGS cannot be granted! 或与 CHANGE_NETWORK_STATE 相同,我尝试同时授予它们,但它们都不起作用。我有没有其他方法可以在测试环境中授予权限?或者从现在开始我无法在 6.0 设备上测试这个 activity?

因为 WRITE_SETTINGS 是敏感权限,您将无法在 API 23 中使用 GrantPermissionRule 授予它。您可能最终需要使用 UIAutomator in your tests to select the appropriate response in the permissions management screen.

我设法通过使用 UiAutomator 和 shell appops 命令授予权限来解决这个问题:

Instrumentation instrumentation = getInstrumentation();
UiDevice device = UiDevice.getInstance(instrumentation);
String targetPackageName = instrumentation.getTargetContext().getPackageName();

if (Build.VERSION.SDK_INT >= 23) {
    String shellCommand = String.format("appops set %s WRITE_SETTINGS allow", targetPackageName);
    device.executeShellCommand(shellCommand);
}