8

I am trying to use BitmapFactory.decodefile() in order to create a scaled down version of a camera photo and set it to an imageview in my framelayout. Am following the following instructions from Android Developers: https://developer.android.com/training/camera/photobasics.html In these instructions, files are created and stored inside a fileprovider which holds some meta-data file formatted in xml. Somehow, BitmapFactory.decodefile() can't seem to access this file which stores a picture whose content uri resides inside the fileprovider. The fileprovider is created inside the androidmanifest file as follows:

<provider android:authorities="mypackagename.fileprovider" android:name="android.support.v4.content.FileProvider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" > </meta-data> </provider> 

the file_paths xml file looks like this:

<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <external-path name="my_images" path="Android/data/mypackagename/files/Pictures/" /> </paths> 

The file name for where the picture will reside is generated via this method:

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,".jpg",storageDir); // Save a file: path for use with ACTION_VIEW intents mCurrentPhotoPath = image.getAbsolutePath(); Log.d("absolute",""+image.getAbsolutePath()); return image; } 

The code starts an intent in order to take a picture with startactivityforresult() like this:

Intent i = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); // Ensure that there's a camera activity to handle the intent if (i.resolveActivity(getPackageManager()) != null) { // Create the File where the photo should go 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,"mypackagename.fileprovider",photoFile); i.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, photoURI); startActivityForResult(i,TAKE_PICTURE); } } 

Now, onActivityForResult() method starts, but if I set my if statement like this if(requestCode == TAKE_PICTURE && resultCode == RESULT_OK) it doesn't work. I don't know why. From reading the android reference documents on fileprovider class, I see that I must open the photoUri which is passed as an extra in my intent. According to the docs, I must open It with ContentResolver.openFileDescriptor which will return a ParcelFileDescriptor. Somehow, this is where the picture the camera just took resides. Somehow I need to access the file name from this ParcelFileDescriptor object and pass it to BitmapFactory.decodefile in order to scale down the picture-bitmap and set it on my imageview. I don't know how to go about this

When trying to scale the picture-bitmap I have the following code that returns -1, meaning that "according to the android reference docs for BitmapFactory class" "there was a problem decoding the file". I don't know why there would be a problem. Here's the code that returns -1:

BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions); int photoW = bmOptions.outWidth; int photoH = bmOptions.outHeight; 

Both photoW and photoH return -1. Remember that the variable mCurrentPhotoPath was initialized inside the method CreateImageFile() , all the way at the top of this question.

I've also tried,

BitmapFactory.decodeFile(photoFile.getAbsolutePath(), bmOptions); 

But still the same result, actually mCurrentPhotoPath and photoFile.getAbsolutePath() are equal strings.

I think that somehow the fileprovider with its meta-data xml file are somehow hiding the file path from BitmapFactory.decodefile().

The picture is taken when I test the app and is also stored inside my phone picture gallery.

Please provide any advice or suggestions since I need to proceed with the tess-two library and perform OCR with the pictures from the camera.

Thanks for your suggestions

2
  • try adding temporary permission for the file you have created - i.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); and try again. let me know if that works. Commented Jan 7, 2017 at 11:31
  • Are you asking storage permission at runtime? Commented Mar 17, 2017 at 18:10

2 Answers 2

12

I have faced exactly the same problem and this is how I dealed with it: first of all set i.setFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); as suggested above, before launching the camera. Then, DO NOT use the BitmapFactory.decodeFile() method as it only works with the file:/// type of Uris retrieved using Uri.fromFile(), but not with the content:// type of Uris retrieved using FileProvider.getUriForFile() which is the required way for APIs >= 24.

Instead, use a ContentResolver to open an InputStream and decode the image as follows:

BitmapFactory.Options bmOptions = new BitmapFactory.Options(); bmOptions.inJustDecodeBounds = true; ContentResolver cr = getActivity().getContentResolver(); InputStream input = null; InputStream input1 = null; try { input = cr.openInputStream(photoUri); BitmapFactory.decodeStream(input, null, bmOptions); if (input != null) { input.close(); } } catch (Exception e) { e.printStackTrace(); } int photoW = bmOptions.outWidth; int photoH = bmOptions.outHeight; try { input1 = cr.openInputStream(photoUri); Bitmap takenImage = BitmapFactory.decodeStream(input1); if (input1 != null) { input1.close(); } } catch (Exception e) { e.printStackTrace(); } 

Note, that in order to obtain the Bitmap, you have to open a 2nd input stream, since the first one cannot be reused.

Sign up to request clarification or add additional context in comments.

1 Comment

BitmapFactory.decodeStream was just what I was looking for! Thank u
3

I ended here, because I was looking for a way to get Bitmap from an Uri of an image in internal storage, written with FileProvider.

(Followed this answer to write image to internal storage: https://stackoverflow.com/a/30172792/529663)

I was able to get back a readable Bitmap image using GrAndroidDeveloper's answer. Here's how:

ContentResolver cr = getApplicationContext().getContentResolver(); InputStream is = cr.openInputStream(uri); Bitmap image = BitmapFactory.decodeStream(is); if (is != null) is.close(); 

This is useful for the official facebook share, which needs a Bitmap.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.