I am trying to set up a foreground service for my Flutter application to perform background tasks using the Flutter library flutter_background_service 5.0.7. This is just a test; ultimately, I want to implement a different service. Although I know that WorkManager is more suited to this specific case, I want to check if the background service works correctly so that I can implement other services in the future.
However, when I run the app, regardless of whether the device is API 33 or API 34, I encounter the following error:
E/AndroidRuntime(10084): java.lang.RuntimeException: Unable to create service id.flutter.flutter_background_service.BackgroundService: java.lang.IllegalArgumentException: foregroundServiceType 0x00000001 is not a subset of foregroundServiceType attribute 0x00000000 in service element of manifest file
This is the AndroidManifest.xml
file I’m using:
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<application
android:label="app_tfm"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
<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>
<service
android:name=".MyForegroundService"
android:foregroundServiceType="dataSync"
android:exported="false"/>
<!-- 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>
<!-- Required to query activities that can process text, see:
https://developer.android.com/training/package-visibility?hl=en and
https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT.
In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
<queries>
<intent>
<action android:name="android.intent.action.PROCESS_TEXT"/>
<data android:mimeType="text/plain"/>
</intent>
</queries>
</manifest>
In my main.dart
file, I have the following implementation:
import 'dart:async';
import 'dart:ui';
import 'package:app_tfm/file_manager.dart';
import 'package:flutter/material.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'my_app.dart';
import 'package:flutter_background_service/flutter_background_service.dart';
import 'package:permission_handler/permission_handler.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
// Solicita el permiso de notificaciones si no esta concedido. Si no lo esta pidelo
if (await Permission.notification.isDenied) {
await Permission.notification.request();
}
Permission.notification.status.isGranted.then((isGranted) {
print('El permiso es $isGranted');
});
if (await Permission.notification.isGranted){
await initializeService();
runApp(const MyApp());
}
}
Future<void> initializeService() async {
final service = FlutterBackgroundService();
const AndroidNotificationChannel channel = AndroidNotificationChannel(
'888', // id
'Notificacion de prueba', // title
description:
'Estamos trabajando', // description
importance: Importance.low,
);
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
await flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>()
?.createNotificationChannel(channel);
await service.configure(
iosConfiguration: IosConfiguration(),
androidConfiguration: AndroidConfiguration(
onStart: onStart,
autoStart: true,
isForegroundMode: true,
notificationChannelId: 'my_foreground',
initialNotificationTitle: 'AWESOME SERVICE',
initialNotificationContent: 'Initializing',
foregroundServiceNotificationId: 888,
foregroundServiceType: AndroidForegroundType.dataSync
));
service.startService();
}
@pragma('vm:entry-point')
void onStart(ServiceInstance service) async {
DartPluginRegistrant.ensureInitialized();
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
service.on('escribe_fichero').listen((event) {
FileManager.writeToFile('prueba', 'escribo la hora: ${DateTime.now()}');
});
Timer.periodic(const Duration(seconds: 1), (timer) async {
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()}",
// );
FileManager.writeToFile('prueba', 'escribo la hora: ${DateTime.now()}');
});
}
I don’t know what I’m doing wrong, and I’ve been stuck on this for several days now. I’m open to suggestions or another way to approach it.
I tried to make sure that the AndroidManifest.xml file was written correctly and that the notification permission was granted before launching the app, but it didn’t work.
Ignacio Ruiz Chicano is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.