import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:dchs_flutter_beacon/dchs_flutter_beacon.dart'; import 'beacon_channel.dart'; class BeaconPermissions { static Future requestPermissions() async { try { // On Android, check native first (fast path) if (Platform.isAndroid) { final hasPerms = await BeaconChannel.hasPermissions(); if (hasPerms) { debugPrint('[BeaconPermissions] Native check: granted'); return true; } debugPrint('[BeaconPermissions] Native check: not granted, requesting...'); } // Request via Flutter plugin (slow but shows system dialogs) final locationStatus = await Permission.locationWhenInUse.request(); debugPrint('[BeaconPermissions] Location: $locationStatus'); bool bluetoothGranted = true; if (Platform.isIOS) { final bluetoothStatus = await Permission.bluetooth.request(); debugPrint('[BeaconPermissions] Bluetooth (iOS): $bluetoothStatus'); bluetoothGranted = bluetoothStatus.isGranted; } else { final bluetoothScan = await Permission.bluetoothScan.request(); final bluetoothConnect = await Permission.bluetoothConnect.request(); debugPrint('[BeaconPermissions] BluetoothScan: $bluetoothScan, BluetoothConnect: $bluetoothConnect'); bluetoothGranted = bluetoothScan.isGranted && bluetoothConnect.isGranted; } final allGranted = locationStatus.isGranted && bluetoothGranted; debugPrint('[BeaconPermissions] All granted: $allGranted'); return allGranted; } catch (e) { debugPrint('[BeaconPermissions] Error: $e'); return false; } } /// Check if Bluetooth is enabled - returns current state without prompting static Future isBluetoothEnabled() async { try { // Use native channel on Android if (Platform.isAndroid) { return await BeaconChannel.isBluetoothEnabled(); } // Use Flutter plugin on iOS final bluetoothState = await flutterBeacon.bluetoothState; return bluetoothState == BluetoothState.stateOn; } catch (e) { debugPrint('[BeaconPermissions] Error checking Bluetooth state: $e'); return false; } } /// Request to enable Bluetooth via system prompt (Android only) static Future requestEnableBluetooth() async { try { debugPrint('[BeaconPermissions] Requesting Bluetooth enable...'); // This opens a system dialog on Android asking user to turn on Bluetooth final result = await flutterBeacon.requestAuthorization; debugPrint('[BeaconPermissions] Request authorization result: $result'); return result; } catch (e) { debugPrint('[BeaconPermissions] Error requesting Bluetooth enable: $e'); return false; } } /// Open Bluetooth settings static Future openBluetoothSettings() async { try { debugPrint('[BeaconPermissions] Opening Bluetooth settings...'); final opened = await flutterBeacon.openBluetoothSettings; debugPrint('[BeaconPermissions] Open Bluetooth settings result: $opened'); return opened; } catch (e) { debugPrint('[BeaconPermissions] Error opening Bluetooth settings: $e'); return false; } } /// Check if Bluetooth is enabled, and try to enable it if not static Future ensureBluetoothEnabled() async { try { // Check current Bluetooth state final isOn = await isBluetoothEnabled(); debugPrint('[BeaconPermissions] Bluetooth state: ${isOn ? "ON" : "OFF"}'); if (isOn) { debugPrint('[BeaconPermissions] Bluetooth is ON'); return true; } // Request to enable Bluetooth via system prompt debugPrint('[BeaconPermissions] Bluetooth is OFF, requesting enable...'); await requestEnableBluetooth(); // Poll for Bluetooth state change - short wait first for (int i = 0; i < 6; i++) { await Future.delayed(const Duration(milliseconds: 500)); final newState = await isBluetoothEnabled(); debugPrint('[BeaconPermissions] Polling Bluetooth state ($i): ${newState ? "ON" : "OFF"}'); if (newState) { debugPrint('[BeaconPermissions] Bluetooth is now ON'); return true; } } // If still off after 3 seconds, try opening Bluetooth settings directly debugPrint('[BeaconPermissions] Bluetooth still OFF, opening settings...'); await openBluetoothSettings(); // Poll again for up to 15 seconds (user needs time to toggle in settings) for (int i = 0; i < 30; i++) { await Future.delayed(const Duration(milliseconds: 500)); final newState = await isBluetoothEnabled(); debugPrint('[BeaconPermissions] Polling Bluetooth state after settings ($i): ${newState ? "ON" : "OFF"}'); if (newState) { debugPrint('[BeaconPermissions] Bluetooth is now ON'); return true; } } debugPrint('[BeaconPermissions] Bluetooth still OFF after waiting'); return false; } catch (e) { debugPrint('[BeaconPermissions] Error checking Bluetooth state: $e'); return false; } } static Future checkPermissions() async { // On Android, use native check (much faster) if (Platform.isAndroid) { return await BeaconChannel.hasPermissions(); } // iOS: use Flutter plugin final locationStatus = await Permission.locationWhenInUse.status; final bluetoothStatus = await Permission.bluetooth.status; return locationStatus.isGranted && bluetoothStatus.isGranted; } static Future openSettings() async { await openAppSettings(); } }