app_limiter 0.1.0
app_limiter: ^0.1.0 copied to clipboard
A Flutter plugin to limit screen time or block apps on Android and iOS
App Limiter Plugin #
A Flutter plugin that allows developers to limit app usage and screen time on Android and iOS by blocking/unblocking apps and managing screen time permissions.
๐ง Features #
- โ Block/unblock individual apps or every user app on Android
- โ Pick, block and unblock apps and categories on iOS (Screen Time API)
- โ Query blocking state and permission/authorization status
- โ Blocking survives reboots and app updates on Android
- โ Live event stream for blocking, selection and permission changes
- โ Optional Android enterprise (device owner) package suspension
๐ง Available Methods #
// Common
Future<String?> getPlatformVersion()
Future<Map<String, dynamic>> getPlatformCapabilities()
Stream<Map<String, dynamic>> events
// Android
Future<bool> isAndroidPermissionAllowed()
Future<void> requestAndroidPermission()
Future<void> blockAndroidApp({required String packageName})
Future<void> unblockAndroidApp({required String packageName})
Future<void> blockAllAndroidApps()
Future<void> unblockAllAndroidApps()
Future<List<String>> getBlockedAndroidApps()
Future<bool> isAndroidBlockingActive()
Future<void> setAndroidEnterpriseModeEnabled({required bool enabled})
Future<bool> isAndroidEnterpriseModeEnabled()
// iOS
Future<bool> requestIosPermission()
Future<String> getIOSAuthorizationStatus() // notDetermined | denied | approved
Future<bool> showIOSAppPicker() // selection only, true if confirmed
Future<void> blockIOSApps() // shield the saved selection
Future<void> unblockIOSApps()
Future<bool> isIOSAppsBlocked()
Future<void> selectAndConfigureIosAppRestrictions({Map<String, dynamic>? schedule}) // pick + block in one step
Future<void> configureIosSchedule(Map<String, dynamic> schedule)
Android-only methods throw MissingPluginException on iOS and vice versa.
Deprecated compatibility methods still available:
blockAndUnblockIOSApp() // -> selectAndConfigureIosAppRestrictions()
blocAndroidApp() // -> blockAllAndroidApps()
unblocAndroidApp() // -> unblockAllAndroidApps()
Errors #
Failures are reported as PlatformException with these codes:
| Code | Meaning |
|---|---|
PERMISSION_DENIED |
Android overlay/usage access or iOS Screen Time access missing |
NO_SELECTION |
blockIOSApps() called before choosing apps |
INVALID_ARGUMENT |
Empty Android package name |
NO_VIEW_CONTROLLER |
iOS picker could not be presented |
ENTERPRISE_ACTION_FAILED / ENTERPRISE_NOT_AVAILABLE |
Device owner operations failed |
๐ชช Setup #
Minimum supported versions: Android 5.0 (API 21), iOS 16.0 for blocking (the pod builds on iOS 15).
๐ข Android #
The plugin's manifest declares every permission, the foreground service (type
specialUse, required on Android 14+) and the receivers; nothing needs to be added
to your app's manifest.
At runtime, call requestAndroidPermission() until isAndroidPermissionAllowed()
returns true. Each call opens the settings screen for the next missing permission:
display over other apps, then usage access, then notifications (Android 13+).
Google Play notes:
QUERY_ALL_PACKAGES,PACKAGE_USAGE_STATSand thespecialUseforeground service need a declaration in the Play Console explaining the app-blocking use.
Limitations:
- Settings, the permission controller and the package installer hide third-party overlays. When they are blocked, the user is sent to the home screen instead.
- The host app, the home launcher and System UI are never blocked.
blockAllAndroidApps()blocks every app with a launcher icon, including preinstalled ones such as YouTube or Gmail, but keeps the phone dialer and Settings usable. Block Settings explicitly withblockAndroidAppif needed.
๐ฃ iOS #
- In Xcode, add the Family Controls capability to the Runner target. This
adds
com.apple.developer.family-controlsto your.entitlementsfile (entitlements do not go inInfo.plist). - Distribution builds need the Family Controls (Distribution) entitlement requested from Apple.
- Schedules set with
configureIosScheduleonly take effect if your app ships aDeviceActivityMonitorextension that applies shields on interval events.
Both Swift Package Manager and CocoaPods are supported.
๐ฑ Platform Support #
| Platform | Support |
|---|---|
| Android | โ |
| iOS | โ |
| Web | โ |
๐งช Example Usage #
final plugin = AppLimiter();
// Android
if (!await plugin.isAndroidPermissionAllowed()) {
await plugin.requestAndroidPermission();
}
await plugin.blockAndroidApp(packageName: 'com.example.target');
await plugin.unblockAndroidApp(packageName: 'com.example.target');
await plugin.blockAllAndroidApps();
await plugin.unblockAllAndroidApps();
// Optional enterprise mode (requires Android device-owner setup)
final capabilities = await plugin.getPlatformCapabilities();
if (capabilities['enterpriseCapable'] == true) {
await plugin.setAndroidEnterpriseModeEnabled(enabled: true);
}
// iOS
if (await plugin.requestIosPermission()) {
if (await plugin.showIOSAppPicker()) {
await plugin.blockIOSApps();
}
}
await plugin.unblockIOSApps();
plugin.events.listen((event) {
// event['name'] is one of: android_blocking_state_changed,
// android_blocking_stopped, ios_blocking_state_changed, ios_permission_status,
// ios_selection_updated, ios_schedule_configured, ios_picker_presented
print(event);
});
Check the full example in the /example directory.
๐งช Testing #
flutter test # Dart unit tests
cd example && flutter test # example widget tests
cd example/android && ./gradlew :app_limiter:testDebugUnitTest # Kotlin unit tests
cd example && flutter test integration_test # on a device or emulator
To cover the Android blocking path in the integration tests, grant the
permissions first (flutter test ... --no-uninstall keeps them between runs):
adb shell appops set com.example.app_limiter_example SYSTEM_ALERT_WINDOW allow
adb shell appops set com.example.app_limiter_example GET_USAGE_STATS allow
๐ Issues #
Please report issues here: https://github.com/connect-rizwan/AppLimiter-Plugin-Flutetr/issues