简体   繁体   中英

Can't load image taken from camera into an ImageView

I am able to save the image taken from camera into internal storage, however I can't load it into ImageView, which remains empty. I've read all relevant suggestions but couldn't find a suitable solution. Please find relevant code below, any help will be MUCH appreciated, as I'm struggling with it for days...

Manifest permissions:

<uses-feature android:name="android.hardware.camera" />
<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"/>

ImageView on XML:

<ImageView
    android:id="@+id/recipeImage"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginRight="10dp"
    android:layout_weight="1"
    android:background="@color/backgroundColorHomeBottomLayout"
    android:padding="30dp" />

Relevant activity:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {

    if (requestCode == REQUEST_IMAGE_CAPTURE) {
        if (resultCode == RESULT_OK) {
            setPic();
            //mImageView.setImageURI(fileUri);
        }
        else if (resultCode == RESULT_CANCELED) {
            /** user cancelled Image capture */
            Toast.makeText(this,
                    "User cancelled image capture", Toast.LENGTH_SHORT)
                    .show();
        } else {
            /** failed to capture image */
            Toast.makeText(this,
                    "Sorry! Failed to capture image", Toast.LENGTH_SHORT)
                    .show();
        }
    }
}

/** Internal memory methods */
private void launchCameraIntent() {
    Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        /** Ensure that there's a camera activity to handle the intent */
    if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
        /** Create the File where the photo should go */
        File photoFile = null;
        try {
            photoFile = createImageFile();
        } catch (IOException ex) {
            // Error occurred while creating the File
        }
        // Continue only if the File was successfully created
        if (photoFile != null) {
            Uri photoURI = FileProvider.getUriForFile(this,
                    "v3.com.mycookbook5.fileprovider",
                    photoFile);
            takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
            startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
        }
    }
}

/** return a unique file name for a new photo using a date-time stamp */
private File createImageFile() throws IOException {
    /** Create an image file name */
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    String imageFileName = "JPEG_" + timeStamp + "_";
    File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
    File image = File.createTempFile(
            imageFileName,  /* prefix */
            ".jpg",         /* suffix */
            storageDir      /* directory */
    );
    /** Save a file: path for use with ACTION_VIEW intents */
    mCurrentPhotoPath = "file:" + image.getAbsolutePath();
    return image;
}

private void setPic() {
    // Get the dimensions of the View
    int targetW = mImageView.getWidth();
    int targetH = mImageView.getHeight();

    // Get the dimensions of the bitmap
    BitmapFactory.Options bmOptions = new BitmapFactory.Options();
    bmOptions.inJustDecodeBounds = true;
    BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
    int photoW = bmOptions.outWidth;
    int photoH = bmOptions.outHeight;

    // Determine how much to scale down the image
    int scaleFactor = Math.min(photoW/targetW, photoH/targetH);

    // Decode the image file into a Bitmap sized to fill the View
    bmOptions.inJustDecodeBounds = false;
    bmOptions.inSampleSize = scaleFactor;
    bmOptions.inPurgeable = true;

    Bitmap bitmap = BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
    mImageView.setImageBitmap(bitmap);
}

Log:

07-03 12:56:07.188 3950-16091/? E/Drive.UninstallOperation: Package still installed v3.com.mycookbook5
07-03 12:56:35.350 19680-19680/v3.com.mycookbook5 E/BitmapFactory: Unable to decode stream: java.io.FileNotFoundException: file:/storage/emulated/0/Android/data/v3.com.mycookbook5/files/Pictures/JPEG_20160703_125629_-664091716.jpg: open failed: ENOENT (No such file or directory)
07-03 12:56:35.350 19680-19680/v3.com.mycookbook5 E/BitmapFactory: Unable to decode stream: java.io.FileNotFoundException: file:/storage/emulated/0/Android/data/v3.com.mycookbook5/files/Pictures/JPEG_20160703_125629_-664091716.jpg: open failed: ENOENT (No such file or directory)

I believe that your problem is because you are not giving the image the required time to be saved to the sdcard as the code starts looking for it before it even completely saved, so you have to provide a delayed handler in order to making sure the image is successfully saved, also use the following way to get the image path:

    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            setPic();
        }
    }, 750);

and for getting the image from the sdcard:

File file = new File(Environment.getExternalStorageDirectory()+File.separator + "image_name.jpg");
Bitmap bitmap = decodeSampledBitmapFromFile(file.getAbsolutePath(), 1000, 700);

public static Bitmap decodeSampledBitmapFromFile(String path, int reqWidth, int reqHeight) 
{ 

    /*
     * here you set all of your bmOptions specs
     */

    return BitmapFactory.decodeFile(path, bmOptions);
}

Problem solved. To help others, here is how it should be performed:

  1. Downgrade targetSdkVersion on build.gradle from 23 --> 22, to avoid permission issues.
  2. Add the following code to launchCameraIntent() method:

     takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI); 
  3. Change setPic method as follow:

      Bitmap bitmap = BitmapFactory.decodeFile(photoFile.getPath()); Matrix matrix = new Matrix(); matrix.postRotate(90); Bitmap rotatedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, false); Bitmap scaledBitmap = Bitmap.createScaledBitmap(rotatedBitmap, 200, 150 ,false); mImageView.setImageBitmap(scaledBitmap); 

I would say you might get a zero size image due to trying to resize it to the imageView size (which, if not rendered yet - may be zero size).

Try to load the image without any manipulation and after succeeding - change your code to reduce the memory consumption , but by but until you get the optimal result.

Good luck.

You realize you will have to pull the extra data from the intent right? 'onActivityResult' will get back to your activity with a result code and WITH EXTRA DATA which is the bitmap of the image, you should pass that data (in whatever way you choose) to your setPic method.
To get the Bitmap photo you can use the code down below

if (requestCode == REQUEST_IMAGE_CAPTURE) { 
            Bitmap photo = (Bitmap) data.getExtras().get("data"); 
}

try this code for marshmallow

Uri imageFileUri = data.getData();

 final Bitmap bitmap = getBitmapFromUri(imageFileUri);

 private Bitmap getBitmapFromUri(Uri uri) throws IOException {
        ParcelFileDescriptor parcelFileDescriptor =
                getLocalContext().getContentResolver().openFileDescriptor(uri, "r");
        FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
        Bitmap image = BitmapFactory.decodeFileDescriptor(fileDescriptor);
        parcelFileDescriptor.close();
        return image;
    }



    @Override 
protected void onActivityResult(int requestCode, int resultCode, Intent data) {

    if (requestCode == REQUEST_IMAGE_CAPTURE) {
        if (resultCode == RESULT_OK) {

            //mImageView.setImageURI(fileUri);
 Uri imageFileUri = data.getData(); 
 final Bitmap bitmap = getBitmapFromUri(imageFileUri);
setPic(bitmap);  
        } 
        else if (resultCode == RESULT_CANCELED) {
            /** user cancelled Image capture */ 
            Toast.makeText(this,
                    "User cancelled image capture", Toast.LENGTH_SHORT)
                    .show();
        } else { 
            /** failed to capture image */ 
            Toast.makeText(this,
                    "Sorry! Failed to capture image", Toast.LENGTH_SHORT)
                    .show();
        } 
    } 
} 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM