Obtener contenido uri de la ruta del archivo en android

271

Sé la ruta absoluta de una imagen (por ejemplo, /sdcard/cats.jpg). ¿Hay alguna forma de obtener la uri de contenido para este archivo?

En realidad, en mi código, descargo una imagen y la guardo en una ubicación en particular. Para configurar la imagen en una instancia de ImageView, actualmente abro el archivo usando la ruta, obtengo los bytes y creo un mapa de bits y luego establezco el mapa de bits en la instancia de ImageView. Este es un proceso muy lento, en cambio, si pudiera obtener el contenido uri, podría usar el método muy fácilmente imageView.setImageUri(uri)

pankajagarwal
fuente
23
Uri uri = Uri.parse ("archivo: ///sdcard/img.png");
Anand Tiwari
13
+1 al comentario, solo Uri.parse ("file: //" + filePath) debería ser el truco
German Latorre
Uri.Parse se deprecia y "se agregará"
pollaris
@pollaris Uri.parse se agregó en la API 1 y no está marcado como obsoleto.
JP de la Torre
Uri.parse ("algo"); no funciona en mí, no puedo encontrar la razón por la que ...
Bay

Respuestas:

480

Probar con:

ImageView.setImageURI(Uri.fromFile(new File("/sdcard/cats.jpg")));

O con:

ImageView.setImageURI(Uri.parse(new File("/sdcard/cats.jpg").toString()));
Francesco Laurita
fuente
3
¡Gracias! el segundo método funciona bien en 1.6, 2.1 y 2.2 pero el primero solo en 2.2
mishkin
28
ninguno de esos métodos resuelve una ruta de archivo a un URI de contenido. Sin embargo, entiendo que resolvió el problema inmediato.
Jeffrey Blattman el
38
No codifique "/ sdcard /"; use Environment.getExternalStorageDirectory (). getPath () en su lugar
ekatz
8
Esto es lo que devuelve las dos soluciones anteriores: 1. archivo: ///storage/emulated/0/DCIM/Camera/VID_20140312_171146.mp4 2. /storage/emulated/0/DCIM/Camera/VID_20140312_171146.mp4 Pero lo que estaba buscando porque es algo diferente. Necesito el contenido: // formato URI. La respuesta de Jinal parece funcionar perfectamente
Ajith Memana
55
oye Uri.fromFile, no funcionará en Android 26+, debes usar el proveedor de archivos
vuhung3990
85

ACTUALIZAR

Aquí se supone que sus medios (Imagen / Video) ya están agregados al proveedor de medios de contenido. Si no es así, no podrá obtener la URL del contenido como exactamente lo que desea. En cambio habrá un archivo Uri.

Tenía la misma pregunta para mi actividad de explorador de archivos. Debe saber que el contenido para archivos solo admite datos de almacenamiento de medios como imagen, audio y video. Le estoy dando el código para obtener el contenido de la imagen uri seleccionando una imagen de sdcard. Prueba este código, tal vez te funcione ...

public static Uri getImageContentUri(Context context, File imageFile) {
  String filePath = imageFile.getAbsolutePath();
  Cursor cursor = context.getContentResolver().query(
      MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
      new String[] { MediaStore.Images.Media._ID },
      MediaStore.Images.Media.DATA + "=? ",
      new String[] { filePath }, null);
  if (cursor != null && cursor.moveToFirst()) {
    int id = cursor.getInt(cursor.getColumnIndex(MediaStore.MediaColumns._ID));
    cursor.close();
    return Uri.withAppendedPath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "" + id);
  } else {
    if (imageFile.exists()) {
      ContentValues values = new ContentValues();
      values.put(MediaStore.Images.Media.DATA, filePath);
      return context.getContentResolver().insert(
          MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
    } else {
      return null;
    }
  }
}
Jinal Jogiyani
fuente
Estaba buscando un método para encontrar el contenido: // URI de mi archivo de video grabado y el código anterior parece funcionar perfectamente en Nexus 4 (Android 4.3). Sería bueno si puede explicar el código.
Ajith Memana
He intentado esto para obtener el Uri de contenido para un archivo con la ruta absoluta "/ sdcard / Image Depo / picture.png". No funcionó, así que depuré la ruta del código y descubrí que el Cursor está vacío, y cuando la entrada se agrega a ContentProvider, se da nulo como Content Uri. Por favor ayuda.
Sri Krishna
1
Tengo la ruta del archivo: file: ///storage/emulated/0/Android/data/com.packagename/files/out.mp4, pero se vuelve nulo cuando intento obtener contentUri. También he intentado cambiar MediaStore.Images.Mediaa MediaStore.Video.Media, pero aún ninguna suerte.
Narendra Singh
1
Esto no funciona en Android Pie api 28. El cursor devuelve nulo
Ibrahim Gharyali
1
¿Puedes actualizar este método para Android 10 ya que la columna DATOS no está accesible en Android 10?
Khushbu Shah
16

// Este código funciona para imágenes en 2.2, no estoy seguro si hay otros tipos de medios

   //Your file path - Example here is "/sdcard/cats.jpg"
   final String filePathThis = imagePaths.get(position).toString();

   MediaScannerConnectionClient mediaScannerClient = new
   MediaScannerConnectionClient() {
    private MediaScannerConnection msc = null;
    {
        msc = new MediaScannerConnection(getApplicationContext(), this);
        msc.connect();
    }

    public void onMediaScannerConnected(){
        msc.scanFile(filePathThis, null);
    }


    public void onScanCompleted(String path, Uri uri) {
        //This is where you get your content uri
            Log.d(TAG, uri.toString());
        msc.disconnect();
    }
   };
AndroidDebaser
fuente
1
genial, me ayudó a compartir en Google+, ya que esa aplicación requiere una transmisión de medios con un contenido Uri: la ruta absoluta no funciona.
Ridcully
1
¡Excelente! Puedo confirmar que esto también funciona con los tipos de medios de audio.
Matt M
16

La solución aceptada es probablemente la mejor opción para sus propósitos, pero para responder realmente la pregunta en la línea de asunto:

En mi aplicación, tengo que obtener el camino de los URI y obtener el URI de los caminos. El primero:

/**
 * Gets the corresponding path to a file from the given content:// URI
 * @param selectedVideoUri The content:// URI to find the file path from
 * @param contentResolver The content resolver to use to perform the query.
 * @return the file path as a string
 */
private String getFilePathFromContentUri(Uri selectedVideoUri,
        ContentResolver contentResolver) {
    String filePath;
    String[] filePathColumn = {MediaColumns.DATA};

    Cursor cursor = contentResolver.query(selectedVideoUri, filePathColumn, null, null, null);
    cursor.moveToFirst();

    int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
    filePath = cursor.getString(columnIndex);
    cursor.close();
    return filePath;
}

El último (que hago para videos, pero también se puede usar para Audio o Archivos u otros tipos de contenido almacenado sustituyendo MediaStore.Audio (etc.) por MediaStore.Video):

/**
 * Gets the MediaStore video ID of a given file on external storage
 * @param filePath The path (on external storage) of the file to resolve the ID of
 * @param contentResolver The content resolver to use to perform the query.
 * @return the video ID as a long
 */
private long getVideoIdFromFilePath(String filePath,
        ContentResolver contentResolver) {


    long videoId;
    Log.d(TAG,"Loading file " + filePath);

            // This returns us content://media/external/videos/media (or something like that)
            // I pass in "external" because that's the MediaStore's name for the external
            // storage on my device (the other possibility is "internal")
    Uri videosUri = MediaStore.Video.Media.getContentUri("external");

    Log.d(TAG,"videosUri = " + videosUri.toString());

    String[] projection = {MediaStore.Video.VideoColumns._ID};

    // TODO This will break if we have no matching item in the MediaStore.
    Cursor cursor = contentResolver.query(videosUri, projection, MediaStore.Video.VideoColumns.DATA + " LIKE ?", new String[] { filePath }, null);
    cursor.moveToFirst();

    int columnIndex = cursor.getColumnIndex(projection[0]);
    videoId = cursor.getLong(columnIndex);

    Log.d(TAG,"Video ID is " + videoId);
    cursor.close();
    return videoId;
}

Básicamente, la DATAcolumna de MediaStore(o la subsección que esté consultando) almacena la ruta del archivo, por lo que utiliza esa información para buscarla.

Jon O
fuente
No siempre es el caso, hay dos columnas semi-garantizadas devueltas, y eso es OpenableColumns.DISPLAY_NAME & OpenableColumns.SIZEsi la aplicación de envío incluso sigue las "reglas". Descubrí que algunas aplicaciones importantes solo devuelven estos dos campos y no siempre el _datacampo. En el caso de que no tenga el campo de datos que normalmente contiene una ruta directa al contenido, primero debe leer el contenido y escribirlo en un archivo o en la memoria y luego tiene su propia ruta.
Pierre
7

Puede usar estas dos formas según el uso

Uri uri = Uri.parse("String file location");

o

Uri uri = Uri.fromFile(new File("string file location"));

He intentado en ambos sentidos y ambos trabajos.

Abhishek Meharia
fuente
5

La forma más fácil y sólida de crear Content Uri content://desde un archivo es usar FileProvider . El Uri proporcionado por FileProvider también se puede usar para proporcionar archivos Uri para compartir archivos con otras aplicaciones. Para obtener File Uri desde una ruta absoluta Filepuede usar DocumentFile.fromFile (nuevo Archivo (ruta, nombre)), se agrega en la Api 22 y devuelve nulo para las versiones a continuación.

File imagePath = new File(Context.getFilesDir(), "images");
File newFile = new File(imagePath, "default_image.jpg");
Uri contentUri = getUriForFile(getContext(), "com.mydomain.fileprovider", newFile);
Tracio
fuente
4

Es tarde, pero puede ayudar a alguien en el futuro.

Para obtener el URI de contenido para un archivo, puede usar el siguiente método:

FileProvider.getUriForFile(Context context, String authority, File file)

Devuelve el contenido URI.

Mira esto para aprender cómo configurar un FileProvider

artenson.art98
fuente
2

Obtención de la ID del archivo sin escribir ningún código, solo con los comandos de la CLI adb shell:

adb shell content query --uri "content://media/external/video/media" | grep FILE_NAME | grep -Eo " _id=([0-9]+)," | grep -Eo "[0-9]+"
BogdanBiv
fuente
Google "adb obtiene una ruta real desde el contenido uri" y esta pregunta es la primera, con el contenido de su respuesta de 0 votos en el resumen de resultados de búsqueda. Déjame ser el primero en votar. ¡Gracias hermano!
Fin de semana
Esto es genial Pero parece que obtendrá: a Permission Denial: Do not have permission in call getContentProviderExternal() from pid=15660, uid=10113 requires android.permission.ACCESS_CONTENT_PROVIDERS_EXTERNALLYmenos que esté rooteado.
not2qubit
Entonces, ¿esto necesita acceso raíz del teléfono?
Samintha Kaveesh
1

Es mejor usar una validación para admitir versiones anteriores a Android N, por ejemplo:

  if (Build.VERSION.SDK_INT >=  Build.VERSION_CODES.N) {
     imageUri = Uri.parse(filepath);
  } else{
     imageUri = Uri.fromFile(new File(filepath));
  }

  if (Build.VERSION.SDK_INT >=  Build.VERSION_CODES.N) {
     ImageView.setImageURI(Uri.parse(new File("/sdcard/cats.jpg").toString()));         
  } else{
     ImageView.setImageURI(Uri.fromFile(new File("/sdcard/cats.jpg")));
  }

https://es.stackoverflow.com/questions/71443/reporte-crash-android-os-fileuriexposedexception-en-android-n

Jorgesys
fuente
0

U puede intentar debajo del fragmento de código

    public Uri getUri(ContentResolver cr, String path){
    Uri mediaUri = MediaStore.Files.getContentUri(VOLUME_NAME);
    Cursor ca = cr.query(mediaUri, new String[] { MediaStore.MediaColumns._ID }, MediaStore.MediaColumns.DATA + "=?", new String[] {path}, null);
    if (ca != null && ca.moveToFirst()) {
        int id = ca.getInt(ca.getColumnIndex(MediaStore.MediaColumns._ID));
        ca.close();
        return  MediaStore.Files.getContentUri(VOLUME_NAME,id);
    }
    if(ca != null) {
        ca.close();
    }
    return null;
}
caopeng
fuente
1
¿Qué es VOLUME_NAME?
Evgenii Vorobei
Es "externo" o "interno"
caopeng