android explicit intent by name not resolving to other activity

Viewed 727

I have 2 apps that are used in conjunction with one another. I want to create a button that launches app A from app B so I am creating an intent like so in app B:

Intent intent = new Intent("com.org.orgmobile.android.action.ACTION_CUSTOM");
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
intent.setData(Uri.parse(url));
startActivity(intent);

where url is https://org.org.com/mobile/Support/action/org/ActionEnumValue/?a=123

the intent filter I have declared in app A's manifest is like so:

<intent-filter>
    <action android:name="com.org.orgmobile.android.action.ACTION_CUSTOM"/>
    <action android:name="android.intent.action.VIEW"/>
    <category android:name="android.intent.category.BROWSABLE"/>
    <category android:name="android.intent.category.DEFAULT"/>
    <data android:scheme="https"/>
    <data android:host="org.org.com"/>
    <data android:pathPrefix="/mobile/Support/action/${manifestplaceholderattr}.*/ActionEnumValue/*"/>
</intent-filter>

and manifestplaceholderattr is an empty string.

I am getting

android.content.ActivityNotFoundException: No Activity found to handle Intent { act=com.org.orgmobile.android.action.ACTION_CUSTOM dat=https://org.org.com/... flg=0x20000000 }
                            at android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:1936)
                            at android.app.Instrumentation.execStartActivity(Instrumentation.java:1615)
                            at android.app.Activity.startActivityForResult(Activity.java:4472)
                            at android.app.Activity.startActivityForResult(Activity.java:4430)
                            at android.app.Activity.startActivity(Activity.java:4791)
                            at android.app.Activity.startActivity(Activity.java:4759)

What am I overlooking here? I have tried using pathPattern instead of path prefix with no success.

Edit: to provide more detail, I don't just want to launch that specific activity, I want to match the specific intent associated with that activity to launch the activity. I don't want to launch the activity directly because in the case that the user's app is out of date because it won't have the desired behavior.

3 Answers

Best way to do this through Package manager as below.

 PackageManager manager = getPackageManager();
    try {
        Intent intent = manager.getLaunchIntentForPackage("app B package name here");
        if (intent == null)
            throw new PackageManager.NameNotFoundException();
        intent.addCategory(Intent.CATEGORY_LAUNCHER);
        startActivity(intent);
    } catch (Exception e) {
        e.printStackTrace();
    }

Package manager checks if app with the given package name is installed, if exists it launches the app else it throws NameNotFoundException

You need to use pathPattern instead of pathPrefix. Also you should use .* instead of * at the end of the pattern:

<data android:pathPattern="/mobile/Support/action/${manifestplaceholderattr}.*/ActionEnumValue/.*"/>

This may also not work. If I recall, pathPattern isn't a real regular expression and you may not be able to match the URL like this. Try it and see. If this doesn't work, you'll probably need to rely on just the first part of the path. Let me know how it goes.

See the documentation on path, pathPattern and pathPrefix.

You need to use code as below to launch other App using custom action.

Intent intent = new Intent();
intent.setAction("com.org.orgmobile.android.action.ACTION_CUSTOM");
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
intent.setData(Uri.parse(url));
startActivity(intent);

Also make sure both of your application is installed. Also it is better to have check as below to make sure application exists on the phone to handle such Intent.

PackageManager packageManager = getPackageManager();
List activities = packageManager.queryIntentActivities(intent,
        PackageManager.MATCH_DEFAULT_ONLY);
boolean isIntentSafe = activities.size() > 0;
Related