android

Android UIAutomator: failing to obtain an intent to start the entry-activity


For an Android application that I am developing I am trying to create a couple of UI tests using UIAutomator. As initialization for the tests (i.e. in the @Before-method) I want to start the application afresh from the launcher. Deriving from this tutorial I came up with the code below but I am stuck because the Intent from the .getLaunchIntentForPackage(<packagename>)-method is always null and I was unable to figure out, why I am not getting a valid intent here.

What do I need to change in my code or what is missing in the AndroidManifest.xml-file (or elsewhere) so that getLaunchIntentForPackage(...) is able to locate and return the application's entry intent so that I can then use that to fire up the application?

...
<imports omitted for brevity>
...

@RunWith(AndroidJUnit4.class)
@SdkSuppress(minSdkVersion = 18)
public class DisplayFilesTest
{
    private static final String PACKAGE_NAME   = DisplayFiles.class.getPackageName();
    private static final int    LAUNCH_TIMEOUT = 5000;
    private UiDevice device;

    @Before
    public void startMainActivityFromHomeScreen() {
        // Initialize UiDevice instance
        device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());

        // Start from the home screen
        device.pressHome();

        // Wait for launcher
        final String launcherPackage = device.getLauncherPackageName();
        assertThat(launcherPackage, notNullValue());
        device.wait(Until.hasObject(By.pkg(launcherPackage).depth(0)), LAUNCH_TIMEOUT);

        final Context context = ApplicationProvider.getApplicationContext();
        assertThat(context, notNullValue());

        final Intent launchIntent = context.getPackageManager().getLaunchIntentForPackage(PACKAGE_NAME);
        assertThat(launchIntent, notNullValue());  // <<<=== this assert always triggers since the returned Intent is null.

        // Clear out any previous instances
        launchIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
        // Launch the app
        context.startActivity(launchIntent);

        // Wait for the app to appear
        device.wait(Until.hasObject(By.pkg(PACKAGE_NAME).depth(0)), LAUNCH_TIMEOUT);
    }

    // actual UI tests later to be added here...
}

The DisplayFiles-activity that I want to start with the above code is the applications entry activity and is declared in the AndroidManifest.xml like so:

        ...
        <activity
            android:name=".activities.DisplayFiles"
            android:icon="@drawable/icon"
            android:exported="true"
            >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        ...

Solution

  • For the benefit of anyone stumbling over this question: I finally found the reason I never got a proper intent! Thanks to a response in this question I found out:

    I had (mis-)understood the placeholder "pckname" in Google's tutorial such that this is the (Java) package name of the Activity that I want to start up. But it is obviously the application class's package name, i.e. the name of the package of the class that "... extends Application" in your application, which - in my case - is two layers higher up than the activity I wanted to trigger. Using the correct "package name" I immediately got the intended intent (pun intended... ;-) ) and my application fired up!