Android 11 打开失败:EACCES(权限被拒绝)

Posted

技术标签:

【中文标题】Android 11 打开失败:EACCES(权限被拒绝)【英文标题】:Android 11 open failed: EACCES (Permission denied) 【发布时间】:2021-07-02 00:15:49 【问题描述】:

我正在开发一个应用程序。我在其中将不同的文件类型(例如 docx、pdf、zip)上传到 WAMP 服务器。以下是我的内部存储的文件路径。

/storage/emulated/0/WhatsApp/Media/WhatsApp Documents/api.txt

我已在 Manifest 文件以及运行时添加并允许存储权限以读取文件。但是没有可用的内部存储权限请求。

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

对于 Android 10,我也使用了这个属性

android:requestLegacyExternalStorage="true"

但是当我从内部存储读取文件进行上传时,我在 Android 11 OS (又名 Android R 板载三星 Galaxy)上遇到此错误。

java.io.FileNotFoundException:/storage/emulated/0/WhatsApp/Media/WhatsApp Documents/api.txt:打开失败:EACCES(权限被拒绝)

【问题讨论】:

这里可能会也可能不会。但是我曾经发现,如果您在手机以 USB 存储模式连接时调试应用程序,则会停止文件权限。无需将手机连接到 USB 到电脑并调试应用程序即可检查此项。 只需从 uri 中复制缓存中的文件或临时文件目录,然后上传即可。 【参考方案1】:

您可以尝试在应用程序标签中的清单文件中使用android:preserveLegacyExternalStorage="true" 标签。此标签用于访问 android 11 设备中的存储。有关更多详细信息,请点击此链接,它将根据您的要求向您解释更多。

我搜索了很多时间,得到了在清单文件中添加&lt;uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/&gt;的解决方案,并尝试在android 11手机中获得文件访问权限。然后您将打开并从存储中读取文件。

但问题是 Play 商店不允许您在应用中使用 MANAGE_EXTERNAL_STORAGE 权限。授予开发人员访问权限以使用它访问所有文件需要时间。 Here the link is

【讨论】:

android:preserveLegacyExternalStorage 对我不起作用,仍然崩溃:/storage/emulated/0/Download/r32r32r.txt:打开失败:EACCES(权限被拒绝) 如果您正在使用 android 11 并处理文件,那么您必须使用 MANAGE_EXTERNAL_STORAGE 权限。【参考方案2】:

在 Android 11 设备上,您的应用只能访问自己的文件。

以及公共目录中的一般媒体。

尝试列出该whatsapp目录中的文件,您会看到它们没有列出。

您有两种读取文件的选项。

    让用户选择带有 ACTION_OPEN_DOCUMENT 的文件。 在 manifest 中请求 MANAGE_EXTERNAL_STORAGE 并让用户确认。

【讨论】:

选项 2 正在工作。但是每当应用程序在设置中获得权限时,应用程序在收到用户响应后就会崩溃。 如果你不是更具体,没有帮助。 MANAGE_EXTERNAL_STORAGE 字段要求最低 API 级别 30。我相信这是一个很大的飞跃。【参考方案3】:

在 Android 11 设备上,您的应用只能访问自己的文件。

以及公共目录中的一般媒体。

尝试列出该whatsapp目录中的文件,您会看到 它们未列出。

您有两个选项来读取文件。

让用户选择带有 ACTION_OPEN_DOCUMENT 的文件。要求 MANAGE_EXTERNAL_STORAGE 在 manifest 并让用户确认。

普通请求不适用于 MANAGE_EXTERNAL_STORAGE 权限。用户必须在 Android 设置中接受此权限

【讨论】:

【参考方案4】:

尝试用这种方法获取路径.....

public static String getDriveFile(Context context, Uri uri) 乌里返回乌里=乌里; 游标 returnCursor = context.getContentResolver().query(returnUri, null, null, null, null);

    int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
    int sizeIndex = returnCursor.getColumnIndex(OpenableColumns.SIZE);
    returnCursor.moveToFirst();
    String name = (returnCursor.getString(nameIndex));
    String size = (Long.toString(returnCursor.getLong(sizeIndex)));
    File file = new File(context.getCacheDir(), name);
    try 
        InputStream inputStream = context.getContentResolver().openInputStream(uri);
        FileOutputStream outputStream = new FileOutputStream(file);
        int read = 0;
        int maxBufferSize = 1 * 1024 * 1024;
        int bytesAvailable = inputStream.available();

        //int bufferSize = 1024;
        int bufferSize = Math.min(bytesAvailable, maxBufferSize);

        final byte[] buffers = new byte[bufferSize];
        while ((read = inputStream.read(buffers)) != -1) 
            outputStream.write(buffers, 0, read);
        
        Log.e("File Size", "Size " + file.length());
        inputStream.close();
        outputStream.close();
        Log.e("File Path", "Path " + file.getPath());
        Log.e("File Size", "Size " + file.length());
     catch (Exception e) 
        Log.e("Exception", e.getMessage());
    
    return file.getPath();


【讨论】:

【参考方案5】:

我在基于 Cordova 的 Android 应用程序上工作,我必须更改应用程序所关注的版本才能将文件保存在设备中。

我将 API 级别版本更改为 28 并正常工作。此更改用于避免在 Android 10 上添加范围存储功能。

此信息摘自此页面: https://developer.android.com/training/data-storage/use-cases#opt-out-scoped-storage

我希望这些信息对您有所帮助。

【讨论】:

【参考方案6】:

首先,检查您是否在应用内实现了范围存储逻辑。 您也可以使用 android:requestLegacyExternalStorage="true" 但是这个 legacyStoragePermission 仅限于版本 10。 您需要实现范围逻辑。

另外,请检查您的 targetSDKVersion 值是否为 30 或更大, 如果您在设备 android 版本 30 或更高版本中使用该应用,则需要这样做。

【讨论】:

【参考方案7】:

我花了一周时间获取有关如何在 Android 11 API 29 及更高版本上从外部存储读取文件的信息。


您仍然需要清单权限 READ_EXTERNAL_STORAGE。

        try 
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) 

            // Open a specific media item using ParcelFileDescriptor.
            ContentResolver resolver = getApplicationContext()
                    .getContentResolver();

            // "rw" for read-and-write;
            // "rwt" for truncating or overwriting existing file contents.
            String readOnlyMode = "r";
            // uri - I have got from onActivityResult
            //uri = data.getData();
            ParcelFileDescriptor parcelFile = resolver.openFileDescriptor(uri, readOnlyMode);

            FileReader fileReader = new FileReader(parcelFile.getFileDescriptor());
            BufferedReader reader = new BufferedReader(fileReader);

            String line;
            while ((line = reader.readLine()) != null) 
                //Your action here!!!
            
            reader.close();
            fileReader.close();

        
     catch (IOException e) 
        e.printStackTrace();
    

阅读:打开一个media 文件。

【讨论】:

【参考方案8】:

对于 Android 11 或更高版本,请在活动的 onCreate() 上使用以下代码。它将运行一次并请求许可。

        if (Build.VERSION.SDK_INT >= 30)
        if (!Environment.isExternalStorageManager())
            Intent getpermission = new Intent();
            getpermission.setAction(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION);
            startActivity(getpermission);
        
    
    

接下来在清单中声明 MANAGE_EXTERNAL_STORAGE 权限。

但是,这种方法的问题是,如果您没有充分的理由说明为什么需要访问所有文件,则无法将其上传到 Play 商店。

【讨论】:

【参考方案9】:

从 android 10 开始,无法通过您的应用访问所有文件, 所以在保存图片之类的数据时,使用下面的代码就可以正常读取了。 getExternalFilesDir 很重要

File file=new File(getActivity().getApplicationContext().getExternalFilesDir(null),"/scantempo"+"/Image_" + System.currentTimeMillis() + ".jpg");
            FileOutputStream out = new FileOutputStream(file);
            bitmap.compress(Bitmap.CompressFormat.PNG, 90, out);
            out.flush();
            out.close();
            Uri uri=Uri.fromFile(file);
            return uri;

【讨论】:

【参考方案10】:

您可以在 Manifest 的应用程序部分将 allowBackup 从 true 更改为 false。它对我有用。

android:allowBackup="false"

【讨论】:

以上是关于Android 11 打开失败:EACCES(权限被拒绝)的主要内容,如果未能解决你的问题,请参考以下文章

打开失败:Android 中的 EACCES(权限被拒绝)

BitmapFactory:无法解码流:java.io.FileNotFoundException:打开失败:Android Q 上的 EACCES(权限被拒绝)

打开失败:EACCES(权限被拒绝)并尝试在空对象引用上调用虚拟方法“int android.graphics.Bitmap.getWidth()”

io.FileNotFoundException:打开失败:EACCES(权限被拒绝)

引起:android.system.ErrnoException:绑定失败:EACCES(权限被拒绝)

Android HTTP POST 请求错误 - 套接字 EACCES 失败(权限被拒绝)