从相机捕获照片时获取 IllegalArgumentException
Getting IllegalArgumentException while capturing photo from Camera
在我的项目中,我使用 FileProvider.getUriForFile
给定 provider_paths.xml 文件:
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-files-path name="StrengGeheim" path="/" />
</paths>
这是我在 标签内的 AndroidManifest.xml 中添加的:
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider>
这是我的相机 Intent 代码:
private void cameraIntent() {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
fileUri = getOutputMediaFileUri();
intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
startActivityForResult(intent, CAMERA);
}
private Uri getOutputMediaFileUri() {
try {
return FileProvider.getUriForFile(getContext(), BuildConfig.APPLICATION_ID + ".provider",getOutputMediaFile());
}
catch (IOException ex){
ex.printStackTrace();
Toast.makeText(getContext(), MESSAGE_FAILED, Toast.LENGTH_SHORT).show();
}
return null;
}
文件Uri中的路径是这样的/storage/emulated/0/StrengGeheim/06673da7-876f-4a53-9a3d-288ae033f7ac,从图库中存储图片的路径也是一样的。但是我在拍摄照片和应用程序关闭时仍然遇到错误。
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.stegano.strenggeheim, PID: 19189
java.lang.IllegalArgumentException: Failed to find configured root that contains /storage/emulated/0/StrengGeheim/8bb91a47-d33f-428d-a6ee-1f974e61e63e.png
at android.support.v4.content.FileProvider$SimplePathStrategy.getUriForFile(FileProvider.java:712)
at android.support.v4.content.FileProvider.getUriForFile(FileProvider.java:401)
at com.stegano.strenggeheim.fragment.FragmentEncode.getOutputMediaFileUri(FragmentEncode.java:68)
at com.stegano.strenggeheim.fragment.FragmentEncode.cameraIntent(FragmentEncode.java:61)
at com.stegano.strenggeheim.fragment.FragmentEncode.access0(FragmentEncode.java:35)
at com.stegano.strenggeheim.fragment.FragmentEncode.onClick(FragmentEncode.java:111)
at android.support.v7.app.AlertController$AlertParams.onItemClick(AlertController.java:1044)
at android.widget.AdapterView.performItemClick(AdapterView.java:318)
at android.widget.AbsListView.performItemClick(AbsListView.java:1165)
at android.widget.AbsListView$PerformClick.run(AbsListView.java:3134)
at android.widget.AbsListView.run(AbsListView.java:4049)
at android.os.Handler.handleCallback(Handler.java:789)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
这就是我处理 OnActivityResult 的方式:
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == getActivity().RESULT_CANCELED) {
return;
}
try {
if (requestCode == GALLERY && data != null) {
Bitmap bitmap = getBitmapFromData(data, getContext());
File mediaFile = getOutputMediaFile();
String path = saveImage(bitmap, mediaFile);
Log.println(Log.INFO, "Message", path);
Toast.makeText(getContext(), MESSAGE_IMAGE_SAVED, Toast.LENGTH_SHORT).show();
loadImage.setImageBitmap(bitmap);
imageTextMessage.setVisibility(View.INVISIBLE);
} else if (requestCode == CAMERA) {
File file = new File(fileUri.getPath());
final Bitmap bitmap = BitmapFactory.decodeFile(fileUri.getPath());
loadImage.setImageBitmap(bitmap);
saveImage(bitmap, file);
Toast.makeText(getContext(), MESSAGE_IMAGE_SAVED, Toast.LENGTH_SHORT).show();
imageTextMessage.setVisibility(View.INVISIBLE);
}
} catch (Exception ex) {
ex.printStackTrace();
Toast.makeText(getContext(), MESSAGE_FAILED, Toast.LENGTH_SHORT).show();
}
}
private Bitmap getBitmapFromData(Intent intent, Context context){
Uri selectedImage = intent.getData();
String[] filePathColumn = { MediaStore.Images.Media.DATA };
Cursor cursor = context.getContentResolver().query(selectedImage,filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
String picturePath = cursor.getString(columnIndex);
cursor.close();
return BitmapFactory.decodeFile(picturePath);
}
private String saveImage(Bitmap bmpImage, File mediaFile) {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
bmpImage.compress(Bitmap.CompressFormat.PNG, 100, bytes);
try {
FileOutputStream fo = new FileOutputStream(mediaFile);
fo.write(bytes.toByteArray());
MediaScannerConnection.scanFile(getContext(),
new String[]{mediaFile.getPath()},
new String[]{"image/png"}, null);
fo.close();
return mediaFile.getAbsolutePath();
} catch (IOException ex) {
ex.printStackTrace();
}
return "";
}
有人可以帮忙吗?
<paths>
<external-files-path name="StrengGeheim" path="/" />
</paths>
此配置适用于存储在 getExternalFilesDir()
下的文件。根据您的错误,那不是您的文件存储位置。将其更改为:
<paths>
<external-path name="StrengGeheim" path="."/>
</paths>
在我的项目中,我使用 FileProvider.getUriForFile
给定 provider_paths.xml 文件:
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-files-path name="StrengGeheim" path="/" />
</paths>
这是我在 标签内的 AndroidManifest.xml 中添加的:
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider>
这是我的相机 Intent 代码:
private void cameraIntent() {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
fileUri = getOutputMediaFileUri();
intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
startActivityForResult(intent, CAMERA);
}
private Uri getOutputMediaFileUri() {
try {
return FileProvider.getUriForFile(getContext(), BuildConfig.APPLICATION_ID + ".provider",getOutputMediaFile());
}
catch (IOException ex){
ex.printStackTrace();
Toast.makeText(getContext(), MESSAGE_FAILED, Toast.LENGTH_SHORT).show();
}
return null;
}
文件Uri中的路径是这样的/storage/emulated/0/StrengGeheim/06673da7-876f-4a53-9a3d-288ae033f7ac,从图库中存储图片的路径也是一样的。但是我在拍摄照片和应用程序关闭时仍然遇到错误。
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.stegano.strenggeheim, PID: 19189
java.lang.IllegalArgumentException: Failed to find configured root that contains /storage/emulated/0/StrengGeheim/8bb91a47-d33f-428d-a6ee-1f974e61e63e.png
at android.support.v4.content.FileProvider$SimplePathStrategy.getUriForFile(FileProvider.java:712)
at android.support.v4.content.FileProvider.getUriForFile(FileProvider.java:401)
at com.stegano.strenggeheim.fragment.FragmentEncode.getOutputMediaFileUri(FragmentEncode.java:68)
at com.stegano.strenggeheim.fragment.FragmentEncode.cameraIntent(FragmentEncode.java:61)
at com.stegano.strenggeheim.fragment.FragmentEncode.access0(FragmentEncode.java:35)
at com.stegano.strenggeheim.fragment.FragmentEncode.onClick(FragmentEncode.java:111)
at android.support.v7.app.AlertController$AlertParams.onItemClick(AlertController.java:1044)
at android.widget.AdapterView.performItemClick(AdapterView.java:318)
at android.widget.AbsListView.performItemClick(AbsListView.java:1165)
at android.widget.AbsListView$PerformClick.run(AbsListView.java:3134)
at android.widget.AbsListView.run(AbsListView.java:4049)
at android.os.Handler.handleCallback(Handler.java:789)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
这就是我处理 OnActivityResult 的方式:
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == getActivity().RESULT_CANCELED) {
return;
}
try {
if (requestCode == GALLERY && data != null) {
Bitmap bitmap = getBitmapFromData(data, getContext());
File mediaFile = getOutputMediaFile();
String path = saveImage(bitmap, mediaFile);
Log.println(Log.INFO, "Message", path);
Toast.makeText(getContext(), MESSAGE_IMAGE_SAVED, Toast.LENGTH_SHORT).show();
loadImage.setImageBitmap(bitmap);
imageTextMessage.setVisibility(View.INVISIBLE);
} else if (requestCode == CAMERA) {
File file = new File(fileUri.getPath());
final Bitmap bitmap = BitmapFactory.decodeFile(fileUri.getPath());
loadImage.setImageBitmap(bitmap);
saveImage(bitmap, file);
Toast.makeText(getContext(), MESSAGE_IMAGE_SAVED, Toast.LENGTH_SHORT).show();
imageTextMessage.setVisibility(View.INVISIBLE);
}
} catch (Exception ex) {
ex.printStackTrace();
Toast.makeText(getContext(), MESSAGE_FAILED, Toast.LENGTH_SHORT).show();
}
}
private Bitmap getBitmapFromData(Intent intent, Context context){
Uri selectedImage = intent.getData();
String[] filePathColumn = { MediaStore.Images.Media.DATA };
Cursor cursor = context.getContentResolver().query(selectedImage,filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
String picturePath = cursor.getString(columnIndex);
cursor.close();
return BitmapFactory.decodeFile(picturePath);
}
private String saveImage(Bitmap bmpImage, File mediaFile) {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
bmpImage.compress(Bitmap.CompressFormat.PNG, 100, bytes);
try {
FileOutputStream fo = new FileOutputStream(mediaFile);
fo.write(bytes.toByteArray());
MediaScannerConnection.scanFile(getContext(),
new String[]{mediaFile.getPath()},
new String[]{"image/png"}, null);
fo.close();
return mediaFile.getAbsolutePath();
} catch (IOException ex) {
ex.printStackTrace();
}
return "";
}
有人可以帮忙吗?
<paths>
<external-files-path name="StrengGeheim" path="/" />
</paths>
此配置适用于存储在 getExternalFilesDir()
下的文件。根据您的错误,那不是您的文件存储位置。将其更改为:
<paths>
<external-path name="StrengGeheim" path="."/>
</paths>