IntentResolver in Android isn't what most tutorials make it seem

I spent three days debugging an app crash that boiled down to how I was using IntentResolver. The app would hang on older devices when trying to resolve an implicit intent for sharing images. Turns out the behavior varied significantly between Android 10 and Android 14, and nobody in those tutorial videos mentioned it. IntentResolver is part of the Android PackageManager system. When you call resolveActivity() or queryIntentActivities() on an Intent, the system uses IntentResolver internally to find matching apps. Most developers interact with it through those methods without ever realizing it exists. The thing nobody tells you is that IntentResolver respects different flags and behaves differently depending on whether you pass QUERY_ALL_PACKAGES permission versus the standard visibility restrictions introduced in Android 11. The actual method signature you will deal with looks like this: your Intent object plus resolution flags. The flags matter more than people admit. PackageInfo.QUERY intent resolver gets pulled from there.

Here is a practical example of what most people get wrong: Code example: PackageManager pm = getPackageManager();

Intent shareIntent = new Intent(Intent.ACTION_SEND); shareIntent.setType("image/jpeg"); List<ResolveInfo> activities = pm.queryIntentActivities(shareIntent, 0);

Get the Full Details

Unlocking Transfer Learning in Machine Learning: The Ultimate Game ...
Unlocking Transfer Learning in Machine Learning: The Ultimate Game ...

If you run this on a device with Android 11 or higher without proper configuration, your list might be empty even though the user definitely has a gallery app installed. That is because scoped storage and package visibility restrictions filter out apps that have not declared their intent filters properly or that fall outside your app's declared permissions. I encountered a case where queryIntentActivities returned inconsistent results between two devices running the same Android version. One device had a custom ROM with aggressive app filtering. The other was stock. The difference came down to how each manufacturer handled the QUERY_DEFAULT_ONLY flag. The workaround was checking the Build.MANUFACTURER and adjusting my query strategy accordingly. I ended up wrapping the resolution logic in a helper method that falls back to explicit component names when the implicit resolution fails. Another thing that trips people up: resolveActivity() and queryIntentActivities() use different internal caches. If you are calling both in quick succession during app startup, you might get stale results from one of them. I learned this the hard way when an app launch optimization caused intermittent crashes on devices with low memory. The cache gets cleared at different times depending on system pressure.

For advanced usage, you should know about the DEFAULT_ONLY and CODE_PATH_ONLY flags. DEFAULT_ONLY strips away activities that require additional permissions you have not declared. CODE_PATH_ONLY limits results to your own application package. Neither of these is mentioned prominently in the official documentation but they save significant debugging time when you are trying to isolate resolution behavior. The performance impact of heavy IntentResolver usage is often overlooked. Each call to queryIntentActivities() triggers a system-level search. If you are doing this inside a RecyclerView adapter or a frequently called callback, you will notice frame drops. The fix is caching results with a lifespan tied to package changes. You can register a ContentObserver on the packages URI to invalidate your cache when apps are installed or removed. This typically reduces repeated queries from dozens per second down to zero unless a package change occurs. One limitation you need to accept: IntentResolver cannot help you bypass package visibility restrictions. If your app targets Android 11+ and you need to query activities from other apps, you either need to declare the specific packages in your manifest or request QUERY_ALL_PACKAGES. Google rarely approves the latter now. The workaround is to use ACTION_PICK or ACTION_GET_CONTENT for media selection instead of trying to enumerate all available handlers.

There is also a gotcha with custom MIME types. If you register a custom scheme or MIME type in your own app and then try to resolve it, IntentResolver will not find it unless you have already launched the activity at least once. The package manager caches resolution results based on first encounter. This means tests run in isolation often produce different results than tests run after normal app usage. I had to add a warmup step in my integration tests to account for this. For anyone building a universal handler or launcher replacement app, the rules change completely. Those apps typically use ACTION_MAIN with CATEGORY_LAUNCHER and get added to the system resolver dialog by default. But even then, the ordering and filtering is controlled by the system and varies by manufacturer. Samsung devices reorder results differently than Pixel devices. Xiaomi adds its own filtering layer. If your app depends on consistent resolver behavior across devices, you will need per-OEM detection and fallback chains. The official Android documentation covers the basics adequately but skips the edge cases that matter in production. I found the source code in the AOSP PackageManagerService helpful for understanding exactly how resolution works under the hood. Specifically the QueryIntentActivities task and the filterCanResolve method show you what gets filtered and why.

Unlocking Potential: Spotlight on Top-Performing Android App Developers ...
Unlocking Potential: Spotlight on Top-Performing Android App Developers ...

If you are starting fresh with this topic, begin by writing a simple test app that logs every call to queryIntentActivities and resolvesActivity. Track the flags you pass, the results you get, and compare them across devices. That single exercise will teach you more than reading any tutorial. The behavior is too varied across Android versions and manufacturer skins for generic advice to be reliable. There is no download link for IntentResolver itself because it is not a library you install. It is a system service component exposed through PackageManager. You access it through context.getPackageManager(). Everything else is implementation detail.