Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to rename a file in Android knowing only its media content Uri

In Android Q the MediaStore.Files.FileColumns.DATA field has been deprecated, and may be null or apps may not have the rights to read it, therefore is there a way to rename the filename section (not the path) of a file using only its media content Uri?

Until now the DATA field could be used to find the real path of a file from a known Uri, but since it has been deprecated then the idea is not to even try to find or resolve the real file path, and use only its content Uri.

Consider that the Uri will be in the standard media content format (not SAF format): content://media/external/images/media/123

The intention is to rename the name of the file that the Uri is pointing to.

I’m aware that I can update the MediaStore’s TITLE and DISPLAY_NAME fields, but this doesn’t change the file name, and if a user decides to move the file outside the device then this one will still have the old filename.

like image 420
PerracoLabs Avatar asked Mar 23 '19 14:03

PerracoLabs


People also ask

How do I rename a file programmatically?

File from = new File(directory, "currentFileName"); For safety, Use the File. renameTo() .

Can you rename a file in Android Studio?

Open the settings. gradle file with a text editor, like VSCode, and change the rootProject.name to your new project name. Done!


1 Answers

Update

Hi, firstly apologies for my previous amateurish answer. But, I can't think of any direct approach to accomplish the requirement. However, there might be a workaround which, I think, is better than nothing.

The only way we can rename a file solely with a Uri is by DocumentsContract via SAF. What we've now in hand is the MediaStore Uri and We need to get the equivalent Document Uri of that file. For that we can use MediaStore.getDocumentUri( context , mediaUri ). The catch is, we need to have permission for the Document Uri before getting it, by calling this method. We can get a persistable Uri permission for the DocumentTree Uri of the mounted storage volume ( or any specific directory alone, which contains the media files we want to modify ). By doing so, now we'll have the permission for the Documents Uri of the media file and we can use DocumentsContract.renameDocument to rename that file.

Steps 1-4 will be one time things ( until manually revoked )

  1. Declare android.permission.READ_MEDIA_IMAGES permission in Manifest.
  2. Ask READ_MEDIA_IMAGES permission to the user.
  3. Ask Uri permission for DocumentTree of the storage volume which has the media file.

        StorageManager manager = getSystemService(StorageManager.class);
    
        StorageVolume primaryStorageVolume = manager.getPrimaryStorageVolume();
    
        startActivityForResult(primaryStorageVolume.createOpenDocumentTreeIntent(), STORAGE_PERMISSION_REQ_CODE);
    

But, please note that according to Android's documentation the user can select a location other than the one that we requested.

  1. onActivityResult take persistable permission of the result Uri

        if (resultCode == RESULT_OK) {
            getContentResolver().takePersistableUriPermission(uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
        }
    
  2. Now get Documents Uri of the media file and rename it.

    Uri docUri = MediaStore.getDocumentUri( context , mediaUri );
    DocumentsContract.renameDocument(contentResolver, docUri, "newFileName.ext");
    

So basically we'll have to ask user permission twice, once for storage access and second for Uri access. Since we'll be getting a persistable Uri permission, this prompt will be a one time thing and it lasts until we revoke it. We can access all the files using it's Document Uri without having the user select it.


Previous Answer

I think we can make use of the DocumentsContract. But for that, you should request the file with Intent.ACTION_OPEN_DOCUMENT instead of Intent.GET_CONTENT. Once you have got the URI, you can rename that file using DocumentsContract.renameDocument

DocumentsContract.renameDocument(contentResolver, uri, "newFileName.ext");

But, the DocumentProvider which provided the URI should support rename function. For example, If I choose a file from Recents, rename is not supported. But, If I choose the same file with some other provider, say the default file manager, rename action will be supported. You can verify that by checking if the flag DocumentsContract.Document.FLAG_SUPPORTS_RENAME is set in the result intent.

like image 50
Maran Subburayan Avatar answered Oct 09 '22 18:10

Maran Subburayan