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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With