0

I want to unzip a .zip file in removable sd card. I am selecting the .zip file using file picker. After selecting the file I get a path like this:

"content://com.android.externalstorage.documents/document/13E7-3B0A%3Azipfolder.zip" and after selecting the folder to unzip that file on selected location it gives some path like this "content://com.android.externalstorage.documents/tree/13E7-3B0A%3ALOST.DIR". After that i am using a method to unzip .zip file System.IO.Compression.ZipFile.ExtractToDirectory("content://com.android.externalstorage.documents/document/13E7-3B0A%3Azipfolder.zip", "content://com.android.externalstorage.documents/tree/13E7-3B0A%3ALOST.DIR");

but it gives the error which is mentioned below:

Unhandled Exception: System.UnauthorizedAccessException: Access to the path "/content:" is denied. occurred

I have also tried to give runtime permission but still, I am getting the same error. Please help me because I have given too much time on this

code for picking a file and getting a path

private async void SelectZipFile(object sender, EventArgs e)
        {
            string[] allowedTypes = { "application/zip" };//i use allowedType in PickFile for selecting only .zip file
            FileData file = await CrossFilePicker.Current.PickFile(allowedTypes);
            if (file != null)
            {
                //string filename = file.FileName;
                _zipFile = file.FilePath;//"content://com.android.externalstorage.documents/document/13E7-3B0A%3Azipfolder.zip"                
                txt1.Text = file.FileName;
                //int indx=_zipFile.IndexOf(filename);
                //string ss=_zipFile.Remove(indx);
                //_zipFile = ss + "/" + filename;
            }
        }

code for unzip file

public static void Unzip(String _location)
        {
            if (_location != null)
            {
                Label lbl1 = new Label();
                lbl1.Text = "Extracting files.......";
                System.IO.Compression.ZipFile.ExtractToDirectory(_zipFile, _location);
                lbl1.IsVisible = false;
            }                
        }

code for getting location

public void SelectDirectory()
        {
            try
            {
                activity = Xamarin.Forms.Forms.Context as MainActivity;
                activity.Intent = new Intent();
                activity.Intent.SetAction(Intent.ActionOpenDocumentTree);                              
                activity.StartActivityForResult(activity.Intent, REQUEST_CODE_OPEN_DIRECTORY);
                activity.ActivityResult += (object sender, ActivityResultEventArgs e) =>
                {
                    FolderPath = e.Intent.Data;
                    //string location = FolderPath.ToString();
                    //string[] arr = FolderPath.LastPathSegment.Split(":");
                    //int indx = location.IndexOf(arr[1]);
                    //string ss = location.Remove(indx);
                    //location = ss + "/" + arr[1];
                    MainPage.Unzip(FolderPath.ToString());
                };

            }
            catch(Exception ex)
            {
                string str = ex.ToString();
            }                       
        }
Asif Hussain
  • 93
  • 2
  • 3
  • 12
  • Based on your error message(access denied) , you could refer to this link https://stackoverflow.com/a/48414487/10627299, If you created this path by yourselves, you could share your code. – Leon May 06 '19 at 08:48
  • No i am not creating the path myself. After picking a file it gives that path. – Asif Hussain May 28 '19 at 04:07
  • Did you try to use dependence service to wirte data to external SD card? – Leon May 30 '19 at 08:14
  • how to use dependency services to wirte data to external SD card? – Asif Hussain Jun 13 '19 at 04:12

2 Answers2

0

You can use the library I created which makes the job so easy, works for SD Card, USB and external storage using android storage access framework (SAF): https://github.com/madnik7/PortableStorage

private const int browseRequestCode = 100; //Just a unique number

// Select a folder by Intent 
private void BrowseOnClick(object sender, EventArgs eventArgs)
{
     SafStorageHelper.BrowserFolder(this, browseRequestCode);
}

// Access the folder via SafStorgeProvider
protected override void OnActivityResult(int requestCode, [GeneratedEnum] Result resultCode, Intent data)
{
    base.OnActivityResult(requestCode, resultCode, data);
    if (requestCode == BROWSE_REQUEST_CODE && resultCode == Result.Ok)
    {
        var uri = SafStorageHelper.ResolveFromActivityResult(this, data);
        var storage = SafStorgeProvider.CreateStorage(this, uri);
        storage.CreateStorage("_PortableStorage.Test");
        storage.WriteAllText("test.txt", "123");
    }
}
Mohammad Nikravan
  • 1,543
  • 2
  • 19
  • 22
0

Unlike the internal SDcard folder, you are not allowed to access any arbitrary folder on the removable SD card except the folder that specifically for your own app, which is in the form of something like /storage/XXXX-XXXX/Android/data/Your_app_bundle_id/files

This is the restriction of the C# runtime, not by the Android system. You can still access to the removable SD card if using native plugins.

Ji Fang
  • 3,288
  • 1
  • 21
  • 18