在外部存储上创建新文件时权限被拒绝

时间:2013-05-03 14:02:40

标签: android file-io

我需要将文件从资产复制到外部存储。这是我的代码:

    File f = new File(Environment.getExternalStorageDirectory() + File.separator
            + "MyApp" + File.separator + "tessdata" + File.separator + "eng.traineddata");
    if (!f.exists()) {
    AssetManager assetManager = getAssets();
    try {
        f.createNewFile();
        InputStream in = assetManager.open("eng.traineddata");
        OutputStream out = new FileOutputStream(Environment.getExternalStorageDirectory() + File.separator
            + "MyApp" + File.separator  + "tessdata" + File.separator + "eng.traineddata");
        byte[] buffer = new byte[1024];
        int read;
            while ((read = in.read(buffer)) != -1)
                    out.write(buffer, 0, read);
            in.close();
            in = null;
            out.flush();
            out.close();
            out = null;
        } catch (IOException e) {
            Log.e("tag", "Failed to copy asset file: ", e);
        }
    }

我还在演出中添加了许可

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

执行f.createNewFile()时发生异常,说“权限被拒绝”。

我该如何解决?

6 个答案:

答案 0 :(得分:27)

在我的情况下,这是由于API 23+所需的权限弹出窗口,即使您已在清单中添加了权限。

// Storage Permissions
private static final int REQUEST_EXTERNAL_STORAGE = 1;
private static String[] PERMISSIONS_STORAGE = {
        Manifest.permission.READ_EXTERNAL_STORAGE,
        Manifest.permission.WRITE_EXTERNAL_STORAGE
};

/**
 * Checks if the app has permission to write to device storage
 *
 * If the app does not has permission then the user will be prompted to grant permissions
 *
 * @param activity
 */
public static void verifyStoragePermissions(Activity activity) {
    // Check if we have write permission
    int permission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE);

    if (permission != PackageManager.PERMISSION_GRANTED) {
        // We don't have permission so prompt the user
        ActivityCompat.requestPermissions(
                activity,
                PERMISSIONS_STORAGE,
                REQUEST_EXTERNAL_STORAGE
        );
    }
}

在应用启动或需要许可时调用此功能。

的AndroidManifest.xml

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

可以找到权限的详细示例代码here

答案 1 :(得分:11)

最近在API级别29,他们更改了访问外部存储的方式。 如果您尝试访问公用文件夹(即下载),则会引发权限被拒绝错误。

您需要在清单文件的应用程序标记中指定以下代码。

android:requestLegacyExternalStorage="true"

或者您可以将文件保存在根目录中,以避免出现此错误。

答案 2 :(得分:9)

f.mkdirs()之前f.createNewFile()。您可能正在尝试在不存在的目录中创建新文件

答案 3 :(得分:2)

试试这个:

private void copy() {

File dirOri = new File(Environment.getExternalStorageDirectory() +"/somefolder/somefile");
File dirDest = new File(Environment.getExternalStorageDirectory() + "/yourfolder");

FileChannel src = null;
FileChannel dst = null;

try {
    src = new FileInputStream(dirOri).getChannel();
    dst = new FileOutputStream(dirDest).getChannel();
    dst.transferFrom(src, 0, src.size());               
    src.close();
    dst.close();
} catch (Exception e) {}
}

- 编辑 -

添加清单:

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

答案 4 :(得分:1)

如果您使用的是SDK-23,则需要像这样在清单文件中写入权限

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

答案 5 :(得分:0)

我一直在努力地寻找答案。大多数解决方案不适用于API29。@ishann的回答启发了我搜索android:requestLegacyExternalStorage。原来,他们引入了范围存储的概念,这意味着应用程序默认情况下只能访问其专用文件夹。例如,“图片”的文件夹模式现在应为:

/storage/emulated/0/Android/data/com.myapp.myapp/files/Pictures

即使授予了两个权限,在全局位置创建文件或文件夹也会失败:

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

以下代码对我有用:

File files[] = this.getApplicationContext().getExternalFilesDirs(Environment.DIRECTORY_PICTURES);

for(File f : files){
    Log.e("debug", f.getAbsolutePath());
    File newdir = new File(f.getAbsolutePath(), "/newtest/");
    boolean result = newdir.mkdirs();
    Log.e("debug", result + " ; " + newdir.exists());
    break;
}

相关文件

https://developer.android.com/training/data-storage#scoped-storage

https://developer.android.com/reference/android/content/Context#getExternalFilesDirs(java.lang.String)