I am writing an app in flutter and need to send the users location as stream to my backend.After using the singleton as suggested in comment the logout works and it stops the stream,but after loging back streaming is not working. I initialize my location stream by calling it in main:
Main:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
LocationService().locationStream;
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Semdatex Patient Portal',
debugShowCheckedModeBanner: false,
//theme for all screens
theme: ThemeData(
primarySwatch: Colors.blue,
primaryColor: Colors.blue[100],
),
//all possible routes within the app
initialRoute: '/loginScreen',
routes: {
'/': (context) => const InitialSite(),
'/chat': (context) => const Chat(),
'/chatPage': (context) => const ChatPage(),
'/multipleChoice': (context) => const MultipleChoice(),
'/scale': (context) => const Scale(),
'/endScreen': (context) => const EndScreen(),
'/singleChoiceNew': (context) => const SelectionWindow(),
'/loginScreen': (context) => const LoginScreen(),
'/registerScreen': (context) => const RegisterScreen(),
},
);
}
}
LocationService:
import 'dart:async';
import 'package:location/location.dart';
import 'package:sdx_patient_portal/Datamodel/user_location.dart';
class LocationService {
static final LocationService _instance = LocationService._internal();
factory LocationService() => _instance;
LocationService._internal() {
getLocationOnchange();
}
var location = Location();
final StreamController<UserLocation> _locationController =
StreamController<UserLocation>.broadcast();
StreamSubscription<LocationData>? listen;
Stream<UserLocation> get locationStream => _locationController.stream;
void getLocationOnchange() async {
location.requestService().then((value) => {
location.requestPermission().then((permissionStatus) {
if (permissionStatus == PermissionStatus.granted) {
location.enableBackgroundMode(enable: true);
location.changeSettings(
interval: 10000, accuracy: LocationAccuracy.high);
listen = location.onLocationChanged.listen((locationData) {
_locationController.add(UserLocation(
locationData.latitude,
locationData.longitude,
locationData.altitude,
locationData.time));
});
}
})
});
}
StreamSubscription<LocationData>? getListener(){
return listen;
}
void dipose(){
listener?.cancel();
listener = null;
}
}
Here is the log in part in which I call the post after user has been loged in successfully:
class LoginScreen extends StatefulWidget {
const LoginScreen({Key? key}) : super(key: key);
@override
State<StatefulWidget> createState() => _State();
}
class _State extends State<LoginScreen> {
TextEditingController nameController = TextEditingController();
TextEditingController passwordController = TextEditingController();
final _formKey = GlobalKey<FormState>();
User user = User("", "");
String url = "http://10.0.2.2:9173/mob/login";
Future save() async {
var res = await http.post(Uri.parse(url),
headers: {'Content-Type': 'application/json'},
body: json.encode({'email': user.email, 'password': user.password}));
if (res.body.isEmpty) {
print('login wasn\'t successfull');
_showMyDialog();
} else {
var data = json.decode(res.body);
if (data["patientNumber"] == null) {
_showMyDialog();
} else {
await savePatientNumber(data["patientNumber"], data["lastAccess"]);
final prefs = await SharedPreferences.getInstance();
await prefs.setBool('loggedIn', true);
//LocationService().getListener()?.resume();
LocationService().locationStream;
startLocationStream();
Navigator.pushNamed(context, '/');
}
}
}
I call the following POST after log in:
postLocation() async {
var patient = await getPatient();
var patNumber = patient[0]["PatNum"];
var l = (LocationService().locationStream);
const String url = "http://10.0.2.2:9173/mob/location";
UserLocation locationData;
l.listen((event) {
locationData = UserLocation(
event.latitude, event.longitude, event.altitude, event.time);
http.post(Uri.parse(url),
headers: {'Content-Type': 'application/json'},
body: json.encode({
'latitude': locationData.latitude,
'altitude': locationData.altitude,
'longitude': locationData.longitude,
'time': locationData.time,
'patientNumber': patNumber
}));
});
}
Then I call cancle the listener by signing out:
void signOut(context) async {
LocationService().dipose();
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(builder: (context) => const LoginScreen()),
(route) => false);
}
Hoe can I get controll over the state of the app and rerun the services after re-login?