How do I take a photo and save it to a specific folder. I know it saves to the sdcard/DCIM/etc
But I don't want it there, I want it to be stored in a folder in /sdcard/Camera
I have made the directory with the following :
String destPath = Android.OS.Environment.ExternalStorageDirectory + "/Camera";
Then I launch the camera intent and try point the save file to the path I made.
Intent launchCamera = new Intent(Android.Provider.MediaStore.ActionImageCapture);
launchCamera.PutExtra(MediaStore.ExtraOutput, destPath);
This isn't working. Images still get saved to /sdcard/dcim/etc
Ideas?
From what I gathered when I developed an application using Monodroid is that the camera is very buggy and does not do what you want it to most of the time. This includes specifying the destination where images capture are to be saved.
To my knowledge these issues aren't specific to Monodroid and do occur with the java android sdk.
A work around to this issue that you may want to look at is capturing the image without specifying a destination, then in the OnActivityResult method retrieve the latest image saved to the gallery. Once you get the latest image you can then move it to your preferred destination.
Here is some example code from within OnActivityResult.
Retrieve the filename of the captured image
Android.Net.Uri targetUri = data.Data;
String origin = "";
String [] proj = { MediaStore.MediaColumns.Data.ToString (), BaseColumns.Id };
var qry = ManagedQuery (MediaStore.Images.Media.ExternalContentUri, proj, null, null, "date_added DESC");
qry.MoveToFirst ();
origin = qry.GetString (qry.GetColumnIndexOrThrow (MediaStore.MediaColumns.Data.ToString ()));
Move the image to your desired destination
System.IO.File.Move (origin, "yourdestinationfilenamehere");
I'd like to add to lanks's solution.
Let's say you use the following code to take a picture
var uri = ContentResolver.Insert(MediaStore.Images.Media.ExternalContentUri,
new ContentValues());
var intent = new Intent(MediaStore.ActionImageCapture);
intent.PutExtra(MediaStore.ExtraOutput, uri);
StartActivityForResult(intent, ACTIVITY_RESULT_PICTURE_TAKEN);
pictureUri = uri;
Where the ACTIVITY_RESULT_PICTURE_TAKEN is just a simple value you can use in the
OnActivityResult to check which activity was completed.
Your OnActivityResult could look something like this:
protected override void OnActivityResult(int requestCode,
Result resultCode, Intent data)
{
if (resultCode == Result.Ok && requestCode == ACTIVITY_RESULT_PICTURE_TAKEN)
{
string picturePath = GetRealPathFromURI(pictureUri);
//Do something with the file
}
}
The Uri you got earlier is something specific to android and needs to be translated.
It looks like "//content://media/external/media/11917" which is not a
valid path.
Which is exactly what the GetRealPathFromURI function does:
public string GetRealPathFromURI(Android.Net.Uri contentUri)
{
var mediaStoreImagesMediaData = "_data";
string[] projection = { mediaStoreImagesMediaData };
Android.Database.ICursor cursor = this.ManagedQuery(contentUri, projection,
null, null, null);
int columnIndex = cursor.GetColumnIndexOrThrow(mediaStoreImagesMediaData);
cursor.MoveToFirst();
return cursor.GetString(columnIndex);
}
Once you've got the real path, you can move it to wherever you want as lanks suggested.
Related
I have seen a couple of other questions on S/O related to this, but the one that was closest to my issue doesn't seem to have got many responses (Xiaomi MI device not picking image from Gallery). Hoping this question will have better luck.
I am trying to select an image from the gallery of the phone, and pass the image path to another activity where it get previewed for the user.
I've tested this on two other devices (Moto E and something called Coolpad?) and they both seem to be working just fine.
(Debugging Android source code doesn't seem to be a practical option.)
In the main activity, on a UI trigger, I launch the gallery picker with the following code:
private void dispatchPickPictureIntent() {
Intent pickPictureIntent = new Intent(Intent.ACTION_PICK);
pickPictureIntent.setType("image/*");
startActivityForResult(pickPictureIntent, REQUEST_IMAGE_PICK);
}
I handle the result like so:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_IMAGE_PICK && resultCode == RESULT_OK) {
Uri selectedImage = data.getData();
mCurrentPhotoPath = getRealPathFromURI(this, selectedImage);
launchUploadActivity();
}
}
private String getRealPathFromURI(Context context, Uri uri) {
Cursor cursor = null;
try {
String [] proj = {MediaStore.Images.Media.DATA};
cursor = context.getContentResolver().query(uri, 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();
}
}
Once I have got the file path stored in the global variable mCurrentPhotoPath the following method gets called:
private void launchUploadActivity() {
Intent intent = new Intent(HomeActivity.this, UploadActivity.class);
intent.putExtra(getString(R.string.photo_path), mCurrentPhotoPath);
startActivityForResult(intent, REQUEST_IMAGE_UPLOAD);
}
Even on the Redmi, up until here, things run smoothly. On the onCreate method of the UploadActivity, I receive the image file path string successfully.
But, then, I try to preview the image:
private void previewPhoto() {
imageView.setVisibility(View.VISIBLE);
BitmapFactory.Options options = new BitmapFactory.Options();
// Avoid OutOfMemory Exception
options.inSampleSize = 8;
// This line returns a null, only on the Xiaomi device
final Bitmap bitmap = BitmapFactory.decodeFile(photopath, options);
imageView.setImageBitmap(bitmap);
}
Now I have tried to debug this issue, but once I step into BitmapFactory's source code, I run in to a seemingly unresolved issue with Android Studio (https://stackoverflow.com/a/40566459/3438497) which renders it useless.
Any pointers on how I can proceed from here would be greatly appreciated.
So I was able to narrow down the issue to an incorrect file path. The Uri to filepath function did not get the desired result on all devices.
I used the approach suggested here:https://stackoverflow.com/a/7265235/3438497
and tweaked the code a little bit so that when picking images from gallery, I use the Uri of the image directly.
The reason is that you get file:// uri back. not content:// so content resolver doesn't work.
I am facing the similar issue in Redmi 5A. And solve the problem using following way.
Add below entities in your manifest file
android:hardwareAccelerated="false"
android:largeHeap="true"
It will work in some environments.
Refer answer at https://stackoverflow.com/a/32245018/2706551
I am dealing with Pick gallery images and show them in app also save their Path for some references in future.
I was able to Pick those images from gallery which are stored on device like in some folder like Downloads by this code:
Intent intent = new Intent (Intent.ActionPick, Android.Provider.MediaStore.Images.Media.ExternalContentUri);
intent.SetType ("image/*");
StartActivityForResult (Intent.CreateChooser (intent, "Select photo"), 0);
and in Result:
public override void OnActivityResult (int requestCode, Result resultCode, Intent data)
{
base.OnActivityResult (requestCode, resultCode, data);
case 0:
string FilePath = GetPathToImage (data.Data);
}
private string GetPathToImage(Android.Net.Uri uri)
{
string path = null;
string[] projection = new[] { Android.Provider.MediaStore.Images.Media.InterfaceConsts.Data };
using (ICursor cursor = this.Activity.ManagedQuery(uri, projection, null, null, null))
{
if (cursor != null)
{
int columnIndex = cursor.GetColumnIndexOrThrow(Android.Provider.MediaStore.Images.Media.InterfaceConsts.Data);
cursor.MoveToFirst();
path = cursor.GetString(columnIndex);
}
else
{
return uri.Path;
}
}
}
My question is : I am able to get paths of images those are placed in some local folder in gallery, but for folders like Picasa/Autobackup I am not able to get Path.
Note:For local images path starts from content://
For Other com.android....like that.
So, Is there any workaround to get paths of those images.
I don't want to do like this to just display image:
final InputStream is = getContentResolver().openInputStream(imageUri);
I need a Path.
If there is no solution, then How can we skip those images being displayed while Picking from Gallery/Photos.
PS: Known Issue
Any Suggestion is appreciated.
Thanks
I would like to implement a Picture Chooser, since there's a bug with the Recent image foler and the Download Folder the Android app crashes when selecting an image from these two folders, I would like to hide them, or open directly the Gallery folder without showing the Folder chooser panel,
This is my actual code :
Intent intent = new Intent (Intent.ACTION_GET_CONTENT);
startActivityForResult (intent, 1000);
and in the on Result Method :
#Override
protected void onActivityResult (int requestCode, int resultCode, Intent intent) {
super.onActivityResult (requestCode, resultCode, intent);
String uri = intent.getDataString ();
String absolutePath = getRealPathFromURI (uri);
String compressedFilePath = compressImage (absolutePath);
encodedResult = base64File (new File (compressedFilePath)); //String
}
protected String getRealPathFromURI (String contentURI, UIView uiView) {
Uri contentUri = Uri.parse(contentURI);
Cursor cursor = ((ContextWrapper) uiView).getContentResolver ().query(contentUri, null, null, null, null);
if (cursor == null) {
return contentUri.getPath();
} else {
cursor.moveToFirst();
int index = cursor.getColumnIndex(MediaColumns.DATA);
return cursor.getString(index);
}
}
So when I select an image from a folder like : Gallery, Pictures etc... It works just fine. But for the 2 folders : Download and Recent it crashes and gives me :
java.lang.IllegalStateException: Couldn't read row 0, col -1 from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it.
Or maybe there is a more correct way of doing that which I'm not aware of it ?
Do you have any idea about this ? How can I achieve that ? Thanks.
it crashes and gives me
That is because you are assuming that any Uri can be converted into a File. That has never been supported.
Use a ContentResolver and consume the Uri via openInputStream() (or openOutputStream(), if appropriate).
I have a problem. I want to make file uploader app. I'm using Intent.ACTION_GET_CONTENT to pick any file from my device. I am receiving the file in onActivityResult like that:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case REQUEST_CHOOSER:
if (resultCode == RESULT_OK) {
final Uri uri = data.getData();
File file = FileUtils.getFile(uri);
String fileName = file.getName();
String filePath = file.getPath();
int fileSize = Integer.parseInt(String.valueOf(file.length()/1024));
tvName.setText(fileName);
tvPath.setText(filePath);
tvSize.setText(String.valueOf(fileSize) + "kB");
}
}
}
I want to show user information about picked file. In general everything is fine, but when I choose Image from gallery then:
The file name shows no format - it's a number (probably reference to file in memory). When I pick Image via installed file explore I get sth like imagename.png etc, but picked from gallery is like "195493"
File.length created from data picked from gallery is 0.
Is there any way to access real image name and size after picking image from Gallery via intent?
Just input URI from the intent and get the size of any file
uri = data.getData();
Cursor returnCursor = getContentResolver().query(uri, null, null, null, null);
int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
int sizeIndex = returnCursor.getColumnIndex(OpenableColumns.SIZE);
returnCursor.moveToFirst();
Log.e("TAG", "Name:" + returnCursor.getString(nameIndex));
Log.e("TAG","Size: "+Long.toString(returnCursor.getLong(sizeIndex)));
I think this will help you.
When picking images from the gallery, you don't get a reference to the actual file but to a row in the database. You have to retrieve the actual file path with a Cursor like in this answer.
I am working on an activity and associated tasks that allow users to select an image to use as their profile picture from the Gallery. Once the selection is made the image is uploaded to a web server via its API. I have this working regular images from the gallery. However, if the image selected is from a Picasa Web Album nothing is returned.
I have done a lot of debugging and narrowed the problem down to this method.
public String getPath(Uri uri) {
String[] projection = { MediaStore.Images.Media.DATA };
Cursor cursor = managedQuery(uri, projection, null, null, null);
//cursor is null for picasa images
if(cursor!=null)
{
int column_index = cursor
.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
}
else return null;
}
Picasa images return a null cursor. MediaStore.Images.Media.DATA is not null for them, however. It only returns an #id, so I am guessing that there is no actual bitmap data at the address. Are Picasa images stored locally on the device at all?
I also noticed from the documentation that MediaStore.Images.ImageColumns.PICASA_ID exists. This value exists for selected picasa images but not other gallery images. I was thinking I could use this value to get a URL for the image if it is not store locally but I can not find any information about it anywhere.
I have faced the exact same problem,
Finally the solution I found, was to launch an ACTION_GET_CONTENT intent instead of an ACTION_PICK, then make sure you provide a MediaStore.EXTRA_OUTPUT extra with an uri to a temporary file.
Here is the code to start the intent :
public class YourActivity extends Activity {
File mTempFile;
int REQUEST_CODE_CHOOSE_PICTURE = 1;
(...)
public showImagePicker() {
mTempFile = getFileStreamPath("yourTempFile");
mTempFile.getParentFile().mkdirs();
Intent intent = new Intent(Intent.ACTION_GET_CONTENT, null);
intent.setType("image/*");
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(mTempFile));
intent.putExtra("outputFormat",Bitmap.CompressFormat.PNG.name());
startActivityForResult(intent,REQUEST_CODE_CHOOSE_PICTURE);
}
(...)
}
You might need to mTempFile.createFile()
Then in onActivityResult, you will be able to get the image this way
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
case REQUEST_CODE_CHOOSE_PICTURE:
Uri imageUri = data.getData();
if (imageUri == null || imageUri.toString().length() == 0) {
imageUri = Uri.fromFile(mTempFile);
file = mTempFile;
}
if (file == null) {
//use your current method here, for compatibility as some other picture chooser might not handle extra_output
}
}
Hope this helps
Then you should delete your temporary file on finish (it is in internal storage as is, but you can use external storage, I guess it would be better).
Why are you using the managedQuery() method? That method is deprecated.
If you want to convert a Uri to a Bitmap object try this code:
public Bitmap getBitmap(Uri uri) {
Bitmap orgImage = null;
try {
orgImage = BitmapFactory.decodeStream(getApplicationContext().getContentResolver().openInputStream(uri));
} catch (FileNotFoundException e) {
// do something if you want
}
return orgImage;
}