I need to remove an image from sd card chosen by user.
In my Activity, after an user select an image from gallery, i execute this code:
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
if (requestCode == SELECT_PICTURE) {
Utils.imgUri = data.getData();
Utils.imgPath = getPath(Utils.imgUri);
File file = new File(Utils.imgPath);
boolean deleted = file.delete();
}
}
}
where getPath method is:
public String getPath(Uri uri) {
String[] projection = { MediaStore.Images.Media.DATA };
Cursor cursor = managedQuery(uri, projection, null, null, null);
if(cursor!=null){
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
}
else return null;
}
The images are correctly removed but in the gallery still remain a preview of the removed image.
When i tap on it, is loaded a black image..
so, How can I update the gallery previews, after I delete some images from my app code?
Why would you make it that complex?
You can do it as simple as this:
getContentResolver().delete(Utils.imgUri, null, null);
Resolved adding:
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://" + Environment.getExternalStorageDirectory())));
It makes the MediaScanner service run again, which should remove the deleted image from the device's cache.
same problem here
Have you set the <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> permission in the manifest file?
Are you sure that the file path is correct? Because the way you do the actual delete should be fine, see this SO thread:
How to delete a file from SD card?
Should the /mnt/ really be there? Also, do you have the permissions to delete files from the storage? (android.permission.WRITE_EXTERNAL_STORAGE)
in the parameter "data" you have the Uri too, just do "data.getUri()". Also, are you testing in a real devices? if so and if it is a samsung, it isn't work (see this thread).
simple one line ;)
new File(uri.getPath()).delete();
and in manifest must use these permissions
android.permission.WRITE_EXTERNAL_STORAGE
add below code in onDestroy method:
if(myFile.exists())
myFile.delete();
and don't forget to add permission in Manifest file
android.permission.WRITE_EXTERNAL_STORAGE
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'm trying to get real path from Uri(Of selected image from gallery) but This function returns always null value :
//Convert the image URI to the direct file system path of the image file
public String getRealPathFromURI(Uri contentUri) {
Cursor cursor = null;
try {
String[] proj = { MediaStore.Images.Media.DATA };
cursor = getActivity().getContentResolver().query(contentUri, proj, null, null, null);
cursor.moveToFirst();
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
return cursor.getString(column_index);
} finally {
if (cursor != null) {
cursor.close();
}
}
}
That's because the image you're selecting is not physically available on the device.
Images from gallery or other choose can come from different sources that does not provide a physical file, like a cloud storage for example.
Check this code here on how to open the Uri as a InputStream that can be used to create a copy of the file (or just read directly).
Android: Getting a file URI from a content URI?
edit:
I'm doing some extra research on it, apparently it also varies on how you request this Uri.
if you request it like this (which is the current preferred method as per Android guides):
i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("image/*");
startActivityForResult(i, REQUEST_STORAGE);
and it opens the KitKat style unified selector, if you choose an image from there, it will always return null. If you open the left-drawer menu, select the gallery (or a file browser), and pick an image from there, then, if it is a local file image, you will have the correct path.
on the other hand, if you request it like this (which is the old method):
i = new Intent(Intent.ACTION_PICK);
i.setType("image/*");
startActivityForResult(i, REQUEST_STORAGE);
it will directly open the Gallery, and again, if it is a local file image, you will have the correct path.
So yeah, I still don't believe there's a way to force local only, but at least you have more information to make an informed decision on your coding.
I am trying to get the full path of a sound file on the SD card.
This launches sound picker - I then use the Play Music app to select a file
Intent intent = new Intent();
intent.setAction(Intent.ACTION_PICK);
intent.setData(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(intent, RESULT_SOUNDPICKER);
On activity result I am trying to get the full path
case RESULT_SOUNDPICKER: {
Log.d("TAG", "onActivityResult "+requestCode+" "+resultCode);
if (resultCode == RESULT_OK)
{
Uri uri = data.getData();
String filePath = uri.getPath();
Log.d("TAG", "FilePath: "+filePath);
// A song was picked.
Log.d("TAG", "PickSongActivity.onActivityResult: "+data.getDataString());
}
}
But this returns a path like
//media/external/audio/media/13085
Rather than a proper path of where the file is held.
I need to get the full path back as I then want to use it to play the file.
Thank you.
Solution
This method can be used to get the full path.
private String getRealPathFromURI(Uri contentUri) {
String[] proj = { MediaStore.Images.Media.DATA };
CursorLoader loader = new CursorLoader(getApplicationContext(), contentUri, proj, null, null, null);
Cursor cursor = loader.loadInBackground();
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
}
I need to get the full path back as I then want to use it to play the file.
There may not be a path (as it does not have to be a file), let alone a path that you can reach (as the file does not have to be on storage that is accessible to you).
MediaPlayer can use a Uri directly, so I suggest going that route.
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;
}
I use the Android camera to take a picture in my activity :
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, getImagePath());
startActivityForResult(intent, TAKE_PHOTO_CODE);
When I leave the camera app, the photo is saved in two places:
At the path specified by the getImagePath() method (which is correct) ;
Into the gallery. I don't whant that.
How can I prevent the photo to be saved into the gallery? And if I can't do it, how can I get the photo path in my onActivityResult() so I can delete it?
For Intent.ACTION_GET_CONTENT you can delete the gallery file (after copying it to your folder). Perhaps this would also work for MediaStore.ACTION_IMAGE_CAPTURE (with MediaStore.EXTRA_OUTPUT). I use the following code snippet for deleting the gallery file on return from Intent.ACTION_GET_CONTENT:
public String getRealPathFromURI(Uri contentUri) {
String[] proj = { MediaStore.Images.Media.DATA };
Cursor cursor = managedQuery(contentUri, proj, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Uri u = data.getData();
new File(getRealPathFromURI(u)).delete();
...
Are you saving the image to the SD card somewhere in your getImagePath() code? If so, the Android Media Scanner is picking it up from that location to display in the gallery. You can create an empty file named .nomedia in the directory where your images are saved to have the Media Scanner ignore all the media files in that folder.