flutter_background_service_enhanced 1.0.0 flutter_background_service_enhanced: ^1.0.0 copied to clipboard
A flutter plugin for executing dart code continously even application closed.
import 'dart:async';
import 'dart:io';
import 'dart:ui';
import 'package:device_info_plus/device_info_plus.dart';
import 'package:flutter/material.dart';
import 'package:flutter_background_service_enhanced/flutter_background_service_enhanced.dart';
import 'package:flutter_background_service_android_enhanced/flutter_background_service_android_enhanced.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:shared_preferences/shared_preferences.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await initializeService();
runApp(const MyApp());
}
Future<void> initializeService() async {
final service = FlutterBackgroundServiceEnhanced();
/// 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) {
await flutterLocalNotificationsPlugin.initialize(
const InitializationSettings(
iOS: IOSInitializationSettings(),
),
);
}
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',
currentDay: "28",
currentJalaliDate: "28 مهر 1401",
currentMiladiDate: "20 اکتبر 2022",
currentHijriDate: "23 ربیع الاول 1444",
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 fetch capability on xcode project
onBackground: onIosBackground,
),
);
service.startService();
}
// to ensure this is executed
// run app from xcode, then from xcode menu, select Simulate Background Fetch
@pragma('vm:entry-point')
Future<bool> onIosBackground(ServiceInstance service) async {
WidgetsFlutterBinding.ensureInitialized();
DartPluginRegistrant.ensureInitialized();
SharedPreferences preferences = await SharedPreferences.getInstance();
await preferences.reload();
final log = preferences.getStringList('log') ?? <String>[];
log.add(DateTime.now().toIso8601String());
await preferences.setStringList('log', log);
return true;
}
@pragma('vm:entry-point')
void onStart(ServiceInstance service) async {
// Only available for flutter 3.0.0 and later
DartPluginRegistrant.ensureInitialized();
// For flutter prior to version 3.0.0
// We have to register the plugin manually
SharedPreferences preferences = await SharedPreferences.getInstance();
await preferences.setString("hello", "world");
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();
});
// bring to foreground
Timer.periodic(const Duration(seconds: 1), (timer) async {
if (service is AndroidServiceInstance) {
if (await service.isForegroundService()) {
// if you don't using custom notification, uncomment this
service.setForegroundNotificationInfo(
currentDay: "28",
currentJalaliDate: "28 مهر 1401",
currentMiladiDate: "20 اکتبر 2022",
currentHijriDate: "23 ربیع الاول 1444",
);
}
}
/// you can see this log in logcat
print('FLUTTER BACKGROUND SERVICE: ${DateTime.now()}');
// test using external plugin
final deviceInfo = DeviceInfoPlugin();
String? device;
if (Platform.isAndroid) {
final androidInfo = await deviceInfo.androidInfo;
device = androidInfo.model;
}
if (Platform.isIOS) {
final iosInfo = await deviceInfo.iosInfo;
device = iosInfo.model;
}
service.invoke(
'update',
{
"current_date": DateTime.now().toIso8601String(),
"device": device,
},
);
});
}
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String text = "Stop Service";
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Service App'),
),
body: Column(
children: [
StreamBuilder<Map<String, dynamic>?>(
stream: FlutterBackgroundServiceEnhanced().on('update'),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return const Center(
child: CircularProgressIndicator(),
);
}
final data = snapshot.data!;
String? device = data["device"];
DateTime? date = DateTime.tryParse(data["current_date"]);
return Column(
children: [
Text(device ?? 'Unknown'),
Text(date.toString()),
],
);
},
),
ElevatedButton(
child: const Text("Foreground Mode"),
onPressed: () {
FlutterBackgroundServiceEnhanced().invoke("setAsForeground");
},
),
ElevatedButton(
child: const Text("Background Mode"),
onPressed: () {
FlutterBackgroundServiceEnhanced().invoke("setAsBackground");
},
),
ElevatedButton(
child: Text(text),
onPressed: () async {
final service = FlutterBackgroundServiceEnhanced();
var isRunning = await service.isRunning();
if (isRunning) {
service.invoke("stopService");
} else {
service.startService();
}
if (!isRunning) {
text = 'Stop Service';
} else {
text = 'Start Service';
}
setState(() {});
},
),
const Expanded(
child: LogView(),
),
],
),
floatingActionButton: FloatingActionButton(
onPressed: () {},
child: const Icon(Icons.play_arrow),
),
),
);
}
}
class LogView extends StatefulWidget {
const LogView({Key? key}) : super(key: key);
@override
State<LogView> createState() => _LogViewState();
}
class _LogViewState extends State<LogView> {
late final Timer timer;
List<String> logs = [];
@override
void initState() {
super.initState();
timer = Timer.periodic(const Duration(seconds: 1), (timer) async {
final SharedPreferences sp = await SharedPreferences.getInstance();
await sp.reload();
logs = sp.getStringList('log') ?? [];
if (mounted) {
setState(() {});
}
});
}
@override
void dispose() {
timer.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: logs.length,
itemBuilder: (context, index) {
final log = logs.elementAt(index);
return Text(log);
},
);
}
}