WRITE_EXTERNAL_STORAGE 无法在棒棒糖上工作,即使它已在清单中设置

Posted

技术标签:

【中文标题】WRITE_EXTERNAL_STORAGE 无法在棒棒糖上工作,即使它已在清单中设置【英文标题】:WRITE_EXTERNAL_STORAGE not working on lollipop even though it's set in the manifest 【发布时间】:2017-05-23 23:08:08 【问题描述】:

我正在尝试将应用程序本地数据文件夹中的图像保存到外部存储。我的清单包含以下内容(在清单的应用程序标记之前):

<uses-sdk android:minSdkVersion="14" android:targetSdkVersion="23" />

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

当我尝试以下操作时

try 
        InputStream in = new FileInputStream(filePath);
        File outPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
        File outFile = new File(outPath, "mypicture.jpg");


        //try fails at this line
        OutputStream out = new FileOutputStream(outFile);

        byte[] buf = new byte[1024];
        int len;

        while ((len = in.read(buf)) > 0) 
            out.write(buf, 0, len);
        

        in.close();
        in = null;
        out.flush();
        out.close();
        out = null;
 catch (IOException e) 
    e.printStackTrace();

我收到此错误:

java.io.FileNotFoundException: /storage/emulated/0/Pictures/mypicture.jpg: open failed: EACCES (Permission denied)

我也尝试了稍微不同的输出路径:

 String sdCardPath = Environment.getExternalStorageDirectory() + "/MyFolder";
 new File(sdCardPath).mkdirs();
 File outFile = new File(sdCardPath, "mypicture.jpg");

但这也给了我一个错误:

java.io.FileNotFoundException: /storage/emulated/0/MyFolder/mypicture.jpg: open failed: ENOENT (No such file or directory)

设备运行的是 Android 4.4.2,因此不需要在运行时请求权限(据我所知无法请求权限)。

为了允许将文件保存到外部存储,是否还缺少其他内容?

【问题讨论】:

【参考方案1】:

问题的原因是通过 gradle 拉入的外部库有自己的清单请求 &lt;uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="18"&gt;

我自己的清单仅在不包括 maxSdkVersion="18" 时才有效,因此添加该参数的清单合并导致了此错误。我的解决方案是将我自己的清单更改为:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="23" tools:replace="android:maxSdkVersion" />

我假设 maxSdkVersion="18" 意味着任何运行 SDK 19-22 的设备都不能拥有此权限(23+ 能够在运行时请求它)。

【讨论】:

【参考方案2】:

在 Android 6 中,您需要在运行时请求权限。如果你在 4.4 上运行,仍然有这个错误,我认为你还没有创建文件夹。

 String sdCardPath = Environment.getExternalStorageDirectory() + "/MyFolder";
 new File(sdCardPath) .mkdirs(); //create folders where write files
 File outFile = new File(sdCardPath, "mypicture.jpg");

【讨论】:

我已经有一行来创建如上所示的文件夹:new File(sdCardPath).mkdirs();这似乎不能解决问题。 哦。对不起我的包。您是否尝试删除android:maxSdkVersion="18"。或者你的目录与你的图片路径MyFolder\mypicture.jpg是否正确? 我已经尝试过使用和不使用 maxSdkVersion,但都没有任何区别。我相信路径是正确的,我也尝试将 mypicture.jpg 直接放入 Environment.getExternalStorageDirectory() 但有同样的错误。就好像在安装时没有授予 WRITE_EXTERNAL_STORAGE 权限,即使它肯定在清单中(我使用 apktool 检查它没有以某种方式被剥离)。 我刚刚注意到一些有趣的事情。当我侧加载应用程序并列出所需的权限时,我看不到“修改或删除 SD 卡的内容”和“读取 SD 卡的内容”,当我安装另一个应用程序时会看到.这似乎很奇怪,因为权限清楚地在清单中,是否需要其他东西才能使这些权限出现在安装时?【参考方案3】:

试试这个:

 String root = Environment.getExternalStorageDirectory().toString();
File myDir = new File(root + "/MyFolder");    
myDir.mkdirs();
Random generator = new Random();
int n = 10000;
n = generator.nextInt(n);
String fname = "Image-" + n + ".jpg";

File file = new File (myDir, fname);
if (file.exists ()) file.delete (); 
file.createNewFile();
try 
       FileOutputStream out = new FileOutputStream(file);
       FileInputStream in = new FileInputStream(filePath);
        byte[] buf = new byte[1024];
        int len;

        while ((len = in.read(buf)) > 0) 
            out.write(buf, 0, len);
        

        in.close();
        out.flush();
        out.close();

 catch (Exception e) 
       e.printStackTrace();

还为清单添加读写权限

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

【讨论】:

【参考方案4】:

这不是必须的,但请尝试在您的 Manifest 中添加此权限。

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

有时 Android 会欺骗我们。

【讨论】:

以上是关于WRITE_EXTERNAL_STORAGE 无法在棒棒糖上工作,即使它已在清单中设置的主要内容,如果未能解决你的问题,请参考以下文章

请求 WRITE_EXTERNAL_STORAGE 权限的正确方法[关闭]

为啥在 Android Q 及更高版本上不需要 WRITE_EXTERNAL_STORAGE

在运行时请求和允许 WRITE_EXTERNAL_STORAGE 权限对当前会话没有影响

请问,我的androi studio中动态申请权限,Manifest.permission.WRITE_EXTERNAL_STORAGE

在没有 WRITE_EXTERNAL_STORAGE 权限的情况下在 Android 8 上使用相机

外部存储、WRITE_EXTERNAL_STORAGE权限与maxSdkVersion属性的使用