vinceglb / FileKit

Pick and save Files, Medias and Folder for Kotlin Multiplatform / KMP and Compose Multiplatform / CMP
https://vinceglb.github.io/FileKit/
MIT License
572 stars 16 forks source link

Good to know, a bit weird that we have to actually create the file and check its path from there when the file can be opened with the name, but idk, Android stuff #126

Closed N7ghtm4r3 closed 1 month ago

N7ghtm4r3 commented 1 month ago

Good to know, a bit weird that we have to actually create the file and check its path from there when the file can be opened with the name, but idk, Android stuff

Originally posted by @santiwanti in https://github.com/vinceglb/FileKit/issues/118#issuecomment-2377069412

Hi, unfortunately the issue was fixed just for the PickerType.Image(), because with the PickerType.File() the issue is the same.

My launcher is this:

// launcher to pick files
val launcher = rememberFilePickerLauncher(mode = PickerMode.Multiple()) { files ->
files?.forEach { asset ->
     val file = asset.path
   }            
 }

I dont know if the problem is related also whether the mode is PickerMode.Multiple or PickerMode.Single

vinceglb commented 1 month ago

Hi! I'm not able to reproduce your issue. Can you provide more details about your config:

Thanks for your help 🙏

N7ghtm4r3 commented 1 month ago

Hi, for sure! I'm using the emulator device Pixel 3aL on Android 14 (API 34). The problem occurs when the file picked is anyway an image, but chosen from the file manager instead of the picker where you can chose only the images or video from the gallery. The extension should be .jpg. With these details and the launcher setup can you reproduce the same scenario I have in my project or you need more specific code?

vinceglb commented 1 month ago

I used the sample-compose of this repository to try reproducing the issue. Here are the steps I tried:

path = /data/user/0/io.github.vinceglb.sample.compose/files/tanya-yarosh-ErnAQXPG2ns-unsplash.jpg
path = /data/user/0/io.github.vinceglb.sample.compose/files/juan-antonio-guzman-MjYYImZjfpE-unsplash.jpg

Do you have any other information that can help us reproduce the issue?

N7ghtm4r3 commented 1 month ago

Have you tried also to create a File with that Path? Because me too saw that path, but when I needed to create a file that error occured, I meant the same of the other issue

N7ghtm4r3 commented 1 month ago

java.io.FileNotFoundException: /data/user/0/com.tecknobit.nova/files/1000000076.jpg: open failed: ENOENT (No such file or directory) at libcore.io.IoBridge.open(IoBridge.java:574) at java.io.FileInputStream.<init>(FileInputStream.java:160) at kotlin.io.FilesKt__FileReadWriteKt.readBytes(FileReadWrite.kt:69) at com.tecknobit.equinox.environment.helpers.EquinoxRequester.changeProfilePic(EquinoxRequester.kt:141) at com.tecknobit.nova.ui.screens.profile.ProfileScreenViewModel.changeProfilePic$lambda$0(ProfileScreenViewModel.kt:56) at com.tecknobit.nova.ui.screens.profile.ProfileScreenViewModel.$r8$lambda$eBfBYVe1QE6psMVpXadslXm3BUg(Unknown Source:0) at com.tecknobit.nova.ui.screens.profile.ProfileScreenViewModel$$ExternalSyntheticLambda4.invoke(Unknown Source:2) at com.tecknobit.equinox.Requester.sendRequest(Requester.kt:513) at com.tecknobit.equinox.Requester.sendRequest$default(Requester.kt:507) at com.tecknobit.nova.ui.screens.profile.ProfileScreenViewModel.changeProfilePic(ProfileScreenViewModel.kt:54) at com.tecknobit.nova.ui.screens.profile.ProfileScreen.ArrangeScreenContent$lambda$3$lambda$2(ProfileScreen.kt:76) at com.tecknobit.nova.ui.screens.profile.ProfileScreen.$r8$lambda$DCOb9jXvX4cmYzRW_GrevacxOx8(Unknown Source:0) at com.tecknobit.nova.ui.screens.profile.ProfileScreen$$ExternalSyntheticLambda23.invoke(Unknown Source:6) at io.github.vinceglb.filekit.compose.FileKitComposeKt$rememberFilePickerLauncher$returnedLauncher$1$1$1.invokeSuspend(FileKitCompose.kt:52) at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33) at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:101) at androidx.compose.ui.platform.AndroidUiDispatcher.performTrampolineDispatch(AndroidUiDispatcher.android.kt:81) at androidx.compose.ui.platform.AndroidUiDispatcher.access$performTrampolineDispatch(AndroidUiDispatcher.android.kt:41) at androidx.compose.ui.platform.AndroidUiDispatcher$dispatchCallback$1.run(AndroidUiDispatcher.android.kt:57) at android.os.Handler.handleCallback(Handler.java:958) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loopOnce(Looper.java:205) at android.os.Looper.loop(Looper.java:294) at android.app.ActivityThread.main(ActivityThread.java:8177) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971) Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [androidx.compose.ui.platform.MotionDurationScaleImpl@8cc4b10, androidx.compose.runtime.BroadcastFrameClock@c3b0609, StandaloneCoroutine{Cancelling}@4ee800e, AndroidUiDispatcher@d64fa2f] Caused by: android.system.ErrnoException: open failed: ENOENT (No such file or directory) at libcore.io.Linux.open(Native Method) at libcore.io.ForwardingOs.open(ForwardingOs.java:563) at libcore.io.BlockGuardOs.open(BlockGuardOs.java:274) at libcore.io.ForwardingOs.open(ForwardingOs.java:563) at android.app.ActivityThread$AndroidOs.open(ActivityThread.java:8063) at libcore.io.IoBridge.open(IoBridge.java:560) ... 26 more

No idea beacause some times happens and other not, this is the picker of the images only

vinceglb commented 1 month ago

Sorry, but I don't understand how to reproduce your issue. Can you provide a reproducible example of the error with reproduction steps? That would help me to fix that issue. Thank you!

N7ghtm4r3 commented 1 month ago

Yes sure! I'll create a little demo repository and I'll invite you as collaborator

N7ghtm4r3 commented 1 month ago

I created the repository and invited you as collaborator!

vinceglb commented 1 month ago

Thank you! Now I understand and reproduce your behaviour.

By experimenting with your repository, I found that passing the Uri.path to a java.io.File isn't working as expected. I also tried Uri.toFile() but it throws an exception java.lang.IllegalArgumentException: Uri lacks 'file' scheme: ....

But by using androidx.DocumentFile on Android, I successfully created a DocumentFile from an Uri with this code: val document = DocumentFile.fromSingleUri(AppContext.get(), uri).

It seems like getting a java.io.File from an android.net.Uri is complicated: https://stackoverflow.com/a/49221353/7947225.

FileKit uses ActivityResultContracts.OpenDocument() and ActivityResultContracts.OpenMultipleDocuments() to open the file picker. That means that it can open a document that could not be a file like explained in the stackoverflow response.

But do you need to convert Android Uri to java.io.File? What are you trying to achieve?

If your need is to read the content of the file, you can use platformFile.readBytes(). It will work on every platform.

N7ghtm4r3 commented 1 month ago

Thank you for the explanation! I need to upload file picked to a server and to do that I need to get the content of the file as bytes and for that reason I was invoking that method from File. Sorry for this issue, I missed to read about the provided method from the PlatformFile. I'll try to use that method instead and if you need I'll let you know if it solves my scenario issue

vinceglb commented 1 month ago

No problem! Sure, let me know if everything is working properly for you 😄

N7ghtm4r3 commented 1 month ago

Yes absolutely! Can I delete the demo repo?

vinceglb commented 1 month ago

Yes you can!