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 设备中的存储。有关更多详细信息,请点击此链接,它将根据您的要求向您解释更多。
我搜索了很多时间,得到了在清单文件中添加<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
的解决方案,并尝试在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(权限被拒绝)的主要内容,如果未能解决你的问题,请参考以下文章
BitmapFactory:无法解码流:java.io.FileNotFoundException:打开失败:Android Q 上的 EACCES(权限被拒绝)
打开失败:EACCES(权限被拒绝)并尝试在空对象引用上调用虚拟方法“int android.graphics.Bitmap.getWidth()”
io.FileNotFoundException:打开失败:EACCES(权限被拒绝)