带有照片拍摄意图的Android FileProvider给出了一个java.io.IOException:写入失败:EPIPE(Broken pipe)

时间:2017-01-10 14:42:15

标签: java android android-intent

我遇到了新的FileProvider API问题:

我有这个代码从文件中生成一个uri:

public Uri generateUri(String authority) {
            File storageDir = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
            File imageFile = fileHelper.from(storageDir, PHOTO_NAME);

            if (!imageFile.exists() && !imageFile.createNewFile()) {
                throw new Exception("Can't create capture file");
            }
            Uri sharedUri = ExtendedFileProvider.getUriForFile(context, authority, imageFile);
            return sharedUri;
    }

它是正确的URI,现在我打开像这样的照相机>

Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            if (takePictureIntent.resolveActivity(context.getPackageManager()) != null) {
                takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, result);
                context.grantUriPermission(context.getPackageName(), result,
                        Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
                context.startActivityForResult(takePictureIntent, BaseActivity.SUBACTIVITY_TAKE_PHOTO);
            }

然后,相机打开,当照片被拍摄并确认时,我有:

01-10 15:37:27.236 W/FastPrintWriter: Write failure
                                      java.io.IOException: write failed: EPIPE (Broken pipe)
                                          at libcore.io.IoBridge.write(IoBridge.java:501)
                                          at java.io.FileOutputStream.write(FileOutputStream.java:316)
                                          at com.android.internal.util.FastPrintWriter.flushBytesLocked(FastPrintWriter.java:336)
                                          at com.android.internal.util.FastPrintWriter.flushLocked(FastPrintWriter.java:359)
                                          at com.android.internal.util.FastPrintWriter.flush(FastPrintWriter.java:394)
                                          at android.view.ThreadedRenderer.dumpGfxInfo(ThreadedRenderer.java:613)
                                          at android.view.WindowManagerGlobal.dumpGfxInfo(WindowManagerGlobal.java:556)
                                          at android.app.ActivityThread$ApplicationThread.dumpGfxInfo(ActivityThread.java:1175)
                                          at android.app.ApplicationThreadNative.onTransact(ApplicationThreadNative.java:577)
                                          at android.os.Binder.execTransact(Binder.java:565)
                                       Caused by: android.system.ErrnoException: write failed: EPIPE (Broken pipe)
                                          at libcore.io.Posix.writeBytes(Native Method)
                                          at libcore.io.Posix.write(Posix.java:273)
                                          at libcore.io.BlockGuardOs.write(BlockGuardOs.java:319)
                                          at libcore.io.IoBridge.write(IoBridge.java:496)
                                          at java.io.FileOutputStream.write(FileOutputStream.java:316) 
                                          at com.android.internal.util.FastPrintWriter.flushBytesLocked(FastPrintWriter.java:336) 
                                          at com.android.internal.util.FastPrintWriter.flushLocked(FastPrintWriter.java:359) 
                                          at com.android.internal.util.FastPrintWriter.flush(FastPrintWriter.java:394) 
                                          at android.view.ThreadedRenderer.dumpGfxInfo(ThreadedRenderer.java:613) 
                                          at android.view.WindowManagerGlobal.dumpGfxInfo(WindowManagerGlobal.java:556) 
                                          at android.app.ActivityThread$ApplicationThread.dumpGfxInfo(ActivityThread.java:1175) 
                                          at android.app.ApplicationThreadNative.onTransact(ApplicationThreadNative.java:577) 
                                          at android.os.Binder.execTransact(Binder.java:565)

我已经完成了使用FileProvider所需的所有明显更改,并且它在一周前工作了.. 有什么想法吗?

1 个答案:

答案 0 :(得分:0)

context.grantUriPermission(context.getPackageName(), result,
                    Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

此代码说“授予我自己的应用程序权限以使用我自己的应用程序的数据”。这不是你想要的。如果您要使用grantUriPermission(),则套餐名称必须是您要授予其权限的应用。

另外,更新的API级别有更简单的选项:

i.putExtra(MediaStore.EXTRA_OUTPUT, outputUri);

if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.LOLLIPOP) {
  i.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
}
else if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.JELLY_BEAN) {
  ClipData clip=
    ClipData.newUri(getContentResolver(), "A photo", outputUri);

  i.setClipData(clip);
  i.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
}
else {
  List<ResolveInfo> resInfoList=
    getPackageManager()
      .queryIntentActivities(i, PackageManager.MATCH_DEFAULT_ONLY);

  for (ResolveInfo resolveInfo : resInfoList) {
    String packageName = resolveInfo.activityInfo.packageName;
    grantUriPermission(packageName, outputUri,
      Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
  }
}

在这里,我:

  • 如果应用在Android 5.0 +上运行,只需使用addFlags()

  • 如果应用在Android 4.1-4.4上运行,请使用ClipData

  • 对所有可能的相机应用进行迭代,并在Android 4.0及更早版本上为每个应用授予权限

我在this blog post更多地覆盖了该代码段。