Android SAF(Storage Access FrameWork): Obtenga un archivo particular Uri de TreeUri
file-io android-sdcard (1)
Estoy tomando la tarjeta PersistableUriPermission de la tarjeta SD externa y la estoy almacenando para su uso posterior. Ahora quiero que cuando el usuario me proporcione la ruta del archivo, de la lista de archivos en mi aplicación, quiero editar el documento y cambiarle el nombre.
Así que tengo la ruta del archivo para editar.
Mi pregunta es cómo obtengo el Uri de ese archivo de mi TreeUri para editarlo.
Acceder a los archivos de la tarjeta SD
Use el cuadro de diálogo
DOCUMENT_TREE
para obtener el
Uri
la tarjeta SD.
Informe al usuario sobre cómo elegir
sd-card
en el cuadro de diálogo.
(con fotos o animaciones gif)
// call for document tree dialog
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
startActivityForResult(intent, REQUEST_CODE_OPEN_DOCUMENT_TREE);
En
onActivityResult
tendrás el directorio
Uri
seleccionado.
(sdCardUri)
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case REQUEST_CODE_OPEN_DOCUMENT_TREE:
if (resultCode == Activity.RESULT_OK) {
sdCardUri = data.getData();
}
break;
}
}
Ahora debe verificar si el usuario,
a. seleccionó la tarjeta sd
si. seleccionó la tarjeta SD en la que está nuestro archivo (algunos dispositivos pueden tener varias tarjetas SD).
Verificamos a y b buscando el archivo a través de la jerarquía, desde la raíz sd hasta nuestro archivo. Si se encuentra el archivo, se adquieren las condiciones ayb.
//First we get `DocumentFile` from the `TreeUri` which in our case is `sdCardUri`.
DocumentFile documentFile = DocumentFile.fromTreeUri(this, sdCardUri);
//Then we split file path into array of strings.
//ex: parts:{"", "storage", "extSdCard", "MyFolder", "MyFolder", "myImage.jpg"}
// There is a reason for having two similar names "MyFolder" in
//my exmple file path to show you similarity in names in a path will not
//distract our hiarchy search that is provided below.
String[] parts = (file.getPath()).split("///");
// findFile method will search documentFile for the first file
// with the expected `DisplayName`
// We skip first three items because we are already on it.(sdCardUri = /storage/extSdCard)
for (int i = 3; i < parts.length; i++) {
if (documentFile != null) {
documentFile = documentFile.findFile(parts[i]);
}
}
if (documentFile == null) {
// File not found on tree search
// User selected a wrong directory as the sd-card
// Here must inform user about how to get the correct sd-card
// and invoke file chooser dialog again.
} else {
// File found on sd-card and it is a correct sd-card directory
// save this path as a root for sd-card on your database(SQLite, XML, txt,...)
// Now do whatever you like to do with documentFile.
// Here I do deletion to provide an example.
if (documentFile.delete()) {// if delete file succeed
// Remove information related to your media from ContentResolver,
// which documentFile.delete() didn''t do the trick for me.
// Must do it otherwise you will end up with showing an empty
// ImageView if you are getting your URLs from MediaStore.
//
Uri mediaContentUri = ContentUris.withAppendedId(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
longMediaId);
getContentResolver().delete(mediaContentUri , null, null);
}
}
Nota:
Debe proporcionar permiso de acceso al almacenamiento externo dentro de su manifiesto y para os> = Marshmallow dentro de la aplicación. https://.com/a/32175771/2123400
Editar los archivos de la tarjeta SD
Para editar una imagen existente en su tarjeta SD, no necesita ninguno de los pasos anteriores si desea invocar otra aplicación para que lo haga por usted.
Aquí invocamos todas las actividades (de todas las aplicaciones instaladas) con la capacidad de editar las imágenes. (Los programadores marcan sus aplicaciones en el manifiesto por sus capacidades para proporcionar accesibilidad desde otras aplicaciones (actividades)).
en su evento editButton click:
String mimeType = getMimeTypeFromMediaContentUri(mediaContentUri);
startActivityForResult(Intent.createChooser(new Intent(Intent.ACTION_EDIT).setDataAndType(mediaContentUri, mimeType).putExtra(Intent.EXTRA_STREAM, mediaContentUri).addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION), "Edit"), REQUEST_CODE_SHARE_EDIT_SET_AS_INTENT);
y así es como se obtiene mimeType:
public String getMimeTypeFromMediaContentUri(Uri uri) {
String mimeType;
if (uri.getScheme().equals(ContentResolver.SCHEME_CONTENT)) {
ContentResolver cr = getContentResolver();
mimeType = cr.getType(uri);
} else {
String fileExtension = MimeTypeMap.getFileExtensionFromUrl(uri
.toString());
mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(
fileExtension.toLowerCase());
}
return mimeType;
}
Nota:
En Android KitKat (4.4) no le pida al usuario que seleccione la tarjeta SD porque en esta versión de Android
DocumentProvider
no es aplicable, por lo tanto, no tenemos oportunidad de tener acceso a la tarjeta SD con este enfoque.
Mire el nivel de API para
DocumentProvider
https://developer.android.com/reference/android/provider/DocumentsProvider.html
No pude encontrar nada que funcione en Android KitKat (4.4).
Si encuentra algo útil con KitKat, comparta con nosotros.
En las versiones debajo de KitKat, el sistema operativo ya proporciona acceso a la tarjeta SD.