【问题标题】:Android 11 open failed: EACCES (Permission denied)Android 11 打开失败:EACCES(权限被拒绝)
【发布时间】: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 中复制缓存中的文件或临时文件目录,然后上传即可。

标签: java android android-studio


【解决方案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目录中的文件,您会看到它们没有列出。

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

  1. 让用户选择带有 ACTION_OPEN_DOCUMENT 的文件。
  2. 在 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"
                

                【讨论】:

                  猜你喜欢
                  • 2021-12-23
                  • 2016-01-06
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2015-01-12
                  • 2016-06-14
                  • 1970-01-01
                  相关资源
                  最近更新 更多