natsuk4ze / gal

How to Save Image or Video to Photo Gallery in Flutter
https://pub.dev/packages/gal
BSD 3-Clause "New" or "Revised" License
82 stars 12 forks source link

Android: Failed to build unique file #198

Closed Lo4D closed 5 months ago

Lo4D commented 5 months ago

Did you check the documentation and it did not help?

Overview

Hi! I use Gal.putImageBytes() and it saves image as image.png. Everything was fine, until the image(32).png, meaning that image(31).png is created perfectly fine, but next one is not. I've tested it by deleting image(31).png and it worked fine again, but not after it. I'm testing on POCO F4 with android 13.

I'm not sure if one will encounter the same error on other devices. But please, consider adding a String name = 'image.png' as a putImageBytes() paramater.

Steps to reproduce

  1. Save any Uint8List image using Gal.putImageBytes
  2. Repeat 31 times
  3. Bug occures

Code sample

Code sample ```dart Future _saveImage(Uint8List screenshot) async { try { await Gal.putImageBytes(screenshot); setState(() { _isSaving = false; }); } catch (e) { log(e.toString()); setState(() { _isSaving = false; }); } } ```

Environment

Logs ```console [✓] Flutter (Channel stable, 3.16.3, on Ubuntu 22.04.3 LTS 6.5.0-14-generic, locale ru_RU.UTF-8) • Flutter version 3.16.3 on channel stable at /home/lo4d/.puro/envs/stable/flutter • Upstream repository https://github.com/flutter/flutter.git • Framework revision b0366e0a3f (7 недель назад), 2023-12-05 19:46:39 -0800 • Engine revision 54a7145303 • Dart version 3.2.3 • DevTools version 2.28.4 [✓] Android toolchain - develop for Android devices (Android SDK version 34.0.0) • Android SDK at /home/lo4d/Android/Sdk • Platform android-34, build-tools 34.0.0 • Java binary at: /home/lo4d/.local/share/JetBrains/Toolbox/apps/android-studio/jbr/bin/java • Java version OpenJDK Runtime Environment (build 17.0.7+0-17.0.7b1000.6-10550314) • All Android licenses accepted. [✓] Chrome - develop for the web • Chrome at google-chrome [✗] Linux toolchain - develop for Linux desktop ✗ clang++ is required for Linux development. It is likely available from your distribution (e.g.: apt install clang), or can be downloaded from https://releases.llvm.org/ ✗ CMake is required for Linux development. It is likely available from your distribution (e.g.: apt install cmake), or can be downloaded from https://cmake.org/download/ ✗ ninja is required for Linux development. It is likely available from your distribution (e.g.: apt install ninja-build), or can be downloaded from https://github.com/ninja-build/ninja/releases • pkg-config version 0.29.2 ✗ GTK 3.0 development libraries are required for Linux development. They are likely available from your distribution (e.g.: apt install libgtk-3-dev) [✓] Android Studio (version 2023.1) • Android Studio at /home/lo4d/.local/share/JetBrains/Toolbox/apps/android-studio • Flutter plugin version 77.1.2 • Dart plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/6351-dart • Java version OpenJDK Runtime Environment (build 17.0.7+0-17.0.7b1000.6-10550314) [✓] Connected device (3 available) • 22021211RG (mobile) • 2e9e00b9 • android-arm64 • Android 13 (API 33) • Linux (desktop) • linux • linux-x64 • Ubuntu 22.04.3 LTS 6.5.0-14-generic • Chrome (web) • chrome • web-javascript • Google Chrome 120.0.6099.224 [✓] Network resources • All expected network resources are available. ! Doctor found issues in 1 category. ```

Logs

Logs ```console PlatformException(UNEXPECTED, java.lang.IllegalStateException: Failed to build unique file: /storage/emulated/0/Pictures/image.png owner_package_name=net.removebackground.photoeditor.filterseffects _display_name=image.png mime_type=image/png _data=/storage/emulated/0/Pictures/image.png relative_path=Pictures/, android.os.Parcel.createExceptionOrNull(Parcel.java:3019) android.os.Parcel.createException(Parcel.java:2995) android.os.Parcel.readException(Parcel.java:2978) android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:190) android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:142) android.content.ContentProviderProxy.insert(ContentProviderNative.java:557) android.content.ContentResolver.insert(ContentResolver.java:2196) android.content.ContentResolver.insert(ContentResolver.java:2157) studio.midoridesign.gal.GalPlugin.writeData(GalPlugin.java:141) studio.midoridesign.gal.GalPlugin.putMediaBytes(GalPlugin.java:132) studio.midoridesign.gal.GalPlugin.lambda$onMethodCall$3$studio-midoridesign-gal-GalPlugin(GalPlugin.java:80) studio.midoridesign.gal.GalPlugin$$ExternalSyntheticLambda2.run(Unknown Source:6) java.lang.Thread.run(Thread.java:1012) , null) ```
natsuk4ze commented 5 months ago

Thank you for filling this issue @Lo4D I have identified the cause of this.

https://takusan.negitoro.dev/posts/android_unique_file/

This article is in Japanese, but is well organized. And I am now working on a solution.

natsuk4ze commented 5 months ago

This issue has been resolved. The latest version will be uploaded to pub.dev later.

No changes have been made to add parameters to putImageBytes at this time. The problem is that Java only checks up to 31 times to create a unique file name. The best solution is to allow users to save media without worrying about duplicate names, not to allow users to specify names for avoiding duplicates.

Lo4D commented 5 months ago

Thanks for your fix, @natsuk4ze !  I wanted to specify a name not to allow users to specify a file name, but to save files with the name of my app, for example, and not generic image.png. I think it would not hurt to have such a paramater. But nonetheless, I'm glad you were able to fix this Java check-up thing

natsuk4ze commented 5 months ago

Thanks for your fix, @natsuk4ze ! 

You're welcome, adding a parameter to putImageBytes is not a bad idea, but it has nothing to do with this bug, so it was passed up.

ellet0 commented 5 months ago

Thanks for your fix, @natsuk4ze !

You're welcome, adding a parameter to putImageBytes is not a bad idea, but it has nothing to do with this bug, so it was passed up.

Why there is a default value for the name parameter? if the user use it multiple times it will cause exception because image.png is already exists

Maybe it's better if it required instead of a default value?

natsuk4ze commented 5 months ago

it will cause exception because image.png is already exists

Is that true? The system should automatically avoid duplicates even if they have the same file name.

ellet0 commented 5 months ago

it will cause exception because image.png is already exists

Is that true? The system should automatically avoid duplicates even if they have the same file name.

I updated gal_linux

static Future putImageBytes(Uint8List bytes, {String? album, required String name}) async { final fileName = '$name.png'; }

Is that code correct?

natsuk4ze commented 5 months ago

static Future putImageBytes(Uint8List bytes, {String? album, required String name}) async { final fileName = '$name.png'; }

Is that code correct?

What is this code?

ellet0 commented 5 months ago

static Future putImageBytes(Uint8List bytes, {String? album, required String name}) async { final fileName = '$name.png'; }

Is that code correct?

What is this code?

The implementation of gal_linux

I'm trying to update gal_linux to be compatible with 2.3.0 of gal

You have added a new parameter called name so I'm trying to adapt the new way of generating file name

natsuk4ze commented 5 months ago

static Future putImageBytes(Uint8List bytes, {String? album, required String name}) async { final fileName = '$name.png'; } Is that code correct?

What is this code?

The implementation of gal_linux

I'm trying to update gal_linux to be compatible with 2.3.0 of gal

You have added a new parameter called name so I'm trying to adapt the new way of generating file name

discord