flutter_android_enterprise 0.1.1 copy "flutter_android_enterprise: ^0.1.1" to clipboard
flutter_android_enterprise: ^0.1.1 copied to clipboard

PlatformAndroid

Android Enterprise and managed-device APIs for Flutter — managed configuration, kiosk mode, compliance reporting, and profile awareness.

example/lib/main.dart

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_android_enterprise/flutter_android_enterprise.dart';

void main() {
  runApp(const EnterpriseExampleApp());
}

class EnterpriseExampleApp extends StatelessWidget {
  const EnterpriseExampleApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Android Enterprise',
      theme: ThemeData(colorSchemeSeed: Colors.blue, useMaterial3: true),
      home: const EnterpriseDashboard(),
    );
  }
}

class EnterpriseDashboard extends StatefulWidget {
  const EnterpriseDashboard({super.key});

  @override
  State<EnterpriseDashboard> createState() => _EnterpriseDashboardState();
}

class _EnterpriseDashboardState extends State<EnterpriseDashboard> {
  final EnterpriseManager _enterprise = EnterpriseManager();
  StreamSubscription<Map<String, String>>? _restrictionsSubscription;

  String _managedConfigurations = 'Loading...';
  String _lastRestrictionsEvent = 'Waiting for managed config updates...';
  String _status = 'Ready';
  String _userProfiles = 'Not loaded';
  bool _deviceManaged = false;
  bool _managedProfile = false;
  bool _deviceOwnerActive = false;

  @override
  void initState() {
    super.initState();
    _restrictionsSubscription = _enterprise.restrictionsChanged.listen((
      config,
    ) {
      setState(() {
        _lastRestrictionsEvent = config.isEmpty
            ? 'No managed configuration received yet.'
            : config.toString();
      });
    });
    _loadTier1State();
  }

  Future<void> _loadTier1State() async {
    try {
      final deviceManaged = await _enterprise.isDeviceManaged();
      final managedProfile = await _enterprise.isManagedProfile();
      final deviceOwnerActive = await _enterprise.isDeviceOwnerActive();
      final configurations = await _enterprise.getManagedConfig();

      if (!mounted) {
        return;
      }

      setState(() {
        _deviceManaged = deviceManaged;
        _managedProfile = managedProfile;
        _deviceOwnerActive = deviceOwnerActive;
        _managedConfigurations = configurations.raw.isEmpty
            ? 'No app restrictions are set.'
            : configurations.raw.toString();
        _status = 'Tier 1 checks completed.';
      });
    } on EnterpriseChannelException catch (error) {
      if (!mounted) {
        return;
      }
      setState(() {
        _status = 'Enterprise channel error (${error.code}): ${error.message}';
      });
    } on PlatformException catch (error) {
      if (!mounted) {
        return;
      }
      setState(() {
        _status =
            'Failed to load enterprise state: ${error.message ?? error.code}';
      });
    }
  }

  Future<void> _reportCompliance() async {
    await _enterprise.reportComplianceState(
      ComplianceState.compliant,
      'All local checks passed in the example app.',
      data: const <String, String>{'source': 'example'},
    );
    if (!mounted) {
      return;
    }
    setState(() {
      _status = 'Reported compliant state to the EMM channel.';
    });
  }

  Future<void> _enterKioskMode() async {
    await _enterprise.startKioskMode(
      allowedPackages: const <String>[
        'com.example.flutter_android_enterprise_example',
      ],
    );
    if (!mounted) {
      return;
    }
    setState(() {
      _status = 'Kiosk mode requested.';
    });
  }

  Future<void> _leaveKioskMode() async {
    await _enterprise.stopKioskMode();
    if (!mounted) {
      return;
    }
    setState(() {
      _status = 'Kiosk mode stopped.';
    });
  }

  Future<void> _checkPrivateSpacePolicy() async {
    try {
      final restricted = await _enterprise.isPrivateSpaceRestricted();
      if (!mounted) {
        return;
      }
      setState(() {
        _status =
            'Private Space creation is ${restricted ? 'blocked' : 'allowed'}.';
      });
    } on RequiresDeviceOwnerException {
      if (!mounted) {
        return;
      }
      setState(() {
        _status = 'Private Space policy requires Device Owner provisioning.';
      });
    } on NotSupportedBelowApiException catch (error) {
      if (!mounted) {
        return;
      }
      setState(() {
        _status =
            'Private Space policy requires Android API ${error.requiredApi}+.';
      });
    }
  }

  Future<void> _loadUserProfiles() async {
    try {
      final profiles = await _enterprise.getUserProfiles();
      if (!mounted) {
        return;
      }
      setState(() {
        _userProfiles = profiles.isEmpty
            ? 'No profiles returned.'
            : profiles
                  .map(
                    (profile) =>
                        '${profile.userType} (running=${profile.isRunning})',
                  )
                  .join(', ');
        _status = 'Loaded ${profiles.length} user profile(s).';
      });
    } on RequiresDeviceOwnerException catch (error) {
      if (!mounted) {
        return;
      }
      setState(() {
        _status = error.message;
      });
    } on EnterpriseChannelException catch (error) {
      if (!mounted) {
        return;
      }
      setState(() {
        _status = 'Failed to load profiles: ${error.message ?? error.code}';
      });
    }
  }

  Future<void> _blockPrivateSpace() async {
    await _setPrivateSpaceAllowed(false);
  }

  Future<void> _allowPrivateSpace() async {
    await _setPrivateSpaceAllowed(true);
  }

  Future<void> _setPrivateSpaceAllowed(bool allowed) async {
    try {
      await _enterprise.setPrivateSpaceAllowed(allowed);
      if (!mounted) {
        return;
      }
      setState(() {
        _status =
            'Private Space creation is now ${allowed ? 'allowed' : 'blocked'}.';
      });
    } on RequiresDeviceOwnerException catch (error) {
      if (!mounted) {
        return;
      }
      setState(() {
        _status = error.message;
      });
    } on NotSupportedBelowApiException catch (error) {
      if (!mounted) {
        return;
      }
      setState(() {
        _status =
            'Private Space policy requires Android API ${error.requiredApi}+.';
      });
    } on EnterpriseChannelException catch (error) {
      if (!mounted) {
        return;
      }
      setState(() {
        _status = 'Private Space policy failed: ${error.message ?? error.code}';
      });
    }
  }

  @override
  void dispose() {
    _restrictionsSubscription?.cancel();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Flutter Android Enterprise')),
      body: ListView(
        padding: const EdgeInsets.all(16),
        children: <Widget>[
          const Text(
            'Works without provisioning',
            style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
          ),
          const SizedBox(height: 12),
          _InfoTile(label: 'Device managed', value: _deviceManaged.toString()),
          _InfoTile(
            label: 'Managed profile',
            value: _managedProfile.toString(),
          ),
          _InfoTile(
            label: 'Device owner active',
            value: _deviceOwnerActive.toString(),
          ),
          _InfoTile(label: 'Managed config', value: _managedConfigurations),
          _InfoTile(
            label: 'Restrictions stream',
            value: _lastRestrictionsEvent,
          ),
          const SizedBox(height: 16),
          Wrap(
            spacing: 12,
            runSpacing: 12,
            children: <Widget>[
              FilledButton(
                onPressed: _loadTier1State,
                child: const Text('Refresh'),
              ),
              FilledButton(
                onPressed: _reportCompliance,
                child: const Text('Report compliance'),
              ),
            ],
          ),
          const SizedBox(height: 24),
          const Text(
            'Requires Device Owner',
            style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
          ),
          const SizedBox(height: 12),
          const Text(
            'Provision with adb shell dpm set-device-owner '
            'com.example.flutter_android_enterprise_example/'
            'com.example.flutter_android_enterprise.DeviceAdminReceiverImpl',
          ),
          const SizedBox(height: 12),
          _InfoTile(label: 'User profiles', value: _userProfiles),
          const SizedBox(height: 12),
          Wrap(
            spacing: 12,
            runSpacing: 12,
            children: <Widget>[
              FilledButton(
                onPressed: _enterKioskMode,
                child: const Text('Start kiosk mode'),
              ),
              FilledButton(
                onPressed: _leaveKioskMode,
                child: const Text('Stop kiosk mode'),
              ),
              FilledButton(
                onPressed: _checkPrivateSpacePolicy,
                child: const Text('Check Private Space policy'),
              ),
              FilledButton(
                onPressed: _loadUserProfiles,
                child: const Text('List user profiles'),
              ),
              FilledButton(
                onPressed: _blockPrivateSpace,
                child: const Text('Block Private Space'),
              ),
              FilledButton(
                onPressed: _allowPrivateSpace,
                child: const Text('Allow Private Space'),
              ),
            ],
          ),
          const SizedBox(height: 24),
          Text(_status, style: Theme.of(context).textTheme.bodyLarge),
        ],
      ),
    );
  }
}

class _InfoTile extends StatelessWidget {
  const _InfoTile({required this.label, required this.value});

  final String label;
  final String value;

  @override
  Widget build(BuildContext context) {
    return Card(
      child: ListTile(title: Text(label), subtitle: Text(value)),
    );
  }
}
0
likes
150
points
27
downloads

Documentation

API reference

Publisher

verified publisheriamsathish.dev

Weekly Downloads

Android Enterprise and managed-device APIs for Flutter — managed configuration, kiosk mode, compliance reporting, and profile awareness.

Repository (GitHub)
View/report issues

Topics

#enterprise #mdm #devicepolicy #android #emm

License

MIT (license)

Dependencies

flutter, flutter_android_enterprise_android, flutter_android_enterprise_platform_interface

More

Packages that depend on flutter_android_enterprise

Packages that implement flutter_android_enterprise