安卓已经授权仍然(Permission denied)FileNotFoundExceptionAndroid

首先,在安卓中,6.0以上需要动态申请读写权限

 if (Build.VERSION.SDK_INT >= 23) {
            int REQUEST_CODE_CONTACT = 101;
            String[] permissions = {Manifest.permission.WRITE_EXTERNAL_STORAGE};
            //验证是否许可权限
            for (String str : permissions) {
                if (this.checkSelfPermission(str) != PackageManager.PERMISSION_GRANTED) {
                    //申请权限
                    this.requestPermissions(permissions, REQUEST_CODE_CONTACT);
                }
            }
        }

但开启权限后依然显示报错,排查后发现目录不对,需要读写的文件目录为data/data/xxx/xx.txt 但是该目录是不允许被读写的,改变路径后成功
引用一下博客的话,
我们在做安卓开过过程中,出于安全性,经常会将一些数据缓存至data/data私有文件夹内。程序都是一步步调试出来的,所以我们在调试过程中需要能直观的看到data/data私有文件夹内部详情。但是安卓系统本身是禁止所有人查看data/data的,即使是开发人员在使用开发者模式。

### Android 读写文件 `Permission denied` 的解决方案 在开发过程中遇到 `java.net.SocketException: socket failed: EACCES (Permission denied)` 或者 `open failed: EACCES (Permission denied)` 错误时,通常是因为应用程序尝试访问受限的外部存储区域而未获得适当权限。以下是针对不同版本 Android 的具体解决方法: #### 权限声明 无论哪个版本的 Android,都需要先在 `AndroidManifest.xml` 中声明必要的权限: ```xml <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> ``` 对于 Android 10(API Level 29)及以上版本,还需要考虑新的隐私保护机制。 --- #### 针对 Android 6.0 到 Android 9.0 的解决方案 从 Android 6.0 开始,运行时权限成为强制要求。如果仅通过静态声明权限而不请求动态权限,则可能导致操作失败并抛出 `Permission denied` 异常[^1]。 实现动态权限请求的方法如下: ```java if (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions((Activity) context, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE); } ``` 上述代码会在必要时弹窗提示用户授予文件读写权限。 --- #### 针对 Android 10 的解决方案 从 Android 10 起,默认启用了 **Scoped Storage** 模型,这意味着应用只能访问其专属目录下的数据(路径类似于 `/storage/emulated/0/Android/data/<package_name>/files/`)。试图访问其他位置可能会触发 `Permission denied` 错误[^2][^3]。 ##### 解决方案一:启用 Legacy 存储模式 可以通过设置 `requestLegacyExternalStorage=true` 属性来暂时禁用 Scoped Storage 功能,从而恢复传统存储行为: ```xml <application android:requestLegacyExternalStorage="true" ... > </application> ``` 注意:此选项将在未来版本中被移除,因此建议作为过渡方案使用。 ##### 解决方案二:调整文件存取逻辑 修改程序设计以适应 Scoped Storage 规范,例如利用 Context 提供的安全 API 访问共享媒体资源: ```java ContentResolver resolver = getContentResolver(); Uri imageUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; Cursor cursor = resolver.query(imageUri, null, null, null, null); while(cursor.moveToNext()){ String filePath = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA)); File file = new File(filePath); // 对目标文件执行进一步处理... } cursor.close(); ``` --- #### 针对 Android 11 及以上的解决方案 自 Android 11 起,引入了更严格的管理策略——即只有具备特殊权限的应用才能完全控制整个外置存储器的内容。普通 App 若需获取此类能力,必须引导用户前往系统设置界面手动开启【允许管理所有文件】开关[^5]。 示例代码片段展示如何跳转至相应配置页: ```java Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION); intent.setData(Uri.parse("package:" + getApplicationContext().getPackageName())); startActivityForResult(intent, REQUEST_CODE); ``` 另外值得注意的是,某些场景下即便已成功授予权限仍可能出现异常情况。此时可以尝试重启进程后再试一次[^4]: ```java Process.killProcess(Process.myPid()); System.exit(0); ``` --- ### 总结 综上所述,面对 Android 不同平台间日益增强的数据隔离特性,“一刀切”的通用解法并不现实;开发者应依据实际需求灵活选用适配措施,并充分测试兼容性表现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值