在 onActivityResult 中使用相机意图捕获的图片文件一段时间为空
Posted
技术标签:
【中文标题】在 onActivityResult 中使用相机意图捕获的图片文件一段时间为空【英文标题】:Picture file captured with camera intent empty for a while in onActivityResult 【发布时间】:2016-06-13 13:03:20 【问题描述】:我遇到了一个非常奇怪的错误,试图通过意图拍照。 活动代码(稍微简化):
private void startCapture() throws IOException
// Create output file
final File photoFile = makePhotoFile();
_photoPath = photoFile.getAbsolutePath();
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
/* IMPORTANT NOTE TO READERS
* As of android N (which went out shortly after I posted this question),
* you cannot use Uri.fromFile this way anymore.
* You should use a FileProvider. */
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));
if (cameraIntent.resolveActivity(getPackageManager()) != null)
startActivityForResult(cameraIntent, REQUEST_CODE_IMAGE_CAPTURE);
else
deleteCurrentPhoto();
private File makePhotoFile() throws IOException
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.ENGLISH).format(new Date());
String imageFileName = "MyPhoto_" + timeStamp + "_";
File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
return File.createTempFile(imageFileName, ".jpg", storageDir);
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == REQUEST_CODE_IMAGE_CAPTURE)
if(resultCode == RESULT_OK)
ByteArrayOutputStream bos = new ByteArrayOutputStream();
final byte[] buffer = new byte[2048];
int read;
byte[] photoBytes;
try(FileInputStream fis = new FileInputStream(_photoPath))
for(int i=0; i<10; i++) // Always working after first iteration though
if( (read = fis.read(buffer)) <= 0)
// Why does this get printed once ??
Log.w("my.package.my.app", "Empty for now...");
else
Log.w("my.package.my.app", "Working now !");
bos.write(buffer, 0, read);
break;
while((read = fis.read(buffer)) >= 0)
bos.write(buffer, 0, read);
photoBytes = bos.toByteArray();
// Catch clauses removed for simplicity
// Everything working OK after that (photoBytes decodes fine with the BitmapFactory)
还有日志输出:
03-01 16:32:34.139 23414-23414/my.package.my.app W/my.package.my.app: 暂时空... 03-01 16:32:34.139 23414-23414/my.package.my.app W/my.package.my.app:现在工作!
如你所见,在拍照后的onActivityResult中,第一次调用FileInputStream.read时文件为空……然后就可以正确读取了! 我认为当相机意图返回到调用活动时,文件已经被写入。有什么延迟吗?我也很惊讶地看到它总是在 for 循环中的一次迭代之后一直工作。
请注意,如果我在 onActivityResult 的开头放置一个断点,它会稍微延迟执行,并且一切正常(文件在第一次尝试时被正确读取)。
我正在使用 Android 6.0.1 下的库存 Nexus 6P 和库存相机应用。
重要编辑:对于 Android N,您应该使用 FileProvider
而不是 Uri.fromFile
,就像我之前所做的那样。见this blog post 和these explanations from the Android team。
【问题讨论】:
File.createTempFile
。不要已经创建该文件。您唯一需要的是文件名。一个文件路径。相机应用程序将创建该文件。所以重命名你的函数来创建新的文件名。
您应该记录read
的值。是0还是-1?或者将 ==0 和
不创建文件解决了问题,指南也创建了一个临时文件:developer.android.com/training/camera/photobasics.html(请参阅“保存全尺寸照片”部分。如果您有时间发布作为答案我可以接受(还有,知道为什么我会看到这种行为吗?),否则我会自己做。
当@greenapps 说不要创建 tempFile 时,您能发布一下您到底做了什么吗?我遇到了同样的问题,但不知道该怎么做
@MakrandGupta 只需将我的示例代码中的“File.create TempFile()”替换为“new File(storageDir, imageFileName + “.jpg”)。然后相机应用程序将为您创建文件。
【参考方案1】:
不要已经创建该文件。删除File.createTempFile()
。
您唯一需要的是文件名。一个文件路径。相机应用程序将自行创建文件。所以改变你的函数来创建新的文件名。例如。 new File(storageDir, imageFileName + ".jpg")
【讨论】:
您可能还想确保您创建的文件名是唯一的,方法File.createTempFile()
可能用于强制您的文件名创建算法防冲突,如 Android documentation about taking pictures。跨度>
以上是关于在 onActivityResult 中使用相机意图捕获的图片文件一段时间为空的主要内容,如果未能解决你的问题,请参考以下文章
Android:使用相机意图时应用程序在 onActivityResult 上崩溃
在 onActivityResult 中使用相机意图捕获的图片文件一段时间为空
使用相机意图时未调用 OnActivityResult()?
在onActivityResult中使用相机意图捕获的图片文件空了一段时间