Saving files to "/storage/emulated/0/MyApp"

Jesse Knott 686 Reputation points
2022-03-04T02:57:37.8+00:00

Hello, I have been using this code to create and use a directory for storing my files, and reports.

        public async Task<string> CreateSavePath(string path = null)
    {
        var filePath = Path.Combine(Android.OS.Environment.ExternalStorageDirectory.AbsolutePath, StringTools.GetStringResource("szSaveFolder"));


        try
        {
            Directory.CreateDirectory(filePath);
        }
        catch (Exception ex)
        {
            Debug.WriteLine($"SaveAndroid.cs->GetSavePath():{ex.Message}{Environment.NewLine}{ex.InnerException}{Environment.NewLine}{ex.StackTrace}");
        }

        var nomediaFile = Path.Combine(filePath, ".NOMEDIA");

        if (!File.Exists(nomediaFile))
        {
            try
            {
                File.Create(nomediaFile);
            }
            catch (Exception ex)
            {
                Debug.WriteLine("Error creating .NOMEDIA in save path" + Environment.NewLine + ex.Message);
            }
        }

        if (path != null)
        {
            //Now create the nested folders requested
            filePath = Path.Combine(filePath, path);

            if (!Directory.Exists(filePath))
            {
                try
                {
                    Directory.CreateDirectory(filePath);
                }
                catch (Exception ex)
                {
                    Debug.WriteLine($"SaveAndroid.cs->GetSavePath():{ex.Message}{Environment.NewLine}{ex.InnerException}{Environment.NewLine}{ex.StackTrace}");
                }
            }

            //Using the combined paths, create the nomedia file for that folder.
            nomediaFile = Path.Combine(filePath, ".NOMEDIA");

            if (!File.Exists(nomediaFile))
            {
                try
                {
                    File.Create(nomediaFile);
                }
                catch (Exception ex)
                {
                    Debug.WriteLine("Error creating .NOMEDIA in save path" + Environment.NewLine + ex.Message);
                }
            }
        }

        return filePath;
    }

To make this work on Android 10+ I've added the following line to the AndroidManifest.xml

     android:requestLegacyExternalStorage="true"

Sadly it seems that this workaround no longer works, and I can't create the folder, or files in this location anymore.

Is there a workaround that I can use to keep using this path, or do I need to create a new path structure? Creating a new path would be problematic for interactions with older versions of the app, but provided I can still access it if it already exists, I can probably make a wrapper to migrate the files in future versions of the app.

Cheers!

Xamarin
Xamarin
A Microsoft open-source app platform for building Android and iOS apps with .NET and C#.
5,325 questions
{count} vote

Accepted answer
  1. Leon Lu (Shanghai Wicresoft Co,.Ltd.) 72,171 Reputation points Microsoft Vendor
    2022-03-04T05:50:35.27+00:00

    Hello,​

    To make this work on Android 10+ I've added the following line to the AndroidManifest.xml android:requestLegacyExternalStorage="true"

    Sadly it seems that this workaround no longer works, and I can't create the folder, or files in this location anymore.

    Yes, if you set the target framework to the Android 10 later, this android:requestLegacyExternalStorage not work, Please see Storage updates in Android 11.

    or do I need to create a new path structure?

    Yes, please save your files to internal path like using FileSystem.AppDataDirectory; instead of Android.OS.Environment.ExternalStorageDirectory.AbsolutePath from Xamarin Essentials: File System Helpers

    Is there a workaround that I can use to keep using this path,

    Yes, have a workaround, but I do not recommend to request MANAGE_EXTERNAL_STORAGE permission. this permission is designed for apps requesting access to the all files access permission, intended and permitted use includes file managers, backup and restore apps, anti-virus apps, and document management apps. If your application is not these types and request this permission, your application will be rejected by google play store.

    Best Regards,

    Leon Lu


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


1 additional answer

Sort by: Most helpful
  1. saudi android 0 Reputation points
    2023-03-26T21:16:47.6133333+00:00
    public async Task<string> CreateSavePath(string path = null)
        {
            var filePath = Path.Combine(Android.OS.Environment.ExternalStorageDirectory.AbsolutePath, StringTools.GetStringResource("szSaveFolder"));
    
    
            try
            {
                Directory.CreateDirectory(filePath);
            }
            catch (Exception ex)
            { app-47--71769067--1625235312
                Debug.WriteLine($"SaveAndroid.cs->GetSavePath():{ex.Message}{Environment.NewLine}{ex.InnerException}{Environment.NewLine}{ex.StackTrace}");
            } app-47--1547699361-1008775857
    
            var nomediaFile = Path.Combine(filePath, ".NOMEDIA");
    
            if (!File.Exists(nomediaFile))
            {
                try
                { analysis_main
                    File.Create(nomediaFile);
                }
                catch (Exception ex)
                {
                    Debug.WriteLine("Error creating .NOMEDIA in save path" + Environment.NewLine + ex.Message);
                }
            }
    
            if (path != null)
            {
                //Now create the nested folders requested
                filePath = Path.Combine(filePath, path);
    
                if (!Directory.Exists(filePath))
                {
                    try
                    {
                        Directory.CreateDirectory(filePath);
                    }
                    catch (Exception ex)
                    {
                        Debug.WriteLine($"SaveAndroid.cs->GetSavePath():{ex.Message}{Environment.NewLine}{ex.InnerException}{Environment.NewLine}{ex.StackTrace}");
                    }
                }
    
                //Using the combined paths, create the nomedia file for that folder.
                nomediaFile = Path.Combine(filePath, ".NOMEDIA");
    
                if (!File.Exists(nomediaFile))
                {
                    try
                    {
                        File.Create(nomediaFile);
                    }
                    catch (Exception ex)
                    {
                        Debug.WriteLine("Error creating .NOMEDIA in save path" + Environment.NewLine + ex.Message);
                    }
                }
            }
    
            return filePath;
        }
    var newPath = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDocuments);  
            var filePath = Path.Combine(newPath.AbsolutePath, StringTools.GetStringResource("szSaveFolder"));  
    
    
            try  
            {  
                Directory.CreateDirectory(filePath);  
            }  
            catch (Exception ex)  
            {  
                Debug.WriteLine($"SaveAndroid.cs->GetSavePath():{ex.Message}{Environment.NewLine}{ex.InnerException}{Environment.NewLine}{ex.StackTrace}");  
            }app-47--1770011590  -808201043  
    Skip to main content
    
    Q&A
    Global navigation
    Saving files to "/storage/emulated/0/MyApp"
    
    Jesse Knott
    666Reputation points
    Mar 4, 2022, 5:57 AM
    Hello, I have been using this code to create and use a directory for storing my files, and reports.
    
    
    Copy
            public async Task<string> CreateSavePath(string path = null)
        {
            var filePath = Path.Combine(Android.OS.Environment.ExternalStorageDirectory.AbsolutePath, StringTools.GetStringResource("szSaveFolder"));
    
    
            try
            {
                Directory.CreateDirectory(filePath);
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"SaveAndroid.cs->GetSavePath():{ex.Message}{Environment.NewLine}{ex.InnerException}{Environment.NewLine}{ex.StackTrace}");
            }
    
            var nomediaFile = Path.Combine(filePath, ".NOMEDIA");
    
            if (!File.Exists(nomediaFile))
            {
                try
                {
                    File.Create(nomediaFile);
                }
                catch (Exception ex)
                {
                    Debug.WriteLine("Error creating .NOMEDIA in save path" + Environment.NewLine + ex.Message);
                }
            }
    
            if (path != null)
            {
                //Now create the nested folders requested
                filePath = Path.Combine(filePath, path);
    
                if (!Directory.Exists(filePath))
                {
                    try
                    {
                        Directory.CreateDirectory(filePath);
                    }
                    catch (Exception ex)
                    {
                        Debug.WriteLine($"SaveAndroid.cs->GetSavePath():{ex.Message}{Environment.NewLine}{ex.InnerException}{Environment.NewLine}{ex.StackTrace}");
                    }
                }
    
                //Using the combined paths, create the nomedia file for that folder.
                nomediaFile = Path.Combine(filePath, ".NOMEDIA");
    
                if (!File.Exists(nomediaFile))
                {
                    try
                    {
                        File.Create(nomediaFile);
                    }
                    catch (Exception ex)
                    {
                        Debug.WriteLine("Error creating .NOMEDIA in save path" + Environment.NewLine + ex.Message);
                    }
                }
            }
    
            return filePath;
        }
    To make this work on Android 10+ I've added the following line to the AndroidManifest.xml
    
    
    Copy
         android:requestLegacyExternalStorage="true"
    Sadly it seems that this workaround no longer works, and I can't create the folder, or files in this location anymore.
    
    Is there a workaround that I can use to keep using this path, or do I need to create a new path structure? Creating a new path would be problematic for interactions with older versions of the app, but provided I can still access it if it already exists, I can probably make a wrapper to migrate the files in future versions of the app.
    
    Cheers!
    
    Xamarin
     0No comments
    Sign in to follow
    
    Report
    I have the same question 
    1
    1 vote
    Sign in to comment
     Accepted answer
    
    Leon Lu (Shanghai Wicresoft Co,.Ltd.)
    43,931 Reputation points• Microsoft Vendor
    Mar 4, 2022, 8:50 AM
    Hello,
    
    To make this work on Android 10+ I've added the following line to the AndroidManifest.xml android:requestLegacyExternalStorage="true"
    
    Sadly it seems that this workaround no longer works, and I can't create the folder, or files in this location anymore.
    
    Yes, if you set the target framework to the Android 10 later, this android:requestLegacyExternalStorage not work, Please see Storage updates in Android 11.
    
    or do I need to create a new path structure?
    
    Yes, please save your files to internal path like using FileSystem.AppDataDirectory; instead of Android.OS.Environment.ExternalStorageDirectory.AbsolutePath from Xamarin Essentials: File System Helpers
    
    Is there a workaround that I can use to keep using this path,
    
    Yes, have a workaround, but I do not recommend to request MANAGE_EXTERNAL_STORAGE permission. this permission is designed for apps requesting access to the all files access permission, intended and permitted use includes file managers, backup and restore apps, anti-virus apps, and document management apps. If your application is not these types and request this permission, your application will be rejected by google play store.
    
    Best Regards,
    
    Leon Lu
    
    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".
    
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.
    
    Please sign in to rate this answer.
     0No comments
    Report
    Sign in to comment
    2 additional answers
    Sort by: Most helpful 
    
    Jesse Knott
    666Reputation points
    Mar 5, 2022, 5:31 PM
    @Leon Lu (Shanghai Wicresoft Co,.Ltd.) Hello, Sorry for the late response, I've got too many irons in too many fires right now.
    The only problem I have with this solution is I need to have access to the folder for the user.
    This folder is going to be a location that reports, and backups are stored. This should then be accessible by the user via an OS browser app (or built in file browser).
    
    I definitely don't want to go for wide reaching OS access, it's a shame that it seems to be an all or nothing type API.
    
    I would write to the OS "Documents" folder, but I've never figured out how to access it directly. I will also need a way to do this for iOS, and potentially for UWP.
    
    Thanks for the help!
    
    Please sign in to rate this answer.
     0No comments
    Report
    Sign in to comment
    
    Jesse Knott
    666Reputation points
    Mar 5, 2022, 5:50 PM
    @Leon Lu (Shanghai Wicresoft Co,.Ltd.) Okay, this is one of the thing's I've always loved and hated about programming at the same time...
    I just tried running the following code, and it appears to be working LOL.
    Is the following code viable?
    Am I really this dense, that I somehow overlooked this!?
    
    
    Copy
     var newPath = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDocuments);  
            var filePath = Path.Combine(newPath.AbsolutePath, StringTools.GetStringResource("szSaveFolder"));  
    
    
            try  
            {  
                Directory.CreateDirectory(filePath);  
            }  
            catch (Exception ex)  
            {  
                Debug.WriteLine($"SaveAndroid.cs->GetSavePath():{ex.Message}{Environment.NewLine}{ex.InnerException}{Environment.NewLine}{ex.StackTrace}");  
            }  
    Cheers!
    
    Please sign in to rate this answer.
     0No comments
    Report
    Sign in to comment
    Sign in to answer
    
    Theme
    Previous Versions
    Blog
    Contribute
    Privacy
    Terms of Use
    Code of Conduct
    Trademarks
    © Microsoft 2023
    
    
    0 comments No comments