AI-translated. Read the original in Korean
Understanding Package Visibility Changes in Android 11
Software Engineer

Android 11 is almost here. According to the official documentation, it is scheduled for release in the third quarter of 2020, so the final version should arrive within a month or two. Like previous major releases, Android 11 introduces important changes that can significantly affect existing apps. The changes to “package visibility” are particularly relevant to Buzzvil’s Android products, so I’d like to share what I found through research and hands-on testing.
Changes to package visibility
Apps with a targetSdkVersion of Android 11 or higher cannot freely obtain the list of other apps installed on a device. They can retrieve information only about apps declared in advance in their manifest. To specify the apps you want to query, add a <queries> element to AndroidManifest.xml, containing package names or intent filter signatures.
Specifying package names
<manifest package="com.example.game">
<queries>
<package android:name="com.example.store" />
<package android:name="com.example.services" />
</queries>
...
</manifest>
Specifying an intent filter
<manifest package="com.example.game">
<queries>
<intent>
<action android:name="android.intent.action.SEND" />
<data android:mimeType="image/jpeg" />
</intent>
</queries>
...
</manifest>
Some use cases—such as launchers, accessibility tools, browsers, and security apps—may need to query or interact with every app installed on a device. Android 11 introduces the QUERY_ALL_PACKAGES permission for those cases.
At the time of writing, the official documentation says that Google Play guidelines for QUERY_ALL_PACKAGES will be provided. Google appears to expect most apps to preserve their existing behavior by requesting only the minimum package visibility they need through <queries>. I therefore expect the permission to be restricted in some way outside exceptional use cases such as those above.
For more details, I recommend the official Android developer documentation.
Affected APIs
The official guide uses only PackageManager.queryIntentActivities() as an example, but Google’s Android 11 meetup also introduced other APIs affected by package visibility:
PackageManager.getPackageInfo("com.another.app", 0)- Throws
NameNotFoundExceptionregardless of whether the app is installed.
- Throws
PackageManager.getInstalledPackage(0)- Returns only the calling app and a small number of essential system packages.
PackageManager.queryIntentActivities(intent, 0)- Returns only the calling app and a small number of essential system packages.
- Using an explicit intent
- Throws an exception.
Testing the behavior
To test APIs likely to be affected, I created a sample app and ran it on an Android 11 virtual device using the Android 11 Beta 2.5 image. The sample code is available here. I selected the four APIs discussed at the Google meetup and two additional APIs with similar roles.
1. PackageManager.getPackageInfo()
- Without a
<queries>declaration, it throwsNameNotFoundException. - With the manifest below, calling the API with "com.android.chrome" works normally.
<manifest package="..."> <queries> <package android:name="com.android.chrome" /> <queries> ... </manifest>
2. PackageManager.queryIntentActivities(intent, 0)
I tested it with this code:
Intent(Intent.ACTION_VIEW, Uri.parse("https://www.google.com")).let { intent ->
val list = packageManager.queryIntentActivities(intent, 0)
}
- Without a
<queries>declaration, it returns an empty list. - Explicitly declaring "com.android.chrome" in the manifest, as in example 1, returns only that package.
- Using the intent filter below in the manifest returns all installed browser apps.
<manifest package="..."> <queries> <intent> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="https" /> </intent> <queries> ... </manifest>
3. Intent.resolveActivity(packageManager)
These results use the same intent as example 2.
- Without a
<queries>declaration, it returns null. - Explicitly declaring "com.android.chrome" in the manifest, as in example 1, returns that package.
- Declaring the intent filter from example 2 returns the most appropriate package among the installed browsers.
4. PackageManager.getInstalledPackages(0)
- Without a
<queries>declaration, it returns only the calling app and a few essential system packages. - Declaring particular packages or intent filters in
<queries>includes the matching packages as well.
5. PackageManager.getInstalledApplications(0)
- Without a
<queries>declaration, it returns only the calling app and a few essential system packages. - Declaring particular packages or intent filters in
<queries>includes the matching packages as well.
6. Context.startActivity(intent) with an explicit intent
I tested it with this code:
Intent(Intent.ACTION_VIEW, Uri.parse("https://www.google.com")).let { i ->
i.flags = Intent.FLAG_ACTIVITY_NEW_TASK
i.setPackage("com.android.chrome")
context.startActivity(i)
}
- Without a
<queries>declaration, it throwsActivityNotFoundException. - Explicitly declaring "com.android.chrome" in the manifest, as in example 1, launches Chrome normally.
- Declaring the intent filter from example 2 also launches Chrome normally.
Closing thoughts
We’ve taken a closer look at Android 11’s package visibility changes. With the release approaching, I encourage other app developers to test their apps and make the necessary compatibility changes early.