Reputation: 101
I am working on a Flutter app with a package called geofence_foreground_service. geofence_foreground_service has a @pragma('vm:entry-point')
isolate that it spawns when triggered. In the isolate, I want to be able to access my SharedPreferences information. However, I can't seem to do this. I understand that there is something specific that I need to do to enable packages in this isolate, but I am not sure what that thing is. Right now I am testing with an iOS simulator, but eventually it will need to work for both iOS and Android. At the bottom of this question is the full example code which errors out when trying to await SharedPreferences. This might be something that can be solved without the example code, but I included it just in case.
Steps to reproduce:
The error will occur here on line 15. The specific error message is:
[ERROR:flutter/runtime/dart_vm_initializer.cc(40)] Unhandled Exception: PlatformException(channel-error, Unable to establish connection on channel: "dev.flutter.pigeon.shared_preferences_foundation.UserDefaultsApi.getKeys"., null, null)
The full code is:
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:geofence_foreground_service/exports.dart';
import 'package:geofence_foreground_service/geofence_foreground_service.dart';
import 'package:geofence_foreground_service/models/zone.dart';
import 'package:geolocator/geolocator.dart';
import 'package:shared_preferences/shared_preferences.dart';
@pragma('vm:entry-point')
void callbackDispatcher() async {
Future<bool> trigger() async {
WidgetsFlutterBinding.ensureInitialized();
SharedPreferencesAsync prefs = SharedPreferencesAsync();
Set<String> test = await prefs.getKeys();
print(test);
return true;
}
GeofenceForegroundService().handleTrigger(
backgroundTriggerHandler: (zoneID, triggerType) {
trigger();
print("Trigger done");
return Future.value(true);
},
);
}
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
static final LatLng _testLocation = LatLng.degree(40.758078, -73.985640);
bool _hasServiceStarted = false;
@override
void initState() {
super.initState();
initPlatformState();
}
// Platform messages are asynchronous, so we initialize in an async method.
Future<void> initPlatformState() async {
bool serviceEnabled;
LocationPermission permission = LocationPermission.denied;
// Test if location services are enabled.
serviceEnabled = await Geolocator.isLocationServiceEnabled();
if (serviceEnabled) {
// Test if permissions are enabled, request if not
permission = await Geolocator.checkPermission();
if (permission == LocationPermission.denied) {
permission = await Geolocator.requestPermission();
}
}
_hasServiceStarted = await GeofenceForegroundService().startGeofencingService(
contentTitle: 'Test app',
contentText: 'Test app will be running to ensure seamless integration with ops team',
notificationChannelId: 'com.app.geofencing_notifications_channel',
serviceId: 525600,
callbackDispatcher: callbackDispatcher,
);
log(_hasServiceStarted.toString(), name: 'hasServiceStarted');
}
Future<void> _createLondonGeofence() async {
if (!_hasServiceStarted) {
log('Service has not started yet', name: 'createGeofence');
return;
}
await GeofenceForegroundService().addGeofenceZone(
zone: Zone(
id: 'TempLocation',
radius: 1000, // measured in meters
coordinates: [_testLocation],
),
);
log('Geofence created', name: 'createGeofence');
}
Future<void> _removeLondonGeofence() async {
if (!_hasServiceStarted) {
log('Service has not started yet', name: 'createGeofence');
return;
}
await GeofenceForegroundService().removeGeofenceZone(zoneId: 'TempLocation');
log('Geofence removed', name: 'createGeofence');
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Plugin example app'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(onPressed: _createLondonGeofence, child: const Text('Create Temporary Geofence')),
const SizedBox(height: 30),
ElevatedButton(onPressed: _removeLondonGeofence, child: const Text('Remove Temporary Geofence')),
],
),
),
),
);
}
}
Upvotes: 0
Views: 10