在 API 级别 29 java 中不推荐使用 Environment.getExternalStorageDirectory()

新手上路,请多包涵

在 android Java 上工作,最近将 SDK 更新到 API 级别 29,现在显示一个警告,指出

Environment.getExternalStorageDirectory() 在 API 级别 29 中已弃用

我的代码是

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");
            }
       });
   }

什么是替代方案?

原文由 Noaman Akram 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.3k
2 个回答

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

或者,修改 mPhotoEditor 以便能够使用 Uri ,然后:

  • 使用 ACTION_CREATE_DOCUMENT 获得 Uri 到用户选择的位置,或

  • Use MediaStore , ContentResolver , and insert() to get a Uri for a particular type of media (eg, an image) — see this 演示如何从网站下载 MP4 视频的 示例应用程序

另外,请注意,您的 Uri.fromFileACTION_MEDIA_SCANNER_SCAN_FILE 应该在 Android 7.0+ 上与 FileUriExposedException 崩溃。在 Android Q 上,只有 MediaStore / insert() 选项会让您的内容快速被 MediaStore 索引。

请注意,如果您的 targetSdkVersion 低于 30,您可以在 <application> 元素中使用 android:requestLegacyExternalStorage="true" 选择退出 Android 10 和 11 上的这些“范围存储”更改的清单。 _这不是一个长期的解决方案_,因为如果您通过 Play 商店(可能还有其他地方)分发您的应用程序,您的 targetSdkVersion 将需要在 2021 年的某个时候达到 30 或更高。

原文由 CommonsWare 发布,翻译遵循 CC BY-SA 4.0 许可协议

无需硬编码即可获取内部存储目录,

权限(适用于所有 Android 版本)。不要忘记从用户那里获得权限。

请求所有文件访问

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="29" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="29" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" tools:ignore="ScopedStorage" />

Android 10 的旧权限(将此添加到 AndroidManifest.xml > 应用程序标记)。

 android:requestLegacyExternalStorage="true"

获取内部存储目录路径:

 public static String getInternalStorageDirectoryPath(Context context) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
        StorageManager storageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
        return storageManager.getPrimaryStorageVolume().getDirectory().getAbsolutePath();
    } else {
        return Environment.getExternalStorageDirectory().getAbsolutePath();
    }
}

原文由 Atakan Yildirim 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题