问题
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.
回答1:
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 )
- Declare
android.permission.READ_MEDIA_IMAGES
permission in Manifest. - Ask READ_MEDIA_IMAGES permission to the user.
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.
onActivityResult take persistable permission of the result Uri
if (resultCode == RESULT_OK) { getContentResolver().takePersistableUriPermission(uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION); }
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.
来源:https://stackoverflow.com/questions/55314476/how-to-rename-a-file-in-android-knowing-only-its-media-content-uri