flutter_background_service
flutter_background_service copied to clipboard
Don't delete global variable in flutter using flutter_background_service
I want to make a background service that continuously checks a database and send a notification (The notification I have tested works correctly). For this I need to send a variable. Previously that code has been saved in a global variable in another file, as shown in LogIn code, in this part of the code, and we call the function initializeService and set the service in Background. `if (Platform.isAndroid) { UsuarioCuidador = usuario[0]; await initializeService();
FlutterBackgroundService().invoke("setAsBackground");
}` However, the problem comes in Task code, when I want to call the CheckAlarm function, a function that is responsible for calling a DB and needs a parameter, the global variable UsuarioCuidador is set to null when we enter the onStart function, which is where the CheckAlarm function is called every second, but until there in the previus part of the code, the variable it is not null. Next I show you the code.
LogIn code, where we store the global variable
`List<Usuario> usuario = []; Usuario UsuarioCuidador = Usuario(0, '', '', '', '', '', '', '', '', '', '');
class LogInScreen extends StatefulWidget { const LogInScreen({Key? key}) : super(key: key);
@override State<LogInScreen> createState() => _LogInScreenSate(); }
class _LogInScreenSate extends State<LogInScreen> { final TextEditingController _EmailController = TextEditingController(); final TextEditingController _PasswordController = TextEditingController(); final scaffoldKey = GlobalKey<ScaffoldState>(); bool _btnActiveEmail = false; bool _btnActivePassword = false; late bool PasswordVisibility = false; late bool circular = false;
@override Widget build(BuildContext context) { ................. }
/*******************************************************************
- Funcion que se le pasa como parametro el Email y el Password. Se
- Busca en la base de datos si existe el usuario y la contraseña,
- en caso de que exista se deculve un true (cheque la variable que
- isEmpty que devuelve la BD) y se redirecciona a la pagina de Home,
- en caso de que no exista se devuelve un false
- En caso de que el usuario sea un SuperAdmin o Admin se redirecciona
- a la pagina inicial de la aplicacion, que para estos usuarios es la
- pagina de Viviendas
********************************************************************/
Future
LoginButton(EmailValidator, PasswordValidator) async { //var users = await DBPostgres().DBGetPendingAdmin(); var User = await DBPostgres().DBLogIn(EmailValidator, PasswordValidator); String UserType = User[0];
usuario.clear();
for (var p in User[1]) {
usuario.add(Usuario(p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8],
UserType, PasswordValidator));
}
if (UserType == 'Admin') {
Navigator.pushNamed(context, '/GestionViviendasPage');
} else if (UserType == 'SuperAdmin') {
Navigator.pushNamed(context, '/GestionViviendasPage');
} else if (UserType == 'Cuidador') {
if (Platform.isAndroid) {
UsuarioCuidador = usuario[0];
await initializeService();
FlutterBackgroundService().invoke("setAsBackground");
}
Navigator.pushNamed(context, '/GestionPacientesCuidadorPage');
} else if (UserType == 'Paciente') {
Navigator.pushNamed(context, '/GestionPacientePacientePage');
} else if (UserType == 'AdminInac' ||
UserType == 'CuidadorInact' ||
UserType == 'PacienteInact') {
showDialog(
context: context,
builder: (BuildContext context) => AlertDialog(
title: const Text(
'Su cuenta esta inactiva, contacte con el administrador',
textAlign: TextAlign.center,
),
actions: <Widget>[
TextButton(
onPressed: () => Navigator.pushNamed(context, '/LoginPage'),
child: const Text('ok'),
),
],
),
);
} else {
showDialog(
context: context,
builder: (BuildContext context) => AlertDialog(
title: const Text(
'Email o Contraseña Incorrecta',
textAlign: TextAlign.center,
),
actions: <Widget>[
TextButton(
onPressed: () => Navigator.pop(context),
child: const Text('ok'),
),
],
),
);
}
}
@override // TODO: implement widget LogInScreen get widget => super.widget; } ` Task code, where the service logic is realised
`final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
Future
await flutterLocalNotificationsPlugin.initialize(initializationSettings); }
Future
const NotificationDetails notificationDetails = NotificationDetails( android: androidNotificationDetails, );
await flutterLocalNotificationsPlugin.show( 1, 'Titulo de notificacion', 'Esta es una notificación de prueba para mostrar en el canal. Los quiero mucho.', notificationDetails); }
Future
var Dbdata = await DBPostgres() .DBGetPacientesViviendasCuidador(UsuarioCuidador.CodUsuario, 'null'); var Estado;
for (var p in Dbdata[0]) { CasaList.add( Casa(p[0], p[1], p[2], p[3], p[4]), ); } for (var p in Dbdata[1]) { if (p[9] == null) { Estado = 'Activo'; } else { Estado = 'Inactivo'; } TodoPacientesList.add( Pacientes(p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15], Estado), ); }
for (Casa casa in CasaList) { for (Pacientes paciente in TodoPacientesList) { if (paciente.CodCasa == casa.CodCasa) { PacientesList.add(paciente); } } }
print('Successfully Fetched data'); }
Future
/// OPTIONAL, using custom notification channel id const AndroidNotificationChannel channel = AndroidNotificationChannel( 'my_foreground', // id 'MY FOREGROUND SERVICE', // title description: 'This channel is used for important notifications.', // description importance: Importance.low, // importance must be at low or higher level );
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
if (Platform.isIOS || Platform.isAndroid) { await flutterLocalNotificationsPlugin.initialize( const InitializationSettings( iOS: DarwinInitializationSettings(), android: AndroidInitializationSettings('ic_bg_service_small'), ), ); }
await flutterLocalNotificationsPlugin .resolvePlatformSpecificImplementation< AndroidFlutterLocalNotificationsPlugin>() ?.createNotificationChannel(channel);
await service.configure( androidConfiguration: AndroidConfiguration( // this will be executed when app is in foreground or background in separated isolate onStart: onStart,
// auto start service
autoStart: true,
isForegroundMode: true,
notificationChannelId: 'my_foreground',
initialNotificationTitle: 'AWESOME SERVICE',
initialNotificationContent: 'Initializing',
foregroundServiceNotificationId: 888,
),
iosConfiguration: IosConfiguration(
// auto start service
autoStart: true,
// this will be executed when app is in foreground in separated isolate
onForeground: onStart,
// you have to enable background fe
),
);
service.startService(); }
@pragma('vm:entry-point') void onStart(ServiceInstance service) async { DartPluginRegistrant.ensureInitialized();
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
if (service is AndroidServiceInstance) { service.on('setAsForeground').listen((event) { service.setAsForegroundService(); });
service.on('setAsBackground').listen((event) {
service.setAsBackgroundService();
});
}
service.on('stopService').listen((event) { service.stopSelf(); });`
No, you can't do that. The background task and UI is running in separated isolates. Each isolate has it's own memory management. So, it's not possible to share variable value between UI and background task.
First of all, thank you very much for answering, could you tell me if there is a way to do what I want to do, that is, how do the rest of the applications to have a task in the background with data that are dynamic?
@AFazakas-UAH did you find any solution for that ? I am facing the same issue unfortunately.