Android- How to get the uri of a photo taken - android

I am trying to get the URI of a photo taken with the phone. I am trying to convert the data passed to "onActivityResult" to a URI, then convert this URI to a string to store in my database. This method does work with videos, so how can this be achieved with a photo? I get a null pointer exception when I try to convert the data to URI. Should I use a different function to convert the photo data to a URI? My code is as follows:
Button intent to start video recorder:
recordVideoButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent startVideoFunction = new Intent();
startVideoFunction.setAction(MediaStore.ACTION_VIDEO_CAPTURE);
startActivityForResult(startVideoFunction, REQUEST_CODE_VIDEO);
}
});
Button intent to start photo capture:
takePhotosButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent startPhotoFunction = new Intent();
startPhotoFunction.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(startPhotoFunction, REQUEST_CODE_PHOTO);
}
});
onActivityResult method:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
try {
switch (requestCode) {
case REQUEST_CODE_VIDEO:
videoUri = data.getData();
String videoPath = videoUri.toString();
videoDB.addVideoRow(videoPath);
//displayVideo.setVideoURI(videoUri);
//displayVideo.start();
break;
case REQUEST_CODE_PHOTO:
photoUri = data.getData();
String photoPath = photoUri.toString();
videoDB.addPhotoRow(photoPath);
break;
}
}catch (NullPointerException e){
//prevent crash when returning with Null data to mainactivity.
}
}
UPDATED onActivityResult:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent
data) {
// try {
switch (requestCode) {
case REQUEST_CODE_VIDEO:
videoUri = data.getData();
String videoPath = videoUri.toString();
videoDB.addVideoRow(videoPath);
//displayVideo.setVideoURI(videoUri);
//displayVideo.start();
break;
case REQUEST_CODE_PHOTO:
Bitmap photo = (Bitmap) data.getExtras().get("data");
Uri tempUri = getImageUri(getApplicationContext(), photo);
File finalFile = new File(getRealPathFromURI(tempUri));
String photoPath = finalFile.toString();
videoDB.addPhotoRow(photoPath);
break;
}
//}catch (NullPointerException e){
//prevent crash when returning with Null data to mainactivity.
//}
}
public Uri getImageUri(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);
}
public String getRealPathFromURI(Uri uri) {
Cursor cursor = getContentResolver().query(uri, null, null, null, null);
cursor.moveToFirst();
int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
return cursor.getString(idx);
}

To get Uri from Image: Convert the Bitmap to Uri using below mentioned code. You can always change the Bitmap compression format to PNG but then avoid using the line .compress as it will be of no use. PNG don't get compressed.
public Uri getImageUri(Context inContext, Bitmap inImage) {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
inImage.compress(Bitmap.CompressFormat.JPEG, 100, bytes); // Used for compression rate of the Image : 100 means no compression
String path = Images.Media.insertImage(inContext.getContentResolver(), inImage, "xyz", null);
return Uri.parse(path);
}
To get the Absolute Path from Uri use this method
public String getRealPathFromURI(Uri uri) {
Cursor cursor = getContentResolver().query(uri, null, null, null, null);
cursor.moveToFirst();
int id_uri = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
return cursor.getString(id_uri);
}
Hope this solves your problem.

You are on the wrong way. Now you will save only a thumbnail of the image taken and save that to file. While the orriginal full image is already in a file on the file system.
Tell the camera app with the intent where to store the image to be taken. Use a putExtra for EXTRA_OUTPUT.

Related

Android attachment / file picker into InputStream string

I want to create a similar function as below image. Allow user to select image / pdf file from device and convert the file into inputstream as string and sent to server. I had go through this Attaching a file of any type in Android application? and successfully to call for document but does not have option for camera. Appreciate if there any source i can refer or library that able to perform this: provide option to select from gallery/take new photo/document Select file and convert to string (inputstream)
//Json that server going to receive
"Attachment": {
"InputStream": "string",
"FileName": "string"
}
/*My Code*/
public void goToAttachment(){
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/*|application/pdf");
startActivityForResult(Intent.createChooser(intent, null), SELECTFILE_RESULT_CODE);
}
#Override
public void onActivityResult(int requestCode, int resultCode, #Nullable Intent data){
switch (requestCode){
case SELECTFILE_RESULT_CODE:
if(resultCode == RESULT_OK){
fileSrc = data.getData().getPath();
}
break;
}
}
You can use below code to get first Bitmap of Image and then get String from Bitmap Object:
#Override
public void onActivityResult(int requestCode, int resultCode, #Nullable Intent data){
switch (requestCode){
case SELECTFILE_RESULT_CODE:
if(resultCode == RESULT_OK){
// Let's read picked image data - its URI
Uri pickedImage = data.getData();
// Let's read picked image path using content resolver
String[] filePath = { MediaStore.Images.Media.DATA };
Cursor cursor = getContentResolver().query(pickedImage, filePath, null, null, null);
cursor.moveToFirst();
String imagePath = cursor.getString(cursor.getColumnIndex(filePath[0]));
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
Bitmap bitmap = BitmapFactory.decodeFile(imagePath, options);
String bmpString= bitMapToString(bitmap)
cursor.close();
}
break;
}
}
You can use below method to convert Bitmap to String:
public String bitMapToString(Bitmap bitmap){
ByteArrayOutputStream baos=new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG,100, baos);
byte [] b=baos.toByteArray();
String temp=Base64.encodeToString(b, Base64.DEFAULT);
return temp;
}
you can change Bitmap Compress format JPG or PNG as par your image.
For PDF and other file you can use below method to convert it into String.
private String getString(String filepath) throws IOException {
InputStream inputStream = new FileInputStream(filepath);
byte[] byteArray = IOUtils.toByteArray(inputStream);
String encoded = Base64.encodeToString(byteArray, Base64.DEFAULT);
return encoded;
}
To get File path you can use bellow code:
public String getRealPathFromURI(Context context, Uri contentUri) {
Cursor cursor = null;
try {
String[] proj = { MediaStore.Images.Media.DATA };
cursor = context.getContentResolver().query(contentUri, proj, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
} finally {
if (cursor != null) {
cursor.close();
}
}
}

Take photo intent returns null on data

I'm creating an app to take photos and delete image from gallery after specific process. Here is my code
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getActivity().getPackageManager()) != null) {
startActivityForResult(takePictureIntent, requestCode);
}
And I handle the result just like this
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
Bundle extras = data.getExtras();
image1 = (Bitmap) extras.get(IMAGE_BUNDLE_NAME);
imageView1.setImageBitmap(image1);
imageUri1 = data.getData();
}
}
The problem is that data.getData(); returns null in some devices. I tried to replace URI with this code
imageUri1 = getImageUri(getActivity(), image1);
And this method
public Uri getImageUri(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);
}
Whe I use this Uri I can't delete file from device. This is how I delete images
private void deleteFileFromMediaStore(final ContentResolver contentResolver, int requestCode) {
String canonicalPath;
File fdelete = new File(imageUri1.getPath());
if(fdelete != null){
try {
canonicalPath = fdelete.getCanonicalPath();
} catch (IOException e) {
canonicalPath = fdelete.getAbsolutePath();
}
final Uri uri = MediaStore.Files.getContentUri(Constants.EXTERNAL_STORAGE_CONSTANT);
final int result = contentResolver.delete(uri,
MediaStore.Files.FileColumns.DATA + "=?", new String[] {canonicalPath});
if (result == 0) {
final String absolutePath = fdelete.getAbsolutePath();
if (!absolutePath.equals(canonicalPath)) {
contentResolver.delete(uri,
MediaStore.Files.FileColumns.DATA + "=?", new String[]{absolutePath});
}
}
}
}
How can I delete the photo or how can I make data.getData() non null on all devices?
The problem is that data.getData(); returns null in some devices
It will return null with most camera apps, as it is supposed to return null.
How can I delete the photo
Save the thumbnail photo to a file (compress() and a FileOutputStream).
Or, use EXTRA_OUTPUT to request that the camera app save a full-size photo to a location that you specify (e.g., using a FileProvider-supplied Uri).
Or, use a library like Fotoapparat to take photos directly in your app, rather than relying on one of hundreds of camera apps.
how can I make "data.getData()" non null on all devices?
You can't.

Convert Image and save in SharedPreferences not working

I want to allow user to upload image from gallery into an android application that i am creating. At the moment i am able to allow the user to chose the image from the gallery here in the codes below:
/* Choose an image from Gallery */
void openImageChooser() {
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Select Picture"), PICK_IMAGE);
}
Then onActivityResult i try to get the path of the image and convert it into URI then i later convert it into into Bitmap to display to the user in my codes below:
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
if (requestCode == PICK_IMAGE) {
// Get the url from data
Uri selectedImageUri = data.getData();
if (null != selectedImageUri) {
// Get the path from the Uri
String path = getPathFromURI(selectedImageUri);
Log.i(TAG, "Image Path : " + path);
// Set the image in ImageView
profileImage.setImageURI(selectedImageUri);
}
final InputStream imageStream;
try {
assert selectedImageUri != null;
imageStream = getContentResolver().openInputStream(selectedImageUri);
final Bitmap selectedImage = BitmapFactory.decodeStream(imageStream);
encodedImage = encodeImage(selectedImage);
Log.i("encodedImage", encodedImage);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
}
public String getPathFromURI(Uri contentUri) {
String res = null;
String[] proj = {MediaStore.Images.Media.DATA};
Cursor cursor = getContentResolver().query(contentUri, proj, null, null, null);
if (cursor.moveToFirst()) {
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
res = cursor.getString(column_index);
}
cursor.close();
return res;
}
private String encodeImage(Bitmap bm)
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.JPEG,100,baos);
byte[] b = baos.toByteArray();
String encImage = Base64.encodeToString(b, Base64.DEFAULT);
return encImage;
}
On click of this button below i want to save the encoded image into SharedPreferences so when the user starts the application again i can show that image to the user but unfortunately i am unable to get the encoded image and i don't know how to set it on onCreateView method.
btnAddImage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
SharedPreferences.Editor editor = prefs.edit();
editor.putString("image", encodedImage);
editor.apply();
showSnackSuccess();
}
});

Get path of Image clicked by Android Camera

I need to click an image using the default camera app on an android device and get the path of the image just clicked. I have taken help from this post
stackoverflow forum link
And my code is as follows
public void MarkIn(View view) {
String fileName = "temp.jpg";
final int CAPTURE_PICTURE_INTENT = 1;
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.TITLE, fileName);
mCapturedImageURI = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, mCapturedImageURI);
startActivityForResult(intent, CAPTURE_PICTURE_INTENT);
String imagePath = capturedImageFilePath;
// .....some code.....
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 1 && resultCode == Activity.RESULT_OK) {
String[] projection = { MediaStore.Images.Media.DATA };
Cursor cursor = null;
cursor = getApplicationContext().getContentResolver().query(mCapturedImageURI, projection, null, null, null);
int column_index_data = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
capturedImageFilePath = cursor.getString(column_index_data);
}
}
The system isn't waiting for Activity to get completed. As my ...some code... in the above snippet is depenedent on the file path, I am getting null pointer exception.
How to make the code execution wait till the activity is completed.
You should first get the image bitmap on image click and then convert that bitmap into uri using this code.:-
public Uri getImageUri(Context inContext, Bitmap inImage) {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
inImage.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
String path = Images.Media.insertImage(inContext.getContentResolver(), inImage, "Title", null);
return Uri.parse(path);
}
try this and let me know.
This is Probably as you are using sdk version 19 or above.Android has changed the way we access data from KitKat.

Getting path of captured image in Android using camera intent

I have been trying to get path of captured image in order to delete image. Found many answers on StackOverflow but none of them are working for me. I got the following answer:
private String getLastImagePath() {
final String[] imageColumns = { MediaStore.Images.Media._ID,
MediaStore.Images.Media.DATA };
final String imageOrderBy = MediaStore.Images.Media._ID + " DESC";
Cursor imageCursor = POS.this.getContentResolver().query(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, imageColumns,
null, null, imageOrderBy);
if (imageCursor.moveToFirst()) {
// int id = imageCursor.getInt(imageCursor
// .getColumnIndex(MediaStore.Images.Media._ID));
String fullPath = imageCursor.getString(imageCursor
.getColumnIndex(MediaStore.Images.Media.DATA));
return fullPath;
} else {
return "";
}
}
This code works in Samsung tab but doesn't work in Lenovo tab and i-ball tab.
So, can anyone help me find another solution to do the same?
Any help will be appreciated. Thank you.
This is my onActivityResult:
if (requestCode == CmsInter.CAMERA_REQUEST && resultCode == RESULT_OK) {
//Bitmap photo = null;
//photo = (Bitmap) data.getExtras().get("data");
String txt = "";
if (im != null) {
String result = "";
//im.setImageBitmap(photo);
im.setTag("2");
int index = im.getId();
String path = getLastImagePath();
try {
bitmap1 = BitmapFactory.decodeFile(path, options);
bitmap = Bitmap.createScaledBitmap(bitmap1, 512, 400, false);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
byte[] bytData = baos.toByteArray();
try {
baos.close();
} catch (IOException e) {
e.printStackTrace();
}
result = Base64.encode(bytData);
bytData = null;
} catch (OutOfMemoryError ooM) {
System.out.println("OutOfMemory Exception----->" + ooM);
bitmap1.recycle();
bitmap.recycle();
} finally {
bitmap1.recycle();
bitmap.recycle();
}
}
}
Try like this
Pass Camera Intent like below
Intent intent = new Intent(this);
startActivityForResult(intent, REQ_CAMERA_IMAGE);
And after capturing image Write an OnActivityResult as below
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == CAMERA_REQUEST && resultCode == RESULT_OK) {
Bitmap photo = (Bitmap) data.getExtras().get("data");
imageView.setImageBitmap(photo);
knop.setVisibility(Button.VISIBLE);
// CALL THIS METHOD TO GET THE URI FROM THE BITMAP
Uri tempUri = getImageUri(getApplicationContext(), photo);
// CALL THIS METHOD TO GET THE ACTUAL PATH
File finalFile = new File(getRealPathFromURI(tempUri));
System.out.println(mImageCaptureUri);
}
}
public Uri getImageUri(Context inContext, Bitmap inImage) {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
inImage.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
String path = Images.Media.insertImage(inContext.getContentResolver(), inImage, "Title", null);
return Uri.parse(path);
}
public String getRealPathFromURI(Uri uri) {
String path = "";
if (getContentResolver() != null) {
Cursor cursor = getContentResolver().query(uri, null, null, null, null);
if (cursor != null) {
cursor.moveToFirst();
int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
path = cursor.getString(idx);
cursor.close();
}
}
return path;
}
And check log.
Edit:
Lots of people are asking how to not get a thumbnail. You need to add this code instead for the getImageUri method:
public Uri getImageUri(Context inContext, Bitmap inImage) {
Bitmap OutImage = Bitmap.createScaledBitmap(inImage, 1000, 1000,true);
String path = MediaStore.Images.Media.insertImage(inContext.getContentResolver(), OutImage, "Title", null);
return Uri.parse(path);
}
The other method Compresses the file. You can adjust the size by changing the number 1000,1000
There is a solution to create file (on external cache dir or anywhere else) and put this file's uri as output extra to camera intent - this will define path where taken picture will be stored.
Here is an example:
File file;
Uri fileUri;
final int RC_TAKE_PHOTO = 1;
private void takePhoto() {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
file = new File(getActivity().getExternalCacheDir(),
String.valueOf(System.currentTimeMillis()) + ".jpg");
fileUri = Uri.fromFile(file);
intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
getActivity().startActivityForResult(intent, RC_TAKE_PHOTO);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == RC_TAKE_PHOTO && resultCode == RESULT_OK) {
//do whatever you need with taken photo using file or fileUri
}
}
}
Then if you don't need the file anymore, you can delete it using file.delete();
By the way, files from cache dir will be removed when user clears app's cache from apps settings.
Try this method to get path of original image captured by camera.
public String getOriginalImagePath() {
String[] projection = { MediaStore.Images.Media.DATA };
Cursor cursor = getActivity().managedQuery(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
projection, null, null, null);
int column_index_data = cursor
.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToLast();
return cursor.getString(column_index_data);
}
This method will return path of the last image captured by camera. So this path would be of original image not of thumbnail bitmap.
Here I updated the sample code in Kotlin. Please note on Nougat and above version Uri.fromFile(file) is not working and it crashes the app for that need to implement FileProvider which is safest way to send files from intent. For implementing this refer this answer or this article
private fun takePhotoFromCamera() {
val isDeviceSupportCamera: Boolean = this.packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA)
if (isDeviceSupportCamera) {
val takePictureIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
file = File(getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS + "/attachments")!!.path,
System.currentTimeMillis().toString() + ".jpg")
// fileUri = Uri.fromFile(file)
fileUri = FileProvider.getUriForFile(this, this.applicationContext.packageName + ".provider", file!!)
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri)
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP) {
takePictureIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
}
startActivityForResult(takePictureIntent, Constants.REQUEST_CODE_IMAGE_CAPTURE)
}
} else {
Toast.makeText(this, this.getString(R.string.camera_not_supported), Toast.LENGTH_SHORT).show()
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == Activity.RESULT_OK) {
if(requestCode == Constants.REQUEST_CODE_IMAGE_CAPTURE) {
realPath = file?.path
//do what ever you want to do
}
}
}
Please refer to Google Documentation:
Camera - Photo Basics
try this
String[] projection = { MediaStore.Images.Media.DATA };
#SuppressWarnings("deprecation")
Cursor cursor = managedQuery(mCapturedImageURI, projection,
null, null, null);
int column_index_data = cursor
.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
image_path = cursor.getString(column_index_data);
Log.e("path of image from CAMERA......******************.........",
image_path + "");
for capturing image:
String fileName = "temp.jpg";
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.TITLE, fileName);
mCapturedImageURI = getContentResolver().insert(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, mCapturedImageURI);
values.clear();

Categories

Resources