我得到了

open failed: EACCES(权限被拒绝)

myOutput = new FileOutputStream(outFileName);

我检查了根目录,并尝试了android.permission.WRITE_EXTERNAL_STORAGE。

我该如何解决这个问题?

try {
    InputStream myInput;

    myInput = getAssets().open("XXX.db");

    // Path to the just created empty db
    String outFileName = "/data/data/XX/databases/"
            + "XXX.db";

    // Open the empty db as the output stream
    OutputStream myOutput = new FileOutputStream(outFileName);

    // Transfer bytes from the inputfile to the outputfile
    byte[] buffer = new byte[1024];
    int length;
    while ((length = myInput.read(buffer)) > 0) {
        myOutput.write(buffer, 0, length);
    }

    // Close the streams
    myOutput.flush();
    myOutput.close();
    myInput.close();
    buffer = null;
    outFileName = null;
}
catch (IOException e1) {
    // TODO Auto-generated catch block
    e1.printStackTrace();
}

当前回答

将文件存储在与应用程序目录无关的目录中受API 29+以上限制。因此,要生成一个新文件或创建一个新文件,使用你的应用程序目录,就像这样

所以正确的做法是:-

val file = File(appContext.applicationInfo.dataDir + File.separator + "anyRandomFileName/")

您可以将任何数据写入这个生成的文件!

上面的文件是可访问的,不会抛出任何异常,因为它位于您自己开发的应用程序的目录中。

另一个选项是android:requestLegacyExternalStorage="true"在清单应用程序标签,由Uriel建议,但它不是一个永久的解决方案!

其他回答

将文件存储在与应用程序目录无关的目录中受API 29+以上限制。因此,要生成一个新文件或创建一个新文件,使用你的应用程序目录,就像这样

所以正确的做法是:-

val file = File(appContext.applicationInfo.dataDir + File.separator + "anyRandomFileName/")

您可以将任何数据写入这个生成的文件!

上面的文件是可访问的,不会抛出任何异常,因为它位于您自己开发的应用程序的目录中。

另一个选项是android:requestLegacyExternalStorage="true"在清单应用程序标签,由Uriel建议,但它不是一个永久的解决方案!

我在运行CM 12.1的三星Galaxy Note 3上也遇到了同样的问题。我的问题是我有

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

而且必须用它来拍摄和存储用户照片。当我试图在ImageLoader中加载这些相同的照片时,我得到了(权限被拒绝)错误。解决方案是显式添加

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

因为上面的权限只限制写权限到API版本18,以及它的读权限。

我希望下面的所有内容/数据都属于“内部存储”。但是,您应该能够写入/sdcard。

我使用下面的过程来处理android 11和targetapi30的情况

作为预先创建的文件dir根据范围存储在我的情况下根目录文件//<图像/视频…按照要求> 复制选中的文件,并在从我的外部存储选择时复制缓存目录中的文件 然后在一次上传(在我的发送/上传按钮点击)复制文件从缓存目录到我的范围存储目录,然后做我的上传过程

使用这个解决方案,因为在播放商店上传应用程序时,它会生成MANAGE_EXTERNAL_STORAGE权限的警告,在我的情况下,有时会被播放商店拒绝。

同样,我们使用目标API 30,所以我们不能从内部存储共享或转发文件到应用程序

在我的例子中,我使用的是一个文件选择器库,它返回到外部存储的路径,但它从/root/开始。即使在运行时授予WRITE_EXTERNAL_STORAGE权限,我仍然得到错误EACCES(权限被拒绝)。 因此,使用Environment.getExternalStorageDirectory()来获取外部存储的正确路径。

例子: 无法写入:/root/storage/emulated/0/newfile.txt 可以写:/storage/emulated/0/newfile.txt

boolean externalStorageWritable = isExternalStorageWritable();
File file = new File(filePath);
boolean canWrite = file.canWrite();
boolean isFile = file.isFile();
long usableSpace = file.getUsableSpace();

Log.d(TAG, "externalStorageWritable: " + externalStorageWritable);
Log.d(TAG, "filePath: " + filePath);
Log.d(TAG, "canWrite: " + canWrite);
Log.d(TAG, "isFile: " + isFile);
Log.d(TAG, "usableSpace: " + usableSpace);

/* Checks if external storage is available for read and write */
public boolean isExternalStorageWritable() {
    String state = Environment.getExternalStorageState();
    if (Environment.MEDIA_MOUNTED.equals(state)) {
        return true;
    }
    return false;
}

输出1:

externalStorageWritable: true
filePath: /root/storage/emulated/0/newfile.txt
isFile: false
usableSpace: 0

输出2:

externalStorageWritable: true
filePath: /storage/emulated/0/newfile.txt
isFile: true
usableSpace: 1331007488