siralam / BSImagePicker

An image picker that extends BottomSheetDialogFragment. Camera and gallery all in one dialog. Single or Multi Selection.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Samsung S8 - Unable to resolve image path

LiamLamb opened this issue · comments

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

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

Sure - We're running this application targetting Oreo

commented

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

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:

  • Target Version: 8.1 Oreo
  • Minimum Android Version: 4.4 KitKat

The permissions currently prompt on install are:

  • Internet
  • Network state access
  • Vibrate
  • Write external storage
  • Read external storage

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

  • Manifest File:
    The following was added into the 'Application' tag of the file.

<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/file_paths.xml:

<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <external-path name="external_files" path="." /> </paths>

  • 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 <d002c74216a24d44bf5e58a5ea253126>: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.<init>(FileInputStream.java:150)
	at java.io.FileInputStream.<init>(FileInputStream.java:103)
	at android.media.ExifInterface.<init>(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)
}
commented

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?

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