Error when get file path of file in Android 11 - android

when I get file path of file in Android 11 .
protected File getOutputMediaFile() {
String timeStamp = new SimpleDateFormat("ddMMyyyy_HHmmss").format(new Date());
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.TITLE, timeStamp + ".jpg");
fileUri = getActivity().getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
Log.e("File Uri Path", "Uri inserted into media store = " + fileUri);
Toast.makeText(getActivity(), "File uri = "+fileUri, Toast.LENGTH_LONG).show();
String path = getImageRealPathFromURI(fileUri);
File file = new File(path);
return file;
}
private String getImageRealPathFromURI(Uri contentUri) {
String realPath = "";
Cursor cursor = null;
try {
String[] proj = {MediaStore.Images.Media.DATA};
cursor = getActivity().getContentResolver().query(contentUri, proj, null, null, null);
if (cursor.getCount() > 0) {
cursor.moveToFirst();
realPath = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA));
} else {
Log.e("Image Real Path", "Cursor count appearing to be zero");
Toast.makeText(getActivity(), "Cursor count appearing to be zero", Toast.LENGTH_LONG).show();
realPath = "";
}
} catch (Exception e) {
Log.e("Image Real Path", "Exception fetching getImageRealPathFromURI() due to " + e.toString());
Toast.makeText(getActivity(),"Exception fetching getImageRealPathFromURI() due to "+e.toString(), Toast.LENGTH_LONG).show();
realPath = "";
} finally {
cursor.close();
}
return realPath;
}
I meet error : /storage/emulated/0/Pictures/1614237849822.jpg: open failed: EEXIST (File exists).
at libcore.io.IoBridge.open(IoBridge.java:492).
When I getOutputMediaFile().getpath.
Anyone help me?

add this line in manifest file :
android:requestLegacyExternalStorage="true"
and make sure that you add Read external storage permission and also allow this permission

The getContentResolver().insert() will give you a nice fresh uri to write the content of a file to.
It gives an uri you can use. It does not create a file for you.
Even if you get the path of the yet non existing file with the .DATA column, that file does not exist yet.
You can simply check that with File.exists().
Only if you open an OutputStream for the obtained uri and write to it the file will be created.
Use the uri! For what do you need that data path?

You can use this type to set mMediaRecoder's path:
final ParcelFileDescriptor parcelFileDescriptor = mContext.getContentResolver().
openFileDescriptor(Uri.parse(mVideoProfile.path), "rw");
mMediaRecorder.setOutputFile(parcelFileDescriptor.getFileDescriptor());
mVideoProfile.path = "content://media/external/video/media/751";

Related

opening an external "file explorer" app: how to get absolute path from a uri pointing to a folder

In my app, the user can choose where the created files (text files) are created.
This part is working fine.
But now, I want to open an external "file explorer" app, pointing directly to the chosen folder.
The "file explorer " apps I know accept an absolute path as input (like /storage/emulated/0/Documents/test_folder)
When the user chooses a folder (with Intent.ACTION_OPEN_DOCUMENT_TREE), I get a content uri (like content://com.android.externalstorage.documents/tree/home%3Atest_folder)
Another example with an external sd card:
uri: content://com.android.externalstorage.documents/tree/3877-DB74%3ADocuments%2Ftest_folder
expected path: /storage/3877-DB74/Documents/test_folder
The uri points to a folder, not a file, so I can't use something like openInputStream
I have tried :
File f = new File(uri.getPath());
String path = f.getAbsolutePath();
but it gives: /tree/home:test_folder or /tree/3877-DB74:Documents/test_folder if on sd card
How can I get the real absolute path?
The code I use to call a file explorer:
Intent intent = new Intent(Intent.ACTION_VIEW);
String path = getExternalFilesDir(null).getAbsolutePath();
intent.setDataAndType(Uri.parse(path), "resource/folder");
if (intent.resolveActivityInfo(getPackageManager(), 0) != null)
{
startActivity(intent);
}
so basically you want to get file path from uri
you give try with this code
https://gist.github.com/pratikbutani/eb56f6f9f7013e31d8bfea9effbd4251
I have tried the suggested code (see above).
Unfortunately, I got an exception:
Caused by: java.lang.UnsupportedOperationException: Unsupported Uri content://com.android.externalstorage.documents/tree/home%3Atest_folder
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:167)
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:135)
at android.content.ContentProviderProxy.query(ContentProviderNative.java:418)
at android.content.ContentResolver.query(ContentResolver.java:760)
at android.content.ContentResolver.query(ContentResolver.java:710)
at android.content.ContentResolver.query(ContentResolver.java:668)
at ....UriUtils.getDataColumn(UriUtils.java:278)
Here is a copy of the code:
private static String getDataColumn(Context context, Uri uri)
{
Cursor cursor = null;
final String column = "_data";
final String[] projection = { column };
try {
cursor = context.getContentResolver().query(uri, projection,
null, null, null);
if (cursor != null && cursor.moveToFirst()) {
final int index = cursor.getColumnIndexOrThrow(column);
return cursor.getString(index);
}
} finally {
if (cursor != null)
cursor.close();
}
return null;
}
I finally wrote my own method to get the absolute path for a folder from a Uri.
It is surely not fully generic, but it meets my need.
if it can help someone, here is my code:
Note: VOLUME_MAP is a map containing all mounted external volumes
/**************************************************************************/
public static String getRealPathFromContentUri(final Uri uri)
{
if (!isExternalStorageDocument(uri))
{
return null;
}
List<String> segs = uri.getPathSegments();
if (!"tree".equalsIgnoreCase(segs.get(0)))
{
return null;
}
String path = uri.getLastPathSegment();
final String[] split = path.split(":");
final String volumeId = split[0];
String userPath = "";
if (split.length > 1)
{
userPath = "/" + split[1];
}
if ("primary".equalsIgnoreCase(volumeId))
{
return Environment.getExternalStorageDirectory().getAbsolutePath() + userPath;
}
if ("home".equalsIgnoreCase(volumeId))
{
return Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS).getAbsolutePath() + userPath;
}
// look for real volumeId
final String volumeName = VOLUME_MAP.get(volumeId);
if (volumeName == null)
{
return null;
}
path = "/storage";
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R)
{
path = Environment.getStorageDirectory().getAbsolutePath();
}
return path + "/" + volumeId + userPath;
}
Thanks to all contributors on this topic.

How to query all images from getExternalFilesDir path through MediaStore

I am writing a camera and gallery app, following the official Google documentation. The problem is that it mostly focuses on how to take a picture and how to save it in memory. I am saving them in the application external memory through getExternalFilesDir().
What I am now trying to do is simpy query that directory in which taken photos are saved, through MediaStore, in order to display all the pictures in there in a recycler view. But I can't seem to find anywhere an explanation on how to do the retrieval. There is something wrong with the Uri that I probably didn't understand well, and I don't know how to solve. Even in here https://developer.android.com/training/data-storage/files#PrivateFiles the article only talks about saving files in the various storage options, but not about retrieving them.
Here is the code of how I save the files:
private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
// Save a file: path for use with ACTION_VIEW intents
currentPhotoPath = image.getAbsolutePath();
return image;
}
This is the function that actually sends the intent (and then onActivityResult handles the returned data):
private void dispatchTakePictureIntent() {
final String TAG = "dispatchTakePic: ";
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Ensure that there's a camera activity to handle the intent
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException ex) {
// Error occurred while creating the File
Log.e(TAG, "Error while creating a file");
ex.printStackTrace();
}
// Continue only if the File was successfully created
// Authority has to be exactly like in manifest
if (photoFile != null) {
Uri photoURI = FileProvider.getUriForFile(
this,
"com.example.android.fileprovider",
photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
}
}
}
This is the code where I'm trying to get the information about the photos taken:
private void populatePhotoArray() {
final String TAG = "popPhotoArray: ";
ContentResolver contentResolver = getContentResolver();
String photo_id, photo_title, photo_path = "";
final String[] PHOTOGRAPHS_PROJECTION = {
MediaStore.Images.Media._ID,
MediaStore.Images.Media.TITLE,
MediaStore.Images.Media.DATA};
File photographsDirectory = getExternalFilesDir(Environment.DIRECTORY_MOVIES);
Uri photographsUri = Uri.fromFile(photographsDirectory);
//Uri photographsUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
//Uri photographsUri = MediaStore.Images.Media.INTERNAL_CONTENT_URI;
String sortOrder = MediaStore.Images.Media.DATE_ADDED + " DESC";
final Cursor cursor = contentResolver.query(
photographsUri,
PHOTOGRAPHS_PROJECTION,
null,
null,
sortOrder);
Log.d(TAG, "created the projection");
if (cursor != null && cursor.getCount() > 0) {
while (cursor.moveToNext()) {
photo_id = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media._ID));
photo_title = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.TITLE));
photo_path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
// save to photo list
applicationPhotosList.add(new Photographs(photo_id, photo_title, photo_path));
Log.d(TAG, "new photo added");
}
cursor.close();
Log.d(TAG, "Photo array filled up");
}
else if (cursor == null){
Log.d(TAG, "No photos present, cursor is null");
Toast.makeText(this, "No photos present", Toast.LENGTH_SHORT).show();
}
Looks like trying to transform the path of getExternalFileDir() into an Uri doesn't work. The cursor is empty. But MediaStore only has MediaStore.Images.Media.EXTERNAL_CONTENT_URI and that's not suitable as that queries the whole device memory, while I only need that particular directory in which my app is saving the pictures taken. What am I missing? It cannot be that hard, right?
There is another way to retrieve the images from a specific folder w/o using the cursor and I think its more faster.
private fun getAllShownImagesPath(): ArrayList<String> {
var filePath: ArrayList<String> = ArrayList<String>()
val path = File(getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).path, "BacFo Camera")
if (path.exists()) {
for (i in path.list().iterator()) {
filePath?.add("" + path.toString() + "/" + i)
}
}
return filePath!!
}
`
In "fileNames" you have the path of all images or videos whatever you have saved in the specific folder

Android delete file from removable sd card (second external storage)

I've read all topics in this forum but nothing works for me. I have arraylist of paths of files and I need to delete some of them. In my code I try to use:
File file = new File(filesPath.get(0));
file.delete();
if (file.exists()) {
try {
file.getCanonicalFile().delete();
} catch (IOException e) {
e.printStackTrace();
}
if (file.exists()) {
file.getAbsoluteFile().delete();
}
}
Log.e("MyLogs", file.exists() ? "true" : "false");
filesPath I get from MediaStore and it looks like "/storage/extSdCard/mmm/bensound-summer.mp3". I can read this path without any problems, but I can't delete it. Here is my code for getting string array:
ArrayList<String> filesPath = new ArrayList<>();
Uri contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
String[] projection = {MediaStore.Images.Media.DATA};
try {
Cursor cursor = context.getContentResolver().query(
contentUri,
projection,
MediaStore.Audio.Media.IS_MUSIC + " != 0",
null,
null);
if (cursor != null && cursor.moveToFirst() && cursor.getCount() > 0) {
do {
String path = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DATA));
File file = new File(path);
if (file.exists())
filesPath.add(path);
} while (cursor.moveToNext());
return filesPath;
} else {
return null;
}
} catch (Exception ex) {
ex.printStackTrace();
return null;
}
Of course I added permissions to manifest:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
From this link I took some code for mine but it didn't help me to solve my problem, that is why I wrote my question here.
EDIT:
Just found the point: I can't delete files from sdcard (removable)!!! from storage of decive everything deletes without any problem.
EDIT 2:
try {
long id = -1;
Cursor cursor = context.getContentResolver().query(
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
new String[] { MediaStore.Audio.Media._ID },
MediaStore.Audio.Media.DATA + "=?",
new String[] { file.getAbsolutePath() },
null);
if (cursor != null && cursor.moveToFirst() && cursor.getCount() > 0) {
id = cursor.getLong(cursor.getColumnIndex(MediaStore.MediaColumns._ID));
cursor.close();
Uri uri = Uri.withAppendedPath(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, String.valueOf(id));
DocumentFile documentFile = DocumentFile.fromSingleUri(context, uri);
if (documentFile.delete()) {
Uri mediaContentUri = ContentUris.withAppendedId(
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
id
);
context.getContentResolver().delete(mediaContentUri, null, null);
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
I got an exception error:
Failed to delete document
java.lang.UnsupportedOperationException: Unsupported call: android:deleteDocument
error points to line documentFile.delete()
it looks like "/storage/extSdCard/mmm/bensound-summer.mp3".
Then that file is on a removable micro SD card.
Micro SD cards are readonly for your app on modern Android systems.
That's why you cannot delete that file from it.
Well not in the way you try to do it now.
First Check Have You Got permission Read External Storage and Write External Storage then
You Can delete by this code..
You can just use File.delete()
File dir2 = new File(Environment.getExternalStorageDirectory() + "/Eraser/temp");
File dir = new File(Environment.getExternalStorageDirectory() + "/Eraser/Capture");
if (dir.isDirectory())
{
String[] children = dir.list();
for (int i = 0; i < children.length; i++)
{
new File(dir, children[i]).delete();
}
}
dir.delete();
if (dir2.isDirectory())
{
String[] children = dir2.list();
for (int i = 0; i < children.length; i++)
{
new File(dir2, children[i]).delete();
}
}
dir2.delete();
Are you sure that you have got the permission WRITE_EXTERNAL_STORAGE in your application before deleting the file?
As you can already access the file, there should not be any other problem calling the delete method. Moreover, you can also check log cat if there are any exceptions captured
i hope you add below permission in android manifest file..
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
for delete file used below code..
File file = new File(selectedFilePath);
boolean deleted = file.delete();

Android Studio App Edited images not showing up in gallery

I created a simple android app for adding frames and cropping images, now after the editing is done the pictures are saved in android root>app folder but non of these pictures show up in the gallery, here is My code
/**
* Create a File for saving an image or video
*/
private File getOutputMediaFile() {
// To be safe, you should check that the SDCard is mounted
// File mediaStorageDir = new File(Environment.getExternalStorageDirectory()
// + "/Android/data"
// + getApplicationContext().getPackageName()
// + "/Files" + Global.AppFolder);
File root = new File(Environment.getExternalStorageDirectory().getAbsolutePath(), "/" + Global.AppFolder);
// Create the storage directory if it does not exist
if (!root.exists()) {
if (!root.mkdirs()) {
return null;
}
}
// Create a media file name
String timeStamp = new SimpleDateFormat("ddMMyyyy_HHmm").format(new Date());
File mediaFile;
String mImageName = "MI_" + timeStamp + ".jpg";
mediaFile = new File(root.getAbsolutePath(), mImageName);
return mediaFile;
}
private String getRealPathFromURI(Uri uri) {
Cursor cursor = getContentResolver().query(uri, null, null, null, null);
if (cursor == null) {
return uri.getPath();
} else {
cursor.moveToFirst();
String s = cursor.getString(cursor.getColumnIndex("_data"));
cursor.close();
return s;
}
}
By the way I am a newbie and don't have a lot of experience with android coding so detailed answers and references(for further learning) shall be highly appreciated.
try this add below code after saving image
ContentValues values = new ContentValues();
values.put(Images.Media.TITLE, "title");
values.put(Images.Media.DESCRIPTION, "description");
values.put(Images.Media.DATE_TAKEN, System.currentTimeMillis());
values.put(Images.ImageColumns.BUCKET_ID, root.toString().toLowerCase(Locale.US).hashCode());
values.put(Images.ImageColumns.BUCKET_DISPLAY_NAME, root.getName().toLowerCase(Locale.US));
values.put("_data", root.getAbsolutePath());
ContentResolver cr = getContentResolver();
cr.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
Add these code after you save the image
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + Environment.getExternalStorageDirectory())));
The Media Scanning is only done when the system Bootup. So you need to tell the media scanner to re-scan the files.

Unable to set picture as. "No appps can perform this action"

I am trying to give users an option to set image as wallpaper/whatsapp dp like this.
But I'm stuck with this code
Uri sendUri = Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.a_day_without_thinking_mobile);
Intent intent = new Intent(Intent.ACTION_ATTACH_DATA);
intent.setDataAndType(sendUri, "image/jpg");
intent.putExtra("mimeType", "image/jpg");
startActivity(Intent.createChooser(intent,"Set As"));
It shows a dialog that no apps can perform this action.
I also tried to check my Uri through this method
ContentResolver cr = getContentResolver();
String[] projection = {MediaStore.MediaColumns.DATA};
Cursor cur = cr.query(sendUri, projection, null, null, null);
if (cur != null) {
if (cur.moveToFirst()) {
String filePath = cur.getString(0);
if (new File(filePath).exists()) {
Log.d("URI: ","File path exist");
} else {
Log.d("URI: ","File not found");
}
} else {
Log.d("URI: ","URI ok but no enty found");
}
cur.close();
} else {
Log.d("URI: ","URI was invalid for some other reason");
}
And It always returned that the URI was invalid. But I'm sure that the image is valid jpg and is present in raw folder.
I tried changing URI paths but to no success.
Android file read format has been changed after targetSdkVersion >= 24
You can find the details here;
https://stackoverflow.com/a/38858040/1367450

Categories

Resources