Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android GrantPermissionRule does not work with api-27

I've the permission rule configured as below in my MainActivityTest class

@Rule
public GrantPermissionRule permissionRule =
    GrantPermissionRule.grant(RECORD_AUDIO, WRITE_EXTERNAL_STORAGE);

When I run below command to execute the tests on emulator with api 27

./gradlew connectedCheck

It fails with the below error

com.example.myapplication.MainActivityTest > testLaunch_main_activity[Pixel_XL_API_27(AVD) - 8.1.0] FAILED 
        androidx.test.espresso.NoActivityResumedException: No activities in stage RESUMED. Did you forget to launch the activity. (test.getActivity() or similar)?
        at dalvik.system.VMStack.getThreadStackTrace(Native Method)

Surprisingly the permissions are showing as granted in the app info settings, but still its asking for permissions when the test is run on emulator with api version 27 (or lower)

Can someone please confirm if it is a bug in some android plugin or if I am missing anything here.

Source Code - https://github.com/vivekweb2013/test-android-project

like image 731
Vivek Avatar asked May 22 '21 15:05

Vivek


2 Answers

You are using ContextCompat's checkSelfPermission to check whether the app has permission or not. This is backward compatible with the support libraries but not sure with androidx. Alternative to this can be to use PermissionChecker's checkSelfPermission api like,

For API level 22 and below,

int permission = PermissionChecker.checkSelfPermission(context, permission);

if (permission == PermissionChecker.PERMISSION_GRANTED) {
    // permission is granted
} else {
    // permission not granted
}

But given that these permissions RECORD_AUDIO and WRITE_EXTERNAL_STORAGE are dangerous permission which requires acknowledgement from the user before our app can start consuming it. Below API level 23, these permissions are granted automatically when it is declared in AndroidManifest so the other way to get rid of this issue can be to verify it only for API level 23+ since it makes sense to validate.

like image 75
Tom Taylor Avatar answered Oct 19 '22 06:10

Tom Taylor


I'd suggest you use a RuleChain with an outer rule for permissions around the ActivityScenarioRule

The problem seems to come from a race between launching the activity through the scenario rule and the permission rule, with a RuleChain in place the order of execution becomes explicit and the behavior should be as expected.

Here's the updated code from your example:

public class MainActivityTest {
    public GrantPermissionRule permissionRule =
          GrantPermissionRule.grant(RECORD_AUDIO, WRITE_EXTERNAL_STORAGE);

    public ActivityScenarioRule<MainActivity> rule = new ActivityScenarioRule<>(MainActivity.class);

    @Rule
    public RuleChain chain = RuleChain.outerRule(permissionRule).around(rule);

    @Test
    public void testLaunch_main_activity() {
        onView(withId(R.id.txt_view)).check(matches(isDisplayed()));
    }
}
like image 37
rahul.taicho Avatar answered Oct 19 '22 06:10

rahul.taicho