如何避免使用 KITKAT 4.4.2 版本的 SD 卡上的“EACCES 权限被拒绝”。谷歌的新政策
Posted
技术标签:
【中文标题】如何避免使用 KITKAT 4.4.2 版本的 SD 卡上的“EACCES 权限被拒绝”。谷歌的新政策【英文标题】:Howto avoid the "EACCES permission denied" ON SDCARD with KITKAT 4.4.2 Version. New policy from google 【发布时间】:2014-04-19 19:21:59 【问题描述】:android kitkat 4.4.2 版本是为 writeaccess 实施的新的 google 策略,目前我不明白。
我在其他应用中阅读了很多关于此问题的信息。他们得到“EACCES 权限被拒绝”。我的应用程序需要编写/解压缩 zip 文件,还需要写入 sqlite 数据库。
如何使用 Android 4.4.2 KITKAT 解决此 EACCES 权限被拒绝问题?
【问题讨论】:
【参考方案1】:来自文档:
从 Android 4.4 开始,多个外部存储设备通过 Context.getExternalFilesDirs()、Context.getExternalCacheDirs() 和 Context.getObbDirs() 呈现给开发人员。
通过这些 API 显示的外部存储设备必须是设备的半永久性部分(例如电池盒中的 SD 卡插槽)。开发人员希望存储在这些位置的数据能够长期可用。因此,临时存储设备(如 USB 大容量存储驱动器)不应通过这些 API 出现。
WRITE_EXTERNAL_STORAGE 权限只能授予对设备上主要外部存储的写入权限。不允许应用程序写入辅助外部存储设备,除非在合成权限允许的特定包目录中。以这种方式限制写入可确保系统在卸载应用程序时清理文件。
【讨论】:
SD 卡安全/权限的这种变化正在左右破坏应用程序。它可能有助于应用程序在卸载时清理文件,但设备正在使用此新规则接收 Android 更新,并且它正在孤立用户 SD 卡上的文件,因为现有应用程序不再有权从以前可写的文件夹中删除或移动文件。这非常令人沮丧。 这对用户和开发者来说都是一个糟糕的改变。了解更多历史:androidpolice.com/2014/02/17/…. 讽刺的是,它打破了their tutorial自己的例子 对我来说应该有一个简单的规则,如果某些东西在旧版本的 Android 中有效,它应该适用于所有新版本。否则,我们冒着用户安装应用程序的风险,并认为“开发人员多么糟糕”。此外,不可能在所有版本的 Android 上测试应用程序(特别是如果您不是一家大公司,而只是为了娱乐而开发的人)。由于他们的做法,Google 每天都让我更加恼火。【参考方案2】:目前唯一的解决方案是这个问题只能通过root你的手机并使用文件资源管理器从根目录更改ext sdcard的权限来解决,不推荐这样做,因为它会使你的手机的保修失效并且还会触发一些安全性三星 Galaxy S5 S4 Note3 和 Note2 等手机中的 KNOX 等应用程序。
很抱歉发布这个痛苦的事实。
让我们希望谷歌本身的更新能够让我们摆脱这种情况。
但在将 jellybean 更新为 kitkat 之前也要考虑一下,因为 JB 是 Android 最方便的操作系统。 而且 JB 和 Kitkat 的黑白差异并没有那么大。
希望我能帮助你......
【讨论】:
【参考方案3】:我在xda forum 中找到了解决此问题的有效方法;无需生根。 这是一个例子:
/**
* Returns an OutputStream to write to the file. The file will be truncated immediately.
*/
public OutputStream write()
throws IOException
if (file.exists() && file.isDirectory())
throw new IOException("File exists and is a directory.");
// Delete any existing entry from the media database.
// This may also delete the file (for media types), but that is irrelevant as it will be truncated momentarily in any case.
String where = MediaStore.MediaColumns.DATA + "=?";
String[] selectionArgs = new String[] file.getAbsolutePath() ;
contentResolver.delete(filesUri, where, selectionArgs);
ContentValues values = new ContentValues();
values.put(MediaStore.Files.FileColumns.DATA, file.getAbsolutePath());
Uri uri = contentResolver.insert(filesUri, values);
if (uri == null)
// Should not occur.
throw new IOException("Internal error.");
return contentResolver.openOutputStream(uri);
【讨论】:
【参考方案4】:你需要像这样实时询问android的权限:
private static final int MY_PERMISSIONS_REQUEST_STORAGE = 123456;
if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)
ActivityCompat.requestPermissions(getActivity(), new String[]android.Manifest.permission.READ_EXTERNAL_STORAGE, MY_PERMISSIONS_REQUEST_STORAGE);
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults)
switch (requestCode)
case MY_PERMISSIONS_REQUEST_STORAGE:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
Intent chooserIntent = cameraHelper.openImageIntent();
startActivityForResult(chooserIntent, MY_PERMISSIONS_REQUEST_STORAGE);
【讨论】:
我认为这不是唯一的变化。大多数常见类返回的路径也发生了变化,现在它不再是直接的干净路径,但它包含资源的 ID,很难或不可能从中获取路径。以上是关于如何避免使用 KITKAT 4.4.2 版本的 SD 卡上的“EACCES 权限被拒绝”。谷歌的新政策的主要内容,如果未能解决你的问题,请参考以下文章
防止应用程序显示在 android kitkat 4.4.2 上的最近应用程序列表中
如何以编程方式在 Android(KitKat 及更高版本)中添加 APN
关于如何彻底搞定Android Kitkat+沉浸式状态栏效果
关于如何彻底搞定Android Kitkat+沉浸式状态栏效果