【问题标题】:Unable to save image file in android oreo update. How to do it?无法在 android oreo 更新中保存图像文件。怎么做?
【发布时间】:2017-12-13 07:23:11
【问题描述】:

我无法在 android oreo(8.0) api 26 中保存图像文件。
该代码在 api 级别 25 (7.0) 中运行良好,我在文档“Android 8.0 Behavior Changes”中没有发现任何更改

这是我的代码

String root = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).toString();
File myrootDir = new File(root);
if (!myrootDir.exists()) {
    myrootDir.mkdir();
}

File myDir = new File(root + "/Myimages");
if (!myDir.exists()) {
    myDir.mkdir();
}
final String fname = System.currentTimeMillis()+"myimage.png";
File file = new File(myDir, fname);
if (file.exists())
    file.delete();
try {
    FileOutputStream out = new FileOutputStream(file);
    b.compress(Bitmap.CompressFormat.PNG, 100, out);
    out.flush();
    out.close();
}catch (Exception e){
   Log.e("MYAPP", "exception", e);
}

异常是 FileNotFoundException,没有这样的文件或目录。 (但为什么不在 android n 中?)

java.io.FileNotFoundException: /storage/emulated/0/Pictures/Myimages/1513151272243myimage.png (No such file or directory)
12-13 13:17:52.243 5839-5839/com.package.package W/System.err:     at java.io.FileOutputStream.open0(Native Method)
12-13 13:17:52.243 5839-5839/com.package.package W/System.err:     at java.io.FileOutputStream.open(FileOutputStream.java:287)
12-13 13:17:52.243 5839-5839/com.package.package W/System.err:     at java.io.FileOutputStream.<init>(FileOutputStream.java:223)
12-13 13:17:52.243 5839-5839/com.package.package W/System.err:     at java.io.FileOutputStream.<init>(FileOutputStream.java:171)
12-13 13:17:52.243 5839-5839/com.package.package W/System.err:     at com.package.package.DetailPage$12.run(DetailPage.java:737)
12-13 13:17:52.244 5839-5839/com.package.package W/System.err:     at android.os.Handler.handleCallback(Handler.java:789)
12-13 13:17:52.244 5839-5839/com.package.package W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:98)
12-13 13:17:52.244 5839-5839/com.package.package W/System.err:     at android.os.Looper.loop(Looper.java:164)
12-13 13:17:52.244 5839-5839/com.package.package W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:6541)
12-13 13:17:52.244 5839-5839/com.package.package W/System.err:     at java.lang.reflect.Method.invoke(Native Method)
12-13 13:17:52.244 5839-5839/com.package.package W/System.err:     at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
12-13 13:17:52.244 5839-5839/com.package.package W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)

【问题讨论】:

  • 你有什么例外吗?请在此处发布
  • 哦,我看到你有一个空的 catch 块,请在 catch 块中添加一些日志记录。作为最佳实践,切勿将 catch 块留空。总是处理它
  • 我可以在 android n 中使用此代码保存图像。但在 android o 中,nop :(
  • @MikeM。检查编辑。
  • @Rinav 感谢您指出

标签: java android android-8.0-oreo


【解决方案1】:

事实上,在 API 26 上运行并以 API 26 为目标的应用的权限发生了细微的变化。

以前,如果用户授予了该组中的至少一项权限,则应用会自动获得该组中的所有权限。这意味着,无论是否明确请求了 WRITE_EXTERNAL_STORAGE,已授予 READ_EXTERNAL_STORAGE 的应用也会立即获得 WRITE_EXTERNAL_STORAGE

从 Oreo 开始,对于面向 API 26+ 的应用,这一问题已得到纠正,并且只有明确请求的权限才会被授予。如果用户已经在同一个组中授予了权限,则不会提示新权限,但仍然必须请求。

在这种情况下,这就是问题所在。当READ_EXTERNAL_STORAGE 权限被授予您在 Nougat 或更低版本上的应用程序时,您也会自动获得WRITE_EXTERNAL_STORAGE,而无需专门请求该权限。当您在 Oreo 中尝试相同的文件保存过程时,您不会自动获得 WRITE_EXTERNAL_STORAGE,因此写入最终会失败。

只需为WRITE_EXTERNAL_STORAGE 添加特定请求。如果用户已经授予READ_EXTERNAL_STORAGE,他们将不会被另一个提示所困扰。或者,您可以从一开始就单独请求 WRITE_EXTERNAL_STORAGE,其中隐含包含 READ_EXTERNAL_STORAGE,这样您就不需要两个单独的请求。

【讨论】:

【解决方案2】:

我也遇到了同样的问题,我从 2 个月开始就被这个问题所困扰。我已经首先在清单中授予了 WRITE_EXTERNAL_STORAGE 的权限,并且再次检查它是否具有写权限。我认为这不是权限问题。因为当我用 oreo 测试时,文件夹正在创建并且我正在创建的文件夹中有损坏的图像文件。因此,它不会进入画廊,然后在保存时返回给我未捕获的图像。我只在 android 7.1.1 和 oreo 中遇到这个问题。到 android 7.0 它工作正常。我已经检查过设备 samsung galaxy note 8 和 google pixel xl 2。我正在使用具有 gps 及以下功能的自定义相机

public void onImageAvailable(ImageReader reader) {
                    Image image = null;
                    try {
                        image = reader.acquireLatestImage();
                        ByteBuffer buffer = image.getPlanes()[0].getBuffer();
                        byte[] bytes = new byte[buffer.capacity()];
                        buffer.get(bytes);
                        save(bytes);

用于图像字节保存,保存功能包含以下代码

OutputStream output = null;
                    try {
                        output = new FileOutputStream(finalFile);
                        output.write(bytes);
                    } finally {
                        if (null != output) {
                            output.close();
                        }
                    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多