无法在外部存储上保存文件,即使具有用户权限 [Android]

4

我正在开发一款 Android 图像处理应用程序,但在编写图像保存代码时遇到了困难。

这是我使用的方法:

private void saveImageToExternalStorage(Bitmap finalBitmap) {
    String root = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).toString();
    File myDir = new File(root + "/saved_images");
    myDir.mkdirs();
    Random generator = new Random();
    int n = 10000;
    n = generator.nextInt(n);
    String fname = "Image-" + n + ".jpg";
    File file = new File(myDir, fname);
    if (file.exists())
        file.delete();
    try {
        FileOutputStream out = new FileOutputStream(file);
        finalBitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
        out.flush();
        out.close();
    }
    catch (Exception e) {
        e.printStackTrace();
    }


    // Tell the media scanner about the new file so that it is
    // immediately available to the user.
    MediaScannerConnection.scanFile(this, new String[]{file.toString()}, null,
            new MediaScannerConnection.OnScanCompletedListener() {
                public void onScanCompleted(String path, Uri uri) {
                    Log.i("ExternalStorage", "Scanned " + path + ":");
                    Log.i("ExternalStorage", "-> uri=" + uri);
                }
            });

}

每次我执行这个操作,FileOutputStream都会抛出FileNotFoundException异常。
我的清单文件:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.gabrielerestuccia.testimmagini">

<application
    ...
</application>

<uses-feature android:name="android.hardware.camera" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

</manifest>

我正在Linux上使用Android Studio 1.5.1,在内置的虚拟Nexus 5上开发,使用的是Android 6.0版本。感谢您的帮助。

https://dev59.com/fFwY5IYBdhLWcg3waXS5 - CommonsWare
每次我执行这个程序时,FileOutputStream 都会抛出 FileNotFoundException 异常。但你仍在调用媒体扫描器。更好的做法是在 catch 语句中返回结果。 - greenapps
请检查myDir.mkdirs();的返回值,如果为false,请不要继续执行。如果目录已经存在,请不要调用mkdirs。 - greenapps
"/saved_images"。你检查过这个目录是否存在了吗? - greenapps
2个回答

6

我在安卓6上也遇到过同样的问题,这是由于新的权限模型导致的。

使用以下代码片段,您可以动态检查是否具有权限:

private static boolean canWriteToExternalStorage(Context context) {
    return ContextCompat.checkSelfPermission(context, android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
}

您还可以通过转到设置 -> 应用程序 -> 您的应用程序 -> 应用程序权限并打开存储项来启用您的应用程序的写入权限。

为了请求用户授予此权限,您应该在您的 Activity 中添加以下代码:

public void onCreate(Bundle savedInstanceState) {
    ...
    checkWritingPermission();
}

@Override
  public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    if (requestCode == REQUEST_CODE_PERMISSION) {
      if (grantResults.length >= 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
        // permission was granted
      } else {
        // permission wasn't granted
      }
    }
  }

  private void checkWritingPermission() {
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
      if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
        // permission wasn't granted
      } else {
        ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE_PERMISSION);
      }
    }
  }

谢谢!我忘记了 Marshmallow 的新权限模型。 - gabrielication

0
 ByteArrayOutputStream bytes = new ByteArrayOutputStream();
        _bitmapScaled.compress(Bitmap.CompressFormat.JPEG, 40, bytes);

        //you can create a new file name "test.jpg" in sdcard folder.
        File f = new File(Environment.getExternalStorageDirectory()
                                + File.separator + "test.jpg")
        f.createNewFile();
        //write the bytes in file
        FileOutputStream fo = new FileOutputStream(f);
        fo.write(bytes.toByteArray());

        // remember close de FileOutput
        fo.close();

1
你可以删除这个语句,因为文件将会被新的文件输出流创建。 - greenapps

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接