Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Environment.getExternalStorageDirectory() deprecated in API level 29 java

Working on android Java, recently updated SDK to API level 29 now there is a warning shown which states that

Environment.getExternalStorageDirectory() is deprecated in API level 29

My code is

private void saveImage() {

if (requestPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {

    final String folderPath = Environment.getExternalStorageDirectory() + "/PhotoEditors";
    File folder = new File(folderPath);
    if (!folder.exists()) {
        File wallpaperDirectory = new File(folderPath);
        wallpaperDirectory.mkdirs();
    }


    showLoading("Saving...");
    final String filepath=folderPath
                + File.separator + ""
                + System.currentTimeMillis() + ".png";
    File file = new File(filepath);

    try {
        file.createNewFile();
        SaveSettings saveSettings = new SaveSettings.Builder()
                .setClearViewsEnabled(true)
                .setTransparencyEnabled(true)
                .build();
        if(isStoragePermissionGranted() ) {
            mPhotoEditor.saveAsFile(file.getAbsolutePath(), saveSettings, new PhotoEditor.OnSaveListener() {
            @Override
            public void onSuccess(@NonNull String imagePath) {
                hideLoading();
                showSnackbar("Image Saved Successfully");
                mPhotoEditorView.getSource().setImageURI(Uri.fromFile(new File(imagePath)));
                sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,Uri.fromFile(new File(filepath))));
                Intent intent = new Intent(EditImageActivity.this, StartActivity.class);
                startActivity(intent);
                finish();

            } 

            @Override
            public void onFailure(@NonNull Exception exception) {
                hideLoading();
                showSnackbar("Failed to save Image");
            }
       });
   }

What will be the alternative for this?

like image 915
Noaman Akram Avatar asked Oct 14 '22 21:10

Noaman Akram


People also ask

What is environment getExternalStorageDirectory ()?

Environment. getExternalStorageDirectory() returns top-level directory of the primary external storage.

Where is getExternalFilesDir?

It returns the path to files folder inside Android/data/data/your_package/ on your SD card. It is used to store any required files for your app (e.g. images downloaded from web or cache files).


4 Answers

Use getExternalFilesDir(), getExternalCacheDir(), or getExternalMediaDirs() (methods on Context) instead of Environment.getExternalStorageDirectory().

Or, modify mPhotoEditor to be able to work with a Uri, then:

  • Use ACTION_CREATE_DOCUMENT to get a Uri to a location of the user's choosing, or

  • Use MediaStore, ContentResolver, and insert() to get a Uri for a particular type of media (e.g., an image) — see this sample app that demonstrates doing this for downloading MP4 videos from a Web site

Also, note that your Uri.fromFile with ACTION_MEDIA_SCANNER_SCAN_FILE should be crashing on Android 7.0+ with a FileUriExposedException. On Android Q, only the MediaStore/insert() option will get your content indexed by the MediaStore quickly.

Note that you can opt out of these "scoped storage" changes on Android 10 and 11, if your targetSdkVersion is below 30, using android:requestLegacyExternalStorage="true" in the <application> element of the manifest. This is not a long-term solution, as your targetSdkVersion will need to be 30 or higher sometime in 2021 if you are distributing your app through the Play Store (and perhaps elsewhere).

like image 184
CommonsWare Avatar answered Oct 21 '22 00:10

CommonsWare


Get the destPath with the new API call:

String destPath = mContext.getExternalFilesDir(null).getAbsolutePath();
like image 49
Russell A Avatar answered Oct 21 '22 00:10

Russell A


For Android Q, you can add android:requestLegacyExternalStorage="true" to your element in the manifest. This opts you into the legacy storage model, and your existing external storage code will work.

<manifest ... >
<!-- This attribute is "false" by default on apps targeting
     Android 10 or higher. -->
  <application android:requestLegacyExternalStorage="true" ... >
    ...
  </application>
</manifest>

Technically, you only need this once you update your targetSdkVersion to 29. Apps with lower targetSdkVersion values default to opting into legacy storage and would need android:requestLegacyExternalStorage="false" to opt out.

like image 31
mahmoud mansour Avatar answered Oct 21 '22 01:10

mahmoud mansour


Please use getExternalFilesDir(), getExternalCacheDir() instead of Environment.getExternalStorageDirectory() when you creating file in Android 10.

See below line:

val file = File(this.externalCacheDir!!.absolutePath, "/your_file_name")
like image 10
Hardik Hirpara Avatar answered Oct 21 '22 00:10

Hardik Hirpara