'MediaStore API is unable to fetch the folder which is already created before Clear Data of the Application
To support Android 11 storage, I have implemented Scoped Storage - MediaStore API successfully. However, I ended up with one scenario which I am not sure how to resolve. Scenario is, When the Application is launched for the first time, we have created the Folder under Documents folder and able to read and write files into this folder without creating any duplicate folders. However, If I do Clear Data and re-login the Application, I am not able to fetch the folder which is already created and each time it is creating a new folder with duplicate name - Suffix as (2), (3) etc..,
Please find my code which I tired and also find the screenshots.
File folder = null;
String folderName = "Duration";
if(Build.VERSION.SDK_INT > Build.VERSION_CODES.Q) {
Uri contentUri = MediaStore.Files.getContentUri("external");
String filePath = FileUtils.readFileExternalStorage(contentUri,context,folderName).getPath();
if (!TextUtils.isEmpty(filePath) && FileUtils.isFileExisting(filePath)) {
folder = new File(filePath);
} else {
Uri uri = FileUtils.createFileExternalStorage(contentUri,context,folderName),Environment.DIRECTORY_DOCUMENTS);
Commons.print("URI "+uri.getPath());
folder = new File(FileUtils.getPath(context,uri));
}
if (!folder.exists()) {
folder.mkdirs();
}
} else {
folder = getStorageDir(folderName);
bmodel.deleteFiles(getStorageDir(folderName) + "/", filename);
}
File file = new File(folder, filename );
if(file.exists()) {
file.delete();
}
if (SynchronizationHelper.bcpJSONData != null) {
FileOutputStream outputStream;
try {
Commons.print("FilePath " + file.getPath());
outputStream = new FileOutputStream(file);//context.openFileOutput(filename, Context.MODE_PRIVATE);
outputStream.write(SynchronizationHelper.bcpJSONData.getBytes());
outputStream.close();
outputStream = null;
SynchronizationHelper.bcpJSONData = null;
} catch (Exception e) {
e.printStackTrace();
}
}
This is FileUtils class:
@RequiresApi(api = Build.VERSION_CODES.Q)
public static File readFileExternalStorage(Uri contentUri, Context context, String filename) {
final String selection = MediaStore.Files.FileColumns.DISPLAY_NAME + "=?";
final String[] selectionArgs = new String[] {filename};
return new File(getDataColumn(context,contentUri,selection,selectionArgs));
}
@RequiresApi(api = Build.VERSION_CODES.Q)
public static Uri createFileExternalStorage(Uri contentUri, Context context, String filename, String folder) {
ContentValues values = new ContentValues();
values.put(MediaStore.MediaColumns.DISPLAY_NAME, filename);
values.put(MediaStore.MediaColumns.RELATIVE_PATH, folder);
return context.getContentResolver().insert(contentUri, values);
}
public static String getDataColumn(Context context, Uri uri,
String selection, String[] selectionArgs) {
Cursor cursor = null;
final String column = "_data";
final String[] projection = { column };
try {
cursor = context.getContentResolver().query(uri, projection,
selection, selectionArgs, null);
if (cursor != null && cursor.moveToFirst()) {
final int index = cursor.getColumnIndexOrThrow(column);
return cursor.getString(index);
}
} finally {
if (cursor != null)
cursor.close();
}
return "";
}
@TargetApi(Build.VERSION_CODES.KITKAT)
@SuppressLint("NewApi")
public static String getPath(final Context context, final Uri uri) {
// check here to KITKAT or new version
final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
// DocumentProvider
if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
// ExternalStorageProvider
if (isExternalStorageDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
if ("primary".equalsIgnoreCase(type)) {
return Environment.getExternalStorageDirectory() + "/"
+ split[1];
}
}
// DownloadsProvider
else if (isDownloadsDocument(uri)) {
final String id = DocumentsContract.getDocumentId(uri);
final Uri contentUri = ContentUris.withAppendedId(
Uri.parse("content://downloads/public_downloads"),
Long.valueOf(id));
return getDataColumn(context, contentUri, null, null);
}
// MediaProvider
else if (isMediaDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
Uri contentUri = null;
if ("image".equals(type)) {
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
} else if ("video".equals(type)) {
contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
} else if ("audio".equals(type)) {
contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
}
final String selection = "_id=?";
final String[] selectionArgs = new String[] { split[1] };
return getDataColumn(context, contentUri, selection,
selectionArgs);
}
}
// MediaStore (and general)
else if ("content".equalsIgnoreCase(uri.getScheme())) {
// Return the remote address
if (isGooglePhotosUri(uri))
return uri.getLastPathSegment();
return getDataColumn(context, uri, null, null);
}
// File
else if ("file".equalsIgnoreCase(uri.getScheme())) {
return uri.getPath();
}
return "";
}
On every instance after clearing data of the application, this method getDataColumn()
is returning "" empty and on Debugging I found that the Cursor inside the try
block, is not fetching anything out of it.
Solution 1:[1]
Well, You should consider 2 things first.
1. Don't create the folder if it already exists
2. Load media from the folder with different code
So, here is a little help.
1. Check the existence of the directory.
if (!file.exists()) {
createFolder();
}
Then
2. Load media differently
private ArrayList<Media> loadMedia(String directory_name) {
mediaList = new ArrayList<>();
String selection;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
selection = MediaStore.MediaColumns.RELATIVE_PATH + " LIKE ? ";
} else {
selection = MediaStore.Images.Media.DATA + " LIKE ? ";
}
String[] selectionArgs = new String[]{directory_name};
Cursor cursor = getContentResolver().query(
MediaStore.Files.getContentUri("external"),
null,
selection,
selectionArgs,
MediaStore.Video.Media.DATE_TAKEN + " DESC");
if (cursor != null) {
if (cursor.getCount() > 0) {
cursor.moveToFirst();
do {
int imageCol = cursor.getColumnIndex(MediaStore.Images.Media.DATA);
long id = cursor.getLong(cursor.getColumnIndexOrThrow(BaseColumns._ID));
String path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
long date = cursor.getLong(cursor.getColumnIndex(MediaStore.Images.Media.DATE_ADDED));
String pathId = cursor.getString(imageCol);
Uri uri = Uri.parse(pathId);
Uri contentUri;
if (uri.toString().endsWith(".mp4")) {
contentUri = ContentUris.withAppendedId(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, id);
} else {
contentUri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, id);
}
Media media = new Media();
media.setPath(path);
media.setMediaStoreUri(contentUri);
media.setUri(uri);
media.setAlbumName(new File(path).getParent());
mediaList.add(media);
}
while (cursor.moveToNext());
cursor.close();
}
}
return mediaList;
}
This code is working perfectly in all of the devices including Android 10 and above. Give it a try.
All the best!
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Dev4Life |