title: How To Properly Save To The Pictures Folder
body: <p>I am trying to save a bitmap that is created by the user to the default 'Pictures' folder on the device. I will start with the option that seems to be the more common method:</p>
  
  <pre><code>public void saveImageToExternalStorage(String filename, Bitmap image) {
      String path = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator;
      try {
          File directory = new File(path);
          if (!directory.exists()) {
              directory.mkdirs();
          }
  
          File file = new File(directory, filename + ".jpeg");
          file.createNewFile();
  
          OutputStream outputStream = new FileOutputStream(file);
          image.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
  
          outputStream.flush();
          outputStream.close();
      } catch (IOException exception) {
          exception.printStackTrace();
      }
  }
  </code></pre>
  
  <p>This is supposed to save to the 'Pictures' folder, but <code>Environment.getExternalStorageDirectory().getAbsolutePath()</code> seems to create a new file structure like this <code>file://storage/emulated/11/Pictures/</code> and save the picture to that. I have also tried <code>Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)</code> with the same result. But this is not the default 'Pictures' folder on any of my test devices or emulators. Which led me to look for other methods, and I found this:</p>
  
  <pre><code>public void saveImageToExternalStorage(String filename, Bitmap image) {
      try {
          ContentValues values = new ContentValues();
          values.put(MediaStore.Images.Media.TITLE, filename);
          values.put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis());
          values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
  
          Uri filepath = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
          OutputStream outputStream = getContentResolver().openOutputStream(filepath);
  
          image.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
          outputStream.close();
      } catch (IOException exception) {
          exception.printStackTrace();
      }
  }
  </code></pre>
  
  <p>This actually saves to the default file structure, which apparently looks like this: <code>content://media/external/images/media/4282</code>. But there seems to be no way to specify the filename of the image (<code>Media.TITLE</code> just sets the title attribute, not the actual filename), it saves as a (seemingly) random string of numbers. I looked at the <a href="http://developer.android.com/reference/android/provider/MediaStore.Images.Media.html" rel="noreferrer">API Guide</a> for <code>MediaStore.Images.Media</code> and there does not seem to be any other variable that would set the filename. This also does not seem to be the correct way of saving, according to the <a href="http://developer.android.com/training/basics/data-storage/files.html" rel="noreferrer">Android Developer Guides</a>. I would like to know if there is any way of saving to this folder, while also setting my own filename. And if this method could produce unforeseen problems on other devices.</p>
  
  <p><strong>EDIT:</strong>
  For anyone interested this is my current code, based on the answer by @CommonsWare:</p>
  
  <pre><code>public void saveImageToExternalStorage(Context context, String filename, Bitmap image) throws IOException {
      File directory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
      File file = new File(directory, filename + ".jpeg");
  
      FileOutputStream outputStream = new FileOutputStream(file);
      mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
  
      outputStream.flush();
      outputStream.getFD().sync();
      outputStream.close();
  
      MediaScannerConnection.scanFile(context, new String[] {file.getAbsolutePath()}, null, null);
  }
  </code></pre>