我正在尝试打开相机意图并在Android中加载捕获的图像。问题是相机应用程序正确地写入输入URI,并且只有在第一次调用时才能将写入的数据成功解码为位图。在后续调用中,它不会向输入文件写入任何字节,并且在从相机应用程序返回控件后,我检查位于该URI的文件仍然有0个字节。
以下是用于创建输入到相机应用程序的文件URI的代码。
private @NonNull Uri getImageUri() {
Uri outputFileUri = null;
final String imageFileName = "JPEG_"
+ new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()) + ".jpeg" ;
File imagePath = new File(getFilesDir(), "images");
if(!imagePath.isDirectory()) {
imagePath.mkdirs();
}
File newFile = new File(imagePath, imageFileName);
if (newFile.exists()) {
newFile.delete();
}
try {
if(!newFile.createNewFile())
Log.e(MyActivity.class.getSimpleName(), "Error creating file");
} catch (IOException e) {
e.printStackTrace();
}
if(!(null != newFile && newFile.isFile())) {
throw new IllegalStateException("Cannot create file ");
}
outputFileUri = FileProvider.getUriForFile(
this.getApplicationContext(), "com.myapp.android.fileprovider", newFile);
if(null == outputFileUri){
throw new IllegalStateException( "Cannot create file for clicking image");
}
Log.e(MyActivity.class.getSimpleName(), "output file uri " + outputFileUri);
return outputFileUri;
}
以下是打开相机意图的代码:
private List<Intent> getCameraIntents(@NonNull final Uri path){
if(!mCameraIntents.isEmpty()) return mCameraIntents;
@NonNull final Intent captureIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
@NonNull final List<ResolveInfo> listCam =
getPackageManager().queryIntentActivities(captureIntent, 0);
@NonNull final ArrayList<Intent> cameraIntents = new ArrayList<>(1);
for (ResolveInfo res : listCam) {
Intent intent = new Intent(captureIntent);
intent.setComponent(new ComponentName(res.activityInfo.packageName, res.activityInfo.name));
intent.setPackage(res.activityInfo.packageName);
intent.putExtra(MediaStore.EXTRA_OUTPUT, path);
cameraIntents.add(intent);
}
mCameraIntents.addAll(cameraIntents);
return cameraIntents;
}
/**
* Create a chooser intent to select the source to get image from.<br />
* The source can be camera's (ACTION_IMAGE_CAPTURE) or gallery's (ACTION_GET_CONTENT).<br />
* All possible sources are added to the intent chooser.
*/
private Intent imageChooser() {
// Determine Uri of camera image to save.
@NonNull final Uri outputFileUri = getImageUri();
@NonNull final List<Intent> allIntents = getCameraIntents(outputFileUri);
allIntents.addAll(getGalleryIntents());
@NonNull final Intent mainIntent = allIntents.remove(allIntents.size() - 1);
// Create a chooser from the main intent
Intent chooserIntent = Intent.createChooser(
mainIntent,
getResources().getString(R.string.snap_app_chooser_message));
// Add all other intents
chooserIntent.putExtra(
Intent.EXTRA_INITIAL_INTENTS,
allIntents.toArray(new Parcelable[allIntents.size()]));
mSnapUri = outputFileUri;
return chooserIntent;
}
然后我简单地称之为,
startActivityForResult(imageChooser(), REQUEST_IMAGE_CAPTURE);
以下是用于解码相机应用程序在文件URI中写入的捕获图像的代码。
@NonNull @Override protected Bitmap doInBackground(@NonNull final Uri... snapUris) {
Bitmap snap = null;
try {
Log.e(MyActivity.class.getSimpleName(), "snap uri " + snapUris[0]);
snap = MediaStore.Images.Media.getBitmap(
mActivity.get().getContentResolver(),
snapUris[0]);
if(null == snap ){
InputStream is =
mActivity.get().getContentResolver()
.openInputStream(snapUris[0]);
snap = BitmapFactory.decodeStream(is);
}
if (null == snap) {
Log.e(MyActivity.class.getSimpleName(), "Problem with uri path");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
return snap;
}
}
有人可以帮我理解为什么相机应用程序在第一次调用后没有将捕获的图像写入文件URI吗?第一次调用相机意图和下次调用它时无法写入第二次和后续文件URI之间会发生什么变化。第一次通话后,相机应用的输出流是否未正确关闭?
我在小米和联想手机上进行了测试,并且得到了同样的行为。