Retrieving a list of installed applications on an Android device is a common requirement for launcher apps, analytics dashboards, app managers, or utilities. Android’s PackageManager API provides a robust way to query installed packages, application labels, icons, and metadata.
In this guide, you’ll learn how to:
- Get all installed apps
- Distinguish between user and system apps
- Retrieve labels and icons
- Handle modern Android permission requirements
Overview – PackageManager and Installed Apps
The Android PackageManager is the central API for interacting with installed apps. It can return:
- Installed packages
- App labels (names)
- App icons
- Version details
- Permissions requested by apps
The key methods used are:
getInstalledApplications()getInstalledPackages()
Both return lists you can iterate over and extract details.
Basic Implementation – Get All Installed Apps
Here’s how to get a list of apps installed on a device:
PackageManager pm = getPackageManager();
List<ApplicationInfo> apps = pm.getInstalledApplications(PackageManager.GET_META_DATA);
for (ApplicationInfo appInfo : apps) {
String packageName = appInfo.packageName;
CharSequence label = pm.getApplicationLabel(appInfo);
Drawable icon = pm.getApplicationIcon(appInfo);
Log.d("InstalledApp", label + " (" + packageName + ")");
}
Explanation:
getInstalledApplications()returns all apps (user + system).pm.getApplicationLabel(appInfo)gets the app name.pm.getApplicationIcon(appInfo)gets the app’s icon.
This is the simplest approach to enumerate installed apps.
Filter for Only Launchable Apps
By default, some entries may be system services or background apps — not user-launchable apps. To filter only launchable apps:
Intent launchIntent = pm.getLaunchIntentForPackage(appInfo.packageName);
if (launchIntent != null) {
// This app has a launcher icon
}
Putting it together:
List<ApplicationInfo> apps = pm.getInstalledApplications(PackageManager.GET_META_DATA);
for (ApplicationInfo appInfo : apps) {
Intent intent = pm.getLaunchIntentForPackage(appInfo.packageName);
if (intent != null) {
String label = pm.getApplicationLabel(appInfo).toString();
Log.d("LaunchableApp", label);
}
}
This ensures you list only apps that the user can launch from the launcher.
Filter System vs User Installed Apps
Often you need to separate system apps (pre-installed by OEM) from user-installed apps. You can use application flags to determine that:
boolean isSystemApp = (appInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Example – Only User Installed Apps
for (ApplicationInfo appInfo : apps) {
if ((appInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
String name = pm.getApplicationLabel(appInfo).toString();
Log.d("UserApp", name);
}
}
This filters out system packages.
Retrieve App Icons Efficiently
Since icons are drawable objects, retrieving them in large lists can be slow. To optimize:
✔ Load icons asynchronously (e.g., on a background thread)
✔ Cache icons with an LRU cache for repeated use
✔ Don’t load icons on main UI thread
Example with asynchronous loading:
new Thread(() -> {
Drawable icon = pm.getApplicationIcon(appInfo);
runOnUiThread(() -> imageView.setImageDrawable(icon));
}).start();
This avoids UI freezes for large app lists.
Advanced: Get Package Info (Version, Permissions)
With getInstalledPackages() you can retrieve more info:
List<PackageInfo> packageList = pm.getInstalledPackages(0);
for (PackageInfo pkg : packageList) {
String name = pkg.packageName;
int versionCode = pkg.versionCode;
String versionName = pkg.versionName;
Log.d("PackageInfo", name + " v" + versionName + " (" + versionCode + ")");
}
This helps if you need version or permission details along with app listings.
Run in Background (Best Practice)
Enumerating installed apps can be slow on devices with many apps. Always run this task off the UI thread:
✔ Use AsyncTask (simple)
✔ Use ExecutorService or ThreadPool
✔ Use Coroutines (Kotlin)
✔ Use LiveData + ViewModel to update UI reactively
Example using AsyncTask:
new AsyncTask<Void, Void, List<ApplicationInfo>>() {
@Override
protected List<ApplicationInfo> doInBackground(Void... voids) {
return pm.getInstalledApplications(PackageManager.GET_META_DATA);
}
@Override
protected void onPostExecute(List<ApplicationInfo> apps) {
// Update UI with listed apps
}
}.execute();
This prevents UI blocking.
Android 11+ and Package Visibility
Starting with Android 11 (API level 30), you must declare package visibility in AndroidManifest.xml if your app queries installed apps:
<queries>
<package android:name="com.example.someapp"/>
<intent>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent>
</queries>
This controls what packages your app can query. Omitting this leads to empty results for getInstalledApplications().
Permissions & Privacy
Unlike older Android versions, you do not need a special permission to list installed apps — but with modern package visibility restrictions you do need to:
✔ Declare visible query intents in manifest
✔ Respect user privacy and not store unnecessary app data
Avoid over-broad visibility permissions — specify only what you truly need.
Displaying Installed Apps in a UI
Typical usage is displaying apps in a RecyclerView. A simple pattern:
- Use
RecyclerView + Adapter - Use Layout with
ImageView(icon) +TextView(app name) - Load icon and label asynchronously
- Bind results into the UI
For example:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="@+id/appIcon"
android:layout_width="48dp"
android:layout_height="48dp"/>
<TextView
android:id="@+id/appName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
Then in adapter:
holder.appName.setText(pm.getApplicationLabel(appInfo));
holder.appIcon.setImageDrawable(pm.getApplicationIcon(appInfo));
Best Practices (Senior Engineering Insight)
✔ Always perform app list queries off the UI thread
✔ Filter out system apps if not relevant
✔ Respect Android 11+ package visibility behavior
✔ Cache icons/text to avoid repeated expensive operations
✔ Avoid unnecessary queries on every activity resume
These practices ensure performant and user-friendly UI.
Summary
Retrieving the installed apps list in Android is straightforward with PackageManager using:
getInstalledApplications()for raw app infogetLaunchIntentForPackage()to filter launchables- Optional package visibility declarations on Android 11+
By combining background execution with efficient UI binding, you can build launchers, app explorers, or analytics dashboards that feel fast and responsive.


