具有PACKAGE_USAGE_STATS权限的AndroidTest

时间:2017-02-08 16:08:32

标签: android automated-tests android-espresso

我们的目标是使用AndroidTest(AndroidJUnit4)来运行自动测试。

我们在SDK> = 23

时使用此代码授予权限
public static void grantPermission(String permission) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        if (!hasPermission(permission))
            getInstrumentation().getUiAutomation()
                                .executeShellCommand("pm grant " + getTargetContext().getPackageName() + " " + permission);
    }
}

@Before
public void setUp() throws Exception {
    grantPermission("android.permission.ACCESS_NETWORK_STATE");
    grantPermission("android.permission.CHANGE_NETWORK_STATE");
    grantPermission("android.permission.CAMERA ");
    grantPermission("android.permission.INTERNET");
    grantPermission("android.permission.READ_EXTERNAL_STORAGE ");
    grantPermission("android.permission.WRITE_EXTERNAL_STORAGE");        
    grantPermission("android.permission.PACKAGE_USAGE_STATS");       
}

该方法适用于

android.permission.READ_EXTERNAL_STORAGE
android.permission.WRITE_EXTERNAL_STORAGE
android.permission.CAMERA

虽然在具有使用权限的设置/安全/应用中,我们的应用已开启,但是当我们使用此代码检查权限时,它仍然没有该权限。

AppOpsManager appOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);

// return MODE_DEFAULT, not MODE_ALLOWED
int result = appOps.checkOpNoThrow("android:get_usage_stats", android.os.Process.myUid(), context.getPackageName())

如何才能成功实现这一目标?

2 个答案:

答案 0 :(得分:1)

我们已经尝试了许多批准。最后,我们成功了。

批准使用“adb shell输入tap [x],[y]”来模拟点击,这就像人类点击屏幕来触发切换。

这是我们使用的代码。

private void grantPermission() throws InterruptedException {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        Context context = InstrumentationRegistry.getTargetContext();
        final AppOpsManager appOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);

        // check if the app doesn't have permission
        if (appOps.checkOpNoThrow("android:get_usage_stats", android.os.Process.myUid(), context.getPackageName()) != AppOpsManager.MODE_ALLOWED) {
            UiAutomation automation = InstrumentationRegistry.getInstrumentation().getUiAutomation();

            //Open UsageAccessSettingsActivity
            automation.executeShellCommand("am start com.android.settings/.Settings$UsageAccessSettingsActivity");
            Thread.sleep(1000);

            //Open the setting of the first app
            automation.executeShellCommand(String.format("input tap %s %s", dpToPx(100), dpToPx(138)));
            Thread.sleep(1000);

            //Tap permit usage access
            automation.executeShellCommand(String.format("input tap %s %s", dpToPx(100), dpToPx(164)));
            Thread.sleep(1000);
        }
    }
}

public static int dpToPx(int dp) {
    return (int) (dp * Resources.getSystem().getDisplayMetrics().density);
}

我们已经使用hdip,xhdip和xxhdip在SDK 23和24上尝试了6个AVD。一切正常。

<强>更新的[2/10]:

我们找到了另一种更简单的方法。使用“adb shell appops”表示赞扬。 这是我们的代码。

@Before
public void setUp() throws Exception {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        Context context = InstrumentationRegistry.getTargetContext();
        final AppOpsManager appOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);

        if (appOps.checkOpNoThrow("android:get_usage_stats", android.os.Process.myUid(), context.getPackageName()) != AppOpsManager.MODE_ALLOWED) {
            InstrumentationRegistry
                    .getInstrumentation()
                    .getUiAutomation()
                    .executeShellCommand("appops set " + context.getPackageName() + " android:get_usage_stats allow");
        }
    }
}

答案 1 :(得分:0)

确保您的应用已启用使用情况统计信息。您可以通过启动Usage Stats Activity来检查这一点。将其添加到onCreate方法的代码中,或者点击按钮时添加:

Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
startActivity(intent);