Warning this is a WIP.
A plugin to list installed applications on an Android device (iOS is not supported). You can also listen to app changes (install, uninstall and update).
Check the latest version on pub.dev.
dependencies:
device_packages: <latest-version>
Import:
import 'package:device_packages/device_packages.dart';
Since Android 11 (API level 30), most user-installed apps are not visible by default. In your manifest, you must statically declare which apps you are going to get info about, as in the following:
<manifest>
<queries>
<!-- Explicit apps you know in advance about: -->
<package android:name="com.example.this.app"/>
<package android:name="com.example.this.other.app"/>
</queries>
...
</manifest>
You also must include these permissions:
<!-- To request install an apk -->
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<!-- To request uninstall a package -->
<uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES" />
<!-- To get all installed apps -->
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
To list installed packages on the device:
// Recommended if you are displaying the apps in list view.
// You can use the stream to lazy-load and improve the UI/UX.
Stream<PackageInfo> packagesStream = await DevicePackages.getInstalledPackagesAsStream();
// Recommended if you are performing a background task
// and don't mind taking several seconds to load all pakckages.
List<PackageInfo> packages = await DevicePackages.getInstalledPackages();
You can filter system apps if necessary.
Note: The list of apps is not ordered! You have to do it yourself.
On android, an openable package means you can launch the application.
To list only the apps with launch intents, simply use the onlyOpenablePackages: true
attribute.
// Returns a list of only those apps that have launch intent (for Android)
// This is also available for [getInstalledPackages].
Stream<PackageInfo> packagesStream = DevicePackages.getInstalledPackagesAsStream(
onlyOpenablePackages: true,
includeSystemApps: true
)
To get a specific application info, provide its package id:
PackageInfo package = await DevicePackages.getPackage('io.alexrintt.kanade');
To check if an app is installed (via its package id):
bool isInstalled = await DevicePackages.isPackageInstalled('io.alexrintt.kanade');
To open a package (on Android the package must have a launch Intent).
DevicePackages.openPackage('io.alexrintt.kanade');
To open package settings:
DevicePackages.openPackageSettings('io.alexrintt.kanade');
To open the screen to uninstall a package:
- Add this permission to the
AndroidManifest.xml
file:
<!-- Remember to add the permission -->
<uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES" />
- Call this method:
DevicePackages.uninstallPackage('io.alexrintt.kanade');
To open the screen to install a package:
- Add this permission to the
AndroidManifest.xml
file:
<!-- Remember to add the permission -->
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
- Call this method:
// Android: If you are working with SAF (or URIs in general).
DevicePackages.installPackage(installerUri: Uri.parse('...'));
// Android: If you are working with old SDKs or managing your files by MANAGE_EXTERNAL_STORAGE (or File APIs in general).
DevicePackages.installPackage(installerPath: '/storage/emulated/0/Downloads/app.apk');
DevicePackages.installPackage(installerFile: File('/storage/emulated/0/Downloads/app.apk'));
When calling getInstalledPackages()
or getPackage()
methods, you can also ask for the icon.
To display the image, just call:
Image.memory(app.icon);
To listen to package events on the device (installation, uninstallation, update):
Stream<ApplicationEvent> apps = await DevicePackages.listenToAppsChanges();
If you only need events for a single app, just use the Stream
API, like so:
DevicePackages.listenToPackageEvents().where(
(PackageEvent event) => event.packageId == 'io.alexrintt.kanade'
)
To get package details from the event, use the DevicePackages.getPackage
API:
DevicePackages.listenToPackageEvents().liste(
(PackageEvent event) async {
if (!await DevicePackages.isPackageInstalled(event.packageId)) {
// You do not have access to package info since
// the package was uninstalled.
// Although you can retrive from your cache (if any).
} else {
final PackageInfo package =
await DevicePackages.getPackage(event.packageId);
print('Action: ${event.action}');
print('Package name: ${package.name}');
print('Package id: ${package.id}');
print('Is system package: ${package.isSystemPackage}');
// Apk file path on Android.
print('Package installerPath: ${package.installerPath}');
}
},
)
This plugin was initially a fork of device_apps
https://github.com/g123k/flutter_plugin_device_apps, but since the plugin author is no longer maintaining the project (resolving issues or merging pull requests) I did decide to create this plugin, make some improvements and add some features:
- Java to Kotlin fully migration.
- List installed apps in lazy-load mode g123k/flutter_plugin_device_apps#90.
- Install packages, on Android this means being able to start a new activity to install an apk file/uri.
- Fixed unresolved bug on
listenToPackageEvents
g123k/flutter_plugin_device_apps#97. - Support for getting the current Android launcher package g123k/flutter_plugin_device_apps#82.
- Getting package info from intaller file/uri, on Android this means generating the
PackageInfo
from an apk file g123k/flutter_plugin_device_apps#92. - Sign-in apk files https://stackoverflow.com/questions/10630796/signing-apk-files-programmatically-in-java.