将文件写入Android中的下载目录

问题描述 投票:0回答:1

下面是我的代码

    File downloadsDirectory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);

    long currentTimestamp = System.currentTimeMillis();
    String filename = "downloaded_image_" + currentTimestamp + ".png";

    File imageFile = new File(downloadsDirectory, filename);

    try {
        FileOutputStream outputStream = new FileOutputStream(imageFile);
        outputStream.write(imageBytes);
        outputStream.close();
    } catch (FileNotFoundException e) {
        throw new RuntimeException(e);
    } catch (IOException e) {
        throw new RuntimeException(e);
    }

我已添加权限

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

现在我上面的代码在 Android 12 上运行良好。

但在 Android 8 和 Android 10 上失败,出现错误

java.lang.RuntimeException:java.io.FileNotFoundException:/storage/emulated/0/Download/downloaded_image_1697897803982.png:打开失败:EACCES(权限被拒绝)

查看互联网,我被告知下面的代码应该适用于所有 API(大于 24),但是下面的代码是否意味着我的代码不应该在 Android 12 上工作,而应该在 Android 8/9 上工作?我不明白,我的代码(上面的代码)在 Android 12 上运行如何,但在 8/9 上不起作用,但下面应该可以运行。

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
  StorageManager storageManager = getSystemService(StorageManager.class);
  StorageVolume storageVolume = storageManager.getStorageVolumes().get(0);
  File downloadsDirectory = storageVolume.getDirectory(Environment.DIRECTORY_DOWNLOADS);

  long currentTimestamp = System.currentTimeMillis();
  String filename = "downloaded_image_" + currentTimestamp + ".png";

  File imageFile = new File(downloadsDirectory, filename);

  try {
    FileOutputStream outputStream = new FileOutputStream(imageFile);
    outputStream.write(imageBytes);
    outputStream.close();
  } catch (FileNotFoundException e) {
    throw new RuntimeException(e);
  } catch (IOException e) {
    throw new RuntimeException(e);
  }
} else {
  File downloadsDirectory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);

  long currentTimestamp = System.currentTimeMillis();
  String filename = "downloaded_image_" + currentTimestamp + ".png";

  File imageFile = new File(downloadsDirectory, filename);

  try {
    FileOutputStream outputStream = new FileOutputStream(imageFile);
    outputStream.write(imageBytes);
    outputStream.close();
  } catch (FileNotFoundException e) {
    throw new RuntimeException(e);
  } catch (IOException e) {
    throw new RuntimeException(e);
  }
}
java android file io
1个回答
0
投票

Android 10 引入了范围存储,这限制了应用程序访问外部存储的方式。为了让您的代码能够跨不同 Android 版本运行,您应该考虑检查运行时权限,尤其是 Android 10 及以上版本。

这是代码的更新版本,适用于 Android 8、9、10 和更高版本。

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
    // Android 10 and above
    Context context = getApplicationContext();
    ContentResolver contentResolver = context.getContentResolver();
    ContentValues contentValues = new ContentValues();
    contentValues.put(MediaStore.Downloads.DISPLAY_NAME, filename);
    contentValues.put(MediaStore.Downloads.MIME_TYPE, "image/png");
    contentValues.put(MediaStore.Downloads.RELATIVE_PATH, Environment.DIRECTORY_DOWNLOADS);

    Uri contentUri = MediaStore.Downloads.EXTERNAL_CONTENT_URI;
    Uri itemUri = contentResolver.insert(contentUri, contentValues);

    if (itemUri != null) {
        try {
            OutputStream outputStream = contentResolver.openOutputStream(itemUri);
            if (outputStream != null) {
                outputStream.write(imageBytes);
                outputStream.close();
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    } else {
        throw new RuntimeException("Failed to create a file in the Downloads directory.");
    }
} else {
    // Android 8 and 9
    File downloadsDirectory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);

    if (!downloadsDirectory.exists()) {
        downloadsDirectory.mkdirs();
    }

    long currentTimestamp = System.currentTimeMillis();
    String filename = "downloaded_image_" + currentTimestamp + ".png";

    File imageFile = new File(downloadsDirectory, filename);

    try {
        FileOutputStream outputStream = new FileOutputStream(imageFile);
        outputStream.write(imageBytes);
        outputStream.close();
    } catch (FileNotFoundException e) {
        throw new RuntimeException(e);
    } catch (IOException e) {
        throw a RuntimeException(e);
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.