flutter_photo_manager icon indicating copy to clipboard operation
flutter_photo_manager copied to clipboard

SaveImage return null on android

Open delfme opened this issue 2 years ago • 6 comments

Version

2.7.2

Platforms

Android

Device Model

Xiaomi Mi lite 5g

flutter info

Doctor summary (to see all details, run flutter doctor -v):
[!] Flutter (Channel [user-branch], 3.13.0-0.2.pre, on macOS 12.6.5 21G531 darwin-arm64, locale en-IT)
    ! Flutter version 3.13.0-0.2.pre on channel [user-branch] at /Users/delf/Development/flutter
      Currently on an unknown channel. Run `flutter channel` to switch to an official channel.
      If that doesn't fix the issue, reinstall Flutter by following instructions at https://flutter.dev/docs/get-started/install.
    ! Upstream repository unknown source is not a standard remote.
      Set environment variable "FLUTTER_GIT_URL" to unknown source to dismiss this error.
[!] Android toolchain - develop for Android devices (Android SDK version 31.0.0)
    ✗ cmdline-tools component is missing
      Run `path/to/sdkmanager --install "cmdline-tools;latest"`
      See https://developer.android.com/studio/command-line for more details.
    ✗ Android license status unknown.
      Run `flutter doctor --android-licenses` to accept the SDK licenses.
      See https://flutter.dev/docs/get-started/install/macos#android-setup for more details.
[✓] Xcode - develop for iOS and macOS (Xcode 14.0.1)
[✓] Chrome - develop for the web
[✓] Android Studio (version 2022.2)
[✓] Connected device (3 available)
[✓] Network resources

How to reproduce?

Flutter camera official example can be used. https://github.com/flutter/packages/blob/main/packages/camera/camera/example/lib/main.dart

Inside onTakePictureButtonPressed() just add code to save the imageFile https://github.com/flutter/packages/blob/ed1b0a3fb707ffd8a9577fbb4c99f4b345e22b71/packages/camera/camera/example/lib/main.dart#L707

final entity = await PhotoManager.editor.saveImage(
                imageFile,
                title: 'Photo${DateTime.now().millisecondsSinceEpoch}',
              );

No error is thrown, just discovered that entity is null.

My Manifest permissions:

    ....
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
    <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
    <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
    <uses-permission android:name="android.permission.READ_MEDIA_VISUAL_USER_SELECTED" />
    <uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION" />
    <uses-permission
        android:name="android.permission.WRITE_EXTERNAL_STORAGE"
        android:maxSdkVersion="29"/>
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
    <uses-permission android:name="android.permission.BACKGROUND_SERVICE" />

Is the issue just a configuration mistake?

Logs

No error is printed on console.

Example code (optional)

No response

Contact

No response

delfme avatar Oct 19 '23 16:10 delfme

Hello @CaiJingLong did extra tests and this looks weird.

I decided to test saving image after downloading a it from the web, using the same code of your example.

  final String imageUrl =
                  'https://ww4.sinaimg.cn/bmiddle/005TR3jLly1ga48shax8zj30u02ickjl.jpg';
              final HttpClient client = HttpClient();
              final HttpClientRequest req = await client.getUrl(Uri.parse(imageUrl));
              final HttpClientResponse resp = await req.close();
              final List<int> bytes = <int>[];
              resp.listen((List<int> data) {
                 bytes.addAll(data);
              }, onDone: () async {
                 await checkRequest(() async {
                   final image = typed_data.Uint8List.fromList(bytes);
                   final entity = await PhotoManager.editor.saveImage(
                   image,
                   title: 'Photo${DateTime.now().millisecondsSinceEpoch}',
              );

And entity is still null. This test was conducted to rule out that issue is somehow due to a corrupted file returned from flutter camera.

I also reinstalled app from scratch and tested it in both debug and release mode.

Then I compiled your example and I see no issue there. Code is exactly the same. The Manifest of the example has these permissions

  <uses-permission
        android:name="android.permission.WRITE_EXTERNAL_STORAGE"
        android:maxSdkVersion="29"/>
    <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
    <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
    <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
    <uses-permission android:name="android.permission.READ_MEDIA_VISUAL_USER_SELECTED" />
    <uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION" />

And they are all included in my Manifest as well.

From device settings, my app has all the permissions granted to your example app, no difference. In terms of permissions, user has been asked to grant:

  • access photos and videos
  • take photos and record videos
  • record audio

Any idea?

delfme avatar Oct 20 '23 08:10 delfme

On iOS it works only if I set set await PhotoManager.setIgnorePermissionCheck(false);

delfme avatar Oct 20 '23 08:10 delfme

Made another quick test to see if I can save image with a different plugin. Used this one https://pub.dev/packages/gal

I can save to gallery

await Gal.putImageBytes(image);
// instead of
 final entity = await PhotoManager.editor.saveImage(
   image,
   title: 'Photo${DateTime.now().millisecondsSinceEpoch}',
 );

Since PhotoManager.editor.saveImage doesnt throw error, I can't understand what it is. Permissions are all granted. LOGS:

permission access media location: true
permission access photos: true
permission access mediaLibrary: true
permission access photosAddOnly: false
permission access storage: false // this is false also with your 

Printing them through package permission_handler. But since that other plugin can save image, issue might be PhotoManager.editor.saveImage not running due permissions internal check or failing to save for some reason.

delfme avatar Oct 20 '23 12:10 delfme

@CaiJingLong Found the issue, it is not permission. Issue is method saveImage which returns null, saveImageWithPath works.

 final entity = await PhotoManager.editor.saveImageWithPath(
                file.path,
                title: 'Photo${DateTime.now().millisecondsSinceEpoch}',
              );

delfme avatar Oct 20 '23 15:10 delfme

@CaiJingLong Found the issue, it is not permission. Issue is method saveImage which returns null, saveImageWithPath works.

 final entity = await PhotoManager.editor.saveImageWithPath(
                file.path,
                title: 'Photo${DateTime.now().millisecondsSinceEpoch}',
              );

saveImageWithPath do not work for me

cmlanche avatar Dec 07 '23 00:12 cmlanche

I'm seeing the same issue on Android 7. And it works correctly on Android 11+ from my tests.

kaciula avatar Jan 03 '24 16:01 kaciula

Does it still reproducible with the latest version?

AlexV525 avatar Sep 16 '24 11:09 AlexV525