在onActivityResult中将相机意图空了一段时间捕获的图片文件 [英] Picture file captured with camera intent empty for a while in onActivityResult

查看:127
本文介绍了在onActivityResult中将相机意图空了一段时间捕获的图片文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到一个非常奇怪的错误,试图通过意图拍照. 活动代码(略有简化):

I am having a very strange bug trying to take a picture via intent. Activity code (a little simplified):

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:现在可以使用!

03-01 16:32:34.139 23414-23414/my.package.my.app W/my.package.my.app: Empty for now... 03-01 16:32:34.139 23414-23414/my.package.my.app W/my.package.my.app: Working now !

如您所见,拍照后在onActivityResult中,第一次调用FileInputStream.read ...时该文件为空,然后可以正确读取它! 我认为,当摄像机意图返回到调用活动时,该文件将已经被写入.有某种延迟吗?我也很惊讶地看到它在for循环中经过一轮迭代后一直可以正常工作.

As you can see, in the onActivityResult after taking the picture, the file is empty for the first call to FileInputStream.read... And then it can be read correctly ! I thought that when the camera intent returns to the calling activity, the file would be already written. Is there some kind of delay ? I am also surprised to see that it is always working after exactly one iteration in the for loop.

请注意,如果我在onActivityResult的开头放置一个断点,则会延迟执行时间,并且一切正常(第一次尝试即可正确读取文件).

Note that if I put a breakpoint at the beginning of onActivityResult, it delays execution a bit, and everything works normally (the file is read correctly at the first try).

我正在使用带有库存摄像头应用的Android 6.0.1下的库存Nexus 6P.

I am using a stock Nexus 6P under Android 6.0.1 with the stock camera app.

重要对于Android N,您应该像以前一样使用FileProvider代替Uri.fromFile.请参阅此博客文章 Android小组的这些解释.

Important edit: As for Android N, you should use a FileProvider instead of Uri.fromFile as I did before. See this blog post and these explanations from the Android team.

推荐答案

尚未创建该文件.删除File.createTempFile().

Do not create that file already. Remove the File.createTempFile().

您唯一需要的就是文件名.文件路径. Camera应用程序将自行创建文件.因此,更改您的功能以创建新的文件名.例如. new File(storageDir, imageFileName + ".jpg")

The only thing you need is a file name. A file path. The Camera app will create the file on its own. So change your function to create new file name. E.g. new File(storageDir, imageFileName + ".jpg")

这篇关于在onActivityResult中将相机意图空了一段时间捕获的图片文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆