screen_pinning 1.0.0
screen_pinning: ^1.0.0 copied to clipboard
Flutter plugin for Android screen pinning, kiosk mode, and lock task mode. Supports both managed (device owner/admin) and unmanaged devices. Uses native Android app pinning and lock task features for [...]
Screen Pinning Plugin - Flutter Kiosk Mode & Lock Task Mode #
A powerful Flutter plugin for Android screen pinning, kiosk mode, and lock task mode. Perfect for creating dedicated device apps, kiosks, digital signage, point-of-sale (POS) systems, and restricted-access applications. Pin your Flutter app to the screen and prevent users from navigating away.
Features #
✨ Screen Pinning - Pin your app to the screen (Android Lock Task mode)
📡 Real-time Monitoring - Event stream for status changes
🔒 Device Owner Detection - Check if app has full lock task capabilities
🎯 Simple API - Easy-to-use helper methods
⚡ Minimal Dependencies - Uses wakelock_plus only for keep screen on feature
🔧 Customizable - Full control over UI and behavior
🏢 Dual Mode Support - Works with both managed devices (full admin) and unmanaged devices (user confirmation)
📱 Native Android APIs - Uses Android's built-in app pinning and lock task mode features
💡 Keep Screen On - Prevent device from sleeping with built-in wakelock support
🖥️ Immersive Mode - Hide system UI (status bar, navigation bar) for true fullscreen
🔄 Orientation Lock - Lock device orientation for consistent UX
📸 Screenshot Prevention - Optional screenshot blocking for secure environments
⚙️ Centralized Configuration - Single config object for all features
How It Works #
This plugin leverages Android's native App Pinning and Lock Task Mode capabilities:
🔓 Unmanaged Devices (Standard Mode) #
- Uses Android App Pinning (available on all Android 5.0+ devices)
- Requires user confirmation via system dialog
- User can exit by holding Back + Recent Apps buttons
- Perfect for: Public kiosks, retail displays, temporary restrictions
- No device admin/MDM setup required
🔒 Managed Devices (Full Kiosk Mode) #
- Uses Lock Task Mode with Device Owner/Admin privileges
- No user confirmation required - automatically locks
- User cannot exit without app permission
- Perfect for: Corporate deployments, dedicated devices, MDM-managed tablets
- Requires device owner setup (ADB or MDM)
The plugin automatically detects device capabilities and uses the appropriate mode!
Use Cases #
🏪 Kiosk Applications - Retail displays, information kiosks, self-service terminals
🏥 Healthcare Apps - Patient check-in, medical device apps, hospital kiosks
🎓 Educational Apps - Student testing apps, exam mode, classroom devices
🍔 Point of Sale (POS) - Restaurant ordering, payment terminals, checkout systems
📺 Digital Signage - Public displays, menu boards, information screens
🏭 Industrial Apps - Factory floor tablets, warehouse management, inventory systems
🚗 Vehicle Apps - In-car tablets, fleet management, driver apps
👶 Parental Control - Child-safe devices, restricted access apps
🏢 Corporate Devices - Dedicated employee apps, single-purpose devices
Platform Support #
| Android | iOS |
|---|---|
| ✅ | ❌ |
Note: Screen pinning is an Android-only feature. iOS has Guided Access but is not currently supported by this plugin.
Installation #
Add this to your pubspec.yaml:
dependencies:
screen_pinning: ^1.0.0
Or install via command:
flutter pub add screen_pinning
Permissions #
The plugin will automatically add required permissions to your Android manifest. No manual configuration needed!
Usage #
Basic Usage #
import 'package:screen_pinning_plugin/screen_pinning_plugin.dart';
// Initialize the helper
final helper = ScreenPinningHelper();
await helper.initialize();
// Start screen pinning
await helper.startScreenPinning();
// Stop screen pinning
await helper.stopScreenPinning();
// Check if currently pinned
if (helper.isScreenPinningEnabled) {
print('Screen is pinned!');
}
Advanced Usage with Configuration #
import 'package:screen_pinning_plugin/screen_pinning_plugin.dart';
// Create configuration
final config = ScreenPinningConfig(
keepScreenOn: true, // Prevent device from sleeping
immersiveMode: true, // Hide system UI (status bar, navigation)
autoStart: true, // Auto-start screen pinning
preventScreenshots: false, // Prevent screenshots (optional)
preferredOrientations: [ // Lock orientation (optional)
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown,
],
);
// Initialize with configuration
final helper = ScreenPinningHelper();
await helper.initialize(config);
// Check status
print('Keep screen on: ${helper.isKeepScreenOnEnabled}');
print('Immersive mode: ${helper.isImmersiveModeEnabled}');
print('Screen pinned: ${helper.isPinned}');
Individual Feature Control #
final helper = ScreenPinningHelper();
// Control keep screen on independently
await helper.enableKeepScreenOn();
await helper.disableKeepScreenOn();
// Control immersive mode independently
helper.enableImmersiveMode();
helper.disableImmersiveMode();
// Update configuration dynamically
final newConfig = ScreenPinningConfig(
keepScreenOn: false,
immersiveMode: true,
);
await helper.updateConfig(newConfig);
With User Confirmation Dialog #
// Show confirmation dialog and start
final confirmed = await ScreenPinningHelper.showConfirmationDialog(context);
if (confirmed) {
await ScreenPinningHelper().startScreenPinning();
}
Watch Status Changes #
// Get real-time updates
ScreenPinningChannel().watchScreenPinningStatus().listen((isPinned) {
print('Screen pinning status: $isPinned');
setState(() {}); // Update UI
});
Check Device Capabilities #
// Check if app is device owner (for full lock task mode)
final isOwner = await ScreenPinningHelper().isDeviceOwner();
if (isOwner) {
print('Full lock task mode available');
} else {
print('Using screen pinning mode (user can exit)');
}
// Check if supported
final isSupported = await ScreenPinningHelper().isSupported();
Complete Example #
import 'package:flutter/material.dart';
import 'package:screen_pinning_plugin/screen_pinning_plugin.dart';
class MyScreen extends StatefulWidget {
@override
State<MyScreen> createState() => _MyScreenState();
}
class _MyScreenState extends State<MyScreen> {
final helper = ScreenPinningHelper();
@override
void initState() {
super.initState();
helper.initialize();
}
Future<void> toggleScreenPinning() async {
if (helper.isScreenPinningEnabled) {
await helper.stopScreenPinning();
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Screen pinning disabled')),
);
} else {
final confirmed = await ScreenPinningHelper.showConfirmationDialog(context);
if (confirmed) {
await helper.startScreenPinning();
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Screen pinning enabled')),
);
}
}
setState(() {});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Screen Pinning Demo'),
actions: [
IconButton(
icon: Icon(
helper.isScreenPinningEnabled ? Icons.lock : Icons.lock_open,
),
onPressed: toggleScreenPinning,
),
],
),
body: Center(
child: Text(
helper.isScreenPinningEnabled
? 'Screen is Pinned'
: 'Screen is Not Pinned',
style: Theme.of(context).textTheme.headlineMedium,
),
),
);
}
}
How It Works #
Not Device Owner (Default) #
When your app is NOT a device owner:
- ✅ Screen pinning mode is used
- ✅ System shows confirmation dialog to user
- ✅ User can exit by pressing Back + Recent Apps buttons simultaneously
- ⚠️ Not a complete "lock" - determined users can exit
Device Owner Mode #
When your app IS a device owner:
- ✅ True lock task mode (no user exit)
- ✅ No confirmation dialog required
- ✅ Only your app or whitelisted apps can run
- ✅ User cannot exit without app permission
Making Your App a Device Owner #
⚠️ Requires factory reset!
# Factory reset device
# Skip Google account during setup
# Enable developer mode and USB debugging
# Run this command:
adb shell dpm set-device-owner com.yourpackage/.YourDeviceAdminReceiver
Note: This requires implementing a DeviceAdminReceiver in your app.
API Reference #
ScreenPinningHelper #
Main helper class for screen pinning operations.
Methods
initialize()- Initialize the plugin and start monitoringstartScreenPinning()- Start screen pinning modestopScreenPinning()- Stop screen pinning modeisSupported()- Check if device supports screen pinningisDeviceOwner()- Check if app is device owner
Properties
isScreenPinningEnabled-bool- Current pinning statusisPinned-bool- Alias for isScreenPinningEnabled
Static Methods
showConfirmationDialog(BuildContext)- Show default confirmation dialog
ScreenPinningChannel #
Low-level platform channel interface.
Methods
startScreenPinning()- Direct channel call to start pinningstopScreenPinning()- Direct channel call to stop pinningisScreenPinned()- Check current statusisScreenPinningSupported()- Check device supportwatchScreenPinningStatus()- Stream of status changesisDeviceOwner()- Check device owner status
Testing #
Testing on Unmanaged Devices (Standard Users) #
- Run your app on an Android device (no special setup needed)
- Call
startScreenPinning() - Confirm the system security dialog - user must accept
- Try pressing Home button → Shows "Screen pinned" message
- Try pressing Recent Apps → Shows "Screen pinned" message
- Exit by holding Back + Recent Apps together for 2-3 seconds
Testing on Managed Devices (Device Owner) #
- Set your app as device owner via ADB:
adb shell dpm set-device-owner com.yourapp/.DeviceAdminReceiver - Call
startScreenPinning()- No dialog shown, immediately locks - User cannot exit without app permission
- Call
stopScreenPinning()to unlock programmatically
Troubleshooting #
Screen pinning doesn't start / Kiosk mode not working #
- Ensure user confirmed the system dialog
- Check Android logs:
flutter logsoradb logcat - Verify device is API 23+ (Android 6.0+)
Flutter kiosk mode not locking properly #
- User must confirm the system security dialog
- If device owner, pinning is automatic without dialog
- Check if REORDER_TASKS permission is in manifest
How to exit screen pinning / kiosk mode #
- Hold Back + Recent Apps buttons together for 2-3 seconds
- Or call
stopScreenPinning()programmatically
Difference between screen pinning and kiosk mode #
- Screen Pinning: User mode - requires confirmation, user can exit
- Kiosk/Lock Task Mode: Device owner mode - fully locked, no exit without code
Can't exit screen pinning #
- Hold Back + Recent Apps buttons together for 2-3 seconds
- Or use the in-app stop method
- If stuck: Restart device
Want full lock task mode? #
- Make your app a device owner (see instructions above)
- Implement
DeviceAdminReceiver - Factory reset device and configure via ADB
Technical Details #
Architecture #
Flutter (Dart)
↓
ScreenPinningHelper (High-level API)
↓
ScreenPinningChannel (Platform Channel)
↓
MethodChannel + EventChannel
↓
Native Android (Kotlin)
↓
Android Lock Task API
Platform Channels #
- Method Channel:
com.vaib.screenpinning/methods - Event Channel:
com.vaib.screenpinning/events
Android Implementation #
Uses Android's Lock Task Mode API:
Activity.startLockTask()Activity.stopLockTask()ActivityManager.getLockTaskModeState()
Contributing #
Contributions are welcome! Please feel free to submit a Pull Request.
Development Setup #
# Clone the repository
git clone https://github.com/yourusername/screen_pinning_plugin.git
# Get dependencies
cd screen_pinning_plugin
flutter pub get
# Run example
cd example
flutter run
License #
This project is licensed under the MIT License - see the LICENSE file for details.
Support #
If you find this plugin useful, please consider:
- ⭐ Starring the repository
- 🐛 Reporting issues
- 💡 Suggesting new features
- 📖 Improving documentation
Changelog #
See CHANGELOG.md for version history.
Author #
Created by Vaibhav Nayak
Keywords #
flutter screen pinning, flutter kiosk mode, flutter lock task mode, android kiosk flutter, flutter dedicated device, flutter pin screen, flutter task lock, android screen pinning flutter, flutter kiosk app, flutter single app mode, flutter app pinning, flutter immersive mode, flutter kiosk browser, flutter restricted access, flutter device owner, flutter full screen lock
Acknowledgments #
- Flutter team for the excellent platform channel documentation
- Android documentation for Lock Task mode details