In my application I would like to open an image and "load" it to the app using File Manager. I've already doneit using Intent.ACTION_GET_CONTENT and onActivityResult() method. Everything works fine, except from the path which I get. It is in a strange format and I can't show the image in ImageView
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == SELECT_PICTURE) {
Uri selectedImageUri = data.getData();
mFileManagerString = selectedImageUri.getPath();
showPreviewDialog(mFileManagerString);
}
}
Here mFileManagerString = /document/image:19552
When I call a method to show the image in the ImageView:
public void setPreviewIV(String pPath) {
Bitmap bmImg = BitmapFactory.decodeFile(pPath);
receiptPreviewIV.setImageBitmap(bmImg);
}
I get the following error:
E/BitmapFactory: Unable to decode stream: java.io.FileNotFoundException: /document/image:19552: open failed: ENOENT (No such file or directory)
How to get the proper path to the image, so that I can show it in the ImageView?
How to get the proper path to the image
You already have it. It is the Uri that is passed into onActivityResult() via the Intent parameter. Pulling just getPath() out of that Uri is pointless. That's akin to thinking that /questions/33827687/wrong-image-file-path-obtained-from-android-file-manager is a path on your hard drive, just because your Web browser shows a URL that contains that path.
In addition, your current code is loading and decoding the Bitmap on the main application thread. Do not do this, because it freezes the UI while that work is being done.
I recommend that you use any one of the many image-loading libraries available for Android. All the decent ones (e.g., Picasso, Universal Image Loader) not only take a Uri as input but also will load the image on a background thread for you, applying it to your ImageView on the main application thread only when the bitmap is ready.
If, for whatever reason, you feel that you have to do this yourself, use ContentResolver and its openInputStream() to get an InputStream for the data represented by the Uri. Then, pass that to decodeStream() on BitmapFactory. Do all of that in a background thread (e.g., doInBackground() of an AsyncTask), and then apply the Bitmap to the ImageView on the main application thread (e.g., onPostExecute() of an AsyncTask).
Related
I'm having a trouble bringing the images from the gallery to my app.
The hard part is that, in some articles they use uri rather than path, but in others vice versa.
Plus, I'm not also sure... when I get Uri from the intent coming back, should I use cursor to get images data? (How to get Images from Cursor in android?) In some other references, they do it in the easy way, just with 'getPath()' method.
Do I need either of path or uri? or Only one of these?
I'm so confused now..
Always use Uri:
File file = new File(uri.getPath());
then
Bitmap bitmap= BitmapFactory.decodeFile(file.getAbsolutePath());
and when you have bitmap simply load it in to ImageView
imageView.setImageBitmap(bitmap);
I have tried:
ThumbnailUtils.createVideoThumbnail(uri.getPath(),
MediaStore.Video.Thumbnails.MINI_KIND);
But this returns null for a content Uri. I have also tried this:
private Bitmap getVideoThumbnail(Context context, Uri uri) throws IllegalArgumentException,
SecurityException{
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
retriever.setDataSource(context,uri);
return retriever.getFrameAtTime();
}
This works for both file scheme and content scheme Uris. But it takes ~1.5s to get thumbnail of content Uris representing remote data blocking the UI. I suppose I could make this async and receive the thumbnail is a callback. But I thought there must be a simpler approach to get thumbnails for both file and content Uris. Also this method throws IllegalArgumentExceptions sporadically.
So, is there a way to reliably get thumbnail from file or content Uri schemes?
I'm developing an application that takes a photo and saves it in Android/data/package/files. I would like to reduce storage used, so I would like to resize the photo before saving it. For the moment I'm calling new intent passing as extra the output path. Is possible to pass also the size wanted or is possible to have the bitmap before saving it?
public void takePicture(View view){
Intent pictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File f = new File(getPath(nameEdit.getText().toString()));
path = f.getAbsolutePath();
pictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(f));
if (pictureIntent.resolveActivity(getPackageManager())!=null){
startActivityForResult(pictureIntent,REQUEST_IMAGE_CAPTURE);
}
}
Is possible to pass also the size wanted
No.
is possible to have the bitmap before saving it?
Not really. You could write your own ContentProvider and use a Uri for that, rather than a file. When the camera app tries saving the content, you would get that information in memory first. However, you will then crash with an OutOfMemoryError, as you will not have enough heap space to hold a full-resolution photo, in all likelihood.
You can use BitmapFactory with inSampleSize set in the BitmapFactory.Options to read in the file once it has been written by the camera, save the resized image as you see fit, then delete the full-resolution image. Or, skip EXTRA_OUTPUT, and you will get a thumbnail image returned to you, obtained by calling getExtra("data") on the Intent passed into onHandleIntent().
I'm trying to implement camera app with certain features. I need to take a picture using phone's camera and then manipulate that image. However, I don't need to save the picture to the file, I only need to get some "data" from the picture. Is there a way to take picture and then immediately load it as bitmap or do I need to at least save it, read it and then delete it.
I read this tutorial: https://developer.android.com/training/camera/photobasics.html, but saving and deleting images seems heavy on processor, so I'd like to avoid it if I can. Ty
As Saiteja Prasadam notes, if you skip EXTRA_OUTPUT on ACTION_IMAGE_CAPTURE, you will get a thumbnail Bitmap back via getExtra("data").
Beyond that, you can work with the camera APIs directly (e.g., android.hardware.Camera).
You could try creating a ContentProvider that supports writing to a memory buffer instead of a file, then use a content: Uri pointing to that provider in EXTRA_OUTPUT. Getting this to work correctly, and without fragmenting your heap space, may be difficult or impossible.
Overall, bear in mind that you might not have heap space for a full-resolution image anyway. I do not know what "some "data" from the picture" means, exactly, but if it depends upon loading the whole image into RAM, you are going to have challenges implementing that.
Here is the relevant API documentation:
https://developer.android.com/reference/android/hardware/Camera.html#takePicture(android.hardware.Camera.ShutterCallback,%20android.hardware.Camera.PictureCallback,%20android.hardware.Camera.PictureCallback,%20android.hardware.Camera.PictureCallback)
void takePicture (Camera.ShutterCallback shutter,
Camera.PictureCallback raw,
Camera.PictureCallback postview,
Camera.PictureCallback jpeg)
shutter: the callback for image capture moment, or null
raw: the callback for raw (uncompressed) image data, or null
postview: callback with postview image data, may be null
jpeg: the callback for JPEG image data, or null
Start Intent
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, CAMERA_REQUEST);
Activity Result
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == CAMERA_REQUEST && resultCode == RESULT_OK) {
Bitmap photo = (Bitmap) data.getExtras().get("data");
}
}
Note: This thumbnail image from "data" might be good for an icon, but not a lot more. Dealing with a full-sized image takes a bit more work.
I am using EasyImage library to take pictures.
I then convert those Files to Bitmap and then I convert Bitmap to Base64 and upload it to server.
I know, it's not a good way to do it, but that's how I currently do it.
When a picture is taken:
#Override
public void onImagePicked(File imageFile, EasyImage.ImageSource source) {
uploadImage(imageFile);
}
This is the first line inside "uploadImage" method:
Image image = new Image(LoginManager.getInstance(getApplicationContext()).getUsername(), file);
This is the constructor:
public Image(String userName, File imageFile) {
this.userName = userName;
this.imageFile = imageFile;
createBase64(getBitmap());
}
Inside "getBitmap" is where the problem begins. These 2 lines in particular:
bitmap = BitmapFactory.decodeFile(imageFile.getPath());
bitmap = Bitmap.createScaledBitmap(bitmap, 100, 100, false);
imageFile is never null.
I checked with debugger at least a 100 times and it is never null. It also always has path.
getPath() is never null.
However, it still often fails to create bitmap.
Sometimes it is successful and everything is OK, but most of the times, the bitmap is null.
I don't know why.
File (the picture taken) is always created successfully and is never null, but it just fails to create the Bitmap for some reason.
From the documentation
Returns
the resulting decoded bitmap, or null if it could not be decoded.
This can have various reasons, most of the times the bitmap is too large and the space could not be allocated.
Check that the path to the image exists and that you have read / write permissions to the URI specified.
If you do have access but it is still failing you should add BitmapFactory.Options to the method call and set inSampleSize to load a smaller version of the image.
If set to a value > 1, requests the decoder to subsample the original image, returning a smaller image to save memory.
Also you should always check for null returned when working with bitmaps, since memory can always be an issue.