4

我有一个非常奇怪的错误,试图通过意图拍照。 活动代码(一点点简化):在onActivityResult中用照相机意图空置一段时间的图片文件

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 /我的。 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 postthese explanations from the Android team

+1

'File.createTempFile'。不要创建该文件。你唯一需要的是一个文件名。一个文件路径。相机应用程序将创建该文件。所以重命名你的函数来创建新的文件名。 – greenapps

+0

你应该记录'read'的值。它是0还是-1?或者将声明分成两个== 0和<0. – greenapps

+0

不创建文件解决了问题,该指南也创建了一个临时文件:https://developer.android.com/training/camera/photobasics.html(请参阅“保存完整尺寸的照片”一节。如果您有时间作为答案发布,我可以接受它(还有,为什么我会看到这种行为?),否则我会自己做。 – personne3000

回答

2

File.createTempFile.不要创建该文件。你唯一需要的是一个文件名。一个文件路径。相机应用程序将创建该文件。所以重命名你的函数来创建新的文件名。

+0

您也可能想要确保您创建的文件名是唯一的,方法'File.createTempFile()'可用于强制执行碰撞抵抗你的文件名创建算法thm,按照[Android拍摄照片的文档](https://developer.android.com/training/camera/photobasics.html)。 – Paolone

相关问题