istornz/flutter_live_activities

Always callback display “Activity update: EndedActivityUpdate”,What's the wrong configuration

Opened this issue · 9 comments

kvenn commented

I'm also getting this issue on physical device (but not on simulator). I've tried all the steps suggested in other threads (removing images, etc).
Also, strangely enough, this was working on physical device for a while and just stopped working.

[EDIT] It was images....I was trying to render an image that was too large. I thought I removed it in my testing but was mistaken. But I've sinced forked the repo and changed the "resizeFactor" logic to instead of using a static value, it just always resizes the images to be under 100kb

        // Check the original image file size and then set a resize factor that
        // will get it to be under 100kb
        final originalImageSize = file.lengthSync();
        const maxBytes = 100 * 1000;
        if (originalImageSize > maxBytes) {
          originalImage.resizeFactor = min(maxBytes / originalImageSize, 1);
        }

Agree with @kvenn, Apple doesn't allow to load high image size into live activities, I added a resize factor to reduce the resolution (and the size). I don't know what is the exact size limit. If I know it, I would change the method to reduce automatically the size to not be greater than this value.

kvenn commented

I've since rewritten this file. I can open a PR into the package in the future. But it just deterministically downscales it so it's always under the threshold. For me, I only show 4 images and each is allowed to be around 75-100kb.

  Future<File> _compressToSize(
    String path,
    int targetWidthPixels,
    int maxSizeKb,
  ) async {
    File compressedFile = await _compressImageToWidth(path, targetWidthPixels);
    int maxSizeBytes = maxSizeKb * 1000;
    int loopLimit = 4;
    while ((compressedFile.lengthSync() > maxSizeBytes) && loopLimit-- > 0) {
      int percentage =
          ((maxSizeBytes / compressedFile.lengthSync()) * 100).round();
      compressedFile = await FlutterNativeImage.compressImage(
        path,
        percentage: percentage,
      );
    }
    if (compressedFile.lengthSync() > maxSizeBytes) {
      throw Exception('Could not compress image to size');
    }
    return compressedFile;
  }

  /// Throws exception if we can't get width and height attributes
  Future<File> _compressImageToWidth(String path, int targetWidth) async {
    ImageProperties properties =
        await FlutterNativeImage.getImageProperties(path);
    int? originalWidth = properties.width;
    int? originalHeight = properties.height;

    if (originalWidth == null || originalHeight == null) {
      throw Exception('Could not get width and height of image');
    }

    if (originalWidth < targetWidth) {
      return File(path);
    }

    // Height multiplier
    final double heightMultiplier =
        targetWidth / originalWidth * originalHeight;
    // TODO: replace this with a less janky plugin?
    return FlutterNativeImage.compressImage(
      path,
      targetWidth: targetWidth,
      targetHeight: heightMultiplier.round(),
    );
  }

Called like this:

          // Throws if it can't compress to size
          // I've observed live activities crashing for images as small as 120kb
          // Resizing to 150 pixels keeps them around 10-20kb
          tempDirectoryFile = await _compressToSize(
            tempDirectoryFile.path,
            150,
            75,
          );
        }

i am also getting this when creating an activity with the example images(under 70kb) any other idea why it could be happening?

I would try 1) no images to see if it's working and then 2) try with much smaller images (or by rescaling them down to be much smaller) to count out that it's not images.

In my case I assumed it was something else for too long and it ended up being the images. So I enforced that they were 10kb max and only show 5 of them.

I would try 1) no images to see if it's working and then 2) try with much smaller images (or by rescaling them down to be much smaller) to count out that it's not images.

In my case I assumed it was something else for too long and it ended up being the images. So I enforced that they were 10kb max and only show 5 of them.

just tried no images at all and still ends the activity any other idea?
i am also getting this error :
ERROR:flutter/shell/common/shell.cc(1038)] The 'live_activities/activity_status' channel sent a message from native to Flutter on a non-platform thread. Platform channel messages must be sent on the platform thread. Failure to do so may result in data loss or crashes, and must be fixed in the plugin or application code creating that channel.
See https://docs.flutter.dev/platform-integration/platform-channels#channels-and-platform-threading for more information.

Strange...I've also seen the live activity terminate immediately when there was an error thrown inside the SwiftUI code.

It could be a bug in how you're passing the information (ContentState) or a bug in one of the UI views itself. It's kind of hard to debug that part, but I'd maybe try rendering just a small box without any logic to see if it's that.

Strange...I've also seen the live activity terminate immediately when there was an error thrown inside the SwiftUI code.

It could be a bug in how you're passing the information (ContentState) or a bug in one of the UI views itself. It's kind of hard to debug that part, but I'd maybe try rendering just a small box without any logic to see if it's that.

i am using exactly the same ui and configs that the example uses... when i clone and run the example project it works fine.
but when i integrate it into my existing app its ending the activity even though i did all the config steps.
group id changed everywhere
activated the scheme
enabled push notifications
both runner and widget extension enable liveactivity support
exactly the same ui in flutter as the example widget (include the same images)
i tried to reconfig from scartch without any success

problem was solved i added app group capability on the widget extension only for release mode instead of "all" :}