Warning! Resolving of “Implicit Intent”s in Android Marshmallow is not working as the same as before. This may break your app’s behavior.

Let me explain the expected behavior and why is not working:

I have recently been working on a small open source project called “Open Link With”. It will hopefully be in the Play Store soon.

My app gives you the ability to switch between other apps. When you share a link with me, I basically grab the link and query all the Activity’s that can handle that link. And finally I mimic the system dialog and let you switch apps.

Switching from already opened youtube web-page to Youtube app.

I was using the below method as always:

List<ResolveInfo> infos = packageManager

.queryIntentActivities(intent, MATCH_DEFAULT_ONLY);

It is a familiar method to almost all Android developers and I am sure that it is currently being used in lots of apps.

I have 2 browsers in my phone. “An Intent with Google+ URL” is expected to give a list of 3 ResolveInfo objects (Google+ app and 2 browsers).

Well, not anymore!

Welcome to Android Marshmallow!

Android Marshmallow introduced App Links. The system basically authenticates with your web-page and opens those URLs automatically using your application without asking anything to user. Or you can go to system Settings, Apps, click an app, click “Open by default” and then set “Open in this app” to use always that app.

Application default setting page in Marshmallow

In that case, queryIntentActivities method will give developers a list with only 1 Activity (which is Google+ in this case).

Even if this is the desired behavior, this should be documented because it breaks the behavior of a public API.

I researched a little bit and found MATCH_ALL flag. It’s documentation says that it will disable all system level filters.

/**

* Querying flag: if set and if the platform is doing any filtering of the results, then

* the filtering will not happen. This is a synonym for saying that all results should

* be returned.

*/

public static final int MATCH_ALL = 0x00020000;

It didn’t do anything for me. I opened the source code (at least we have that!) and investigated the method.

It looks like they prioritize the domain verified applications. They did not just prioritize in their internal system, they also did it in the public API.

If there is a domain verified application, it does not return anything else. MATCH_ALL flag removes some system filters but only if there is no verified application.