我想用相机拍照。我只是暂时需要它们,所以我做了以下几点:
private void takePicture() {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (intent.resolveActivity(this.getActivity().getPackageManager()) != null) {
try {
this.imageFile = File.createTempFile("CROP_SHOT", ".jpg", this.getActivity().getCacheDir());
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(this.imageFile));
intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);
this.startActivityForResult(intent, Globals.REQUEST_TAKE_PHOTO);
} catch (IOException e) {
e.printStackTrace();
}
}
}
很遗憾,RESULT_CANCELED
onActivityResult
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.v("PictureEdit", "onActivityResult");
super.onActivityResult(requestCode, resultCode, data);
if(resultCode == Activity.RESULT_OK) {
if(requestCode == Globals.REQUEST_TAKE_PHOTO) {
Log.v("PictureEdit", "onActivityResult take photo");
this.startCropImage(Uri.fromFile(this.imageFile));
} else if (requestCode == Globals.REQUEST_PICK_PHOTO) {
Log.v("PictureEdit", "onActivityResult pick photo");
this.startCropImage(data.getData());
} else if (requestCode == Globals.REQUEST_CROP_PHOTO) {
Log.v("PictureEdit", "onActivityResult crop photo");
this.imageEncoded = data.getStringExtra(Globals.KEY_IMAGE_ENCODED);
this.imageView.setImageBitmap(Images.decodeImage(imageEncoded));
this.buttonSave.setEnabled(true);
} else {
Log.v("PictureEdit", "onActivityResult requestCode: " + requestCode + ", result: " + resultCode);
}
} else {
Log.v("PictureEdit", "onActivityResult resultCode is not ok: " + resultCode);
}
}
到目前为止我在stackoverflow和网络上找到的每个解决方案都没有解决我的问题。我使用缓存目录来创建临时文件:
File.createTempFile("CROP_SHOT", ".jpg", this.getActivity().getCacheDir());
我拥有正确的权限:
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
从智能手机中挑选图片总能正常使用:
private void pickPicture() {
Intent intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
this.startActivityForResult(intent, Globals.REQUEST_PICK_PHOTO);
}
那么为什么相机总是返回RESULT_CANCELED
?
它出现在Android 6.0的Nexus 4和Android 4.2的三星Galaxy S III上。
答案 0 :(得分:12)
我使用缓存目录来创建临时文件:
首先,第三方相机应用无权使用internal storage上应用的私有缓存目录。
其次,您不应该创建该文件。相机应用程序应该创建该文件。某些相机应用可能会混淆并拒绝覆盖您的文件。
因此,创建一个指向external storage上某个位置的File
对象(例如getExternalCacheDir()
),但尚未创建该文件。使用File
对象作为EXTRA_OUTPUT
值的基础。
另请注意,MediaStore.EXTRA_VIDEO_QUALITY
用于录制视频;它对ACTION_IMAGE_CAPTURE
毫无意义。
答案 1 :(得分:0)
更好的解决方案是使用FileProvider。因此,您的应用不需要任何写入外部存储空间的权限,您的应用可以授予相机写入
的权限启动相机并允许使用应用程序文件夹:
Intent camera = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
camera.putExtra(MediaStore.EXTRA_OUTPUT, getPhotoFile(context));
camera.addFlags(FLAG_GRANT_READ_URI_PERMISSION);
camera.addFlags(FLAG_GRANT_WRITE_URI_PERMISSION);
public static Uri getPhotoFile(Context context) {
File file = new File(context.getExternalCacheDir(), "camera.jpg");
return FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".provider.files", file);
}
答案 2 :(得分:0)
@CommonsWare提到的是正确的,但如果您仍想遵循官方文档所说的内容,我所做的就是授予那些能够处理您的意图的第三方应用程序,临时读写URI权限:< / p>
List<ResolveInfo> resolvedIntentActivities = getContext().getPackageManager().queryIntentActivities(takePhotoIntent, PackageManager.MATCH_DEFAULT_ONLY);
for (ResolveInfo resolvedIntentInfo : resolvedIntentActivities) {
String packageName = resolvedIntentInfo.activityInfo.packageName;
getContext().grantUriPermission(packageName, photoURI, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
上述代码段应插在startActivityForResult()
。