简体   繁体   English

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

[英]Permission denied when creating new file on external storage

I need to copy a file from the assets to the external storage.我需要将文件从资产复制到外部存储。 Here is my code:这是我的代码:

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

I've also added the permission in the manifet我还在清单中添加了权限

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

The exception occurred when is executed f.createNewFile() , saying "Permission denied".执行f.createNewFile()时发生异常,说“权限被拒绝”。

How can I fix it please?请问我该如何解决?

In my case it was due to the Permissions popup required for API 23+, even if u have added permission in the manifest.在我的情况下,这是由于 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
        );
    }
}

Call this function when the app launches or when you need the permission.当应用程序启动或需要权限时调用此函数。

AndroidManifest.xml AndroidManifest.xml

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

Detailed sample code for permissions can be found here .可以在此处找到权限的详细示例代码。

Recently in API level 29, they have changed the way of accessing external storage.最近在 API 级别 29 中,他们更改了访问外部存储的方式。 If you are trying to access public folders(ie Downloads) it will throw permission denied error.如果您尝试访问公共文件夹(即下载),它将抛出权限被拒绝错误。

You need to specify below code in your application tag in Manifest file.您需要在清单文件中的应用程序标签中指定以下代码。

android:requestLegacyExternalStorage="true"

Or you can save files in the root directory to avoid this error.或者您可以将文件保存在根目录中以避免此错误。

Do f.mkdirs() before f.createNewFile() .f.mkdirs()之前执行f.createNewFile() You are probably trying to create a new file in a non-existent directory您可能正在尝试在不存在的目录中创建新文件

try this:试试这个:

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) {}
}

-- EDIT -- - 编辑 -

Add in manifest:在清单中添加:

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

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

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

I have googled so hard for an answer.我已经用谷歌搜索了答案。 Most solutions don't work for API 29. @ishann 's answer inspired me to search for android:requestLegacyExternalStorage .大多数解决方案不适用于 API 29。@ishann 的回答激励我搜索 android:requestLegacyExternalStorage 。 It turned out that they introduced the concept of scoped storage, which means an app can only access its dedicated folder by default.事实证明,他们引入了范围存储的概念,这意味着默认情况下应用程序只能访问其专用文件夹。 For example, the folder pattern for Pictures should now be like:例如,图片的文件夹模式现在应该是这样的:

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

Creating files or folders in the global location will fail, even both permissions are granted:在全局位置创建文件或文件夹将失败,即使授予了两个权限:

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

the following code worked for me:以下代码对我有用:

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

relevant documents相关文件

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM