Reputation: 150
Our goal is to use AndroidTest(AndroidJUnit4) to run automatic tests.
We have used this code to grant permissions when 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");
}
The method is fine for
android.permission.READ_EXTERNAL_STORAGE
android.permission.WRITE_EXTERNAL_STORAGE
android.permission.CAMERA
Although in the Settings/Security/Apps with usage access, our app is on, but when we use this code to check permission, it still doesn't have that permission.
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())
How can I do to succeed this goal?
Upvotes: 1
Views: 1426
Reputation: 150
We have tried many approved. Finally, we succeeded.
The approved was use "adb shell input tap [x], [y]" to simulate tap, so it is like human tap the screen to trigger the switch.
This is the code us use.
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);
}
We have tried 6 AVDs on SDK 23 and 24 with hdip, xhdip and xxhdip. All works.
UPDATED[2/10]:
We found another easier way to do it. use "adb shell appops" commend. This is ours code.
@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");
}
}
}
Upvotes: 4
Reputation: 500
Make sure your app has usage stats enabled. You can check this by launching the Usage Stats Activity. add this to your code on your onCreate
method or possible on a button click:
Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
startActivity(intent);
Upvotes: 0