installed_apps_manager
A strictly focused, high-performance Flutter plugin for managing installed applications on Android devices.
Designed with open-source scalability in mind, it safely handles large application counts (1000+ apps) by utilizing Native Caching, Pagination, and Lazy Icon Loading.
Features
- Fetch Installed Apps: Retrieve all user and system apps.
- Robust Pagination: Fetch applications in chunks to prevent
TransactionTooLargeExceptionand UI stutter on devices with hundreds of apps. - Lazy Icon Loading: Load app icons dynamically on-demand using
AppIconImageProvider. - App Actions: Launch apps, open app settings, and uninstall applications directly from Flutter.
- Extract APKs: Extract the raw APK (or split
.apks) of any installed app to the user's Downloads folder. - Save Icons: Save the high-resolution icon of any app directly to the device's Pictures gallery.
Permissions
To fetch the list of installed applications on Android 11 (API level 30) and above, you must declare the QUERY_ALL_PACKAGES permission in your android/app/src/main/AndroidManifest.xml:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.app">
<!-- Required to query ALL installed applications -->
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>
<application>
...
</application>
</manifest>
Note: If you are publishing to the Google Play Store, you will need to justify the use of this permission in your Play Console declarations.
Safe Alternative: Targeted Intent Fetching
If you do not want to declare QUERY_ALL_PACKAGES and risk Play Store rejection, you can fetch specific apps by providing an intent action:
// Safely fetch only apps that appear in the device launcher
List<AppInfo> apps = await InstalledAppsManager.getAppsWithIntent('android.intent.action.MAIN');
Usage
1. Fetching Apps (Paginated - Recommended)
To avoid freezing the UI when fetching a large list of applications, use the paginated method:
import 'package:installed_apps_manager/installed_apps_manager.dart';
// Fetch the first 50 apps, searching for "whatsapp", sorted by base APK size
Page<AppInfo> page = await InstalledAppsManager.getInstalledAppsPaginated(
limit: 50,
offset: 0,
includeSystemApps: false,
searchQuery: 'whatsapp',
sortBy: AppSortBy.size,
sortOrder: SortOrder.descending,
);
List<AppInfo> apps = page.items;
bool isLast = page.isLastPage;
2. Rendering Lazy Icons
To render the icon of an app, use the AppIconImageProvider. This fetches the icon from the native Android side only when the widget is rendered on the screen.
CircleAvatar(
backgroundImage: AppIconImageProvider(app.packageName),
)
3. Application Actions
All application actions throw strongly-typed exceptions (AppLaunchException, AppUninstallException, etc.) instead of returning weak booleans. This allows you to handle failures gracefully in your UI.
try {
// Launch the app
await InstalledAppsManager.openApp('com.whatsapp');
// Open App Settings
await InstalledAppsManager.openSettingsScreen('com.whatsapp');
// Prompt Uninstall
await InstalledAppsManager.uninstallApp('com.whatsapp');
} on InstalledAppsManagerException catch (e) {
print('Action failed: ${e.message}');
}
4. Extracting APKs & Icons
Extract the base APK or split APKs to the user's Downloads folder:
String? path = await InstalledAppsManager.extractApk('com.whatsapp', 'WhatsApp');
print('Saved to: $path');
Save the app's icon to the gallery:
String? path = await InstalledAppsManager.saveAppIcon('com.whatsapp', 'WhatsApp');
print('Saved to: $path');