After restarting the phone, the service does not start automatically. You need to log in to the application, only after that it will start
AndroidManifest.xml
`
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE"/>
<application
android:label="background_service"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
<service
android:name="id.flutter.flutter_background_service.BackgroundService"
android:foregroundServiceType="specialUse"
/>
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
Future initializeService() async {
final service = FlutterBackgroundService();
/// 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();
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,
autoStartOnBoot: 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 fetch capability on xcode project
onBackground: onIosBackground,
),
);
}
// to ensure this is executed
// run app from xcode, then from xcode menu, select Simulate Background Fetch
@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
// bring to foreground
Timer.periodic(const Duration(seconds: 1), (timer) async {
if (service is AndroidServiceInstance) {
if (await service.isForegroundService()) {
/// OPTIONAL for use custom notification
/// the notification id must be equals with AndroidConfiguration when you call configure() method.
flutterLocalNotificationsPlugin.show(
888,
'COOL SERVICE',
'Awesome ${DateTime.now()}',
const NotificationDetails(
android: AndroidNotificationDetails(
'my_foreground',
'MY FOREGROUND SERVICE',
icon: 'ic_bg_service_small',
ongoing: true,
),
),
);
// if you don't using custom notification, uncomment this
service.setForegroundNotificationInfo(
title: "My App Service",
content: "Updated at ${DateTime.now()}",
);
}
}
/// 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,
},
);
After restarting the phone, the service does not start automatically. You need to log in to the application, only after that it will start AndroidManifest.xml `
main.dart
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/flutter_background_service.dart'; import 'package:flutter_background_service_android/flutter_background_service_android.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:shared_preferences/shared_preferences.dart';
Future main() async {
WidgetsFlutterBinding.ensureInitialized();
await initializeService();
runApp(const MyApp());
}
Future initializeService() async {
final service = FlutterBackgroundService();
/// 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,
); }
// to ensure this is executed // run app from xcode, then from xcode menu, select Simulate Background Fetch
@pragma('vm:entry-point') Future onIosBackground(ServiceInstance service) async {
WidgetsFlutterBinding.ensureInitialized();
DartPluginRegistrant.ensureInitialized();
SharedPreferences preferences = await SharedPreferences.getInstance(); await preferences.reload(); final log = preferences.getStringList('log') ??[];
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");
/// OPTIONAL when use custom notification final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
if (service is AndroidServiceInstance) { service.on('setAsForeground').listen((event) { service.setAsForegroundService(); });
}
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()) { /// OPTIONAL for use custom notification /// the notification id must be equals with AndroidConfiguration when you call configure() method. flutterLocalNotificationsPlugin.show( 888, 'COOL SERVICE', 'Awesome ${DateTime.now()}', const NotificationDetails( android: AndroidNotificationDetails( 'my_foreground', 'MY FOREGROUND SERVICE', icon: 'ic_bg_service_small', ongoing: true, ), ), );
}); }
class MyApp extends StatefulWidget { const MyApp({Key? key}) : super(key: key);
@override State createState() => _MyAppState();
}
class _MyAppState extends State {
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: FlutterBackgroundService().on('update'),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return const Center(
child: CircularProgressIndicator(),
);
}
} }
class LogView extends StatefulWidget { const LogView({Key? key}) : super(key: key);
@override State createState() => _LogViewState();
}
class _LogViewState extends State {
late final Timer timer;
List 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); }, ); } } `