Getting FileNotFoundException while capturing phot

2019-08-17 08:01发布

问题:

I am using FileProvider.getUriForFile with given provider_paths.xml file. I am doing something wrong which I am not getting.

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
  <external-path name="StrengGeheim" path="."/>
</paths>

This I added in my AndroidManifest.xml inside tag:

<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>

This is my camera Intent code:

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 {
        File file = getOutputMediaFile();
        return FileProvider.getUriForFile(getActivity(), BuildConfig.APPLICATION_ID + ".provider", file);
    }
    catch (IOException ex){
        ex.printStackTrace();
        Toast.makeText(getContext(), MESSAGE_FAILED, Toast.LENGTH_SHORT).show();
    }
    return null;
}

private File getOutputMediaFile() throws IOException {
    File encodeImageDirectory =
            new File(Environment.getExternalStorageDirectory() + IMAGE_DIRECTORY);

    if (!encodeImageDirectory.exists()) {
        encodeImageDirectory.mkdirs();
    }
    String uniqueId = UUID.randomUUID().toString();
    File mediaFile = new File(encodeImageDirectory, uniqueId + ".png");
    mediaFile.createNewFile();
    return mediaFile;
}

In file Uri the path is something like this /StrengGeheim/StrengGeheim/21a70d51-3375-4d44-b698-0727b6f90065.png while creating the media file to store captured image but the path of storing image from gallery is /storage/emulated/0/StrengGeheim/06673da7-876f-4a53-9a3d-288ae033f7ac. I am getting below error while capturing photo and app is closing.

 E/BitmapFactory: Unable to decode stream: java.io.FileNotFoundException: /StrengGeheim/StrengGeheim/21a70d51-3375-4d44-b698-0727b6f90065.png (No such file or directory)
W/System.err: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.graphics.Bitmap.compress(android.graphics.Bitmap$CompressFormat, int, java.io.OutputStream)' on a null object reference
W/System.err:     at com.stegano.strenggeheim.fragment.FragmentEncode.saveImage(FragmentEncode.java:166)
W/System.err:     at com.stegano.strenggeheim.fragment.FragmentEncode.onActivityResult(FragmentEncode.java:143)
W/System.err:     at android.support.v4.app.FragmentActivity.onActivityResult(FragmentActivity.java:151)
W/System.err:     at android.app.Activity.dispatchActivityResult(Activity.java:7235)
W/System.err:     at android.app.ActivityThread.deliverResults(ActivityThread.java:4320)
W/System.err:     at android.app.ActivityThread.handleSendResult(ActivityThread.java:4367)
W/System.err:     at android.app.ActivityThread.-wrap19(Unknown Source:0)
W/System.err:     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1649)
W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:105)
W/System.err:     at android.os.Looper.loop(Looper.java:164)
W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:6541)
W/System.err:     at java.lang.reflect.Method.invoke(Native Method)
W/System.err:     at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)

This is how I am handling 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 "";
}

Can someone help, please?

回答1:

File file =  new File(fileUri.getPath());

As I pointed out previously, this is wrong. Get rid of this line.

The File that you need is the one that you that you are using as part of creating the Uri value that you are putting into EXTRA_OUTPUT. Instead of holding onto fileUri in a field, hold onto that File in a field.

Also:

  • Please load bitmaps and do disk I/O on background thread

  • Please do not waste the user's time creating a second image file, since you already have one (IOW, do not call saveImage() when you already have the file)