1

I started an Intent

Intent = new Intent();
Intent.SetType("image/*");
Intent.PutExtra(Intent.ExtraAllowMultiple,true);
Intent.SetAction(Intent.ActionGetContent);
StartActivityForResult(Intent.CreateChooser(Intent, "Select Picture"), code);`

I am working with bitmap.Compress(...) function and took the uri from above intent. I want to delete that bitmap file and recreate the file with the same name (in short: Replacing the existing file).

My physical devices is Samsung J5 having Internal storage and external sd card storage like /storage/emulated/0/ and /storage/D660-18BD/ (D668-18BD is not fixed, it changes according to devices).

When I tried to create a new file in the storage/D660-18BD/newfile.jpg, it says Access to the path is denied.

I googled a lot but no success

What I had tried 1. Added Read/Write External Storage (but android take it as Internal storage) in the manifest file 2. Added the above permission at Runtime also alongwith Read/Write URI permission.

Amit
  • 264
  • 1
  • 4
  • 18
  • As I already stated that `storage/D660-18BD/` is an external storage that holds by SD card slot (its an mmc card). You can observe that ES File explorer can write into any path of that card (sometimes it needs to inkove the permission) flawlessly. What I have to do to create file/folder in any path of the card – Amit Jan 24 '18 at 10:12

1 Answers1

2

Here is a demo in the thread, download it, it is a Xamarin.Forms project,

1) Run it on your phone, then it will create this path:/storage/11E3-2116/Android/data/com.companyname.cropsample/files/Pictures

2) Add this in the MainActivity, under LoadApplication(new App());:

    Java.IO.File sdCardPath = Environment.GetExternalStoragePublicDirectory(Environment.DirectoryPictures);
    //  filePath: /storage/11E3-2116/Android/data/com.companyname.cropsample/files/Pictures
    string destPath = Path.Combine("/storage/11E3-2116/Android/data/com.companyname.cropsample/files/Pictures/", "test.png");
    string originPath = Path.Combine(sdCardPath.AbsolutePath, "nULSa.png");
    Android.Util.Log.Error("lv", destPath);
    FileOutputStream fos = new FileOutputStream(destPath, false);
    FileInputStream fis = new FileInputStream(originPath);
    int b;
    byte[] d = new byte[1024 * 1024];
    while ((b = fis.Read(d)) != -1)
    {
        fos.Write(d, 0, b);
    }
    fos.Flush();
    fos.Close();
    fis.Close();

storage/D660-18BD/ is wrong path, you can't get the permission, you have the permission only in your package folder. So you need create the path. Sorry I can't find where the path created, maybe you can find it.

This is the result:

enter image description here

The only thing you need to is to create this path: /storage/11E3-2116/Android/data/com.companyname.cropsample/files/Pictures firstly, once it created, then you can write. I hope it will help.


Update:

I find the solution:

using Android.App;
using Android.Widget;
using Android.OS;
using System.IO;
using Java.IO;
using System.Collections.Generic;
using Android.Content;
using Android.OS.Storage;
using Java.Lang.Reflect;
using System;

namespace WritToSd
{
    [Activity(Label = "WritToSd", MainLauncher = true)]
    public class MainActivity : Activity
    {
        string s;
        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);

            // Set our view from the "main" layout resource
            SetContentView(Resource.Layout.Main);
            // important codes start:
            List<string> avaliableStorages = getAvaliableStorages(this);

            for (int i=0;i<avaliableStorages.Count;i++) {
                // because there is only one external sd card, so s is the path we need.
                s = avaliableStorages[i];
            }

            var str=this.GetExternalFilesDir(null).AbsolutePath;
            string direction = s + "/Android/data/" + this.PackageName + "/files/Pictures";
            Java.IO.File file = new Java.IO.File(direction);
            if (!file.Exists())
            {
                file.Mkdirs();
            }
            // end
            Java.IO.File sdCardPath = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryPictures);
            //  filePath: /storage/11E3-2116/Android/data/com.companyname.cropsample/files/Pictures
            string destPath = Path.Combine(direction, "test.png");
            string originPath = Path.Combine(sdCardPath.AbsolutePath, "test.png");
            Android.Util.Log.Error("lv", destPath);
            FileOutputStream fos = new FileOutputStream(destPath, false);
            FileInputStream fis = new FileInputStream(originPath);
            int b;
            byte[] d = new byte[1024 * 1024];
            while ((b = fis.Read(d)) != -1)
            {
                fos.Write(d, 0, b);
            }
            fos.Flush();
            fos.Close();
            fis.Close();

        }
        public List<string> getAvaliableStorages(Context context)
        {
            List<string> list = null;
            try
            {

                var storageManager = (Android.OS.Storage.StorageManager)context.GetSystemService(Context.StorageService);

                var volumeList = (Java.Lang.Object[])storageManager.Class.GetDeclaredMethod("getVolumeList").Invoke(storageManager);

                list = new List<string>();

                foreach (var storage in volumeList)
                {
                    Java.IO.File info = (Java.IO.File)storage.Class.GetDeclaredMethod("getPathFile").Invoke(storage);

                    if ((bool)storage.Class.GetDeclaredMethod("isEmulated").Invoke(storage) == false && info.TotalSpace > 0)
                    {
                        list.Add(info.Path);
                    }
                }
            }
            catch (Exception e)
            {

            }
            return list;
        }



    }

}
}
Robbit
  • 4,300
  • 1
  • 13
  • 29
  • I can able to create file in `storage/11E3-2116/Android/data/com.companyname.cropsample/files/Pictures` but I don't want this, when user uninstall the app then those folder will automatically get deleted because it was a part of app. I want to create file in the `storage/11E3-2116/newfile.jpg` (in the storage root and not inside the app folder. As I am able to read all the file/folder from the sd card but unable to create file. As I have to perform the task in a bulk so I need to delete the existing uri file and create a new uri file from where the user had picked the file. – Amit Jan 24 '18 at 10:00
  • If I don't​ have the right to write at the destination url, atleast my app have that permission to create a folder and save the images. Hope you got my point – Amit Jan 24 '18 at 10:00
  • You can't create this `storage/11E3-2116/newfile.jpg`, unless you have the root permission. By `when user uninstall the app then those folder will automatically get deleted because it was a part of app`, `/storage/emulated/0/Pictures` is the right path to write. – Robbit Jan 24 '18 at 10:06
  • My phone is not rooted and ES File Explorer just ctrates the file wherever I want – Amit Jan 24 '18 at 10:14
  • I understand that writing files on emulated storage is the correct path to write but when this storage is full then user might have some external sd card storage, right? He should pick the file from there – Amit Jan 24 '18 at 10:17
  • I have searched it, it said , <4.4, you can write any where in the sdcard, >=4.4, you only can write the specific path. Maybe there is hack in EX. – Robbit Jan 24 '18 at 10:20
  • I found it, it is hack, I can't help you, sorry. – Robbit Jan 24 '18 at 10:27
  • > kitkat requures SAF (storage access framework) and Es File Explorer uses that to create that, if ES can then why can't my app? – Amit Jan 24 '18 at 10:31
  • [Have you seen this permission `android.permission.WRITE_MEDIA_STORAGE`](https://stackoverflow.com/questions/12853752/eaccess-permission-denied-in-android) – Robbit Jan 24 '18 at 10:56