Problems with picture uploading - android

I have this activity in which the user can either choose one image from Gallery or just take a picture and (along with other data) upload it to a website.
So far I've encountered 2 different problems:
1) If I try it with a picture from the gallery, I get an IOException with message
/external/images/media/2305: open failed: ENOENT (No such file or directory)
That happens when it comes to open the file stream.
2) If I try it by taking the picture, it goes ok, but the encoded data string is composed of "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" (really longer, but only A's) and I guess that's not a good sign. This is only a guess since I still cannot properly upload it to the website, but different pictures showing the same data string just smells funny.
The code here
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case TAKE_PICTURE:
if (resultCode == Activity.RESULT_OK) {
//Uri selectedImage = imageUri;
loadImage(imageUri);
}
break;
case SELECT_PHOTO:
if(resultCode == Activity.RESULT_OK){
imageUri = data.getData();
loadImage(imageUri);
}
}
}
This is how I load the image (either pic taken or from the gallery) onto the ImageView. It works ok.
public void loadImage(Uri selectedImage){
mActivity.getContentResolver().notifyChange(selectedImage, null);
ContentResolver cr = mActivity.getContentResolver();
Bitmap bitmap;
try {
bitmap = android.provider.MediaStore.Images.Media
.getBitmap(cr, selectedImage);
ivPicture.setImageBitmap(bitmap);
ivPicture.setVisibility(View.VISIBLE);
mActivity.croutonInfo(selectedImage.toString());
} catch (Exception e) {
mActivity.croutonAlert("Failed to load");
e("Camera " + e.toString());
}
}
This is the method I use to mock the data upload. When I get the API it will have an asynctask to deal with the http transfer, so far it only puts the data into a logicless transfer object
public void uploadTapa() throws IOException{
mActivity.croutonInfo("subiendo tapa ");
d("uploadTapa new ");
TapaUploadParametros tup = new TapaUploadParametros();
d("uploadTapa bar: " + nombreBar);
tup.setBarNombre(etBarName.getText().toString());
d("uploadTapa tapa: " + nombreTapa);
tup.setNombre(etTapaName.getText().toString());
d("uploadTapa municipio: " + municipio);
tup.setLocalidad(municipio);
d("uploadTapa provincia: " + provincia);
tup.setProvincia(provincia);
d("uploadTapa tipologiaId: " + tipologiaId);
tup.setTipo(tipologiaId);
d("uploadTapa precioId: " + precioId);
tup.setPrecio(precioId);
String encodedImage = encodeImgForHTTP(imageUri);
d("uploadTapa encoded image: " + encodedImage);
tup.setPic(encodedImage);
d("uploadTapa direccionBar: " + direccionBar);
tup.setBarDireccion(direccionBar);
}
And this is the method to encode the image for http transfer. Images from gallery fail just after "before opening stream"
private String encodeImgForHTTP (Uri imageUri) throws IOException{
ContentResolver cr = mActivity.getContentResolver();
d("encodeImgForHTTP before opening stream ");
FileInputStream fis = new FileInputStream(imageUri.getPath());
d("encodeImgForHTTP after opening stream ");
// Get binary bytes for encode
byte[] imageBytes = new byte[fis.available()];
d("encodeImgForHTTP after getting byte array ");
// base 64 encode for text transmission (HTTP)
d("encodeImgForHTTP pre 64: " + imageBytes);
String data_string = Base64.encodeToString(imageBytes, Base64.URL_SAFE);
d("encodeImgForHTTP before returning the encoded data string " + data_string);
return data_string;
}
What am I doing wrong with the gallery images? Why does the encoding of different pictures look the same?

I think you should buffer your input stream into smaller byte arrays, and not use the available function as it is an estimate, in your encoding function, to start with.
In order to take a picture you have to determine a path where you would like the image saved and pass that as an extra in the intent, for example:
private void capture(){
String directoryPath = Environment.getExternalStorageDirectory() + "/" + IMAGE_DIRECTORY + "/";
String filePath = directoryPath+Long.toHexString(System.currentTimeMillis())+".jpg";
File directory = new File(directoryPath);
if (!directory.exists()) {
directory.mkdirs();
}
this.capturePath = filePath; // you will process the image from this path if the capture goes well
Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra( MediaStore.EXTRA_OUTPUT, Uri.fromFile( new File(filePath) ) );
startActivityForResult(intent, REQUEST_CAPTURE);
}

I guess I finally got it to work. First I used Emil's advice and saved the image. DCIM_PATH is the path to the DCIM folder.
public void takePhoto() {
String directoryPath = DCIM_PATH;
d("takePhoto directoryPath: " + directoryPath);
this.pictureFileName = Long.toHexString(System.currentTimeMillis())+".jpg";
String filePath = directoryPath + pictureFileName ;
File directory = new File(directoryPath);
if (!directory.exists()) { // in case there's no DCIM folder
directory.mkdirs(); // just create it
}
d("takePhoto filePath: " + filePath);
this.imageUri = Uri.parse(filePath);
d("takePhoto imageUri: " + filePath);
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// here's where I tell the intent where to save the file
intent.putExtra(
MediaStore.EXTRA_OUTPUT,Uri.fromFile( new File(filePath) )
);
startActivityForResult(intent, TAKE_PICTURE);
}
I had to use two different methods for loading the picture to the imageview. If it's a picture just taken, I use this one:
public void loadImageJustTaken(Uri selectedImage) {
mActivity.getContentResolver().notifyChange(selectedImage, null);
Bitmap bitmap =
BitmapFactory.decodeFile(imageUri.getPath());
ivPicture.setImageBitmap(bitmap);
ivPicture.setVisibility(View.VISIBLE);
}
But to use one from the gallery I have to use the contentResolver
public void loadImage(Uri selectedImage){
imageUri = selectedImage;
mActivity.getContentResolver().notifyChange(selectedImage, null);
ContentResolver cr = mActivity.getContentResolver();
Bitmap bitmap;
try {
bitmap = android.provider.MediaStore.Images.Media
.getBitmap(cr, imageUri);
ivPicture.setImageBitmap(bitmap);
ivPicture.setVisibility(View.VISIBLE);
mActivity.croutonInfo(imageUri.getPath());
} catch (Exception e) {
e("Camera " + e.toString());
}
}
When I want to upload the image, I have to encode it. This method works as long as you provide it with the right file path
private String encodeImgForHTTP (Uri imageUri) throws IOException{
String realPicPath = getPath(imageUri);
d("encodeImgForHTTP before opening stream " + realPicPath);
FileInputStream fis = new FileInputStream(realPicPath);
d("encodeImgForHTTP after opening stream ");
// Get binary bytes for encode
byte[] imageBytes = IOUtils.toByteArray(fis);
d("encodeImgForHTTP after getting byte array ");
// base 64 encode for text transmission (HTTP)
//String data_string = Base64.encodeToString(data, Base64.URL_SAFE);
d("encodeImgForHTTP pre 64: " + imageBytes);
String data_string = Base64.encodeToString(imageBytes, Base64.URL_SAFE);
d("encodeImgForHTTP before returning the encoded data string " + data_string);
return data_string;
}
And here's how I get the "real path" for the picture:
public String getPath(Uri uri) throws IOException {
String[] projection = { MediaStore.Images.Media.DATA };
Cursor cursor = mActivity.
managedQuery(uri, projection, null, null, null);
if (cursor == null){ // with pictures just taken, the uri returned by the onActivityResult makes cursor to be null. Following method takes care of that
uri = saveMediaEntry(imageUri.getPath(), pictureFileName, "");
d("cursor nulo, segundo cursor con uri " + uri.getPath());
cursor = mActivity.
managedQuery(uri, projection, null, null, null);
}
int column_index = cursor
.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
}
The method saveMediaEntry creates an entry to the device's media database returning its Uri. Using that Uri, the cursor now will point to the picture file we want
private Uri saveMediaEntry(
String imagePath,String title,String description) throws IOException {
ExifInterface exif = new ExifInterface(imagePath);
ContentValues v = new ContentValues();
v.put(Images.Media.TITLE, title);
v.put(Images.Media.DISPLAY_NAME, title);
v.put(Images.Media.DESCRIPTION, description);
v.put(Images.Media.DATE_ADDED, System.currentTimeMillis());
v.put(Images.Media.DATE_TAKEN, exif.getAttribute(ExifInterface.TAG_DATETIME));
//v.put(Images.Media.DATE_MODIFIED, dateTaken) ;
v.put(Images.Media.MIME_TYPE, "image/jpeg");
v.put(Images.Media.ORIENTATION, exif.getAttribute(ExifInterface.TAG_ORIENTATION));
File f = new File(imagePath) ;
File parent = f.getParentFile() ;
String path = parent.toString().toLowerCase() ;
String name = parent.getName().toLowerCase() ;
v.put(Images.ImageColumns.BUCKET_ID, path.hashCode());
v.put(Images.ImageColumns.BUCKET_DISPLAY_NAME, name);
v.put(Images.Media.SIZE,f.length()) ;
f = null ;
v.put(Images.Media.LATITUDE, exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE));
v.put(Images.Media.LONGITUDE, exif.getAttribute(ExifInterface.TAG_GPS_LONGITUDE));
v.put("_data",imagePath) ;
ContentResolver c = mActivity.getContentResolver() ;
return c.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, v);
}
After all this, pictures get loaded OK, and the Base64.encodeToString returns are different for different pictures :)
Hope it helps someone :)

Related

ThumbnailUtils.createVideoThumbnail not working for nougat device

Bitmap bitmap = ThumbnailUtils.createVideoThumbnail(localUrl,
MediaStore.Video.Thumbnails.MINI_KIND);
Here bitmap gives me null value.
The exact same condition I have faced, Only it was unable to create video thumbnail in higher version or high rated device. You are getting path of video in OnActivityResult something like this.
if (requestCode == 3 && resultCode == RESULT_OK && data != null && data.getData() != null) {
Uri uri = data.getData();
String mimeType = getActivity().getContentResolver().getType(uri);
String extension = MimeTypeMap.getSingleton().getExtensionFromMimeType(mimeType);
String[] filePathColumn = {MediaStore.Images.Media.DATA};
Cursor cursor = getActivity().getContentResolver().query(uri, filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
picturePath = cursor.getString(columnIndex);
Log.e("PICTURE PATH", picturePath);
File file = new File(picturePath);
long length = file.length();
length = length / 1024;
long length2 = length / 1024;
if (length2 > 25) {
Toast.makeText(getActivity(), "You cannot upload file more than 25 MB", Toast.LENGTH_SHORT).show();
} else {
if (mimeType.contains("image")) {
Log.e("mimeType", mimeType);
Log.e("gif", picturePath);
Intent intent = new Intent(getActivity(), UploadImagePostActivity.class);
intent.putExtra("DESTINATION", picturePath);
startActivity(intent);
getActivity().finish();
} else if (mimeType.contains("video")) {
Log.e("mimeType", mimeType);
Log.e("Video path", picturePath);
Intent intent = new Intent(getActivity(), UploadVideoPostActivity.class);
intent.putExtra("VIDEO_DESTINATION", picturePath);
startActivity(intent);
getActivity().finish();
}
}
}
Now you will get the path of video and you have to make video thumbnail after getting video path. sometime it may raise the problem of not getting correct path because some devices have different path hierarchy. so you have to save your thumbnail at a particular position and retrieve it back. code is give below.
// type 2 for video
File uri = new File(filePath);
//create thumbnail image
thumb = ThumbnailUtils.createVideoThumbnail(filePath, MediaStore.Video.Thumbnails.MINI_KIND);
img_tumbnail.setImageBitmap(thumb);
runOnUiThread(new Runnable() {
#Override
public void run() {
try {
thumbNailfile = savebitmap(thumb);
Log.e("Thumbnail path", "" + thumbNailfile);
} catch (IOException e) {
e.printStackTrace();
}
}
});
and the saving thumbnail file at specific path. now it will return the correct path of file.
// save bitmap into internal memory
public static File savebitmap(Bitmap bmp) throws IOException {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
bmp = ((BitmapDrawable) img_tumbnail.getDrawable()).getBitmap();
bmp.compress(Bitmap.CompressFormat.JPEG, 40, bytes);
//
thumnailImagePath = Environment.getExternalStorageDirectory() + File.separator + "123.jpg";
File f = new File(Environment.getExternalStorageDirectory()
+ File.separator + "123.jpg");
f.createNewFile();
FileOutputStream fo = new FileOutputStream(f);
fo.write(bytes.toByteArray());
fo.close();
return f;
}

How to read files at a specific path in android?

I am developing an application in which I open the file explorer and select any file of my choice and retrieve its contents. The default path that opens is /storage/sdcard0 . I am able to read contents of any file that resides directly in this path. However, for any file that in contained in any folder inside /storage/sdcard0/. is inaccessible. The program gives a file not found error. Also, I cannot understand the path that these files have, like for example, if a file resides in path:
/storage/sdcard0/DCIM/100ANDRO/DSC_0001.jpg
,
the logcat shows the path to be:
content:/media/external/images/media/84290/DSC_0001.jpg
How to access this file in my Java code?
Below is the code snippet:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Log.d(TAG, "requestCode received: "+requestCode+" result code: "+resultCode);
if (requestCode == 1 && resultCode == RESULT_OK) {
Bitmap thumbnail = (Bitmap) data.getExtras().get("data");
String folderPath = "Anant";
String filePath = "image.jpg";
String imagePath = saveToInternalStorage(thumbnail, folderPath,
sImageName);
Log.i(TAG, "DeviceAPIS:actual path :: "
+ imagePath.trim().toString());
sendCameraData(imagePath.toString().trim(),
ptrAppContainerForCamera);
}
else if (requestCode == REQUEST_PATH){
if (resultCode == RESULT_OK) {
// Get the Uri of the selected file
Uri uri = data.getData();
Log.d(TAG, "data.getData() result line 742: " + uri);
String uriString = uri.toString();
File myFile = new File(uriString);
String path = myFile.getAbsolutePath();
String base64 ="Error";
byte[] bytesRead = base64.getBytes();
String displayName = null;
String fileName = null;
if (uriString.startsWith("content://")) {
Cursor cursor = null;
try {
cursor = mContext.getContentResolver().query(uri, null, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
displayName = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
displayName = path + "/" + displayName;
Log.d(TAG, "BEFORE REPLACE: "+displayName);
int index = displayName.indexOf(':');
fileName = displayName.substring(index + 1, displayName.length());
Log.d(TAG,"displayName line 762 " + Part);
}
} finally {
cursor.close();
}
} else if (uriString.startsWith("file://")) {
Log.d(TAG, "FILE BLOCK LINE 768");
displayName = myFile.getName();
Log.d(TAG,"displayName 11" + displayName);
}
try{
File sdcard = Environment.getExternalStorageDirectory();
File readFile = new File(sdcard, fileName);
// File readFile = new File(uri);
int length = (int)readFile.length();
byte[] bytes = new byte[length];
FileInputStream in = new FileInputStream(readFile);
try{
in.read(bytes);
}finally {
in.close();
}
String contents = new String(bytes);
Log.d(TAG,"contents read :: \\n" + contents);
//convert to Base64
bytesRead = contents.getBytes("UTF-8");
base64 = Base64.encodeToString(bytesRead,Base64.DEFAULT);
}catch (Exception e){
Log.d(TAG, "THROWING EXCEPTION");
Log.e(TAG,e.getMessage(),e);
}
}
The exception thrown is java.io.FileNotFoundException. Any help is greatly appreciated.
You can try as below:
String path = null;
Uri originalUri = data.getData();
try {
String[] proj = { MediaStore.Images.Media.DATA };
Cursor cursor = this.managedQuery(originalUri, proj, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
path = cursor.getString(column_index);
} catch (Exception e) {
} finally {
cursor.close();
}
And if path is null, you can get bitmap first and then copy it to your local path.
ContentResolver resolver = this.getContentResolver();
Bitmap photo = MediaStore.Images.Media.getBitmap(resolver, originalUri);
.... // copy photo to your local path
you can try this,
1. make sure you have added permission in you manifest file
2. Settings -> Apps -> Your App -> Permissions -> Storage = true/enabled
I had faced a same issue of FileNotFound and i was able to resolve it by #2 above.

open failed:ENOENT (No such file or directory) error

I've got a problem trying to upload an image I get from taking a picture with the camera,using amazon S3 android library.
To save the picture
File _photoFile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM), (cal.getTimeInMillis() + ".jpg"));
try {
if (_photoFile.exists() == false) {
_photoFile.getParentFile().mkdirs();
_photoFile.createNewFile();
}
} catch (IOException e) {
// Log.e(TAG, "Could not create file.", e);
}
// Log.i(TAG, path);
filePath = Uri.fromFile(_photoFile);
Intent cameraIntent = new Intent(
android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, filePath);
startActivityForResult(cameraIntent, 1);
To upload the picture with the filePath:
try {
s3Client.createBucket(Constants.getPictureBucket());
// Content type is determined by file extension.
PutObjectRequest por = new PutObjectRequest(
Constants.getPictureBucket(), Constants.PICTURE_NAME,
new java.io.File(filePath));
s3Client.putObject(por);
} catch (Exception exception) {
result.setErrorMessage(exception.getMessage());
}
I keep getting an error Unable to calclualte MD5 hash:/file:/storage/sdcard0/DCIM/13161272646580.jpg open failed:ENOENT (No such file or directory)
but when I browse my sd card's directory I can find the picture there(the picture has been created), and I've created the relevant permissions.
The problem is in your file path. Use a method like that to get the Real Path.
I give you an example, if you are getting the image from onActivityResult()
You should have a onActivityResult(int requestCode, int resultCode, Intent data) where you can get the Uri of your image.
Uri uri = data.getData();
Then you use it and get the real path from Uri and pass this to the PutObjectRequest(BUCKET_NAME, IMAGE_NAME, REAL_PATH);
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();
}
}
}
I had the same problem and I solve it doing this. Hope it helps!
I don't really remember what I did. But this is the code I use that works. Hope it can help you guys!
AmazonS3Client s3Client = new AmazonS3Client(new BasicAWSCredentials("XXX", "XXX"));
String time = "" + System.currentTimeMillis();
PutObjectRequest por = new PutObjectRequest("fraternity", xyz_url_xyz + "/avatar" + time + ".jpg", new java.io.File(params[0]));
por.setCannedAcl(CannedAccessControlList.PublicRead);
s3Client.putObject(por);
ResponseHeaderOverrides override = new ResponseHeaderOverrides();
override.setContentType("image/jpeg");
GeneratePresignedUrlRequest urlRequest = new GeneratePresignedUrlRequest("xyz_url_xyz/avatar.jpg");
urlRequest.setExpiration(new Date(System.currentTimeMillis() + 3600000));
urlRequest.setResponseHeaders( override );
s3Client.generatePresignedUrl(urlRequest);

Android, MediaStore.EXTRA_OUTPUT, stores two images [duplicate]

I'm currently developing an app which uses the built-in Camera.
I call this snippet by clicking a button :
Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
//Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
String path = Environment.getExternalStorageDirectory().getAbsolutePath();
path += "/myFolder/myPicture.jpg";
File file = new File( path );
//file.mkdirs();
Uri outputFileUri = Uri.fromFile( file );
//String absoluteOutputFileUri = file.getAbsolutePath();
intent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
startActivityForResult(intent, 0);
After taking the picture with the camera, the jpg is well stored in sdcard/myFolder/myPicture.jpg, but it is also stored in /sdcard/DCIM/Camera/2011-06-14 10.36.10.jpg, which is the default path.
Is there a way to prevent the built-in Camera to store the picture in the default folder?
Edit : I think I will use the Camera class directly
Another way, tested on android 2.1, is take the ID or Absolute path of the gallery last image, then you can delete the duplicated image.
It can be done like that:
/**
* Gets the last image id from the media store
* #return
*/
private int getLastImageId(){
final String[] imageColumns = { MediaStore.Images.Media._ID, MediaStore.Images.Media.DATA };
final String imageOrderBy = MediaStore.Images.Media._ID+" DESC";
Cursor imageCursor = managedQuery(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));
Log.d(TAG, "getLastImageId::id " + id);
Log.d(TAG, "getLastImageId::path " + fullPath);
imageCursor.close();
return id;
}else{
return 0;
}
}
And to remove the file:
private void removeImage(int id) {
ContentResolver cr = getContentResolver();
cr.delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, MediaStore.Images.Media._ID + "=?", new String[]{ Long.toString(id) } );
}
This code was based on the post: Deleting a gallery image after camera intent photo taken
While the answer from "Ilango J" provides the basic idea.. I thought I'd actually write in how I actually did it.
The temporary file path that we were setting in intent.putExtra() should be avoided as it's a non standard way across different hardwares. On HTC Desire (Android 2.2) it did not work, And i've heard it works on other phones. It's best to have a neutral approach which works every where.
Please note that this solution (using the Intent) requires that the phone's SD Card is available and is not mounted onto the PC. Even the normal Camera app wouldn't work when the SD Card is connected to the PC.
1) Initiate the Camera Capture intent. Note, I disabled temporary file writes (non-standard across different hardware)
Intent camera = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(camera , 0);
2) Handle callback and retrieve the captured picture path from the Uri object and pass it to step#3
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case CAPTURE_PIC: {
if (resultCode == RESULT_OK && data != null) {
Uri capturedImageUri = data.getData();
String capturedPicFilePath = getRealPathFromURI(capturedImageUri);
writeImageData(capturedImageUri, capturedPicFilePath);
break;
}
}
}
}
public String getRealPathFromURI(Uri contentUri) {
String[] projx = { MediaStore.Images.Media.DATA };
Cursor cursor = managedQuery(contentUri, projx, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
}
3) Clone and delete the file. See that I used the Uri's InputStream to read the content.
The same can be read from the File of the capturedPicFilePath too.
public void writeImageData(Uri capturedPictureUri, String capturedPicFilePath) {
// Here's where the new file will be written
String newCapturedFileAbsolutePath = "something" + JPG;
// Here's how to get FileInputStream Directly.
try {
InputStream fileInputStream = getContentResolver().openInputStream(capturedPictureUri);
cloneFile(fileInputStream, newCapturedFileAbsolutePath);
} catch (FileNotFoundException e) {
// suppress and log that the image write has failed.
}
// Delete original file from Android's Gallery
File capturedFile = new File(capturedPicFilePath);
boolean isCapturedCameraGalleryFileDeleted = capturedFile.delete();
}
public static void cloneFile(InputStream currentFileInputStream, String newPath) {
FileOutputStream newFileStream = null;
try {
newFileStream = new FileOutputStream(newPath);
byte[] bytesArray = new byte[1024];
int length;
while ((length = currentFileInputStream.read(bytesArray)) > 0) {
newFileStream.write(bytesArray, 0, length);
}
newFileStream.flush();
} catch (Exception e) {
Log.e("Prog", "Exception while copying file " + currentFileInputStream + " to "
+ newPath, e);
} finally {
try {
if (currentFileInputStream != null) {
currentFileInputStream.close();
}
if (newFileStream != null) {
newFileStream.close();
}
} catch (IOException e) {
// Suppress file stream close
Log.e("Prog", "Exception occured while closing filestream ", e);
}
}
}
try this code:
Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
//Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
String path = Environment.getExternalStorageDirectory().getAbsolutePath();
path += "/myFolder/myPicture.jpg";
File file = new File( path );
//file.mkdirs();
Uri outputFileUri = Uri.fromFile( file );
//String absoluteOutputFileUri = file.getAbsolutePath();
intent.putExtra("output", outputFileUri);
startActivityForResult(intent, 0);

Built-in Camera, using the extra MediaStore.EXTRA_OUTPUT stores pictures twice (in my folder, and in the default)

I'm currently developing an app which uses the built-in Camera.
I call this snippet by clicking a button :
Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
//Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
String path = Environment.getExternalStorageDirectory().getAbsolutePath();
path += "/myFolder/myPicture.jpg";
File file = new File( path );
//file.mkdirs();
Uri outputFileUri = Uri.fromFile( file );
//String absoluteOutputFileUri = file.getAbsolutePath();
intent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
startActivityForResult(intent, 0);
After taking the picture with the camera, the jpg is well stored in sdcard/myFolder/myPicture.jpg, but it is also stored in /sdcard/DCIM/Camera/2011-06-14 10.36.10.jpg, which is the default path.
Is there a way to prevent the built-in Camera to store the picture in the default folder?
Edit : I think I will use the Camera class directly
Another way, tested on android 2.1, is take the ID or Absolute path of the gallery last image, then you can delete the duplicated image.
It can be done like that:
/**
* Gets the last image id from the media store
* #return
*/
private int getLastImageId(){
final String[] imageColumns = { MediaStore.Images.Media._ID, MediaStore.Images.Media.DATA };
final String imageOrderBy = MediaStore.Images.Media._ID+" DESC";
Cursor imageCursor = managedQuery(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));
Log.d(TAG, "getLastImageId::id " + id);
Log.d(TAG, "getLastImageId::path " + fullPath);
imageCursor.close();
return id;
}else{
return 0;
}
}
And to remove the file:
private void removeImage(int id) {
ContentResolver cr = getContentResolver();
cr.delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, MediaStore.Images.Media._ID + "=?", new String[]{ Long.toString(id) } );
}
This code was based on the post: Deleting a gallery image after camera intent photo taken
While the answer from "Ilango J" provides the basic idea.. I thought I'd actually write in how I actually did it.
The temporary file path that we were setting in intent.putExtra() should be avoided as it's a non standard way across different hardwares. On HTC Desire (Android 2.2) it did not work, And i've heard it works on other phones. It's best to have a neutral approach which works every where.
Please note that this solution (using the Intent) requires that the phone's SD Card is available and is not mounted onto the PC. Even the normal Camera app wouldn't work when the SD Card is connected to the PC.
1) Initiate the Camera Capture intent. Note, I disabled temporary file writes (non-standard across different hardware)
Intent camera = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(camera , 0);
2) Handle callback and retrieve the captured picture path from the Uri object and pass it to step#3
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case CAPTURE_PIC: {
if (resultCode == RESULT_OK && data != null) {
Uri capturedImageUri = data.getData();
String capturedPicFilePath = getRealPathFromURI(capturedImageUri);
writeImageData(capturedImageUri, capturedPicFilePath);
break;
}
}
}
}
public String getRealPathFromURI(Uri contentUri) {
String[] projx = { MediaStore.Images.Media.DATA };
Cursor cursor = managedQuery(contentUri, projx, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
}
3) Clone and delete the file. See that I used the Uri's InputStream to read the content.
The same can be read from the File of the capturedPicFilePath too.
public void writeImageData(Uri capturedPictureUri, String capturedPicFilePath) {
// Here's where the new file will be written
String newCapturedFileAbsolutePath = "something" + JPG;
// Here's how to get FileInputStream Directly.
try {
InputStream fileInputStream = getContentResolver().openInputStream(capturedPictureUri);
cloneFile(fileInputStream, newCapturedFileAbsolutePath);
} catch (FileNotFoundException e) {
// suppress and log that the image write has failed.
}
// Delete original file from Android's Gallery
File capturedFile = new File(capturedPicFilePath);
boolean isCapturedCameraGalleryFileDeleted = capturedFile.delete();
}
public static void cloneFile(InputStream currentFileInputStream, String newPath) {
FileOutputStream newFileStream = null;
try {
newFileStream = new FileOutputStream(newPath);
byte[] bytesArray = new byte[1024];
int length;
while ((length = currentFileInputStream.read(bytesArray)) > 0) {
newFileStream.write(bytesArray, 0, length);
}
newFileStream.flush();
} catch (Exception e) {
Log.e("Prog", "Exception while copying file " + currentFileInputStream + " to "
+ newPath, e);
} finally {
try {
if (currentFileInputStream != null) {
currentFileInputStream.close();
}
if (newFileStream != null) {
newFileStream.close();
}
} catch (IOException e) {
// Suppress file stream close
Log.e("Prog", "Exception occured while closing filestream ", e);
}
}
}
try this code:
Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
//Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
String path = Environment.getExternalStorageDirectory().getAbsolutePath();
path += "/myFolder/myPicture.jpg";
File file = new File( path );
//file.mkdirs();
Uri outputFileUri = Uri.fromFile( file );
//String absoluteOutputFileUri = file.getAbsolutePath();
intent.putExtra("output", outputFileUri);
startActivityForResult(intent, 0);

Categories

Resources