How I can delete image by Uri using scoped storage android 10?
I saved my images to this scoped
final String relativeLocation = Environment.DIRECTORY_PICTURES + File.separator + "myApp" + File.separator + constants.PhotoDirName;
ContentResolver resolver = context.getContentResolver();
ContentValues contentValues = new ContentValues();
contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, name);
contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpg");
contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, relativeLocation);
Uri imageUri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
fos = resolver.openOutputStream(Objects.requireNonNull(imageUri));
I need to delete an image using Uri using this code
String[] projection;
projection = new String[]{MediaStore.MediaColumns._ID};
Uri externalUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
Cursor cursor = context.getContentResolver().query(externalUri, projection,
MediaStore.MediaColumns.DISPLAY_NAME + " LIKE ?", new String[]{displayName}, null);
assert cursor != null;
cursor.moveToFirst();
if (cursor.getCount() > 0) {
int columnIndex = cursor.getColumnIndex(projection[0]);
long fileId = cursor.getLong(columnIndex);
cursor.close();
Uri uri= Uri.parse(externalUri.toString() + "/" + fileId);
if (uri != null) {
final ContentResolver resolver = context.getContentResolver();
String[] selectionArgsPdf = new String[]{displayName};
try {
resolver.delete(uri, MediaStore.MediaColumns.DISPLAY_NAME + "=?", selectionArgsPdf);
} catch (Exception ex) {
ex.printStackTrace();
// show some alert message
}
}
}
But the image did not deleted!!
this error appears
android.app.RecoverableSecurityException: com.xxxx.xxxx has no access to content://media/external/images/media/11774
Related
I am able to read the file i created with mediastore in android 10
But I can't read files created by other apps
'java.io.IOException: setDataSource failed.: status=0x80000000' error occurs when trying to access mediaPlayer from other apps
How can I read files created by other apps?
Below is the code to get the list of files in the MUSIC folder
public void getFileListInFolderApiQ(String path) {
mDataSet.clear();
Uri externalUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
String selection = MediaStore.MediaColumns.RELATIVE_PATH + "=?";
String[] selectionArgs = new String[]{Environment.DIRECTORY_MUSIC + "/" + "tts" + "/"};
String[] projection = new String[]{
MediaStore.Audio.Media._ID,
MediaStore.Audio.Media.DISPLAY_NAME,
MediaStore.Audio.Media.MIME_TYPE
};
Cursor cursor = getContentResolver().query(externalUri, projection, selection, selectionArgs, null);
Uri testUri = null;
if (cursor == null || !cursor.moveToFirst()) {
return;
}
do {
String contentUrl = externalUri.toString() + "/" + cursor.getString(0);
long id = cursor.getLong(cursor.getColumnIndex(MediaStore.MediaColumns._ID));
Uri uri = ContentUris.withAppendedId(externalUri, id);
String tmpFilename = cursor.getString(cursor.getColumnIndex(MediaStore.MediaColumns.DISPLAY_NAME));
testUri = uri;
mDataSet.add(new CustomTTSListData(tmpFilename, getPathFromUri(testUri), 1, 1, uri));
} while (cursor.moveToNext());
}
Before SDK 29 this is the correct way to find the Uri but now it won't work anymore for sdk greater than 28. Let's assume I save the BITMAP using scoped-storage like:
#RequiresApi(api = Build.VERSION_CODES.Q)
#NonNull
private Uri saveBitmap(#NonNull final Context context, #NonNull final Bitmap bitmap,
#NonNull final Bitmap.CompressFormat format, #NonNull final String mimeType,
#NonNull final String displayName, #Nullable final String subFolder) throws IOException {
String relativeLocation = Environment.DIRECTORY_PICTURES;
if (!TextUtils.isEmpty(subFolder)) {
relativeLocation += File.separator + subFolder;
}
final ContentValues contentValues = new ContentValues();
contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, displayName);
contentValues.put(MediaStore.MediaColumns.MIME_TYPE, mimeType);
contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, relativeLocation);
final ContentResolver resolver = context.getContentResolver();
OutputStream stream = null;
Uri uri = null;
try {
final Uri contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
uri = resolver.insert(contentUri, contentValues);
if (uri == null) {
throw new IOException("Failed to create new MediaStore record.");
}
stream = resolver.openOutputStream(uri);
if (stream == null) {
throw new IOException("Failed to get output stream.");
}
if (!bitmap.compress(format, 95, stream)) {
throw new IOException("Failed to save bitmap.");
}
return uri;
} catch (IOException e) {
if (uri != null) {
// Don't leave an orphan entry in the MediaStore
resolver.delete(uri, null, null);
}
throw e;
} finally {
if (stream != null) {
stream.close();
}
}
}
This code works for SDK <= 28. But, How to get URI using fileName which is saved in the external storage for SDK version 29 and above?
private String getFilePathUri(String enteredFileName) {
String file_uri_string = Environment.getExternalStorageDirectory() + "/"
+ AppConstants.APP_FOLDER + "/" + enteredFileName + ".jpg";
AppUtils.showLog(TAG, file_uri_string + "");
return file_uri_string;
}
Android 10 and above: Here the uri gives the file_id based you the given displayName.
/**
* Returns the Uri which can be used to delete/work with images in the photo gallery.
* #param displayName Path to IMAGE on SD card
* #return Uri in the format of... content://media/external/images/media/[NUMBER]
*/
private Uri getUriFromPath(String displayName) {
long photoId;
Uri photoUri = MediaStore.Images.Media.getContentUri("external");
String[] projection = {MediaStore.Images.ImageColumns._ID};
// TODO This will break if we have no matching item in the MediaStore.
Cursor cursor = getContentResolver().query(photoUri, projection, MediaStore.Images.ImageColumns.DISPLAY_NAME + " LIKE ?", new String[] { displayName }, null);
assert cursor != null;
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(projection[0]);
photoId = cursor.getLong(columnIndex);
cursor.close();
return Uri.parse(photoUri.toString() + "/" + photoId);
}
I want to query all of the files in a folder called as memories through the Mediastore API. I have tried looking at these questions but didn't get an appropriate answer.
https://android.jlelse.eu/handling-files-in-code-after-the-android-10-released-2bea0e16d35
https://developer.android.com/training/data-storage/shared/media#query-collection
How to I read and write a txt file from android 10 and above from internal storage
How to get the path of a specific folder in Android Q
How do I list all file in a directory in android 10 using Android Studio?
EDIT: Abs Path: imageUri: content://media/external/images/media/31
EDIT: How I save the image:
private void saveImage(Bitmap bitmap, #NonNull String name) throws IOException {
boolean saved;
OutputStream fos;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
ContentResolver resolver = getContext().getContentResolver();
ContentValues contentValues = new ContentValues();
contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, name);
contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/png");
contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, "DCIM/" + IMAGES_FOLDER_NAME);
Uri imageUri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
Log.d(TAG, "imageUri: " + imageUri);
fos = resolver.openOutputStream(imageUri);
} else {
String imagesDir = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DCIM).toString() + File.separator + IMAGES_FOLDER_NAME;
File file = new File(imagesDir);
if (!file.exists()) {
file.mkdir();
}
File image = new File(imagesDir, name + ".png");
Log.d(TAG, "File file: " + image);
fos = new FileOutputStream(image);
}
saved = bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
Log.d(TAG, "Bitmap Image AndroidQ: " + saved);
fos.flush();
fos.close();
}
EDIT:
I looked up many questions with the tag Mediastore and formed this solution but I am not able to write SQLite Placeholder syntax so can anyone help me with that. #blackapps
String selection = MediaStore.MediaColumns.RELATIVE_PATH + "/DCIM/" + IMAGES_FOLDER_NAME;
String[] selectionArgs = new String[] {"%memories%"};
try (Cursor cursor = requireContext().getContentResolver().query(
MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
projection,
selection,
selectionArgs,
null
)) {
assert cursor != null;
int nameColumn =
cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DISPLAY_NAME);
Log.d(TAG, "name column: " + nameColumn);
while (cursor.moveToNext()) {
String name = cursor.getString(nameColumn);
byte[] bytes = name.getBytes();
Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
Log.d(TAG, "file name: " + name);
imageList.add(bitmap);
}
}
You can do like this
fun getFiles(var directory_name){
var selection: String
selection = MediaStore.Files.FileColumns.RELATIVE_PATH+ " =? "
var selectionArgs = arrayOf(directory_name)
val cursor: Cursor? = contentResolver.query(
MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY),
null,
selection,
selectionArgs,
null
)
}
you need to iterate cursor with do while loop or any other
function call:
getFiles(Lyrics/) //folder name from internal meomery if you want to use sd card then use MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL). I have tested this and its working fine for me
I am trying to get Images and videos from Media store (album wise).It is working properly in devices having OS version < 10. In Android Q i am getting an syntax error.
System.err: android.database.sqlite.SQLiteException: near "GROUP": syntax error (code 1 SQLITE_ERROR): , while compiling: SELECT _id, _data, date_modified, bucket_display_name, media_type FROM files WHERE ((is_pending=0) AND (is_trashed=0) AND (volume_name IN ( 'external_primary' ))) AND ((media_type=1 OR media_type=3) GROUP BY (bucket_display_name)) ORDER BY bucket_display_name ASC
I am using below code to get data.
Uri queryUri = MediaStore.Files.getContentUri("external");
Uri intqueryUri = MediaStore.Files.getContentUri("internal");
String[] projection = {MediaStore.Images.Media._ID,
MediaStore.MediaColumns.DATA,
MediaStore.MediaColumns.DATE_MODIFIED,
MediaStore.Images.Media.BUCKET_DISPLAY_NAME,
MediaStore.Files.FileColumns.MEDIA_TYPE};
// Return only video and image metadata.
String selection;
selection = MediaStore.Files.FileColumns.MEDIA_TYPE + "="
+ MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE
+ " OR "
+ MediaStore.Files.FileColumns.MEDIA_TYPE + "="
+ MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO;
Cursor cursorExternal,cursorInternal;
cursorExternal = getContentResolver().query(queryUri, projection, selection+") GROUP BY (bucket_display_name",
null, MediaStore.Images.Media.BUCKET_DISPLAY_NAME+" ASC");
cursorInternal = getContentResolver().query(intqueryUri, projection, selection+") GROUP BY (bucket_display_name",
null, MediaStore.Images.Media.BUCKET_DISPLAY_NAME+" ASC");
Cursor cursor = new MergeCursor(new Cursor[]{cursorExternal, cursorInternal});
while (cursor.moveToNext()) {
path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA));
album = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.BUCKET_DISPLAY_NAME));
Log.w( "album:** ",album+"" );
HashMap<String, String> listData = Function.mappingInboxAlbum(album, path, countPhoto);
if (!albumList.contains(listData)) {
albumList.add(listData);
}
}
cursor.close();
I googled it but not getting any solution.
Please help...
Add this line in AndroidManifest :
android:requestLegacyExternalStorage="true"
Here is my approach:
first you will need the album_id
Uri path = Uri
.parse("content://media/external/audio/albumart");
Bitmap bmp = Album.getAlbumart(getActivity(), Long.parseLong(album_id), path);
then
public Bitmap getAlbumart(Context context, long album_id, Uri sArtworkUri) {
Bitmap bm = null;
try {
Uri uri = ContentUris.withAppendedId(sArtworkUri, album_id);
ParcelFileDescriptor pfd = context.getContentResolver()
.openFileDescriptor(uri, "r");
if (pfd != null) {
FileDescriptor fd = pfd.getFileDescriptor();
bm = BitmapFactory.decodeFileDescriptor(fd);
}
} catch (Exception e) {
}
return bm;
}
finally to display use Glide library
try {
Glide.with(mContext)
.load(uri)
.asbitmap
.error(Glide.with(ivcircle).load(R.drawable.playlist))
.into(ivcircle);
} catch (Exception e) {
e.printStackTrace();
}
you can use this method
public static ArrayList<Album> loadAlbum(Context context) {
ContentResolver contentResolver = context.getContentResolver();
ArrayList<Album> albumList = new ArrayList<>();
Uri uri = MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI;
String[] projection = new String[]
{
MediaStore.Audio.Albums.ALBUM,
MediaStore.Audio.Albums.ARTIST,
MediaStore.Audio.Albums.NUMBER_OF_SONGS
};
//String sortOrder = MediaStore.Audio.Albums.ALBUM + " ASC";
Cursor cursor = contentResolver.query(uri, projection, null, null, null);
if (cursor != null && cursor.getCount() > 0) {
while (cursor.moveToNext()) {
String title = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Albums.ALBUM));
String artist = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Albums.ARTIST));
int numberOfSongs = cursor.getInt(cursor.getColumnIndex(MediaStore.Audio.Albums.NUMBER_OF_SONGS));
// Save to albumList
albumList.add(new Album(title, artist, numberOfSongs));
}
}
assert cursor != null;
cursor.close();
return albumList;
}
i am getting below type of uri:
/mnt/sdcard/Pictures/WW/ww_1360248819300.jpg
how to convert above type of URI to below URI:
content://media/external/images/media/12
please help
Thanks
public static Uri getImageContentUri(Context context, File imageFile) {
String filePath = imageFile.getAbsolutePath();
Cursor cursor = context.getContentResolver().query(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
new String[] { MediaStore.Images.Media._ID },
MediaStore.Images.Media.DATA + "=? ",
new String[] { filePath }, null);
if (cursor != null && cursor.moveToFirst()) {
int id = cursor.getInt(cursor
.getColumnIndex(MediaStore.MediaColumns._ID));
Uri baseUri = Uri.parse("content://media/external/images/media");
return Uri.withAppendedPath(baseUri, "" + id);
} else {
if (imageFile.exists()) {
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.DATA, filePath);
return context.getContentResolver().insert(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
} else {
return null;
}
}
}