Flutter - 共享首选项在后台进程中返回 null?

问题描述 投票:0回答:1

我正在使用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 dart background sharedpreferences background-process
1个回答
0
投票

核心挑战在于使用

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);
  });
}
© www.soinside.com 2019 - 2024. All rights reserved.