Unable to load image from sdcard to canvas - android

How can I load an image from sdcard to canvas. I tried this code and it is not working.
Uri selectedImage = data.getData();
if (selectedImage == null) {
Log.e(getString(R.string.app_name), "selected image uri is null");
return;
}
String[] filePath = { MediaStore.Images.Media.DATA };
Cursor cursor = getActivity().getContentResolver().query(selectedImage, filePath, null, null, null);
if(cursor==null){
Log.e(getString(R.string.app_name), "image cursor is null");
return;
}
cursor.moveToFirst();
String imagePath = cursor.getString(cursor.getColumnIndex(filePath[0]));
cursor.close();
Bitmap bitmap = BitmapFactory.decodeFile(imagePath);
Bitmap bitmap2 = Bitmap.createBitmap(bitmap.getHeight(),bitmap.getWidth(),bitmap.getConfig());
mCanvas.setBitmap(bitmap2);
Paint p = new Paint();
mCanvas.drawBitmap(bitmap,0,0,p);
What is wrong in this code?

I do not know where this Uri is coming from. However:
Get rid of all the MediaStore stuff
Use ContentResolver and openInputStream() to get an InputStream on the content identified by the Uri
Use BitmapFactory.decodeStream() to decode from that stream
Also:
Make sure that you request READ_EXTERNAL_STORAGE or WRITE_EXTERNAL_STORAGE, including handling runtime permissions
Eventually, move the openInputStream() and decodeStream() work to a background thread
Consider switching to an image-loading library

Related

Download image from new Google+ (plus) Photos Application

Recently Google added the Photos app for Google+ (plus) and it shows up when you launch an Intent to choose an image. However, if I select an image from Google+ Photos and try to use it in my application none of my current logic is able to return a usable URI or URL to actually get an image that I can download and manipulate. I'm currently using the "common" methods to try to manipulate the URI that can be found here on Stack Overflow and elsewhere. I can provide code if needed, but at this point I think it's kind of irrelevant since it works well for everything else except this new app. Any ideas on how to get a usable image?
The URI looks something like the following:
content://com.google.android.apps.photos.content/0/https%3A%2F%2Flh5.googleusercontent.com%<a bunch of letters and numbers here>
The MediaColumns.DATA info always returns null and the MediaColumns.DISPLAY_NAME always returns image.jpg no matter what I select from the Google Photos app. If I try to paste everything from https to the end in my browser, nothing comes up. Not sure how to get usable info from this.
When receiving the data intent, you should use the contentResolver to get the photos.
Here's what you should do:
String url = intent.getData().toString();
Bitmap bitmap = null;
InputStream is = null;
if (url.startsWith("content://com.google.android.apps.photos.content")){
is = getContentResolver().openInputStream(Uri.parse(url));
bitmap = BitmapFactory.decodeStream(is);
}
I did faced issues selecting images from new Google Photos app. I was able to resolve it by below code.
It works for me, basically what i did is i am checking if there is any authority is there or not in content URI. If it is there i am writing to temporary file and returning path of that temporary image. You can skip compression part while writing to temporary image
public static String getImageUrlWithAuthority(Context context, Uri uri) {
InputStream is = null;
if (uri.getAuthority() != null) {
try {
is = context.getContentResolver().openInputStream(uri);
Bitmap bmp = BitmapFactory.decodeStream(is);
return writeToTempImageAndGetPathUri(context, bmp).toString();
} catch (FileNotFoundException e) {
e.printStackTrace();
}finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
public static Uri writeToTempImageAndGetPathUri(Context inContext, Bitmap inImage) {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
inImage.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
String path = MediaStore.Images.Media.insertImage(inContext.getContentResolver(), inImage, "Title", null);
return Uri.parse(path);
}
P.S. : I have answered a similar question here
You have to use projection in order to get ImageColumns.DATA (or MediaColumns.DATA):
private String getRealPathFromURI(Uri contentURI) {
// Projection makes ContentResolver to get needed columns only
String[] medData = { MediaStore.Images.Media.DATA };
Cursor cursor = getContentResolver().query(contentURI, medData, null, null, null);
// this is how you can simply get Bitmap
Bitmap bmp = MediaStore.Images.Media.getBitmap(getContentResolver(), contentURI);
// After using projection cursor will have needed DATA column
cursor.moveToFirst();
final int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
return cursor.getString(idx);
}

Referencing a file on SD-Card, Android

I currently trying to carry out the same operation (OCR) on images in android, one option is to use the camera and the other is to load an image from the SD-CARD. The code works when taken from a camera where the code is
Bitmap bitmap = BitmapFactory.decodeFile(_path,options);
where _path is equal to the last image taken using the application ( _path = DATA_PATH + "ocr.jpg"; ) . However when I try to use an image selected from the gallery where _path would equal,
imageCaptureUri = data.getData();
_path = imageCaptureUri.getPath();
The program locks up with the error
Failure deleiving result ResultInfo{who=null, request = 2, result = -1, data=intent {dat=content://media/external/images/media/26 typ=image/jpeg(has extras)}} to activity{com.project.projectActivity}: java.lang.NullPointerException
If anybody has an idea of whats going on I'd like to hear from you !!
You can get path of the image as..
_path = getPath(imageCaptureUri);
public String getPath(Uri uri) {
String[] projection = { MediaColumns.DATA };
Cursor cursor = managedQuery(uri, projection, null, null, null);
column_index = cursor
.getColumnIndexOrThrow(MediaColumns.DATA);
cursor.moveToFirst();
imagePath = cursor.getString(column_index);
return cursor.getString(column_index);
}
and then
Bitmap bitmap = BitmapFactory.decodeFile(_path,options);
Note : If you are cropping image then this method does not work in this case Gallery will generate cropped image on same directory of image which you are cropping.
The Gallery returns you an Uri to access the image.
You need to use the decodeStream method from BitmapFactory, and for that you need to open an InputStream on the Uri given :
InputStream is = getContentResolver().openInputStream(imageCaptureUri);
Bitmap bitmap = BitmapFactory.decodeStream(is, options);

"Permission denied" when trying to handle a "Share Image" intent from Browser in my own activity

I'm trying to write a simple activity which does the following:
A user holds down on an image viewed in the Android Browser and then presses "Share image" and chooses my Activity to handle it. I want to be able to open the image file from within my activity.
The file path ends up being: /data/data/com.android.browser/app_sharedimage/SOME_FILE_NAME.jpg
and calling "File()" on the path results in a permission error:
java.io.FileNotFoundException: /data/data/com.android.browser/app_sharedimage/SOME_FILE_NAME.jpg (Permission denied")
How can I open this image file? Is there some permission I need to put in the manifest?
Here's the relevant code:
if (Intent.ACTION_SEND.equals(intent.getAction())) {
if (extras.containsKey(Intent.EXTRA_STREAM)) {
Uri uri = (Uri) extras.getParcelable(Intent.EXTRA_STREAM);
String scheme = uri.getScheme();
if (scheme.equals("content")) {
String mimeType = intent.getType();
ContentResolver contentResolver = getContentResolver();
Cursor cursor = contentResolver.query(uri, null, null,
null, null);
cursor.moveToFirst();
String filePath = cursor.getString(cursor
.getColumnIndexOrThrow(Images.Media.DATA));
...
...
new FileBody(new File(filePath))
...
AFAIK you wont be able to access private files of any other applications unless your phone is rooted. So I think you wont be able open the image.
I can display (I suppose this is what you mean by opening) an image from the browser on a HTC Desire and it is not rooted.
I use the URI just like you from the extras in the Intent. Then I get an InputStream and create a Drawable from it, which can be displayed in an ImageView.
The URI I get is:
content://htcbrowser/share_image/data/data/com.android.browser/app_sharedimage/logo3w.png?image/png
if (intent.getType() != null && intent.getType().indexOf("image/") != -1) {
Bundle extras = intent.getExtras();
if (extras.containsKey(Intent.EXTRA_STREAM)) {
Uri uri = (Uri) extras.getParcelable(Intent.EXTRA_STREAM);
ImageView iv = (ImageView) findViewById(R.id.imageView1);
try {
InputStream is = getContentResolver().openInputStream(uri);
Drawable myDrawable = Drawable.createFromStream(is, "srcName");
iv.setImageDrawable(myDrawable);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}

How to use ExifInterface with a stream or URI

I'm writing an app that can be sent a photo URI from the "Share via" menu in Android.
The kind of URI you get is content://media/external/images/media/556 however ExifInterface wants a standard file name. So how do I read the exif data (I just want orientation) of that file? Here's my (non-working) code:
Uri uri = (Uri)extras.getParcelable(Intent.EXTRA_STREAM);
ContentResolver cr = getContentResolver();
InputStream is = cr.openInputStream(uri);
Bitmap bm = BitmapFactory.decodeStream(is);
// This line doesn't work:
ExifInterface exif = new ExifInterface(uri.toString());
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1);
Any help (other than "you have to write your own ExifInterface class") is appreciated!
I found the answer randomly in the Facebook Android SDK examples. I haven't tested it, but it looks like it should work. Here's the code:
public static int getOrientation(Context context, Uri photoUri) {
/* it's on the external media. */
Cursor cursor = context.getContentResolver().query(photoUri,
new String[] { MediaStore.Images.ImageColumns.ORIENTATION }, null, null, null);
int result = -1;
if (null != cursor) {
if (cursor.moveToFirst()) {
result = cursor.getInt(0);
}
cursor.close();
}
return result;
}
You can get an ExifInterface using a filename string or InputStream, by doing importing the support ExifInterface in your build.gradle file:
compile 'com.android.support:exifinterface:26.1.0'
then:
private getExifInterfaceFromUri(Uri uri) throws IOException{
FileInputStream fi = new FileInputStream(uri.getPath());
return new ExifInterface(stream);
}
Remember that in Android there are multiple Uri types and you may need to use a Content Resolver and other approaches to get the real path from an Uri.

Getting full-sized image from the camera does not work on Galaxy S

I am having a problem capturing an image from the built-in camera app on the Samsung Galaxy S.
I have a button on my app that when pressed launches the camera:
ContentValues values = new ContentValues();
values.put(Images.Media.MIME_TYPE, "image/jpeg");
mPicUri = getContentResolver().insert(Media.EXTERNAL_CONTENT_URI, values);
intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, mPicUri.getPath());
startActivityForResult(intent, REQ_CODE_TAKE_PIC);
From what I read on the interwebz, I can get the full-sized just-taken picture using the URI I passed to the intent. And so I have this on my onActivityResult:
Uri selectedImage = mPicUri;
String[] filePathColumn = {MediaStore.Images.Media.DATA};
Cursor cursor = getContentResolver().query(selectedImage, filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
String filePath = cursor.getString(columnIndex);
cursor.close();
And then using the variable filePath, I set the image in an ImageView. I am getting no image, and when I stepped through the code, I found out that BitmapFactory.decodeFile() is returning null.
Bitmap chosenPic = BitmapFactory.decodeFile(filePath);
So I tried a little more debugging. I found out that mPicUri returns a seemingly valid URI, such as: content://media/external/images/media/90. After the picture is taken and the user chooses to save the picture, the cursor resolves to the following filePath: /sdcard/DCIM/Camera/1285601413961.jpg. No bitmap is decoded though, BUT when I looked through the gallery, the picture I just took is there. So I tried to take a look at the URI of that picture, and this is what I got:
URI is: content://media/external/images/media/91
File path is: /sdcard/DCIM/Camera/2010-09-27 23.30.30.jpg
And so, it looks like the value I got from mPicUri is not the final URI that will be used.
Am I missing a step here? All I really want to do is retrieve the file of the just-taken picture.
Thanks in advance,
Zarah.
Did you try to specify File in both cases before taking picture and the same after?
public static File getTempFile() {
//it will return /sdcard/image.jpg
final File path = new File(Environment.getExternalStorageDirectory(), "MyApp");
if (!path.exists()) {
path.mkdir();
}
return new File(path, "image.jpg");
}
I'm using this function to get and set file path.

Categories

Resources