title: How to properly save a file in a shared folder in Xamarin?
body: <p>I've been trying to save a file, more precisely an image, in a shared folder (&quot;Downloads&quot;, &quot;Documents&quot;, etc...), but it seems that I'm missing something.</p>
  <p>This is the <code>MainPage.cs</code>:</p>
  <pre class="lang-cs prettyprint-override"><code>private async void GenerateQRCode()
  {
      // Generate QR Code
      QRCodeGenerator qrCodeGenerator = new QRCodeGenerator();
      QRCodeData qrCodeData = qrCodeGenerator.CreateQrCode(ShopName.ToUpper() + ShopLocation.ToUpper(), QRCodeGenerator.ECCLevel.Q);
      PngByteQRCode qRCode = new PngByteQRCode(qrCodeData);
      byte[] qrCodeBytes = qRCode.GetGraphic(20);
  
      // Set the new image source to be the QR Code
      QRCodeImage.Source = ImageSource.FromStream(() =&gt; new MemoryStream(qrCodeBytes));
  
      // Get the permissions
      PermissionStatus statusWrite = await Permissions.RequestAsync&lt;Permissions.StorageWrite&gt;();
      PermissionStatus statusRead = await Permissions.RequestAsync&lt;Permissions.StorageRead&gt;();
  
      // Debug the permissions
      await DisplayAlert(&quot;Write&quot;, statusWrite.ToString(), &quot;OK&quot;);
      await DisplayAlert(&quot;Read&quot;, statusRead.ToString(), &quot;OK&quot;);
  
      // Get the Downloads path (only Android)
      string path = (string)Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDownloads);
      
      // Get the final file name
      string fileName = Path.Combine(path, &quot;QRCode.png&quot;);
  
      // Debug the file name
      await DisplayAlert(&quot;Debug&quot;, fileName, &quot;OK&quot;);
  
      // Save the QR Code as a byte[]
      File.WriteAllBytes(path, qrCodeBytes);
  }
  </code></pre>
  <p>These are the permissions in the <code>AndroidManifest.xml</code>:</p>
  <pre class="lang-xml prettyprint-override"><code>&lt;uses-permission android:name=&quot;android.permission.ACCESS_NETWORK_STATE&quot; /&gt;
  &lt;uses-permission android:name=&quot;android.permission.READ_EXTERNAL_STORAGE&quot; /&gt;
  &lt;uses-permission android:name=&quot;android.permission.WRITE_EXTERNAL_STORAGE&quot; /&gt;
  </code></pre>
  <p>When I run this code I get this error:</p>
  <blockquote>
  <p>System.UnauthorizedAccessException: 'Access to the path '/storage/emulated/0/Download' is denied.'</p>
  </blockquote>
  <p>I've read that from <code>Android's API 23</code> the user has to accept the permissions at run-time, but I've tried many solutions, but it still tells me that the access is denied. (The debug messages I get from the code I've posted are (<code>Granted</code>, <code>Granted</code> and <code>/storage/emulated/0/Download/QRCode.png</code>).</p>
  <p>I've also read that <code>Android.OS.Environment.GetExternalStoragePublicDirectory</code> is deprecated, so if anyone has a &quot;newer&quot; way to get the desired directory, feel free to suggest!</p>
  <p><strong>UPDATE - MY SOLUTION:</strong></p>
  <p>Create a service interface in your &quot;Global Project&quot; (not only in the Android or in the iOS project) to make it more tidy:</p>
  <pre class="lang-cs prettyprint-override"><code>public interface IFileService
  {
      void Save(byte[] data, string name);
  }
  </code></pre>
  <p>Create a new <code>DependencyService</code> in your <strong>Android project</strong>:</p>
  <pre class="lang-cs prettyprint-override"><code>[assembly: Xamarin.Forms.Dependency(typeof(ProjectNamespace.Droid.FileService))]
  namespace ProjectNamespace.Droid
  {
      public class FileService : IFileService
      {
          public void Save(byte[] data, string name)
          {
              if (MainActivity.Instance.CheckSelfPermission(Manifest.Permission.WriteExternalStorage) == Android.Content.PM.Permission.Granted)
              {
                  string path = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDownloads).AbsolutePath;
                  string filePath = System.IO.Path.Combine(path, name);
                  FileOutputStream fileOutputStream = new FileOutputStream(new Java.IO.File(filePath));
                  fileOutputStream.Write(data);
                  fileOutputStream.Close();
              }
              else
              {
                  MainActivity.Instance.RequestPermissions(new string[] { Manifest.Permission.WriteExternalStorage }, 0);
              }
          }
      }
  }
  </code></pre>
  <p>Finally, in order to use <code>MainActivity</code>, we need a reference to it, and so I've created a Singleton (yeah, I know, I should have done it in a safer way, but since it was a learning project, I decided to make it in this way):</p>
  <pre class="lang-cs prettyprint-override"><code>
  public static MainActivity Instance { get; private set; }
  
  protected override void OnCreate(Bundle savedInstanceState)
  {
      ...
      Instance = this;
      ...
  }
  
  </code></pre>