Search code examples
androidimagexamarinandroid-external-storage

Xamarin android display image from external Storage


I'm currently trying to displa an image from the storage, but I have no success.

What I'm dooing.

  public Stream ReadImage(string path) 
    {

        //var uri = Android.Net.Uri.Parse(path);
        //var stream = MainActivity._activity.ContentResolver.OpenInputStream(uri);
        //return stream;
        var memoryStream = new MemoryStream();

        using (var source = System.IO.File.OpenRead(path))
        {
            source.CopyTo(memoryStream);
        }

        return memoryStream;
    }

string path = "/storage/emulated/0/DCIM/Camera/IMG_20190521_094202.jpg"

     var imageSource = ImageSource.FromStream(
            delegate { 
                return DependencyService.Get<IMediaHelper>().ReadImage(path);
            });

But in the using line the programm doese not proceed, it does not reach the following lines and it does not load the file from the storage, the way with the contetn resolver does end teh same way, in the contentresolver line.

I have the Read/write external storage permission.

I am using android x, with Xamarin 5.0.0.2012. Under android 10 & and 11, on multiple different xiaomi devices.

This might be a bug, because I think, I had it running in an earlier project.

Some insight woult be appreciated, I'm biting my teath out on this nut.


Solution

  • To give users more control over their files and to limit file clutter, apps that target Android 10 (API level 29) and higher are given scoped access into external storage, or scoped storage, by default. Such apps have access only to the app-specific directory on external storage, as well as specific types of media that the app has created.You could read it here.

    For android 10,you could request the requestLegacyExternalStorage attribute in your Application tag in the AndroidManifest.

    <application android:label="NewForms.Android" android:resizeableActivity="true" android:requestLegacyExternalStorage="true" android:theme="@style/MainTheme"> 
    

    For android 11,you need add <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" /> in your AndroidManifest.And determine in the Activity whether the permission is enabled.

    And you can't forget to dynamically request WRITE_EXTERNAL_STORAGE permissions (this was added after Android 6.0,named Runtime Permissions).

    The final code is as follows:

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="com.companyname.newforms" android:installLocation="preferExternal">
    <uses-sdk android:minSdkVersion="18" android:targetSdkVersion="30" />
    <application android:label="NewForms.Android" android:requestLegacyExternalStorage="true" android:theme="@style/MainTheme"></application>   
       <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
       <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
       <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
    
    </manifest>
    

    and you could request the runtime permission like this in your MainActivity:

    RequestPermissions(new string[] { Manifest.Permission.WriteExternalStorage}, 0);
    if (Build.VERSION.SdkInt > BuildVersionCodes.Q)
          {
              if (!Environment.IsExternalStorageManager)
              {
                 StartActivityForResult(new Intent( Android.Provider.Settings.ActionManageAllFilesAccessPermission), 101);
              }
          }