In mobile applications, background services allow certain tasks to run even when the app is not actively in use by the user. These services are essential for enhancing user experience by providing timely information, performing periodic tasks, and supporting features like location tracking, notifications, and syncing. Here are the main types of background services commonly used in mobile app development and how they are implemented in Flutter with examples :
Here's a detailed look at how to work with various types of background services in Flutter, including some code samples to illustrate their implementation.
1. Foreground Services
To run tasks that are visible to the user, like media playback, you can use plugins like audio_service
. For advanced customization, you may need to write platform-specific code for Android or use background modes on iOS.
Code Example with audio_service
for Media Playback
First, add audio_service
and just_audio
for audio playback in pubspec.yaml
:
dependencies:
audio_service: ^0.18.0
just_audio: ^0.9.12
Then initialize the audio service:
import 'package:audio_service/audio_service.dart';
import 'package:just_audio/just_audio.dart';
AudioHandler audioHandler;
void main() async {
WidgetsFlutterBinding.ensureInitialized();
audioHandler = await AudioService.init(
builder: () => MyAudioHandler(),
config: AudioServiceConfig(
androidNotificationChannelId: 'com.example.myapp.audio',
androidNotificationChannelName: 'Audio Playback',
),
);
runApp(MyApp());
}
class MyAudioHandler extends BaseAudioHandler {
final _player = AudioPlayer();
MyAudioHandler() {
_player.setUrl("https://example.com/audio.mp3");
}
Future<void> play() => _player.play();
Future<void> pause() => _player.pause();
}
This code sets up a basic foreground service for audio playback that can keep running even when the app is backgrounded.
2. Background Fetch
To fetch data periodically in the background, use background_fetch
.
Code Example with background_fetch
Add the dependency in pubspec.yaml
:
dependencies:
background_fetch: ^0.7.3
In your main Dart file:
import 'package:background_fetch/background_fetch.dart';
void backgroundFetchHeadlessTask(HeadlessTask task) async {
BackgroundFetch.finish(task.taskId);
}
void main() {
runApp(MyApp());
BackgroundFetch.registerHeadlessTask(backgroundFetchHeadlessTask);
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: HomeScreen(),
);
}
}
class HomeScreen extends StatefulWidget {
@override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
@override
void initState() {
super.initState();
BackgroundFetch.configure(BackgroundFetchConfig(
minimumFetchInterval: 15,
stopOnTerminate: false,
enableHeadless: true,
), _onBackgroundFetch);
}
void _onBackgroundFetch(String taskId) async {
// Fetch your data here and update the app.
BackgroundFetch.finish(taskId);
}
}
The _onBackgroundFetch
method will be called every 15 minutes or so, allowing you to perform data fetches or other tasks.
3. Push Notifications
Firebase Cloud Messaging (FCM) is used to handle notifications, even when the app is closed or backgrounded.
Code Example with firebase_messaging
Add firebase_messaging
to pubspec.yaml
:
dependencies:
firebase_messaging: ^11.2.0
Then configure FCM:
import 'package:firebase_messaging/firebase_messaging.dart';
class PushNotificationService {
final FirebaseMessaging _fcm = FirebaseMessaging.instance;
Future<void> initialize() async {
// Request permission on iOS
NotificationSettings settings = await _fcm.requestPermission();
// Listen for messages while app is in the foreground
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
print('Received a foreground message: ${message.notification}');
});
// Handle background messages
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
}
static Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
print("Handling a background message: ${message.notification}");
}
}
This code configures FCM to receive notifications both in the foreground and background.
4. Location Services
For background location tracking, use plugins like flutter_background_geolocation
.
Code Example with flutter_background_geolocation
Add to pubspec.yaml
:
dependencies:
flutter_background_geolocation: ^1.8.0
Then configure background location tracking:
import 'package:flutter_background_geolocation/flutter_background_geolocation.dart' as bg;
void main() {
runApp(MyApp());
bg.BackgroundGeolocation.onLocation((bg.Location location) {
print('[location] ${location.coords}');
});
bg.BackgroundGeolocation.ready(bg.Config(
desiredAccuracy: bg.Config.DESIRED_ACCURACY_HIGH,
distanceFilter: 10.0,
stopOnTerminate: false,
startOnBoot: true,
)).then((bg.State state) {
if (!state.enabled) {
bg.BackgroundGeolocation.start();
}
});
}
This code sets up continuous location tracking in the background.
5. Periodic Tasks
You can use workmanager
to schedule periodic background tasks.
Code Example with workmanager
Add the dependency:
dependencies:
workmanager: ^0.4.1
Then initialize periodic tasks:
import 'package:workmanager/workmanager.dart';
void callbackDispatcher() {
Workmanager().executeTask((task, inputData) {
print("Running background task: $task");
return Future.value(true);
});
}
void main() {
runApp(MyApp());
Workmanager().initialize(callbackDispatcher, isInDebugMode: true);
Workmanager().registerPeriodicTask(
"1",
"simplePeriodicTask",
frequency: Duration(minutes: 15),
);
}
In this example, callbackDispatcher
is called every 15 minutes to execute the task.
6. Alarm Services
Use android_alarm_manager
to set alarms on Android.
Code Example with android_alarm_manager
Add android_alarm_manager
to pubspec.yaml
:
dependencies:
android_alarm_manager: ^0.4.5+15
Then set an alarm:
import 'package:android_alarm_manager/android_alarm_manager.dart';
void main() async {
runApp(MyApp());
await AndroidAlarmManager.initialize();
AndroidAlarmManager.oneShot(Duration(seconds: 5), 0, alarmCallback);
}
void alarmCallback() {
print("Alarm triggered!");
}
This example schedules a one-shot alarm that triggers after 5 seconds.
7. Bluetooth and NFC Background Tasks
Use flutter_blue
for Bluetooth and custom platform code for NFC.
Code Example with flutter_blue
Add to pubspec.yaml
:
dependencies:
flutter_blue: ^0.8.0
Then configure Bluetooth scanning:
import 'package:flutter_blue/flutter_blue.dart';
FlutterBlue flutterBlue = FlutterBlue.instance;
void startBluetoothScan() {
flutterBlue.startScan(timeout: Duration(seconds: 4)).listen((scanResult) {
print('Device found: ${scanResult.device.name}');
});
}
void main() {
runApp(MyApp());
startBluetoothScan();
}
These code samples provide a foundation for handling background services in Flutter across different functionalities. However, it’s essential to carefully test these services across devices and platforms to handle the differences in background restrictions effectively.