Obtenga el nombre de archivo y la ruta del URI del almacén de medios

390

Tengo un onActivityResultretorno de una selección de imágenes de mediastore que puedo obtener un URI para una imagen usando lo siguiente:

Uri selectedImage = data.getData();

Convertir esto en una cadena da esto:

content://media/external/images/media/47

O a un camino da:

/external/images/media/47

Sin embargo, parece que no puedo encontrar una manera de convertir esto en una ruta absoluta, ya que quiero cargar la imagen en un mapa de bits sin tener que copiarla en alguna parte. Sé que esto se puede hacer usando el URI y el solucionador de contenido, pero parece que esto no funciona al reiniciar el teléfono, supongo MediaStoreque no mantiene su numeración igual entre los reinicios.

Stealthcopter
fuente
API 19 y superior, la solución está aquí, stackoverflow.com/a/51227392/9815519 . Espero que esto les pueda ayudar.
Hasib Akter

Respuestas:

609

Debajo de la API 19, use este código para obtener la Ruta del archivo desde el URI:

public String getRealPathFromURI(Context context, Uri contentUri) {
  Cursor cursor = null;
  try { 
    String[] proj = { MediaStore.Images.Media.DATA };
    cursor = context.getContentResolver().query(contentUri,  proj, null, null, null);
    int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
    cursor.moveToFirst();
    return cursor.getString(column_index);
  } finally {
    if (cursor != null) {
      cursor.close();
    }
  }
}
Miša Peić
fuente
65
En lugar de managedQuery (.........) (en desuso) puede usar getContentResolver (). Query (.....) con los mismos parámetros. Buen trabajo
Pablo Johnson
44
En la versión más reciente de Android (KitKat) esto da un error: la cadena de ruta es nula.
Christopher Masser
17
como Christopher señala: esto no es compatible con 4.4+. Consulte esta pregunta para obtener más información: stackoverflow.com/questions/20067508/…
ılǝ
13
No funciona. El cursor es nulo. Y no estoy en Android 4.4+, estoy en 4.1.2.
matteo
11
Probado en 5 dispositivos. Da nulo a todos excepto a Android 4.1.2. En todos los androides más nuevos devuelve nulo.
Tina
127

Solo una simple actualización de la primera respuesta: mActivity.managedQuery()ahora está en desuso. He actualizado el código con el nuevo método.

private String getRealPathFromURI(Uri contentUri) {
    String[] proj = { MediaStore.Images.Media.DATA };
    CursorLoader loader = new CursorLoader(mContext, contentUri, proj, null, null, null);
    Cursor cursor = loader.loadInBackground();
    int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
    cursor.moveToFirst();
    String result = cursor.getString(column_index);
    cursor.close();
    return result;
}

fuente de desarrollo de Android

Sebastiano
fuente
3
@dextor: Esto no funcionó para mí. Funciona cuando hago clic en un archivo en un explorador de archivos, pero cuando hago clic en un archivo adjunto de correo electrónico, todavía obtengo el mensaje content://.... Intenté todas las sugerencias aquí sin suerte. ¿Alguna idea de por qué?
Luis A. Florit
@Luis yo también tengo el mismo problema
Linkandzelda
1
@dextor necesita cerrar el cursor.
etherton
Puede ayudarle en esto: stackoverflow.com/questions/27103529/...
Chlebta
@dextor Probé esta solución, no funcionó, probablemente algo cambió mientras tanto. Sin embargo, la solución de Paul Burke de esta pregunta stackoverflow.com/questions/20067508/… funcionó.
AndyZ
111

Para Oreo

Uri uri = data.getData(); 
File file = new File(uri.getPath());//create path from uri
final String[] split = file.getPath().split(":");//split the path.
filePath = split[1];//assign it to a string(your choice).

Para todas las versiones debajo de Oreo, he hecho este método que obtiene una ruta real desde uri

 @SuppressLint("NewApi")
    public static String getFilePath(Context context, Uri uri) throws URISyntaxException {
        String selection = null;
        String[] selectionArgs = null;
        // Uri is different in versions after KITKAT (Android 4.4), we need to
        if (Build.VERSION.SDK_INT >= 19 && DocumentsContract.isDocumentUri(context.getApplicationContext(), uri)) {
            if (isExternalStorageDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                return Environment.getExternalStorageDirectory() + "/" + split[1];
            } else if (isDownloadsDocument(uri)) {
                final String id = DocumentsContract.getDocumentId(uri);
                uri = ContentUris.withAppendedId(
                        Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
            } else if (isMediaDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];
                if ("image".equals(type)) {
                    uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                } else if ("video".equals(type)) {
                    uri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
                } else if ("audio".equals(type)) {
                    uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
                }
                selection = "_id=?";
                selectionArgs = new String[]{
                        split[1]
                };
            }
        }
        if ("content".equalsIgnoreCase(uri.getScheme())) {


          if (isGooglePhotosUri(uri)) {
              return uri.getLastPathSegment();
           }

            String[] projection = {
                    MediaStore.Images.Media.DATA
            };
            Cursor cursor = null;
            try {
                cursor = context.getContentResolver()
                        .query(uri, projection, selection, selectionArgs, null);
                int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
                if (cursor.moveToFirst()) {
                    return cursor.getString(column_index);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else if ("file".equalsIgnoreCase(uri.getScheme())) {
            return uri.getPath();
        }
        return null;
    }

    public static boolean isExternalStorageDocument(Uri uri) {
        return "com.android.externalstorage.documents".equals(uri.getAuthority());
    }

    public static boolean isDownloadsDocument(Uri uri) {
        return "com.android.providers.downloads.documents".equals(uri.getAuthority());
    }

    public static boolean isMediaDocument(Uri uri) {
        return "com.android.providers.media.documents".equals(uri.getAuthority());
    }

  public static boolean isGooglePhotosUri(Uri uri) {
    return "com.google.android.apps.photos.content".equals(uri.getAuthority());
}
Jitendra ramoliya
fuente
77
esa es la única versión que funciona a la perfección en cada tipo de Uri - debería ser la respuesta principal ..
Matthew Fisher
66
Este código funciona si el usuario no ha seleccionado el archivo de la tarjeta SD. Si el usuario ha seleccionado el archivo de la tarjeta SD, la ruta devuelta es, por ejemplo, / almacenamiento / emulado / 0 / filePath aunque el archivo se encuentre en / storage / sdCard / filePath
adi9090
¿Hay alguna solución para resolver este problema @ adi9090? Estoy atrapado en este problema durante casi 2 días :(
Ali Nawaz
2
así se puede probar algunos biblioteca como selector de material para Android url: github.com/nbsp-team/MaterialFilePicker esto puede tomar más de u más cerca de la solución todavía estoy en él si u obtener cualquier solución amablemente que lo ponga a continuación ..
Ali Nawaz
44
Tampoco funciona: java.lang.UnsupportedOperationException: Contenido de Uri no admitido: //com.android.externalstorage.documents/tree/primary%3ADCIM%2FCamera ... por qué el equipo de Android hizo la vida tan difícil
Leon
97

No intentes encontrar una uri en el sistema de archivos, es lento para buscar cosas en la base de datos.

Puede obtener un mapa de bits de una uri dando un flujo de entrada a la fábrica como si le entregara un archivo a la fábrica:

InputStream is = getContentResolver().openInputStream(uri);
Bitmap bitmap = BitmapFactory.decodeStream(is);
is.close();
mig
fuente
55
En realidad, esta es la única respuesta correcta. A nadie realmente le importa el nombre del archivo. Lo que necesitamos es el contenido. El archivo real puede estar en la carpeta privada de la aplicación, en internet, sqlite o ser puramente virtual y generado sobre la marcha.
durilka
18
La pregunta específica que se hace es el nombre del archivo y la ruta. Sí, el OP está buscando derivar un mapa de bits del archivo, pero eso no es cierto para todos los que buscan la ruta. A veces necesitamos el contenido real del archivo.
Huperniketes
3
@durilka, un ejemplo: si el archivo es un video y desea una miniatura, la función "ThumbnailUtils.createVideoThumbnail" solo se puede llamar con una ruta de tipo String, no acepta ningún tipo de inputStreams.
ElYeante
1
Primero verificaría si el proveedor de contenido para videos proporciona miniaturas junto con metadatos. Android se trata de "no lo implemente usted mismo si alguien ya lo hizo". Realmente me asusta cómo cada aplicación ambiciosa intenta crear su propia captura de fotos.
durilka
44
Acaba de introducir un camino que conduce al error
OutOfMemory
39

Aquí está mi ejemplo de cómo obtener el nombre del archivo, de URI como file: // ... y content: // .... Me funciona no solo con Android MediaStore sino también con aplicaciones de terceros como EzExplorer.

public static String getFileNameByUri(Context context, Uri uri)
{
    String fileName="unknown";//default fileName
    Uri filePathUri = uri;
    if (uri.getScheme().toString().compareTo("content")==0)
    {      
        Cursor cursor = context.getContentResolver().query(uri, null, null, null, null);
        if (cursor.moveToFirst())
        {
            int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);//Instead of "MediaStore.Images.Media.DATA" can be used "_data"
            filePathUri = Uri.parse(cursor.getString(column_index));
            fileName = filePathUri.getLastPathSegment().toString();
        }
    }
    else if (uri.getScheme().compareTo("file")==0)
    {
        fileName = filePathUri.getLastPathSegment().toString();
    }
    else
    {
        fileName = fileName+"_"+filePathUri.getLastPathSegment();
    }
    return fileName;
}
Nikolay Nikiforchuk
fuente
44
¿Puede esto convertir entre file: // y content: // URIs y viceversa? Intenté incluir el código en mi proyecto, pero dice que ApplicationObject no se puede resolver.
user280109
55
Es un problema con ApplicationObject, ¿me puede dar un código?
Nikolay Nikiforchuk
oh, está bien, no te preocupes, encontré otro código de ejemplo que funcionó, saludos.
user280109
2
Esta merece ser la mejor respuesta, es más completa y resolvió un problema que tuve.
Andreas Rudolph el
¿Por qué llama a getLastPathSegment (). ToString () cuando getLastPathSegment () ya devuelve una cadena?
droid8421
15

Buenas respuestas existentes, algunas de las cuales solía tener las mías:

Tengo que obtener la ruta de los URI y obtener el URI de las rutas, y Google tiene dificultades para distinguir la diferencia, por lo que para cualquier persona que tenga el mismo problema (por ejemplo, para obtener la miniatura MediaStorede un video cuya ubicación física ya tiene ) 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 al sustituir 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 puede usar lo que sabe para buscar ese DATAcampo o usar el campo para buscar lo que quiera.

Luego utilizo lo Schemeanterior para descubrir qué hacer con mis datos:

 private boolean  getSelectedVideo(Intent imageReturnedIntent, boolean fromData) {

    Uri selectedVideoUri;

    //Selected image returned from another activity
            // A parameter I pass myself to know whether or not I'm being "shared via" or
            // whether I'm working internally to my app (fromData = working internally)
    if(fromData){
        selectedVideoUri = imageReturnedIntent.getData();
    } else {
        //Selected image returned from SEND intent 
                    // which I register to receive in my manifest
                    // (so people can "share via" my app)
        selectedVideoUri = (Uri)getIntent().getExtras().get(Intent.EXTRA_STREAM);
    }

    Log.d(TAG,"SelectedVideoUri = " + selectedVideoUri);

    String filePath;

    String scheme = selectedVideoUri.getScheme(); 
    ContentResolver contentResolver = getContentResolver();
    long videoId;

    // If we are sent file://something or content://org.openintents.filemanager/mimetype/something...
    if(scheme.equals("file") || (scheme.equals("content") && selectedVideoUri.getEncodedAuthority().equals("org.openintents.filemanager"))){

        // Get the path
        filePath = selectedVideoUri.getPath();

        // Trim the path if necessary
        // openintents filemanager returns content://org.openintents.filemanager/mimetype//mnt/sdcard/xxxx.mp4
        if(filePath.startsWith("/mimetype/")){
            String trimmedFilePath = filePath.substring("/mimetype/".length());
            filePath = trimmedFilePath.substring(trimmedFilePath.indexOf("/"));
        }

        // Get the video ID from the path
        videoId = getVideoIdFromFilePath(filePath, contentResolver);

    } else if(scheme.equals("content")){

        // If we are given another content:// URI, look it up in the media provider
        videoId = Long.valueOf(selectedVideoUri.getLastPathSegment());
        filePath = getFilePathFromContentUri(selectedVideoUri, contentResolver);

    } else {
        Log.d(TAG,"Failed to load URI " + selectedVideoUri.toString());
        return false;
    }

     return true;
 }
Jon O
fuente
11

Ninguna de estas respuestas me funcionó en todos los casos. Tuve que ir directamente a la documentación de Google https://developer.android.com/guide/topics/providers/document-provider.html sobre este tema y encontré este método útil:

private Bitmap getBitmapFromUri(Uri uri) throws IOException {
    ParcelFileDescriptor parcelFileDescriptor =
    getContentResolver().openFileDescriptor(uri, "r");
    FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
    Bitmap image = BitmapFactory.decodeFileDescriptor(fileDescriptor);
    parcelFileDescriptor.close();
    return image;
}

Puede usar este mapa de bits para mostrarlo en una Vista de imagen.

Yamil
fuente
7

API 19 y superior , la ruta del archivo de imagen de Uri funciona perfectamente. También reviso esta última PIE API 28 .

public String getImageFilePath(Uri uri) {
    String path = null, image_id = null;

    Cursor cursor = getContentResolver().query(uri, null, null, null, null);
    if (cursor != null) {
        cursor.moveToFirst();
        image_id = cursor.getString(0);
        image_id = image_id.substring(image_id.lastIndexOf(":") + 1);
        cursor.close();
    }

    Cursor cursor = getContentResolver().query(android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI, null, MediaStore.Images.Media._ID + " = ? ", new String[]{image_id}, null);
    if (cursor!=null) {
        cursor.moveToFirst();
        path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
        cursor.close();
    }
    return path;
}
Hasib Akter
fuente
3
En primer lugar, ha inicializado el cursor dos veces. En segundo lugar, este código arroja CursorIndexOutOfBoundsException: Index 0 requested, with a size of 0en esta línea:path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
Harshil Pansare
Estoy usando Oreo stock android y no funciona en él por alguna razón
Harshil Pansare
cómo conseguir pdf Ruta del archivo de URI ¿me pueden ayudar
@HarshilPansare, ¿cómo lo hiciste funcionar para Android Oreo? Estoy atrapado en eso por 2 días.
Kashish Malhotra
Esto no funciona si el elemento seleccionado no es una imagen
Mustansir
5

intente esto obtener la ruta del archivo de imagen de Uri

public void getImageFilePath(Context context, Uri uri) {

    Cursor cursor = context.getContentResolver().query(uri, null, null, null, null);
    cursor.moveToFirst();
    String image_id = cursor.getString(0);
    image_id = image_id.substring(image_id.lastIndexOf(":") + 1);
    cursor.close();
    cursor = context.getContentResolver().query(android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI, null, MediaStore.Images.Media._ID + " = ? ", new String[]{image_id}, null);
    cursor.moveToFirst();
    String path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
    cursor.close();
    upLoadImageOrLogo(path);
}
Shiv Kumar
fuente
4

Solución para aquellos que tienen problemas después de mudarse a KitKat:

"Esto obtendrá la ruta del archivo de MediaProvider, DownloadsProvider y ExternalStorageProvider, mientras recurre al método no oficial ContentProvider" https://stackoverflow.com/a/20559175/690777

peter.bartos
fuente
parece la respuesta perfecta
AndroidPlayer2
3

Después de obtener una imagen de la galería, simplemente pase el URI en el siguiente método solo para Android 4.4 (KitKat):

public String getPath(Uri contentUri) {// Will return "image:x*"

    String wholeID = DocumentsContract.getDocumentId(contentUri);

    // Split at colon, use second item in the array
    String id = wholeID.split(":")[1];

    String[] column = { MediaStore.Images.Media.DATA };

    // Where id is equal to
    String sel = MediaStore.Images.Media._ID + "=?";

    Cursor cursor = getContentResolver().query(
            MediaStore.Images.Media.EXTERNAL_CONTENT_URI, column, sel,
            new String[] { id }, null);

    String filePath = "";

    int columnIndex = cursor.getColumnIndex(column[0]);

    if (cursor.moveToFirst()) {
        filePath = cursor.getString(columnIndex);
    }

    cursor.close();
    return filePath;
}
sharma_kunal
fuente
Este es el único que funcionó para mí. Quería algo de la galería. ¿Tiene un método de trabajo para debajo de Kitkat? @sharma_kunai
Sr. Codealot
3

Prueba esto

Aún así, si tiene el problema para obtener el camino real, puede probar mis respuestas. Las respuestas anteriores no me ayudaron.

Explicación : - Este método obtiene el URI y luego verifica el nivel de API de su dispositivo Android después de eso, de acuerdo con el nivel de API, generará la ruta Real. El código para generar el método de ruta real es diferente según los niveles de API.

  1. método para obtener la ruta Real desde URI

    @SuppressLint("ObsoleteSdkInt")
    public String getPathFromURI(Uri uri){
        String realPath="";
    // SDK < API11
        if (Build.VERSION.SDK_INT < 11) {
            String[] proj = { MediaStore.Images.Media.DATA };
            @SuppressLint("Recycle") Cursor cursor = getContentResolver().query(uri, proj, null, null, null);
            int column_index = 0;
            String result="";
            if (cursor != null) {
                column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
                realPath=cursor.getString(column_index);
            }
        }
        // SDK >= 11 && SDK < 19
        else if (Build.VERSION.SDK_INT < 19){
            String[] proj = { MediaStore.Images.Media.DATA };
            CursorLoader cursorLoader = new CursorLoader(this, uri, proj, null, null, null);
            Cursor cursor = cursorLoader.loadInBackground();
            if(cursor != null){
                int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
                cursor.moveToFirst();
                realPath = cursor.getString(column_index);
            }
        }
        // SDK > 19 (Android 4.4)
        else{
            String wholeID = DocumentsContract.getDocumentId(uri);
            // Split at colon, use second item in the array
            String id = wholeID.split(":")[1];
            String[] column = { MediaStore.Images.Media.DATA };
            // where id is equal to
            String sel = MediaStore.Images.Media._ID + "=?";
            Cursor cursor = getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, column, sel, new String[]{ id }, null);
            int columnIndex = 0;
            if (cursor != null) {
                columnIndex = cursor.getColumnIndex(column[0]);
                if (cursor.moveToFirst()) {
                    realPath = cursor.getString(columnIndex);
                }
                cursor.close();
            }
        }
        return realPath;
     }
  2. Usa este método así

    Log.e(TAG, "getRealPathFromURI: "+getPathFromURI(your_selected_uri) );

Salida:-

04-06 12: 39: 46.993 6138-6138 / com.app.qtm E / tag: getRealPathFromURI: /storage/emulated/0/Video/avengers_infinity_war_4k_8k-7680x4320.jpg

Sunil
fuente
1
Mi dispositivo físico con API nivel 25 devuelve EXCEPCIÓN FATAL con el comando String wholeID = DocumentsContract.getDocumentId(uri);que obtengo:java.lang.RuntimeException: Failure delivering result
Aliton Oliveira
3

He hecho así:

    Uri queryUri = MediaStore.Files.getContentUri("external");
    String columnData = MediaStore.Files.FileColumns.DATA;
    String columnSize = MediaStore.Files.FileColumns.SIZE;

    String[] projectionData = {MediaStore.Files.FileColumns.DATA};


    String name = null;
    String size = null;

    Cursor cursor = getContentResolver().query(contentURI, null, null, null, null);
    if ((cursor != null)&&(cursor.getCount()>0)) {
        int nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
        int sizeIndex = cursor.getColumnIndex(OpenableColumns.SIZE);

        cursor.moveToFirst();

        name = cursor.getString(nameIndex);
        size = cursor.getString(sizeIndex);

        cursor.close();
    }

    if ((name!=null)&&(size!=null)){
        String selectionNS = columnData + " LIKE '%" + name + "' AND " +columnSize + "='" + size +"'";

        Cursor cursorLike = getContentResolver().query(queryUri, projectionData, selectionNS, null, null);

        if ((cursorLike != null)&&(cursorLike.getCount()>0)) {
            cursorLike.moveToFirst();
            int indexData = cursorLike.getColumnIndex(columnData);
            if (cursorLike.getString(indexData) != null) {
                result = cursorLike.getString(indexData);
            }
            cursorLike.close();
        }
    }

    return result;
user7590744
fuente
2

Dado que managedQuery ha quedado en desuso, puede intentar:

CursorLoader cursorLoader = new CursorLoader(context, uri, proj, null, null, null);
Cursor cursor = cursorLoader.loadInBackground();
lokoko
fuente
2

Aquí voy a mostrarle cómo crear un botón NAVEGAR, que cuando haga clic, abrirá la tarjeta SD, seleccionará un Archivo y, como resultado, obtendrá el nombre y la ruta del archivo seleccionado uno:

Un botón que golpearás

browse.setOnClickListener(new OnClickListener()
{
    public void onClick(View v)
    {
        Intent intent = new Intent();
        intent.setAction(Intent.ACTION_PICK);
        Uri startDir = Uri.fromFile(new File("/sdcard"));
        startActivityForResult(intent, PICK_REQUEST_CODE);
    }
});

La función que obtendrá el nombre del archivo resultante y la ruta del archivo

protected void onActivityResult(int requestCode, int resultCode, Intent intent)
{
    if (requestCode == PICK_REQUEST_CODE)
    {
        if (resultCode == RESULT_OK)
        {
            Uri uri = intent.getData();

            if (uri.getScheme().toString().compareTo("content")==0)
            {
                Cursor cursor =getContentResolver().query(uri, null, null, null, null);
                if (cursor.moveToFirst())
                {
                    int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);//Instead of "MediaStore.Images.Media.DATA" can be used "_data"
                    Uri filePathUri = Uri.parse(cursor.getString(column_index));
                    String file_name = filePathUri.getLastPathSegment().toString();
                    String file_path=filePathUri.getPath();
                    Toast.makeText(this,"File Name & PATH are:"+file_name+"\n"+file_path, Toast.LENGTH_LONG).show();
                }
            }
        }
    }
}
Pir Fahim Shah
fuente
Seguí las sugerencias aquí, y no funcionó. Cuando hago clic en un archivo adjunto de cliente de correo electrónico K9, obtengo content://com.fsck.k9.attachmentprovider/34fc2cc9-aa46-45e9-9e3f-2f27f0457249/1‌​/VIEW. Después de aplicar los métodos aquí, sigo obteniendo la misma cadena, no la ruta correcta, es decir /mnt/sdcard/Android/data/com.fsck.k9/files/34fc2cc9-aa46-45e9-9e3f-2f27f0457249‌​.db_att/1. ¿Alguna pista?
Luis A. Florit
2

¿De alguna manera para Android Q anterior , cuando MediaStore.Images.Media.DATA ya no estará disponible? Este campo se deprecia en Android Q:

Esta constante quedó en desuso en el nivel 29 de la API. Es posible que las aplicaciones no tengan permisos del sistema de archivos para acceder directamente a esta ruta. En lugar de intentar abrir esta ruta directamente, las aplicaciones deben usar ContentResolver # openFileDescriptor (Uri, String) para obtener acceso.

https://developer.android.com/reference/android/provider/MediaStore.MediaColumns.html#DATA

--- Editado

Por lo que sé para el pasado Android Q, la única forma es retransmitir en RELATIVE_PATH

Ruta relativa de este elemento multimedia dentro del dispositivo de almacenamiento donde se conserva. Por ejemplo, un artículo almacenado en /storage/0000-0000/DCIM/Vacation/IMG1024.JPG tendría una ruta de DCIM / Vacation /.

https://developer.android.com/reference/android/provider/MediaStore.MediaColumns.html#RELATIVE_PATH

Malaquiasz
fuente
¿Todos los archivos en Android Q tienen una ruta relativa o necesitamos agregarlos, como si el archivo ya está presente en el dispositivo, su ruta relativa estará disponible?
1234567
1
@ 1234567 según la descripción en el enlace, si lo pasa como nulo, el sistema lo configurará correctamente. Si el archivo ya está presente, el escáner de medios debe agregar el campo.
Malachiasz
necesita Android Q como API de destino y quizás active el almacenamiento con alcance
Malachiasz
1

Versión ligeramente modificada de @PercyPercy: no se lanza y solo devuelve nulo si algo sale mal :

public String getPathFromMediaUri(Context context, Uri uri) {
    String result = null;

    String[] projection = { MediaStore.Images.Media.DATA };
    Cursor cursor = context.getContentResolver().query(uri, projection, null, null, null);
    int col = cursor.getColumnIndex(MediaStore.Images.Media.DATA);
    if (col >= 0 && cursor.moveToFirst())
        result = cursor.getString(col);
    cursor.close();

    return result;
}
sberezin
fuente
1

Aquí obtienes el nombre del archivo

String[] projection = {MediaStore.MediaColumns.DISPLAY_NAME};
                    Uri uri = data.getData();
                    String fileName = null;
                    ContentResolver cr = getActivity().getApplicationContext().getContentResolver();

                    Cursor metaCursor = cr.query(uri,
                            projection, null, null, null);
                    if (metaCursor != null) {
                        try {
                            if (metaCursor.moveToFirst()) {
                                fileName = metaCursor.getString(0);
                            }
                        } finally {
                            metaCursor.close();
                        }
                    }
Copo de nieve
fuente
Probablemente no sea tan útil para el operador ya que estaba buscando la ruta absoluta (no solo el nombre del archivo) ... pero seguro que ME ayudó a comprender el proceso.
Mystic Cola
1

Simple y fácil. ¡Puedes hacer esto desde el URI como se muestra a continuación!

public void getContents(Uri uri)
{
    Cursor vidCursor = getActivity.getContentResolver().query(uri, null, null,
                                                              null, null);
    if (vidCursor.moveToFirst())
    {
        int column_index =
        vidCursor .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
        Uri filePathUri = Uri.parse(vidCursor .getString(column_index));
        String video_name =  filePathUri.getLastPathSegment().toString();
        String file_path=filePathUri.getPath();
        Log.i("TAG", video_name + "\b" file_path);
    }
}
Nowshad
fuente
1

Esta solución funciona para cada caso:

Es demasiado difícil en algunos casos obtener la ruta desde la URL. Entonces, ¿por qué necesitas el camino? Para copiar el archivo en otro lugar? No necesitas el camino.

public void SavePhotoUri (Uri imageuri, String Filename){

    File FilePath = context.getDir(Environment.DIRECTORY_PICTURES,Context.MODE_PRIVATE);
    try {
        Bitmap selectedImage = MediaStore.Images.Media.getBitmap(context.getContentResolver(), imageuri);
        String destinationImagePath = FilePath + "/" + Filename;
        FileOutputStream destination = new FileOutputStream(destinationImagePath);
        selectedImage.compress(Bitmap.CompressFormat.JPEG, 100, destination);
        destination.close();
    }
    catch (Exception e) {
        Log.e("error", e.toString());
    }
}
toni
fuente
0

Perfectamente trabajando para mí código fijo de esta publicación :

  public static String getRealPathImageFromUri(Uri uri) {
        String fileName =null;
        if (uri.getScheme().equals("content")) {
            try (Cursor cursor = MyApplication.getInstance().getContentResolver().query(uri, null, null, null, null)) {
                if (cursor.moveToFirst()) {
                    fileName = cursor.getString(cursor.getColumnIndexOrThrow(ediaStore.Images.Media.DATA));
                }
            } catch (IllegalArgumentException e) {
                Log.e(mTag, "Get path failed", e);
            }
        }
        return fileName;
    }
Serg Burlaka
fuente
0

Como complemento, si necesita ver si existe un archivo antes de intentar abrir una secuencia de entrada, puede usar DocumentsContract.

(Código de Kotlin)

var iStream = null
if(DocumentsContract.isDocumentUri(context,myUri)) {
   val pfd: ParcelFileDescriptor? = context.contentResolver.openFileDescriptor(
            myUri, "r") ?: return null
   iStream = ParcelFileDescriptor.AutoCloseInputStream(pfd)
}
johnml1135
fuente
0

Como las respuestas anteriores no funcionaron para mí, aquí está la solución que funcionó para mí:

Para ambos> 19 y <= 19 niveles de API.

Este método cubre todos los casos para obtener filePath desde uri

/**
 * Get a file path from a Uri. This will get the the path for Storage Access
 * Framework Documents, as well as the _data field for the MediaStore and
 * other file-based ContentProviders.
 *
 * @param context The activity.
 * @param uri The Uri to query.
 * @author paulburke
 */
public static String getPath(final Context context, final Uri uri) {

    // DocumentProvider
    if ( Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && DocumentsContract.isDocumentUri(context, uri)) {
        // ExternalStorageProvider
        if (isExternalStorageDocument(uri)) {
            final String docId = DocumentsContract.getDocumentId(uri);
            final String[] split = docId.split(":");
            final String type = split[0];

            if ("primary".equalsIgnoreCase(type)) {
                return Environment.getExternalStorageDirectory() + "/" + split[1];
            }else{
                Toast.makeText(context, "Could not get file path. Please try again", Toast.LENGTH_SHORT).show();
            }
        }
        // DownloadsProvider
        else if (isDownloadsDocument(uri)) {

            final String id = DocumentsContract.getDocumentId(uri);
            final Uri contentUri = ContentUris.withAppendedId(
                    Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));

            return getDataColumn(context, contentUri, null, null);
        }
        // MediaProvider
        else if (isMediaDocument(uri)) {
            final String docId = DocumentsContract.getDocumentId(uri);
            final String[] split = docId.split(":");
            final String type = split[0];

            Uri contentUri = null;
            if ("image".equals(type)) {
                contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
            } else if ("video".equals(type)) {
                contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
            } else if ("audio".equals(type)) {
                contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
            } else {
                contentUri = MediaStore.Files.getContentUri("external");
            }

            final String selection = "_id=?";
            final String[] selectionArgs = new String[] {
                    split[1]
            };

            return getDataColumn(context, contentUri, selection, selectionArgs);
        }
    }
    // MediaStore (and general)
    else if ("content".equalsIgnoreCase(uri.getScheme())) {
        return getDataColumn(context, uri, null, null);
    }
    // File
    else if ("file".equalsIgnoreCase(uri.getScheme())) {
        return uri.getPath();
    }

    return null;
}
Harshil Pansare
fuente
0

Para obtener cualquier tipo de ruta de archivo, use esto:

/*
 * Copyright (C) 2007-2008 OpenIntents.org
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.yourpackage;

import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.util.Log;
import android.webkit.MimeTypeMap;

import java.io.File;
import java.io.FileFilter;
import java.text.DecimalFormat;
import java.util.Comparator;
import java.util.List;

/**
 * @author Peli
 * @author paulburke (ipaulpro)
 * @version 2013-12-11
 */
public class FileUtils {
    private FileUtils() {
    } //private constructor to enforce Singleton pattern

    /**
     * TAG for log messages.
     */
    static final String TAG = "FileUtils";
    private static final boolean DEBUG = true; // Set to true to enable logging

    public static final String MIME_TYPE_AUDIO = "audio/*";
    public static final String MIME_TYPE_TEXT = "text/*";
    public static final String MIME_TYPE_IMAGE = "image/*";
    public static final String MIME_TYPE_VIDEO = "video/*";
    public static final String MIME_TYPE_APP = "application/*";

    public static final String HIDDEN_PREFIX = ".";

    /**
     * Gets the extension of a file name, like ".png" or ".jpg".
     *
     * @param uri
     * @return Extension including the dot("."); "" if there is no extension;
     * null if uri was null.
     */
    public static String getExtension(String uri) {
        if (uri == null) {
            return null;
        }

        int dot = uri.lastIndexOf(".");
        if (dot >= 0) {
            return uri.substring(dot);
        } else {
            // No extension.
            return "";
        }
    }

    /**
     * @return Whether the URI is a local one.
     */
    public static boolean isLocal(String url) {
        if (url != null && !url.startsWith("http://") && !url.startsWith("https://")) {
            return true;
        }
        return false;
    }

    /**
     * @return True if Uri is a MediaStore Uri.
     * @author paulburke
     */
    public static boolean isMediaUri(Uri uri) {
        return "media".equalsIgnoreCase(uri.getAuthority());
    }

    /**
     * Convert File into Uri.
     *
     * @param file
     * @return uri
     */
    public static Uri getUri(File file) {
        if (file != null) {
            return Uri.fromFile(file);
        }
        return null;
    }

    /**
     * Returns the path only (without file name).
     *
     * @param file
     * @return
     */
    public static File getPathWithoutFilename(File file) {
        if (file != null) {
            if (file.isDirectory()) {
                // no file to be split off. Return everything
                return file;
            } else {
                String filename = file.getName();
                String filepath = file.getAbsolutePath();

                // Construct path without file name.
                String pathwithoutname = filepath.substring(0,
                        filepath.length() - filename.length());
                if (pathwithoutname.endsWith("/")) {
                    pathwithoutname = pathwithoutname.substring(0, pathwithoutname.length() - 1);
                }
                return new File(pathwithoutname);
            }
        }
        return null;
    }

    /**
     * @return The MIME type for the given file.
     */
    public static String getMimeType(File file) {

        String extension = getExtension(file.getName());

        if (extension.length() > 0)
            return MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension.substring(1));

        return "application/octet-stream";
    }

    /**
     * @return The MIME type for the give Uri.
     */
    public static String getMimeType(Context context, Uri uri) {
        File file = new File(getPath(context, uri));
        return getMimeType(file);
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is {@link LocalStorageProvider}.
     * @author paulburke
     */
    public static boolean isLocalStorageDocument(Uri uri) {
        return LocalStorageProvider.AUTHORITY.equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is ExternalStorageProvider.
     * @author paulburke
     */
    public static boolean isExternalStorageDocument(Uri uri) {
        return "com.android.externalstorage.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is DownloadsProvider.
     * @author paulburke
     */
    public static boolean isDownloadsDocument(Uri uri) {
        return "com.android.providers.downloads.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is MediaProvider.
     * @author paulburke
     */
    public static boolean isMediaDocument(Uri uri) {
        return "com.android.providers.media.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is Google Photos.
     */
    public static boolean isGooglePhotosUri(Uri uri) {
        return "com.google.android.apps.photos.content".equals(uri.getAuthority());
    }

    /**
     * Get the value of the data column for this Uri. This is useful for
     * MediaStore Uris, and other file-based ContentProviders.
     *
     * @param context       The context.
     * @param uri           The Uri to query.
     * @param selection     (Optional) Filter used in the query.
     * @param selectionArgs (Optional) Selection arguments used in the query.
     * @return The value of the _data column, which is typically a file path.
     * @author paulburke
     */
    public static String getDataColumn(Context context, Uri uri, String selection,
                                       String[] selectionArgs) {

        Cursor cursor = null;
        final String column = "_data";
        final String[] projection = {
                column
        };

        try {
            cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
                    null);
            if (cursor != null && cursor.moveToFirst()) {
                if (DEBUG)
                    DatabaseUtils.dumpCursor(cursor);

                final int column_index = cursor.getColumnIndexOrThrow(column);
                return cursor.getString(column_index);
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if (cursor != null)
                cursor.close();
        }
        return null;
    }

    /**
     * Get a file path from a Uri. This will quickGet the the path for Storage Access
     * Framework Documents, as well as the _data field for the MediaStore and
     * other file-based ContentProviders.<br>
     * <br>
     * Callers should check whether the path is local before assuming it
     * represents a local file.
     *
     * @param context The context.
     * @param uri     The Uri to query.
     * @author paulburke
     * @see #isLocal(String)
     * @see #getFile(Context, Uri)
     */
    public static String getPath(final Context context, final Uri uri) {

        if (DEBUG)
            Log.d(TAG + " File -",
                    "Authority: " + uri.getAuthority() +
                            ", Fragment: " + uri.getFragment() +
                            ", Port: " + uri.getPort() +
                            ", Query: " + uri.getQuery() +
                            ", Scheme: " + uri.getScheme() +
                            ", Host: " + uri.getHost() +
                            ", Segments: " + uri.getPathSegments().toString()
            );
        // DocumentProvider
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && DocumentsContract.isDocumentUri(context, uri)) {
            // LocalStorageProvider
            if (isLocalStorageDocument(uri)) {
                // The path is the id
                return DocumentsContract.getDocumentId(uri);
            }
            // ExternalStorageProvider
            else if (isExternalStorageDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];

//                if ("primary".equalsIgnoreCase(type)) {
//                    return Environment.getExternalStorageDirectory() + "/" + split[1];
//                }
                return Environment.getExternalStorageDirectory() + "/" + split[1];

                // TODO handle non-primary volumes
            }
            // DownloadsProvider
            else if (isDownloadsDocument(uri)) {
                try {
                    final String id = DocumentsContract.getDocumentId(uri);
                    Log.d(TAG, "getPath: id= " + id);
                    final Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
                    return getDataColumn(context, contentUri, null, null);
                }catch (Exception e){
                    e.printStackTrace();
                    List<String> segments = uri.getPathSegments();
                    if(segments.size() > 1) {
                        String rawPath = segments.get(1);
                        if(!rawPath.startsWith("/")){
                            return rawPath.substring(rawPath.indexOf("/"));
                        }else {
                            return rawPath;
                        }
                    }
                }
            }
            // MediaProvider
            else if (isMediaDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];

                Uri contentUri = null;
                if ("image".equals(type)) {
                    contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                } else if ("video".equals(type)) {
                    contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
                } else if ("audio".equals(type)) {
                    contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
                }

                final String selection = "_id=?";
                final String[] selectionArgs = new String[]{
                        split[1]
                };

                return getDataColumn(context, contentUri, selection, selectionArgs);
            }
        }
        // MediaStore (and general)
        else if ("content".equalsIgnoreCase(uri.getScheme())) {

            // Return the remote address
            if (isGooglePhotosUri(uri))
                return uri.getLastPathSegment();

            return getDataColumn(context, uri, null, null);
        }
        // File
        else if ("file".equalsIgnoreCase(uri.getScheme())) {
            return uri.getPath();
        }

        return null;
    }

    /**
     * Convert Uri into File, if possible.
     *
     * @return file A local file that the Uri was pointing to, or null if the
     * Uri is unsupported or pointed to a remote resource.
     * @author paulburke
     * @see #getPath(Context, Uri)
     */
    public static File getFile(Context context, Uri uri) {
        if (uri != null) {
            String path = getPath(context, uri);
            if (path != null && isLocal(path)) {
                return new File(path);
            }
        }
        return null;
    }

    /**
     * Get the file size in a human-readable string.
     *
     * @param size
     * @return
     * @author paulburke
     */
    public static String getReadableFileSize(int size) {
        final int BYTES_IN_KILOBYTES = 1024;
        final DecimalFormat dec = new DecimalFormat("###.#");
        final String KILOBYTES = " KB";
        final String MEGABYTES = " MB";
        final String GIGABYTES = " GB";
        float fileSize = 0;
        String suffix = KILOBYTES;

        if (size > BYTES_IN_KILOBYTES) {
            fileSize = size / BYTES_IN_KILOBYTES;
            if (fileSize > BYTES_IN_KILOBYTES) {
                fileSize = fileSize / BYTES_IN_KILOBYTES;
                if (fileSize > BYTES_IN_KILOBYTES) {
                    fileSize = fileSize / BYTES_IN_KILOBYTES;
                    suffix = GIGABYTES;
                } else {
                    suffix = MEGABYTES;
                }
            }
        }
        return String.valueOf(dec.format(fileSize) + suffix);
    }

    /**
     * Attempt to retrieve the thumbnail of given File from the MediaStore. This
     * should not be called on the UI thread.
     *
     * @param context
     * @param file
     * @return
     * @author paulburke
     */
    public static Bitmap getThumbnail(Context context, File file) {
        return getThumbnail(context, getUri(file), getMimeType(file));
    }

    /**
     * Attempt to retrieve the thumbnail of given Uri from the MediaStore. This
     * should not be called on the UI thread.
     *
     * @param context
     * @param uri
     * @return
     * @author paulburke
     */
    public static Bitmap getThumbnail(Context context, Uri uri) {
        return getThumbnail(context, uri, getMimeType(context, uri));
    }

    /**
     * Attempt to retrieve the thumbnail of given Uri from the MediaStore. This
     * should not be called on the UI thread.
     *
     * @param context
     * @param uri
     * @param mimeType
     * @return
     * @author paulburke
     */
    public static Bitmap getThumbnail(Context context, Uri uri, String mimeType) {
        if (DEBUG)
            Log.d(TAG, "Attempting to quickGet thumbnail");

        if (!isMediaUri(uri)) {
            Log.e(TAG, "You can only retrieve thumbnails for images and videos.");
            return null;
        }

        Bitmap bm = null;
        if (uri != null) {
            final ContentResolver resolver = context.getContentResolver();
            Cursor cursor = null;
            try {
                cursor = resolver.query(uri, null, null, null, null);
                if (cursor.moveToFirst()) {
                    final int id = cursor.getInt(0);
                    if (DEBUG)
                        Log.d(TAG, "Got thumb ID: " + id);

                    if (mimeType.contains("video")) {
                        bm = MediaStore.Video.Thumbnails.getThumbnail(
                                resolver,
                                id,
                                MediaStore.Video.Thumbnails.MINI_KIND,
                                null);
                    } else if (mimeType.contains(FileUtils.MIME_TYPE_IMAGE)) {
                        bm = MediaStore.Images.Thumbnails.getThumbnail(
                                resolver,
                                id,
                                MediaStore.Images.Thumbnails.MINI_KIND,
                                null);
                    }
                }
            } catch (Exception e) {
                if (DEBUG)
                    Log.e(TAG, "getThumbnail", e);
            } finally {
                if (cursor != null)
                    cursor.close();
            }
        }
        return bm;
    }

    /**
     * File and folder comparator. TODO Expose sorting option method
     *
     * @author paulburke
     */
    public static Comparator<File> sComparator = new Comparator<File>() {
        @Override
        public int compare(File f1, File f2) {
            // Sort alphabetically by lower case, which is much cleaner
            return f1.getName().toLowerCase().compareTo(
                    f2.getName().toLowerCase());
        }
    };

    /**
     * File (not directories) filter.
     *
     * @author paulburke
     */
    public static FileFilter sFileFilter = new FileFilter() {
        @Override
        public boolean accept(File file) {
            final String fileName = file.getName();
            // Return files only (not directories) and skip hidden files
            return file.isFile() && !fileName.startsWith(HIDDEN_PREFIX);
        }
    };

    /**
     * Folder (directories) filter.
     *
     * @author paulburke
     */
    public static FileFilter sDirFilter = new FileFilter() {
        @Override
        public boolean accept(File file) {
            final String fileName = file.getName();
            // Return directories only and skip hidden directories
            return file.isDirectory() && !fileName.startsWith(HIDDEN_PREFIX);
        }
    };

    /**
     * Get the Intent for selecting content to be used in an Intent Chooser.
     *
     * @return The intent for opening a file with Intent.createChooser()
     * @author paulburke
     */
    public static Intent createGetContentIntent() {
        // Implicitly allow the user to select a particular kind of data
        final Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
        // The MIME data type filter
        intent.setType("*/*");
        // Only return URIs that can be opened with ContentResolver
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        return intent;
    }
}
Sajid2067
fuente
no puede resolver LocalStorageProvider
Zain
¡Finalmente, un método que funciona! (de este código acabo de eliminar el LocalStorageProvider)
Starwave
0

Compruebe a continuación el método está funcionando increíble también Oreo 8.1 ..

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    // TODO ManualMT-generated method stub
    switch (requestCode) {
        case PICKFILE_RESULT_CODE:
            if (resultCode == RESULT_OK) {

                try {
                    FilePath = data.getData().getPath();
                    Uri selectedImageUri = data.getData();

                    if (selectedImageUri.toString().contains("storage/emulated")){
                        String[] split = selectedImageUri.toString().split("storage/");
                        FilePath = "storage/"+split[1];
                    } else {
                        FilePath = ImageFilePath.getPath(getApplicationContext(), selectedImageUri);
                    }

                    recyclerview.setVisibility(View.VISIBLE);

                    if (FilePath == null) {
                        FilePath = "";
                    }
                    File file = new File(FilePath);
                    reqFile = RequestBody.create(MediaType.parse("multipart/form-data"), file);
                    image_list.add(FilePath);
                    composeImageAdapter.notifyDataSetChanged();
                } catch (Exception e){
                    Toast.makeText(ClusterCreateNote.this , e.toString(),Toast.LENGTH_SHORT).show();
                }
            }
            break;
    }

}

Clase de ruta URI:

public static class ImageFilePath {

    /**
     * Method for return file path of Gallery image
     *
     * @param context
     * @param uri
     * @return path of the selected image file from gallery
     */
    public static String getPath(final Context context, final Uri uri) {
        String selection = null;
        String[] selectionArgs = null;

        // DocumentProvider
        if (DocumentsContract.isDocumentUri(context, uri)) {

            // ExternalStorageProvider
            if (isExternalStorageDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];

                if ("primary".equalsIgnoreCase(type)) {
                    return Environment.getExternalStorageDirectory() + "/" + split[1];
                }
            }
            // DownloadsProvider
            else if (isDownloadsDocument(uri)) {

                final String id = DocumentsContract.getDocumentId(uri);
                final Uri contentUri = ContentUris.wifAppendedId(
                        Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));

                return getDataColumn(context, contentUri, null, null);
            }
            // MediaProvider
            else if (isMediaDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];

                Log.e("typetype",type);

                Uri contentUri = null;
                if ("image".equals(type)) {
                    contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                } else if ("video".equals(type)) {
                    contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
                } else if ("audio".equals(type)) {
                    contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
                }

                selection = "_id=?";
                selectionArgs = new String[]{
                        split[1]
                };

                Log.e("gddhjf",getDataColumn(context, contentUri, selection, selectionArgs));

                return getDataColumn(context, contentUri, selection, selectionArgs);
            }
        }
        if ("content".equalsIgnoreCase(uri.getScheme())) {


            if (isGooglePhotosUri(uri)) {
                return uri.getLastPathSegment();
            }

            String[] projection = {
                    MediaStore.Images.Media.DATA
            };
            Cursor cursor = null;
            try {
                cursor = context.getContentResolver()
                        .query(uri, projection, selection, selectionArgs, null);
                int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
                if (cursor.moveToFirst()) {
                    return cursor.getString(column_index);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        // File
        else if ("file".equalsIgnoreCase(uri.getScheme())) {
            return uri.getPath();
        }

        return null;
    }


    public static String getDataColumn(Context context, Uri uri, String selection,
                                       String[] selectionArgs) {

        Cursor cursor = null;
        final String column = "_data";
        final String[] projection = {
                column
        };

        try {
            cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
                    null);
            if (cursor != null && cursor.moveToFirst()) {
                final int index = cursor.getColumnIndexOrThrow(column);
                return cursor.getString(index);
            }
        } finally {
            if (cursor != null)
                cursor.close();
        }
        return null;
    }

    public static boolean isExternalStorageDocument(Uri uri) {
        return "com.android.externalstorage.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is DownloadsProvider.
     */
    public static boolean isDownloadsDocument(Uri uri) {
        return
                "com.android.providers.downloads.documents".equals(uri.getAuthority());
    }

    public static boolean isMediaDocument(Uri uri) {
        return "com.android.providers.media.documents".equals(uri.getAuthority());
    }

    public static boolean isGooglePhotosUri(Uri uri) {
        return
                "com.google.android.apps.photos.content".equals(uri.getAuthority());
    }
}
murugan mani
fuente
1
Está utilizando la columna de datos, esto ya no funcionará.
HB.
0

Hago esto con un trazador de líneas:

val bitmap = MediaStore.Images.Media.getBitmap(contentResolver, uri)

Que en el onActivityResult se ve así:

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    if (resultCode == Activity.RESULT_OK && requestCode == REQUEST_CODE_IMAGE_PICKER ) {
        data?.data?.let { imgUri: Uri ->
            val bitmap = MediaStore.Images.Media.getBitmap(contentResolver, imgUri)
        }
    }
}
Joel Broström
fuente
Por alguna razón, este enfoque no funciona si uso la aplicación de la galería de Samsung para seleccionar una imagen
KMC
Extraño. Estaba desarrollando en un Samsung Galaxy S10.
Joel Broström
0

Las cosas se complican ahora, especialmente después del nivel de API 29 Android Q. Así es como debe obtener el nombre de archivo del contenido Uri

        public static String getNameFromContentUri(Context context, Uri contentUri){  
                            Cursor returnCursor = context.getContentResolver().query(contentUri, null, null, null, null);
                            int nameColumnIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
                            returnCursor.moveToFirst();
                            String fileName = returnCursor.getString(nameColumnIndex);
                            return fileName;}

y así es como obtienes la ruta completa de Content Uri para todas las versiones de Android

public static String getFullPathFromContentUri(final Context context, final Uri uri) {

        final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;

        // DocumentProvider
        if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
            // 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];

                if ("primary".equalsIgnoreCase(type)) {
                    return Environment.getExternalStorageDirectory() + "/" + split[1];
                }

                // TODO handle non-primary volumes
            }
            // DownloadsProvider
            else if ("com.android.providers.downloads.documents".equals(uri.getAuthority())) {

                final String id = DocumentsContract.getDocumentId(uri);
                final Uri contentUri = ContentUris.withAppendedId(
                        Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));

                return getDataColumn(context, contentUri, null, null);
            }
            // MediaProvider
            else if ("com.android.providers.media.documents".equals(uri.getAuthority())) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];

                Uri contentUri = null;
                if ("image".equals(type)) {
                    contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                } else if ("video".equals(type)) {
                    contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
                } else if ("audio".equals(type)) {
                    contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
                }

                final String selection = "_id=?";
                final String[] selectionArgs = new String[]{
                        split[1]
                };

                   Cursor cursor = null;
                   final String column = "_data";
                   final String[] projection = {
                      column
                    };

        try {
            cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
                    null);
            if (cursor != null && cursor.moveToFirst()) {
                final int column_index = cursor.getColumnIndexOrThrow(column);
                return cursor.getString(column_index);
            }
        } finally {
            if (cursor != null)
                cursor.close();
        }
        return null;
            }
        }
        // MediaStore (and general)
        else if ("content".equalsIgnoreCase(uri.getScheme())) {
            return getDataColumn(context, uri, null, null);
        }
        // File
        else if ("file".equalsIgnoreCase(uri.getScheme())) {
            return uri.getPath();
        }

        return null;
    }

private static String getDataColumn(Context context, Uri uri, String selection,
                                 String[] selectionArgs) {

        Cursor cursor = null;
        final String column = "_data";
        final String[] projection = {
                column
        };

        try {
            cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
                    null);
            if (cursor != null && cursor.moveToFirst()) {
                final int column_index = cursor.getColumnIndexOrThrow(column);
                return cursor.getString(column_index);
            }
        } finally {
            if (cursor != null)
                cursor.close();
        }
        return null;
    }
Nasib
fuente
0

Esto funciona perfectamente para mí si la versión de su sistema es superior a 19, espero que esto pueda ayudarlo.

  @TargetApi(Build.VERSION_CODES.KITKAT)
    public static String getPath(final Context context, final Uri uri) {
        final boolean isOverKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
        // DocumentProvider
        if (isOverKitKat && DocumentsContract.isDocumentUri(context, uri)) {
            // ExternalStorageProvider
            if (isExternalStorageDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];
                if ("primary".equalsIgnoreCase(type)) {
                    return Environment.getExternalStorageDirectory() + "/"
                            + split[1];
                }
            }
            // DownloadsProvider
            else if (isDownloadsDocument(uri)) {
                final String id = DocumentsContract.getDocumentId(uri);
                final Uri contentUri = ContentUris.withAppendedId(
                        Uri.parse("content://downloads/public_downloads"),
                        Long.valueOf(id));
                return getDataColumn(context, contentUri, null, null);
            }
            // MediaProvider
            else if (isMediaDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];
                Uri contentUri = null;
                if ("image".equals(type)) {
                    contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                } else if ("video".equals(type)) {
                    contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
                } else if ("audio".equals(type)) {
                    contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
                }
                final String selection = "_id=?";
                final String[] selectionArgs = new String[]{split[1]};
                return getDataColumn(context, contentUri, selection,
                        selectionArgs);
            }
        }
        // MediaStore (and general)
        else if ("content".equalsIgnoreCase(uri.getScheme())) {
            // Return the remote address
            if (isGooglePhotosUri(uri))
                return uri.getLastPathSegment();
            return getDataColumn(context, uri, null, null);
        }
        // File
        else if ("file".equalsIgnoreCase(uri.getScheme())) {
            return uri.getPath();
        }
        return null;
    }
Ciro
fuente
-2

Bitmap bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), uri);

Drastaro
fuente
Esto no proporciona una respuesta a la pregunta. Una vez que tenga suficiente reputación , podrá comentar cualquier publicación ; en su lugar, proporcione respuestas que no requieran una aclaración del autor de la pregunta . - De la opinión
ישו אוהב אותך
"Quiero cargar la imagen en un mapa de bits sin tener que copiarla en alguna parte". , creo que esta respuesta proporciona una respuesta a la pregunta!
Drastaro