我正在使用flutter_background_service。当应用程序进入后台时,我需要处理图像。我需要一些用于处理的值,这些值在处理之前存储在共享首选项中。
///
Future<void> initializeService() async {
final service = FlutterBackgroundService();
// Create notification channel for Android
const AndroidNotificationChannel channel = AndroidNotificationChannel(
notificationChannelId, // id
'IMAGE STAMPING SERVICE', // title
description: 'This channel is used for important notifications.',
importance: Importance.high, // Set importance
);
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
// Create the notification channel
await flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>()
?.createNotificationChannel(channel);
await service.configure(
androidConfiguration: AndroidConfiguration(
onStart: onStart,
autoStart: true,
isForegroundMode: true,
notificationChannelId: notificationChannelId,
initialNotificationTitle: 'Image Stamping Service',
initialNotificationContent: 'Initializing',
foregroundServiceNotificationId: notificationId,
),
iosConfiguration: IosConfiguration(
autoStart: true,
onForeground: onStart,
),
);
}
/// Function to initialize photo watcher
void initializePhotoWatcher() async {
try {
// Initialize SharedPreferences
SharedPreferences prefs = await SharedPreferences.getInstance();
// Retrieve the value from SharedPreferences
bool arePermissionsGranted = prefs.getBool('permissionsGranted') ?? false;
if (arePermissionsGranted) {
photoDirectory = Directory(AppConstants.directoryPath);
if (await photoDirectory?.exists() ?? false) {
final watcher = DirectoryWatcher(photoDirectory!.path);
print("DirectoryWatcher created for path: ${photoDirectory!.path}");
watcher.events.listen((event) {
print("Event detected: ${event.toString()}");
if (event.type == ChangeType.ADD &&
!event.path.contains("stamped_") &&
!event.path.contains(".pending")) {
print("Scheduling processing for file: ${event.path}");
<------------ Invoking Service Here ------------>
final service = FlutterBackgroundService();
service.invoke('processImage', {'imagePath': event.path});
}
});
} else {
print("Camera directory does not exist or is not accessible");
}
} else {
// Request permissions and wait for them to be granted
bool permissionsGranted = await requestPermissions();
if (permissionsGranted) {
// Permissions were granted, continue with initialization
photoDirectory = Directory(AppConstants.directoryPath);
// Rest of the code...
} else {
// Permissions were not granted, handle accordingly
print("Need more permissions.");
}
}
} catch (e) {
print(e.toString());
}
}
///
Future<void> onStart(ServiceInstance service) async {
// DartPluginRegistrant.ensureInitialized();
// final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
// FlutterLocalNotificationsPlugin();
// Set up listeners for foreground and background state transitions
if (service is AndroidServiceInstance) {
service.on('processImage').listen((data) {
final String imagePath = data?['imagePath'];
service.setAsBackgroundService();
// Rest of the code to process the image
processImage(imagePath);
});
service.on('setAsForeground').listen((event) {
service.setAsForegroundService();
});
service.on('setAsBackground').listen((event) {
service.setAsBackgroundService();
});
}
service.on('stopService').listen((event) {
service.stopSelf();
});
}
在此检索:
void processImage(String imagePath) async {
try {
final File imageFile = File(imagePath);
final SharedPreferences prefs = await SharedPreferences.getInstance();
<------- Reloading as suggested in other solutions -------->
await prefs.reload();
// Retrieve user preferences
<------------ Everything takes the default value as the prefs return null ------------>
int fontSize = prefs.getInt('fontSize') ?? AppConstants.fontSize;
int scaledFontSize = fontSize * 2;
final Color fontColor = _getFontColorFromString(prefs);
// Retrieve text position
String textPositionString =
prefs.getString('textPlacement') ?? AppConstants.textPosition.name;
TextPosition textPosition = TextPosition.values.firstWhere(
(e) => e.name == textPositionString,
orElse: () => AppConstants.textPosition // default value if not found
);
String text = prefs.getString('text') ?? AppConstants.text;
// Check if the file exists and is not a temporary file
if (await imageFile.exists() && !imageFile.path.contains('.pending-')) {
// Call the function to add a stamp to the photo
await addStampToPhoto(
image: imageFile,
fontSize: scaledFontSize,
text: text,
fontColor: fontColor,
textPosition: textPosition,
photoDirectoryPath: AppConstants.directoryPath,
);
} else {
// Log and handle the situation, perhaps by retrying later
print('File does not exist or is a temporary file: $imagePath');
}
} //
catch (e) {
print('Error in processing file $imagePath: $e');
// Optionally implement a retry mechanism or other error handling
}
}
核心挑战在于使用
flutter_background_service
时跨隔离访问 SharedPreferences 值。这种限制是由于为了提高效率和安全性而在单独的隔离区中运行的后台服务造成的。
所以我建议将值作为参数传递。
喜欢
service.invoke('processImage', {
'imagePath': event.path,
'fontSize': prefs.getInt('fontSize') ?? AppConstants.fontSize,
});
和
onStart
功能
Future<void> onStart(ServiceInstance service) async {
service.on('processImage').listen((data) {
final String imagePath = data?['imagePath'];
final int fontSize = data?['fontSize'];
processImage(imagePath, fontSize);
});
}