Android: ¿Cómo obtener un URI de archivo de un URI de contenido?

En mi aplicación, el usuario debe seleccionar un archivo de audio que luego la aplicación maneja. El problema es que para que la aplicación haga lo que quiero que haga con los archivos de audio, necesito que el URI esté en formato de archivo. Cuando uso el reproductor de música nativo de Android para buscar el archivo de audio en la aplicación, el URI es un URI de contenido, que se ve así:

content://media/external/audio/media/710 

Sin embargo, usando la popular aplicación de administración de archivos Astro, obtengo lo siguiente:

 file:///sdcard/media/audio/ringtones/GetupGetOut.mp3 

Este último es mucho más accesible para mí, pero, por supuesto, quiero que la aplicación tenga funcionalidad con el archivo de audio que el usuario elija independientemente del progtwig que utilice para explorar su colección. Entonces mi pregunta es, ¿hay alguna manera de convertir el content:// URI de estilo en un file:// URI? De lo contrario, ¿qué me recomendarías para resolver este problema? Aquí está el código que llama al selector, para referencia:

 Intent ringIntent = new Intent(); ringIntent.setType("audio/mp3"); ringIntent.setAction(Intent.ACTION_GET_CONTENT); ringIntent.addCategory(Intent.CATEGORY_OPENABLE); startActivityForResult(Intent.createChooser(ringIntent, "Select Ringtone"), SELECT_RINGTONE); 

Hago lo siguiente con el URI de contenido:

 m_ringerPath = m_ringtoneUri.getPath(); File file = new File(m_ringerPath); 

Luego haga algo de FileInputStream con dicho archivo.

Simplemente use getContentResolver().openInputStream(uri) para obtener un InputStream desde un URI.

http://developer.android.com/reference/android/content/ContentResolver.html#openInputStream(android.net.Uri)

Puede usar Content Resolver para obtener una ruta de file:// desde el content:// URI:

 String filePath = null; Uri _uri = data.getData(); Log.d("","URI = "+ _uri); if (_uri != null && "content".equals(_uri.getScheme())) { Cursor cursor = this.getContentResolver().query(_uri, new String[] { android.provider.MediaStore.Images.ImageColumns.DATA }, null, null, null); cursor.moveToFirst(); filePath = cursor.getString(0); cursor.close(); } else { filePath = _uri.getPath(); } Log.d("","Chosen path = "+ filePath); 

Intentar manejar el URI con contenido: // esquema llamando a ContentResolver.query() no es una buena solución. En HTC Desire ejecutando 4.2.2 puede obtener NULL como resultado de la consulta.

¿Por qué no usar ContentResolver en su lugar? https://stackoverflow.com/a/29141800/3205334

Si tiene un contenido Uri con content://com.externalstorage... puede usar este método para obtener la ruta absoluta de una carpeta o archivo en Android 19 o superior .

 public static String getPath(final Context context, final Uri uri) { final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; // DocumentProvider if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) { System.out.println("getPath() uri: " + uri.toString()); System.out.println("getPath() uri authority: " + uri.getAuthority()); System.out.println("getPath() uri path: " + uri.getPath()); // ExternalStorageProvider if ("com.android.externalstorage.documents".equals(uri.getAuthority())) { final String docId = DocumentsContract.getDocumentId(uri); final String[] split = docId.split(":"); final String type = split[0]; System.out.println("getPath() docId: " + docId + ", split: " + split.length + ", type: " + type); // This is for checking Main Memory if ("primary".equalsIgnoreCase(type)) { if (split.length > 1) { return Environment.getExternalStorageDirectory() + "/" + split[1] + "/"; } else { return Environment.getExternalStorageDirectory() + "/"; } // This is for checking SD Card } else { return "storage" + "/" + docId.replace(":", "/"); } } } return null; } 

Puede verificar que cada parte de Uri esté usando println. Los valores devueltos para mi tarjeta SD y la memoria principal del dispositivo se enumeran a continuación. Puede acceder y eliminar si el archivo está en la memoria, pero no pude eliminar el archivo de la tarjeta SD con este método, solo leí o abrí la imagen usando esta ruta absoluta. Si ha encontrado una solución para eliminar utilizando este método, por favor comparta. TARJETA SD

 getPath() uri: content://com.android.externalstorage.documents/tree/612E-B7BF%3A/document/612E-B7BF%3A getPath() uri authority: com.android.externalstorage.documents getPath() uri path: /tree/612E-B7BF:/document/612E-B7BF: getPath() docId: 612E-B7BF:, split: 1, type: 612E-B7BF 

MEMORIA PRINCIPAL

 getPath() uri: content://com.android.externalstorage.documents/tree/primary%3A/document/primary%3A getPath() uri authority: com.android.externalstorage.documents getPath() uri path: /tree/primary:/document/primary: getPath() docId: primary:, split: 1, type: primary 

Si desea obtener Uri con el file:/// después de obtener el uso de la ruta

 DocumentFile documentFile = DocumentFile.fromFile(new File(path)); documentFile.getUri() // will return a Uri with file Uri 

Bueno, estoy un poco tarde para responder, pero mi código está probado

verifique el esquema de uri:

  byte[] videoBytes; if (uri.getScheme().equals("content")){ InputStream iStream = context.getContentResolver().openInputStream(uri); videoBytes = getBytes(iStream); }else{ File file = new File(uri.getPath()); FileInputStream fileInputStream = new FileInputStream(file); videoBytes = getBytes(fileInputStream); } 

En la respuesta anterior, convertí el video uri a array de bytes, pero eso no está relacionado con la pregunta, simplemente copié mi código completo para mostrar el uso de FileInputStream y InputStream ya que ambos funcionan igual en mi código.

Usé el contexto variable que es getActivity () en mi Fragmento y en Activity simplemente es ActivityName.this

context=getActivity(); // en Fragmento

context=ActivityName.this; // en actividad

Deberías usar getContentResolver().openInputStream(uri) para obtener un InputStream desde un URI. Porque es muy fácil y fácil de entender. Para obtener más openInputStream(android.net.Uri)