Replace geofence polling with native Android geofence
This commit is contained in:
40
lib/features/homes/services/geofence_automation_service.dart
Normal file
40
lib/features/homes/services/geofence_automation_service.dart
Normal file
@@ -0,0 +1,40 @@
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
import '../../../models/home_config.dart';
|
||||
import '../../../services/settings_service.dart';
|
||||
|
||||
class GeofenceAutomationService {
|
||||
GeofenceAutomationService({SettingsService? settingsService})
|
||||
: _settingsService = settingsService ?? SettingsService();
|
||||
|
||||
static const _channel = MethodChannel('ignis/geofence_automation');
|
||||
|
||||
final SettingsService _settingsService;
|
||||
|
||||
Future<void> syncActiveHome(HomeConfig? home) async {
|
||||
if (home == null || !home.geofenceReady) {
|
||||
await _invoke('disarmGeofence');
|
||||
return;
|
||||
}
|
||||
|
||||
final apiKey = await _settingsService.requireHomeApiKey(home.id);
|
||||
await _invoke('armGeofence', {
|
||||
'homeId': home.id,
|
||||
'baseUrl': home.url,
|
||||
'apiKey': apiKey,
|
||||
'latitude': home.latitude,
|
||||
'longitude': home.longitude,
|
||||
'radiusMeters': home.geofenceRadiusMeters,
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _invoke(String method, [Map<String, Object?>? arguments]) async {
|
||||
try {
|
||||
await _channel.invokeMethod<void>(method, arguments);
|
||||
} on MissingPluginException {
|
||||
// В тестах и на не-Android средах platform channel может отсутствовать.
|
||||
} on PlatformException {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||
|
||||
class GeofenceNotificationsService {
|
||||
final FlutterLocalNotificationsPlugin _plugin;
|
||||
|
||||
GeofenceNotificationsService({FlutterLocalNotificationsPlugin? plugin})
|
||||
: _plugin = plugin ?? FlutterLocalNotificationsPlugin();
|
||||
|
||||
Future<void> initialize() async {
|
||||
if (kIsWeb || defaultTargetPlatform != TargetPlatform.android) {
|
||||
return;
|
||||
}
|
||||
|
||||
const settings = InitializationSettings(
|
||||
android: AndroidInitializationSettings('@mipmap/ic_launcher'),
|
||||
);
|
||||
await _plugin.initialize(settings);
|
||||
}
|
||||
|
||||
Future<bool> areNotificationsEnabled() async {
|
||||
if (kIsWeb || defaultTargetPlatform != TargetPlatform.android) {
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
final android = _plugin
|
||||
.resolvePlatformSpecificImplementation<
|
||||
AndroidFlutterLocalNotificationsPlugin
|
||||
>();
|
||||
return await android?.areNotificationsEnabled() ?? true;
|
||||
} catch (_) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> requestNotificationsPermission() async {
|
||||
if (kIsWeb || defaultTargetPlatform != TargetPlatform.android) {
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
final android = _plugin
|
||||
.resolvePlatformSpecificImplementation<
|
||||
AndroidFlutterLocalNotificationsPlugin
|
||||
>();
|
||||
final granted = await android?.requestNotificationsPermission();
|
||||
return granted ?? await areNotificationsEnabled();
|
||||
} catch (_) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
import '../models/geofence_runtime_state.dart';
|
||||
|
||||
class GeofenceRuntimeStore {
|
||||
static const String _runtimeKey = 'ignis_geofence_runtime';
|
||||
|
||||
Future<GeofenceRuntimeState> load() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final raw = prefs.getString(_runtimeKey);
|
||||
if (raw == null || raw.isEmpty) {
|
||||
return const GeofenceRuntimeState();
|
||||
}
|
||||
|
||||
final decoded = jsonDecode(raw);
|
||||
if (decoded is! Map<String, dynamic>) {
|
||||
return const GeofenceRuntimeState();
|
||||
}
|
||||
|
||||
return GeofenceRuntimeState.fromJson(decoded);
|
||||
}
|
||||
|
||||
Future<void> save(GeofenceRuntimeState state) async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final data = state.toJson();
|
||||
if (data.isEmpty) {
|
||||
await prefs.remove(_runtimeKey);
|
||||
return;
|
||||
}
|
||||
|
||||
await prefs.setString(_runtimeKey, jsonEncode(data));
|
||||
}
|
||||
|
||||
Future<GeofenceRuntimeState> armForHome(String homeId) async {
|
||||
final next = (await load()).armForHome(homeId);
|
||||
await save(next);
|
||||
return next;
|
||||
}
|
||||
|
||||
Future<GeofenceRuntimeState> disarm() async {
|
||||
final next = (await load()).disarm();
|
||||
await save(next);
|
||||
return next;
|
||||
}
|
||||
|
||||
Future<GeofenceRuntimeState> removeHome(String homeId) async {
|
||||
final next = (await load()).removeHome(homeId);
|
||||
await save(next);
|
||||
return next;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user