siralam / BSImagePicker

An image picker that extends BottomSheetDialogFragment. Camera and gallery all in one dialog. Single or Multi Selection.
201 stars 62 forks source link

Samsung S8 - Unable to resolve image path #20

Closed LiamLamb closed 5 years ago

LiamLamb commented 6 years ago

Hi @siralam,

I'm using your plugin for an application that should support users to take picture and upload them to a server. Your plugin tool works great - but i have noticed a few small 'compatibility' issues when i comes to selecting images from the gallery on certain devices.

We develop on a number of devices, but Samsung generally seems to show the most amount of issues when it comes to working with the camera / gallery in general. The picker works fine on one of our Samsung devices (SM-G360F), but has issues on one of our later devices: Samsung Galaxy A5 (2017). The issues tends to be that it can't resolve the path of the selected image. Do you have any suggestion on how to fix this ?

I can send you more details about replicating the issue if you like, as well as some detailed error logging if that helps ?

I look forward to hearing from you.

Liam

EmmanuelGuther commented 5 years ago

Please can you tell us in which Android version it happens?

LiamLamb commented 5 years ago

Sure - We're running this application targetting Oreo

siralam commented 5 years ago

@LiamLamb Yes I do need more detailed logs as I don't have that particular device, do you have any?

LiamLamb commented 5 years ago

Hi @siralam and @EmmanuelGuther , Here are some details to help you reproduce the error. I would like to first give a bit of context as to what development environment we are in, what we are using etc.

We are developing an application as part of a cross platform project, using MvvmCross in Xamarin. All of the following code is therefore my interpretation into c#, which to be fair didn't really need much interpreting.

Android Environment Settings:

The permissions currently prompt on install are:

Steps that i've taken to setup the Image Picker on Android:

<provider android:name="android.support.v4.content.FileProvider" android:authorities="PACKAGENAME.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths"/> </provider>

`<?xml version="1.0" encoding="utf-8"?>

` - **FragmentViewWithBSImage**: On click method snippet for opening the image picker: ``` public void OnRandomButtonClick(object sender, EventArgs e) { try { //NOTE: It is intentional that we Set maximum display images to 2 as we currently only want to show // the gallery and camera button - as images don't always load correctly into the picker :( BSImagePicker singleSelectionPicker = new BSImagePicker.Builder("PACKAGENAME.fileprovider") .SetMaximumDisplayingImages(2) .SetSpanCount(2) .SetGridSpacing(Utils.Dp2Px(2)) .SetPeekHeight(Utils.Dp2Px(200)) .Build(); singleSelectionPicker.Show(ChildFragmentManager, "Picker"); } catch (Exception ex) { _logService.LogException("An error has occured opening the mother image picker.", ex); _alertService.ShowAlert("Information", "Something went wrong setting up the image picker. Please try again later."); } } ``` I then implement the IOnSingleImageSelectedListener to catch the selected image Uri ``` public void OnSingleImageSelected(Android.Net.Uri uri) { byte[] resizedImageBytes = null; try { // In the method below is where we get the issue var imageBytes = GetImageBytes(uri); resizedImageBytes = ResizeImage(imageBytes, uri); // Set the original image bytes to the image data. If the image data is null, then we will default to default image ViewModel.OriginalBytes = ViewModel.ImageData; // Set the image data to the new image bytes ViewModel.ImageData = resizedImageBytes; ViewModel.UploadEntryImageCommand.Execute(null); } catch (Exception ex) { _logService.LogException("An error has occured proessing a baby's selected image.", ex); _alertService.ShowAlert("Information", "Something went wrong processing the selected image. Please try again later."); ViewModel.ResetButtonsState(); } } ``` The method causing the actual exception: ``` // Method to get the image bytes in a helper class: public static byte[] GetImageBytes(Uri uri) { byte[] imageBytes = null; // This guy sometime throws an exception - whereby it cannot resolve the path provided. System.IO.Stream stream = Application.Context.ContentResolver.OpenInputStream(uri); using (var memoryStream = new MemoryStream()) { stream.CopyTo(memoryStream); imageBytes = memoryStream.ToArray(); } return imageBytes; } ``` These are pretty much the steps to reproduce the issue. As mentioned in my previous comments - this doesn't happen on all devices. It seems to however be happening on later devices like Samsung S8 and One+ 5 device. Here are some log of image pathing issues from today: **These logs are pulled from the exception during debugging:** ``` {Java.IO.FileNotFoundException: /0/1/content:/media/external/images/media/153678/ORIGINAL/NONE/879549069 (No such file or directory) at Java.Interop.JniEnvironment+InstanceMethods.CallNonvirtualVoidMethod (Java.Interop.JniObjectReference instance, Java.Interop.JniObjectReference type, Java.Interop.JniMethodInfo method, Java.Interop.JniArgumentValue* args) [0x00089] in <588bdbe85f2c4d10b23065ee1d01a212>:0 at Java.Interop.JniPeerMembers+JniInstanceMethods.FinishCreateInstance (System.String constructorSignature, Java.Interop.IJavaPeerable self, Java.Interop.JniArgumentValue* parameters) [0x0004f] in <588bdbe85f2c4d10b23065ee1d01a212>:0 at Android.Media.ExifInterface..ctor (System.String filename) [0x00072] in :0 at CompanyName.Droid.Helpers.EntryImageHelpers.ResizeImage (System.Byte[] originalBytes, Android.Net.Uri uri) [0x00065] in /Users/CompanyEngineer/Documents/_git/Central/PatientPortal/Mobile/CompanyName.Shared.Droid/Helpers/EntryImageHelpers.cs:186 at CompanyName.Droid.Views.PregnancyPlannerFragments.MotherOverviewView.OnSingleImageSelected (Android.Net.Uri uri) [0x00011] in /Users/CompanyEngineer/Documents/_git/Central/PatientPortal/Mobile/CompanyName.Shared.Droid/Views/PregnancyPlannerFragments/MotherOverviewView.cs:236 --- End of managed Java.IO.FileNotFoundException stack trace --- java.io.FileNotFoundException: /0/1/content:/media/external/images/media/153678/ORIGINAL/NONE/879549069 (No such file or directory) at java.io.FileInputStream.open0(Native Method) at java.io.FileInputStream.open(FileInputStream.java:200) at java.io.FileInputStream.(FileInputStream.java:150) at java.io.FileInputStream.(FileInputStream.java:103) at android.media.ExifInterface.(ExifInterface.java:1336) at com.asksira.bsimagepicker.BSImagePicker.n_onActivityResult(Native Method) at com.asksira.bsimagepicker.BSImagePicker.onActivityResult(BSImagePicker.java:88) at android.support.v4.app.FragmentActivity.onActivityResult(FragmentActivity.java:149) at md5c44e626e43e5b8d6d42d28410a243d52.MvxEventSourceAppCompatActivity.n_onActivityResult(Native Method) at md5c44e626e43e5b8d6d42d28410a243d52.MvxEventSourceAppCompatActivity.onActivityResult(MvxEventSourceAppCompatActivity.java:119) at android.app.Activity.dispatchActivityResult(Activity.java:7317) at android.app.ActivityThread.deliverResults(ActivityThread.java:4436) at android.app.ActivityThread.handleSendResult(ActivityThread.java:4484) at android.app.ActivityThread.-wrap19(Unknown Source:0) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1743) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loop(Looper.java:164) at android.app.ActivityThread.main(ActivityThread.java:6753) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:482) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807) } ```
siralam commented 5 years ago

I think there is a better way to convert Uri into byteArray.

For me, I usually turn the Uri into a File before I start working with it, so the File class looks promising to me, I think this SO post might help you, could you try with it first?

abbath0767 commented 5 years ago

Strange way. Why not use contentResolver.query(//...) for to get a string file path?