Antes de KitKat (o antes de la nueva Galería) el Intent.ACTION_GET_CONTENT devuelve una URI como este

contenido://media/external/images/media/3951.

El uso de la ContentResolver y hacer para
MediaStore.Images.Media.DATA devuelve la URL del archivo.

En KitKat sin embargo la Galería devuelve un URI (a través de «el Pasado») como este:

content://com.android.proveedores.los medios de comunicación.documentos/documento/imagen:3951

¿Cómo puedo manejar esto?

  • Sacado de la manga, me gustaría encontrar la manera de utilizar el contenido que no requieren acceso directo al archivo. Por ejemplo, que Uri se debe abrir como un flujo a través de ContentResolver. Siempre he sido nervioso acerca de las aplicaciones que se supone que una content:// Uri que representa un archivo siempre se puede convertir en un File.
  • Creo que una respuesta válida es cambiar a la ContentResolver y trabajar con Uri lugar de Archivo-Url. Voy a hacer eso. También permite un mejor manejo de la no-Galería de Uris.
  • Quiero guardar una imagen en db sqlite para que yo pueda abrir más tarde, debo guardar el URI absoluta o ruta de acceso del archivo?
  • Estoy de acuerdo con su nerviosismo. 🙂 Sin embargo, tengo que ser capaz de pasar un nombre de archivo (una imagen) a código nativo. Una solución es copiar los datos obtenidos a través de un InputStream en el ContentResolver a un pre-designado lugar, por lo que tiene un conocido de nombre de archivo. Sin embargo, esto parece un despilfarro de mí. Otras sugerencias?
  • Ummm…, vuelva a escribir el código nativo para trabajar con un InputStream más de JNI? No hay tantas opciones para usted, por desgracia.
  • Eso es útil conocer. Gracias por tu respuesta. Desde entonces he descubierto que estamos ahora pasando la imagen a la de C++ en la memoria en lugar de a través de un archivo de modo que ahora podemos utilizar un InputStream en lugar de un archivo (que es grande). Sólo etiqueta EXIF de la lectura es un poco complicado y requiere de Drew Noakes’ de la biblioteca. Muchas gracias por tus comentarios.
  • hay un error reportado en córdoba sobre este tema para intentar buscador de respuesta es de trabajo
  • Pero eso sólo funciona para las imágenes, ¿qué pasa con otros tipos de medios.
  • Que los medios de comunicación que usted quiera, por favor especifique
  • Me refiero a un archivo de vídeo.
  • tagasks.com/…
  • mejor respuesta es stackoverflow.com/questions/20067508/… de Paul Burke

19 Comentarios

  1. 108

    Intente esto:

    if (Build.VERSION.SDK_INT <19){
        Intent intent = new Intent(); 
        intent.setType("image/jpeg");
        intent.setAction(Intent.ACTION_GET_CONTENT);
        startActivityForResult(Intent.createChooser(intent, getResources().getString(R.string.select_picture)),GALLERY_INTENT_CALLED);
    } else {
        Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        intent.setType("image/jpeg");
        startActivityForResult(intent, GALLERY_KITKAT_INTENT_CALLED);
    }
    
    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode != Activity.RESULT_OK) return;
        if (null == data) return;
        Uri originalUri = null;
        if (requestCode == GALLERY_INTENT_CALLED) {
            originalUri = data.getData();
        } else if (requestCode == GALLERY_KITKAT_INTENT_CALLED) {
            originalUri = data.getData();
            final int takeFlags = data.getFlags()
                    & (Intent.FLAG_GRANT_READ_URI_PERMISSION
                    | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
            //Check for the freshest data.
            getContentResolver().takePersistableUriPermission(originalUri, takeFlags);
        }
    
        loadSomeStreamAsynkTask(originalUri);
    
    }

    Probablemente necesite

    @SuppressLint(«NewApi»)

    para

    takePersistableUriPermission

    • ¿Te importaría elaborar lo que el KitKat código que está haciendo? ¿Esto requiere ningún nuevo permiso? El pre KitKat código me funciona en KitKat, también. Así que ¿por qué debería elegir utilizar un código diferente para KitKat? Gracias.
    • Mi viejo código se negó a trabajar en KitKat. Tuve que leer el manual. Bueno, que los nuevos no se requieren permisos.
    • parece que no puede obtener la ruta de nuevo sdk de uri. También es una lástima que google ha hecho este tipo de cambio, sin la debida documantation y anuncio.
    • Podría usted explicar cómo obtener la URL del archivo? Me gustaría obtener la ruta de acceso real en la sdcard. Por ejemplo, si es una imagen, me gustaría obtener este camino /storage/sdcard0/DCIM/Camera/IMG_20131118_153817_119.jpg en lugar de la Uri del documento.
    • Basada en KitKat docs (developer.android.com/about/versions/…) esto puede no ser lo que el OP necesita a menos que él hace intención de uso/editar los documentos que son propiedad de la aplicación de otro(s). Si el OP quiere una copia o hacer las cosas de una manera consistente con las versiones anteriores, la respuesta por @voytez sería más apropiado.
    • Esto no está funcionando para mí. Tengo la siguiente excepción (en la stock 4.4.2): E/AndroidRuntime(29204): Causada por: java.lang.SecurityException: Solicita banderas 0x1, pero sólo se permite 0x0
    • Este no es trabajo para mí también, originalUri = datos.getData() es siempre nulo..
    • Perfeito. Obrigado
    • si de los datos.getData() es nulo, uso: bitmap = (mapa de bits)de datos.getExtras().get(«datos»);
    • Tengo en el Samsung s7, turrón. SecurityException: No con persistencia concesiones de permisos encontrado UID 10206 y Uri 0 @ content://com.android.proveedores.los medios de comunicación.documentos/documento/imagen:958

  2. 173

    Este no requiere de permisos especiales, y trabaja con el Almacenamiento del Marco de Acceso, así como la no oficial ContentProvider patrón (ruta de acceso del archivo en _data campo).

    /**
    * 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 context.
    * @param uri The Uri to query.
    * @author paulburke
    */
    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)) {
    //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];
    }
    //TODO handle non-primary volumes
    }
    //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;
    }
    /**
    * 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.
    */
    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;
    }
    /**
    * @param uri The Uri to check.
    * @return Whether the Uri authority is ExternalStorageProvider.
    */
    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());
    }
    /**
    * @param uri The Uri to check.
    * @return Whether the Uri authority is MediaProvider.
    */
    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());
    }

    Ver un up-to-fecha de la versión de este método aquí.

    • Esto funcionó fantásticamente en un 4.4 Nexus 5 Documentos de interfaz de usuario y algunas otras pref KitKat dispositivos que utilizan el estándar de la galería de aplicaciones, gracias Pablo!
    • Gracias por esto, me ha tomado años para llegar a este momento con el sdk de 19!! Mi problema es que mi dispositivo es cómo utilizar Google drive como explorador de archivos. Si el archivo está en el dispositivo, ruta de la imagen se dieron bien, pero si el archivo se encuentra en la unidad de disco no se abre. Tal vez sólo tengo que mirar a tratar con la apertura de imágenes de google drive. La cosa es que mi aplicación está escrita para utilizar la ruta de acceso del archivo y obtener una imagen utilizando el insampling…
    • Cuando se selecciona una Unidad de archivo, se le da la espalda Authority: com.google.android.apps.docs.storage y Segments: [document, acc=1;doc=667]. No estoy seguro, pero supongamos que el doc valor es el Uri de IDENTIFICACIÓN que usted puede consultar en contra. Es probable que necesite permisos para ser configurado como se detalla en «Autorizar la aplicación en Android» aquí: developers.google.com/drive/integrate-android-ui. Por favor, actualice aquí si usted averiguar.
    • Gracias, pensé que si se optó por utilizar la Unidad con la que iba a hacer todas las descargas etc. y me acaba de dar el archivo. Como yo wan no la uso para subir. Parece extraño pero a programar para ella. Gracias de nuevo
    • Hey, hasta este momento, ha estado trabajando muy bien, muchas gracias! Hizo el Google Drive problema jamás te ordenan a cabo?
    • me estoy enfrentando el mismo problema con el Archivo de plugin el valor es el id no es el camino, puedo usar la misma solución? y dime por favor, ¿cómo llamar a este método desde el archivo de plugin de clase, es urgente para mí 🙁
    • Me gusta que el código es checkstyle compatible con otras que faltan @return en el método inicial de javadoc (y algunos otros de menor importancia cositas). Felicitaciones, señor! Tenga en cuenta que se apareció a requerir 4.4 también, así que he marcado con la anotación @TargetApi(Compilación.VERSION_CODES.KITKAT) – ah, y por último, es grato constatar que alguien distinto de mí utiliza «final» fuertemente. 🙂
    • Esta solución funciona maravillosa ! gracias por que. @RuAware me pregunto si los de Google Drive problema se ha solucionado! Me necesitaba a mí también 🙂
    • esto es absolutamente horrible! usted no debe seguir para propagar código que «los tramposos» como esta. sólo es compatible con la fuente de las aplicaciones que usted sabe que el patrón, y el punto central de todo el documento modelo de proveedor de soporte de fuentes arbitrarias
    • Gracias, bro. Ha funcionado.
    • Alguien sabe si esto funciona en Lollipop también?
    • Sí funciona en Lollipop @KickingLettuce.
    • Mediante el uso de if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) estás asumiendo que si isKitKates falso, que DocumentsContract.isDocumentUri(context, uri) no ser controlados (razonable pensar) ? si es así, entonces ¿cómo puede usted estar seguro de eso? si no, entonces ¿no debería el if (isKitKat) comprobarse en primer lugar, a continuación,if (DocumentsContract.isDocumentUri(context, uri)) ? @Paul Burke
    • Grandes respuestas, funciona en android L! Gracias 🙂
    • Solución para Google nueva aplicación de Fotos gist.github.com/alexzaitsev/75c9b36dfcffd545c676
    • Cómo conseguir pdf o un archivo de texto de google drive usando este código ?Por favor me ayuda tan pronto como sea posible
    • Para algunos de mis usuarios me estoy haciendo la ruta de acceso como nulo si el uri.getScheme() es el contenido de utilizar este código. Alguna idea de cómo solucionar este @PaulBurke, que es un gran error en la aplicación?
    • considere la posibilidad de if (a() && b()). En este caso, si una es falsa, b no será revisado por la JVM ya que no hay punto de comprobación para b — resultado ya es false.
    • Hola, si puedo utilizar el código anterior, junto con una 3ª parte de explorador de archivos, null devuelve el tiempo. Me preguntaba, es que este es de los defectos de la anterior código, o la incorrecta aplicación de 3 ª parte explorador de archivos de aplicación? Gracias – stackoverflow.com/q/34465905/72437
    • De mayo de 2016 y se sigue trabajando en la melcocha con un min de destino de la api de 15 .Gran trabajo
    • >Obtener el valor de la columna de datos para este Uri. Esto es útil para MediaStore Uris, y de otros archivos ContentProviders. ¿Cuál es el propósito de getDataColumn? ¿Qué hacer?
    • >// TODO manejar no primaria volúmenes. Funciona con almacenamiento externo como externo de tarjetas sd?
    • El _data no funciona cuando ContentProvider no lo admite. Se recomienda seguir @CommonsWare instrucciones y no utilizar la ruta completa del archivo más, porque podría ser un archivo en Dropbox en la nube en lugar de un archivo real.
    • Yo tenía esto en mi app y ahora se rompe en Android 7+ turrón dispositivos
    • Gracias Bro.. a mí me funcionó..
    • Para aquellos que están recibiendo Error Unknown URI: content://downloads/public_downloads stackoverflow.com/a/53021624/5996106

  3. 67

    Tenía el mismo problema, probé con la solución anterior, pero a pesar de que trabajó en general, por alguna razón me fue conseguir el permiso de la negación en Uri proveedor de contenido de algunas de las imágenes aunque tenía la android.permission.MANAGE_DOCUMENTS permiso ha añadido correctamente.

    De todos modos encontrado otra solución que es la fuerza de apertura de la galería de imágenes en lugar de KITKAT documentos que ver con :

    //KITKAT
    i = new Intent(Intent.ACTION_PICK,android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    startActivityForResult(i, CHOOSE_IMAGE_REQUEST);

    y, a continuación, cargar la imagen:

    Uri selectedImageURI = data.getData();
    input = c.getContentResolver().openInputStream(selectedImageURI);
    BitmapFactory.decodeStream(input , null, opts);

    EDITAR

    ACTION_OPEN_DOCUMENT puede requerir que persisten banderas etc y en general, los resultados a menudo en las Excepciones de Seguridad…

    Otra solución es el uso de la ACTION_GET_CONTENT combinado con c.getContentResolver().openInputStream(selectedImageURI) que funcionará tanto en la pre-KK y KK. Kitkat va a utilizar de nuevo la vista de documentos y, a continuación, la solución funciona con todas las aplicaciones como Fotos, Galería, Explorador de Archivos, Dropbox, Google Drive, etc…) pero recuerde que cuando se utiliza esta solución tiene que crear la imagen en su onActivityResult() y la almacenan en la Tarjeta SD, por ejemplo. Recrear esta imagen de guardado uri en el próximo inicio de la aplicación de lanzaría la Excepción de Seguridad sobre el contenido de la resolución, incluso cuando se agrega el permiso de banderas como se describe en la API de Google docs (que es lo que pasó cuando hice algunas pruebas)

    Además, el Desarrollador de Android API Directrices sugieren:

    ACTION_OPEN_DOCUMENT no pretende ser un sustituto de ACTION_GET_CONTENT. La que debe usar dependerá de las necesidades de
    de su aplicación:

    Uso ACTION_GET_CONTENT si quieres que tu aplicación para simplemente leer/importación
    de datos. Con este enfoque, la aplicación de las importaciones de una copia de los datos, tales como
    un archivo de imagen.

    Uso ACTION_OPEN_DOCUMENT si quieres que tu aplicación tiene
    a largo plazo, la persistencia de acceso a los documentos de propiedad de un documento
    proveedor de. Un ejemplo podría ser una foto en la app de edición que permite a los usuarios editar
    las imágenes almacenadas en un documento del proveedor.

    • Esta respuesta contiene el derecho de información para mis propósitos. De forma condicional mediante el ACTION_PICK y EXTERNAL_CONTENT_URI en KitKat la misma capacidad para conseguir la meta-datos acerca de las Imágenes en la galería a través de ContentResolver como es posible que en versiones anteriores utilizando simplemente ACTION_GET_CONTENT.
    • Puede que esta URI se devuelven a través de su mensaje de convertir a la plena ruta de acceso real de la imagen?
    • Yo creo que sí, debería funcionar igual que antes de KitKat como este código obliga a la apertura de la galería de imágenes en lugar de KK la vista de documentos. Pero si usted va a utilizar para crear la imagen, entonces esta solución es mejor que convertir a la ruta real es un extra innecesarios paso.
    • Trabajó también para mí, en lugar de Intent.ACTION_GET_CONTENT. De todos modos me quedé con el Intent.createChooser() contenedor en el nuevo Intent, para permitir al usuario elegir la aplicación para la navegación, y funcionó como se esperaba. Alguien puede ver los inconvenientes de esta solución?
    • Podrían aclarar si el ACTION_PICK / EXTERNAL_CONTENT_URI intención de llamar trabaja en la pre-KitKat, tales como la 4.3 (API 18)?
    • lo que si tengo que elegir un archivo de audio?
    • Para cualquier persona que está preguntando la cita proviene de developer.android.com/guide/topics/providers/…

  4. 38

    Sólo como Commonsware mencionado, no se debe asumir que la corriente se obtiene a través de ContentResolver es convertible en el archivo.

    Lo que realmente debe hacer es abrir el InputStream de la ContentProvider, a continuación, crear un mapa de bits fuera de él. Y funciona en 4.4 y versiones anteriores así, sin necesidad de reflexión.

        //cxt -> current context
    InputStream input;
    Bitmap bmp;
    try {
    input = cxt.getContentResolver().openInputStream(fileUri);
    bmp = BitmapFactory.decodeStream(input);
    } catch (FileNotFoundException e1) {
    }

    Por supuesto, si usted manejar grandes volúmenes de imágenes, usted debe cargar con la adecuada inSampleSize: http://developer.android.com/training/displaying-bitmaps/load-bitmap.html. Pero eso es otro tema.

    • Esto no está funcionando para mí con un Nexus 4 corriendo Kitkat pero con un Galaxy S3 4.1.2 ejecución
    • que parte no está funcionando? Usted obtener alguna excepción?
    • Resultó que yo estaba usando mal la intención de llamar a la galería. Yo estaba usando uno que era para cualquier tipo de documentos, pero con un filtro extensión de archivo.
    • Qué bien simple respuesta, gracias! Para otros después de esta respuesta ‘cxt’ se refiere al contexto actual y por lo general se ‘este’.
    • Gracias, voy a editar mi respuesta por lo que es claro lo que cxt es
    • Este no me funciona, me sale FileNotFoundException llamar openInputStream en un LG Nexus 5 con Android 4.4.4 en una uri como este: content://com.android.proveedores.las descargas.documentos/documento/532
    • Esto probablemente significa que el archivo no existe. La URI a la que le parece bien.
    • Muchas gracias, su trabajo, que acaba de hacer mi día .
    • Bitmap bitmap = MediaStore.Images.Media.getBitmap(getActivity().getContentResolver(), uri). ¿Qué hay de malo con esto?
    • ¿Cómo se puede utilizar esta entrada para escribir los datos EXIF de la imagen de las versiones anteriores a Android 7.1. ? En Android 7.1 ExifInterface puede utilizar inputStream pero en las versiones antes de que ExifInterface sólo toma Cadena como argumento

  5. 31

    Creo que las respuestas ya publicado debe conseguir que la gente va en la dirección correcta. Sin embargo, aquí es lo que hice ese sentido para que el código de la herencia que me estaba actualizando. El código de la herencia fue el uso de la URI de la galería para cambiar y, a continuación, guardar las imágenes.

    Antes de 4.4 (y google drive), las direcciones Uri tendría este aspecto:
    contenido://media/external/images/media/41

    Como se indica en la pregunta, que más a menudo se parecen a este:
    content://com.android.proveedores.los medios de comunicación.documentos/documento/imagen:3951

    Ya que necesitaba la capacidad para guardar imágenes y no perturbar el código ya existente, he copiado el URI de la galería en la carpeta de datos de la aplicación. A continuación, se originó un nuevo URI del archivo de imagen guardado en la carpeta de datos.

    Esta es la idea:

    Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
    intent.setType("image/*");
    startActivityForResult(intent), CHOOSE_IMAGE_REQUEST);
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    File tempFile = new File(this.getFilesDir().getAbsolutePath(), "temp_image");
    //Copy URI contents into temporary file.
    try {
    tempFile.createNewFile();
    copyAndClose(this.getContentResolver().openInputStream(data.getData()),new FileOutputStream(tempFile));
    }
    catch (IOException e) {
    //Log Error
    }
    //Now fetch the new URI
    Uri newUri = Uri.fromFile(tempFile);
    /* Use new URI object just like you used to */
    }

    Nota – copyAndClose() hace e/S de archivos para copiar InputStream en un FileOutputStream. El código no está publicado.

    • muy inteligente. yo necesitaba el real archivo de uri
    • eres mi héroe, esto es exactamente lo que yo necesitaba! funciona muy bien para archivos de Google Drive, así
    • Pensar fuera de la caja, a la derecha? 😀 Este código funciona exactamente como yo esperaba.
  6. 20

    Sólo quería decir que esta respuesta es brillante y lo estoy usando para un largo tiempo sin problemas. Pero hace algún tiempo me he tropezado con un problema que DownloadsProvider devuelve el Uri en formato content://com.android.providers.downloads.documents/document/raw%3A%2Fstorage%2Femulated%2F0%2FDownload%2Fdoc.pdf y, por tanto, de la aplicación se estrelló con NumberFormatException, ya que es imposible analizar su uri segmentos de tiempo. Pero raw: segmento contiene directo uri que puede ser utilizado para recuperar un archivo de referencia. Así que me he fijado mediante la sustitución de isDownloadsDocument(uri) if con el siguiente contenido:

    final String id = DocumentsContract.getDocumentId(uri);
    if (!TextUtils.isEmpty(id)) {
    if (id.startsWith("raw:")) {
    return id.replaceFirst("raw:", "");
    }
    try {
    final Uri contentUri = ContentUris.withAppendedId(
    Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
    return getDataColumn(context, contentUri, null, null);
    } catch (NumberFormatException e) {
    Log.e("FileUtils", "Downloads provider returned unexpected uri " + uri.toString(), e);
    return null;
    }
    }
    • Funciona perfecto! Gracias
  7. 7

    He combinar múltiples respuestas en una solución de trabajo de que los resultados con la ruta de acceso del archivo

    Tipo Mime es irrelevante para el ejemplo de propósito.

                Intent intent;
    if(Build.VERSION.SDK_INT >= 19){
    intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
    intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, false);
    intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
    }else{
    intent = new Intent(Intent.ACTION_GET_CONTENT);
    }
    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    intent.setType("application/octet-stream");
    if(isAdded()){
    startActivityForResult(intent, RESULT_CODE);
    }

    Manejo de resultado

        @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if( requestCode == RESULT_CODE && resultCode == Activity.RESULT_OK) {
    Uri uri = data.getData();
    if (uri != null && !uri.toString().isEmpty()) {
    if(Build.VERSION.SDK_INT >= 19){
    final int takeFlags = data.getFlags() & Intent.FLAG_GRANT_READ_URI_PERMISSION;
    //noinspection ResourceType
    getActivity().getContentResolver()
    .takePersistableUriPermission(uri, takeFlags);
    }
    String filePath = FilePickUtils.getSmartFilePath(getActivity(), uri);
    //do what you need with it...
    }
    }
    }

    FilePickUtils

    import android.annotation.SuppressLint;
    import android.content.ContentUris;
    import android.content.Context;
    import android.database.Cursor;
    import android.net.Uri;
    import android.os.Build;
    import android.os.Environment;
    import android.provider.DocumentsContract;
    import android.provider.MediaStore;
    public class FilePickUtils {
    private static String getPathDeprecated(Context ctx, Uri uri) {
    if( uri == null ) {
    return null;
    }
    String[] projection = { MediaStore.Images.Media.DATA };
    Cursor cursor = ctx.getContentResolver().query(uri, projection, null, null, null);
    if( cursor != null ){
    int column_index = cursor
    .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
    cursor.moveToFirst();
    return cursor.getString(column_index);
    }
    return uri.getPath();
    }
    public static String getSmartFilePath(Context ctx, Uri uri){
    if (Build.VERSION.SDK_INT < 19) {
    return getPathDeprecated(ctx, uri);
    }
    return  FilePickUtils.getPath(ctx, uri);
    }
    @SuppressLint("NewApi")
    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)) {
    //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];
    }
    //TODO handle non-primary volumes
    }
    //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 getDataColumn(context, uri, null, null);
    }
    //File
    else if ("file".equalsIgnoreCase(uri.getScheme())) {
    return uri.getPath();
    }
    return null;
    }
    /**
    * 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.
    */
    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 column_index = cursor.getColumnIndexOrThrow(column);
    return cursor.getString(column_index);
    }
    } finally {
    if (cursor != null)
    cursor.close();
    }
    return null;
    }
    /**
    * @param uri The Uri to check.
    * @return Whether the Uri authority is ExternalStorageProvider.
    */
    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());
    }
    /**
    * @param uri The Uri to check.
    * @return Whether the Uri authority is MediaProvider.
    */
    public static boolean isMediaDocument(Uri uri) {
    return "com.android.providers.media.documents".equals(uri.getAuthority());
    }
    }
    • yo estaba frente a la cuestión …. uri.getPath() volvía a uri con /externo y no regresan camino. he añadido este else if («contenido».equalsIgnoreCase(uri.getScheme())) bloque y este funciona bien, ahora .. u puede explicar qué hace
    • filePath es llegar null.. En uri: content://com.android.externalstorage.documents/document/799B-1419%3AScreenshot%2FScreenshot_20181117_162826.png
    • Tu código me salvó del horror
  8. 7

    Pregunta

    Cómo obtener un archivo ruta de acceso de un URI

    Respuesta

    A mi conocimiento, no necesitamos para obtener la ruta de acceso del archivo a partir de una URI, porque para la mayoría de los casos podemos utilizar directamente el URI para terminar nuestro trabajo (como 1. obtención de mapa de bits 2. Envío de un archivo en el servidor, etc.)

    1. Enviando al servidor

    Nos puede enviar directamente el archivo en el servidor usando el URI.

    El uso de la URI a la que podemos llegar InputStream, que podemos enviar directamente al servidor mediante MultiPartEntity.

    Ejemplo

    /**
    * Used to form Multi Entity for a URI (URI pointing to some file, which we got from other application).
    *
    * @param uri     URI.
    * @param context Context.
    * @return Multi Part Entity.
    */
    public MultipartEntity formMultiPartEntityForUri(final Uri uri, final Context context) {
    MultipartEntity multipartEntity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE, null, Charset.forName("UTF-8"));
    try {
    InputStream inputStream = mContext.getContentResolver().openInputStream(uri);
    if (inputStream != null) {
    ContentBody contentBody = new InputStreamBody(inputStream, getFileNameFromUri(uri, context));
    multipartEntity.addPart("[YOUR_KEY]", contentBody);
    }
    }
    catch (Exception exp) {
    Log.e("TAG", exp.getMessage());
    }
    return multipartEntity;
    }
    /**
    * Used to get a file name from a URI.
    *
    * @param uri     URI.
    * @param context Context.
    * @return File name from URI.
    */
    public String getFileNameFromUri(final Uri uri, final Context context) {
    String fileName = null;
    if (uri != null) {
    //Get file name.
    //File Scheme.
    if (ContentResolver.SCHEME_FILE.equals(uri.getScheme())) {
    File file = new File(uri.getPath());
    fileName = file.getName();
    }
    //Content Scheme.
    else if (ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
    Cursor returnCursor =
    context.getContentResolver().query(uri, null, null, null, null);
    if (returnCursor != null && returnCursor.moveToFirst()) {
    int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
    fileName = returnCursor.getString(nameIndex);
    returnCursor.close();
    }
    }
    }
    return fileName;
    }

    2. Obtención de un mapa de bits de un URI

    Si el URI que apunta a la imagen de a continuación, nos pondremos de mapa de bits, más null:

    /**
    * Used to create bitmap for the given URI.
    * <p>
    * 1. Convert the given URI to bitmap.
    * 2. Calculate ratio (depending on bitmap size) on how much we need to subSample the original bitmap.
    * 3. Create bitmap bitmap depending on the ration from URI.
    * 4. Reference - http://stackoverflow.com/questions/3879992/how-to-get-bitmap-from-an-uri
    *
    * @param context       Context.
    * @param uri           URI to the file.
    * @param bitmapSize Bitmap size required in PX.
    * @return Bitmap bitmap created for the given URI.
    * @throws IOException
    */
    public static Bitmap createBitmapFromUri(final Context context, Uri uri, final int bitmapSize) throws IOException {
    //1. Convert the given URI to bitmap.
    InputStream input = context.getContentResolver().openInputStream(uri);
    BitmapFactory.Options onlyBoundsOptions = new BitmapFactory.Options();
    onlyBoundsOptions.inJustDecodeBounds = true;
    onlyBoundsOptions.inDither = true;//optional
    onlyBoundsOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;//optional
    BitmapFactory.decodeStream(input, null, onlyBoundsOptions);
    input.close();
    if ((onlyBoundsOptions.outWidth == -1) || (onlyBoundsOptions.outHeight == -1)) {
    return null;
    }
    //2. Calculate ratio.
    int originalSize = (onlyBoundsOptions.outHeight > onlyBoundsOptions.outWidth) ? onlyBoundsOptions.outHeight : onlyBoundsOptions.outWidth;
    double ratio = (originalSize > bitmapSize) ? (originalSize / bitmapSize) : 1.0;
    //3. Create bitmap.
    BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
    bitmapOptions.inSampleSize = getPowerOfTwoForSampleRatio(ratio);
    bitmapOptions.inDither = true;//optional
    bitmapOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;//optional
    input = context.getContentResolver().openInputStream(uri);
    Bitmap bitmap = BitmapFactory.decodeStream(input, null, bitmapOptions);
    input.close();
    return bitmap;
    }
    /**
    * For Bitmap option inSampleSize - We need to give value in power of two.
    *
    * @param ratio Ratio to be rounded of to power of two.
    * @return Ratio rounded of to nearest power of two.
    */
    private static int getPowerOfTwoForSampleRatio(final double ratio) {
    int k = Integer.highestOneBit((int) Math.floor(ratio));
    if (k == 0) return 1;
    else return k;
    }

    Comentarios

    1. Android no proporciona ningún método para obtener la ruta de archivo de una URI, y en la mayoría de las respuestas anteriores hemos codificado algunas constantes, que se puede romper en función de liberación (lo siento, puedo estar equivocado).
    2. Antes de ir directamente a ir a una solución de la ruta de acceso del archivo a partir de una URI, probar si se puede resolver el caso de uso, con una URI y Android por defecto métodos.

    Referencia

    1. https://developer.android.com/guide/topics/providers/content-provider-basics.html
    2. https://developer.android.com/reference/android/content/ContentResolver.html
    3. https://hc.apache.org/httpcomponents-client-ga/httpmime/apidocs/org/apache/http/entity/mime/content/InputStreamBody.html
    • Gracias. El uso de la Uri y ContentResolver de esta manera simplificada mi solicitud significativamente al tratar con archivos.
  9. 3

    Para aquellos que todavía está utilizando @Paul Burke código con el SDK de Android de la versión 23 y encima, si el proyecto se conoció el error que dice que falta EXTERNAL_PERMISSION, y usted está muy seguro de que ya han añadido el usuario permiso en su AndroidManifest.xml archivo. Eso es porque usted puede en Android API 23 o superior y Google hacen que sea necesario para garantizar el permiso de nuevo mientras la acción de acceso a los archivos en tiempo de ejecución.

    Que significa: Si su versión del SDK es de 23 o superior, se le pedirá que LEA & permiso de ESCRITURA mientras selecciona el archivo de imagen y quiere saber la URI de la misma.

    Y la siguiente es mi código, además de Paul Burke solución. Agrego estos código y mi proyecto empiece a funcionar bien.

    private static final int REQUEST_EXTERNAL_STORAGE = 1;
    private static final String[] PERMISSINOS_STORAGE = {
    Manifest.permission.READ_EXTERNAL_STORAGE,
    Manifest.permission.WRITE_EXTERNAL_STORAGE
    };
    public static void verifyStoragePermissions(Activity activity) {
    int permission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE);
    if (permission != PackageManager.PERMISSION_GRANTED) {
    ActivityCompat.requestPermissions(
    activity,
    PERMISSINOS_STORAGE,
    REQUEST_EXTERNAL_STORAGE
    );
    }
    }

    Y en su actividad&fragmento de donde usted está pidiendo el URI:

    private void pickPhotoFromGallery() {
    CompatUtils.verifyStoragePermissions(this);
    Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
    intent.setType("image/*");
    //startActivityForResult(intent, REQUEST_PHOTO_LIBRARY);
    startActivityForResult(Intent.createChooser(intent, "选择照片"),
    REQUEST_PHOTO_LIBRARY);
    }

    En mi caso, CompatUtils.java es donde puedo definir el verifyStoragePermissions método (como de tipo estático, por eso la llamo dentro de otra actividad).

    También se debe tomar más sentido si se hacen una, y si el estado primero para ver si la actual versión del SDK está por encima de 23 o no antes de llamar a la verifyStoragePermissions método.

  10. 2

    Esto es lo que yo hago:

    Uri selectedImageURI = data.getData();    imageFile = new File(getRealPathFromURI(selectedImageURI)); 
    private String getRealPathFromURI(Uri contentURI) {
    Cursor cursor = getContentResolver().query(contentURI, null, null, null, null);
    if (cursor == null) { //Source is Dropbox or other similar local file path
    return contentURI.getPath();
    } else { 
    cursor.moveToFirst(); 
    int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA); 
    return cursor.getString(idx); 
    }
    }

    NOTA: managedQuery() método está en desuso, por lo que no estoy utilizando.

    Esta respuesta es de m3n0R en cuestión android conseguir el verdadero camino por Uri.getPath() y afirman que no hay crédito. Yo pensaba que la gente que no ha resuelto este problema, podrían utilizar este.

    • Esta no es una respuesta a la nueva aplicación de Galería (estrictamente «los Medios de comunicación los Documentos del Proveedor de» app) en KitKat.
    • Esto funciona bien con la aplicación de la Galería.
    • La aplicación que interrogador llama «Galería», es probablemente nuevo selector de archivos en kitkat. FYI: addictivetips.com/android/…
    • Hago similares y consiguió IndexOutOfBound en el Nexus 5, Android 6 en esta línea: cursor.getString(idx);
  11. 1

    Intenta evitar el uso de takePersistableUriPermission método porque se levantó excepción en tiempo de ejecución para mí.
    /**
    * Seleccionar de la galería.
    */

    public void selectFromGallery() {
    if (Build.VERSION.SDK_INT < AppConstants.KITKAT_API_VERSION) {
    Intent intent = new Intent(); 
    intent.setType("image/*");
    intent.setAction(Intent.ACTION_GET_CONTENT);
    ((Activity)mCalledContext).startActivityForResult(intent,AppConstants.GALLERY_INTENT_CALLED);
    } else {
    Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
    intent.setType("image/*");
    ((Activity)mCalledContext).startActivityForResult(intent, AppConstants.GALLERY_AFTER_KITKAT_INTENT_CALLED);
    }
    }

    OnActivity para el resultado para manejar los datos de la imagen:

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {

        //gallery intent result handling before kit-kat version
    if(requestCode==AppConstants.GALLERY_INTENT_CALLED 
    && resultCode == RESULT_OK) {
    Uri selectedImage = data.getData();
    String[] filePathColumn = {MediaStore.Images.Media.DATA};
    Cursor cursor = getContentResolver().query(selectedImage,filePathColumn, null, null, null);
    cursor.moveToFirst();
    int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
    String filePath = cursor.getString(columnIndex);
    cursor.close();
    photoFile = new File(filePath);
    mImgCropping.startCropImage(photoFile,AppConstants.REQUEST_IMAGE_CROP);
    }
    //gallery intent result handling after kit-kat version
    else if (requestCode == AppConstants.GALLERY_AFTER_KITKAT_INTENT_CALLED 
    && resultCode == RESULT_OK) {
    Uri selectedImage = data.getData();
    InputStream input = null;
    OutputStream output = null;
    try {
    //converting the input stream into file to crop the 
    //selected image from sd-card.
    input = getApplicationContext().getContentResolver().openInputStream(selectedImage);
    try {
    photoFile = mImgCropping.createImageFile();
    } catch (IOException e) {
    e.printStackTrace();
    }catch(Exception e) {
    e.printStackTrace();
    }
    output = new FileOutputStream(photoFile);
    int read = 0;
    byte[] bytes = new byte[1024];
    while ((read = input.read(bytes)) != -1) {
    try {
    output.write(bytes, 0, read);
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    } catch (FileNotFoundException e) {
    e.printStackTrace();
    } catch (IOException e) {
    e.printStackTrace();
    } catch (Exception e) {
    e.printStackTrace();
    }
    }
    • Donde se te muestra la imagen en el segundo caso?
    • lo siento, no pudo añadir esta línea de código en persona si mImgCropping.startCropImage(photoFile,AppConstants.REQUEST_IMAGE_CROP); de nuevo es necesario llamar a la imagecropping función como por mi necesidad de proyecto
    • ¿Qué tipo de archivo se photoFile y mImgCropping?
  12. 1

    Si alguien está interesado, he hecho un trabajo de Kotlin versión para ACTION_GET_CONTENT:

    var path: String = uri.path //uri = any content Uri
    val databaseUri: Uri
    val selection: String?
    val selectionArgs: Array<String>?
    if (path.contains("/document/image:")) { //files selected from "Documents"
    databaseUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
    selection = "_id=?"
    selectionArgs = arrayOf(DocumentsContract.getDocumentId(uri).split(":")[1])
    } else { //files selected from all other sources, especially on Samsung devices
    databaseUri = uri
    selection = null
    selectionArgs = null
    }
    try {
    val projection = arrayOf(MediaStore.Images.Media.DATA,
    MediaStore.Images.Media._ID,
    MediaStore.Images.Media.ORIENTATION,
    MediaStore.Images.Media.DATE_TAKEN) //some example data you can query
    val cursor = context.contentResolver.query(databaseUri,
    projection, selection, selectionArgs, null)
    if (cursor.moveToFirst()) {
    //do whatever you like with the data
    }
    cursor.close()
    } catch (e: Exception) {
    Log.e(TAG, e.message, e)
    }
    • excelente hombre…. Usted puede hacer el día.. gracias.
    • Sólo quiero un código de trabajo de kotlin. Es un trabajo para mí. gracias
  13. 1

    He intentado varias de las respuestas aquí, y creo que tengo una solución que funcionará cada vez y gestiona los permisos así.

    Se basa en la solución inteligente de LEO. Este post debe contener todo el código que necesitamos para hacer este trabajo, y que debería funcionar en cualquier teléfono y versión de Android 😉

    Con el fin de tener la capacidad de seleccionar un archivo desde una tarjeta SD, usted necesitará esta en su manifiesto:

    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

    Constantes:

    private static final int PICK_IMAGE = 456; //Whatever number you like
    public static final int MY_PERMISSIONS_REQUEST_READ_EXTERNAL = 28528; //Whatever number you like
    public static final String FILE_TEMP_NAME = "temp_image"; //Whatever file name you like

    De verificación de permisos y launchImagePick si es posible

    if (ContextCompat.checkSelfPermission(getThis(),
    Manifest.permission.READ_EXTERNAL_STORAGE)
    != PackageManager.PERMISSION_GRANTED) {
    ActivityCompat.requestPermissions(getThis(),
    new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
    MY_PERMISSIONS_REQUEST_READ_EXTERNAL);
    }
    else {
    launchImagePick();
    }

    Permiso respuesta

    @Override
    public void onRequestPermissionsResult(int requestCode,
    @NonNull
    String permissions[],
    @NonNull
    int[] grantResults) {
    if (manageReadExternalPermissionResponse(this, requestCode, grantResults)) {
    launchImagePick();
    }
    }

    Gestionar el permiso de respuesta

    public static boolean manageReadExternalPermissionResponse(final Activity activity, int requestCode, int[] grantResults) {
    if (requestCode == MY_PERMISSIONS_REQUEST_READ_EXTERNAL) {
    //If request is cancelled, the result arrays are empty.
    if (grantResults.length > 0
    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
    //Permission was granted, yay! Do the
    //contacts-related task you need to do.
    return true;
    } else if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_DENIED) {
    boolean showRationale = ActivityCompat.shouldShowRequestPermissionRationale(activity,
    Manifest.permission.READ_EXTERNAL_STORAGE);
    if (!showRationale) {
    //The user also CHECKED "never ask again".
    //You can either enable some fall back,
    //disable features of your app
    //or open another dialog explaining
    //again the permission and directing to
    //the app setting.
    } else {
    //The user did NOT check "never ask again".
    //This is a good place to explain the user
    //why you need the permission and ask if he/she wants
    //to accept it (the rationale).
    }
    } else {
    //Permission denied, boo! Disable the
    //functionality that depends on this permission.
    }
    }
    return false;
    }

    Lanzamiento de recogida de imagen

    private void launchImagePick() {
    Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
    intent.setType("image/*");
    intent.addCategory(Intent.CATEGORY_OPENABLE);
    startActivityForResult(intent, PICK_IMAGE);
    //see onActivityResult
    }

    Gestionar la Imagen de selección de respuesta

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == PICK_IMAGE) {
    if (resultCode == Activity.RESULT_OK) {
    if (data != null && data.getData() != null) {
    try {
    InputStream inputStream = getContentResolver().openInputStream(data.getData())
    if (inputStream != null) {
    //No special persmission needed to store the file like that
    FileOutputStream fos = openFileOutput(FILE_TEMP_NAME, Context.MODE_PRIVATE);
    final int BUFFER_SIZE = 1 << 10 << 3; //8 KiB buffer
    byte[] buffer = new byte[BUFFER_SIZE];
    int bytesRead = -1;
    while ((bytesRead = inputStream.read(buffer)) > -1) {
    fos.write(buffer, 0, bytesRead);
    }
    inputStream.close();
    fos.close();
    File tempImageFile = new File(getFilesDir()+"/"+FILE_TEMP_NAME);
    //Do whatever you want with the File
    //Delete when not needed anymore
    deleteFile(FILE_TEMP_NAME);
    }
    }
    catch (Exception e) {
    e.printStackTrace();
    }
    } else {
    //Error display
    }
    } else {
    //The user did not select any image
    }
    }
    }

    Eso es todo amigos; esto me funciona en todos los teléfonos que tengo.

  14. 0

    Esto es un total hack, pero aquí es lo que hice…

    Así, mientras que jugando con la configuración de una DocumentsProvider, me di cuenta de que la código de ejemplo (en getDocIdForFile, alrededor de la línea 450) genera un identificador único para un documento seleccionado basado en el archivo de la (única) ruta relativa a la raíz especificado vas a dar (que es, de lo que se establece mBaseDir en la línea 96).

    Por lo que la URI termina buscando algo como:

    content://com.example.provider/document/root:path/to/the/file

    Como la documentación decir, suponiendo que sólo una sola raíz (en mi caso es la Environment.getExternalStorageDirectory() pero usted puede usar en algún otro lugar… y luego se toma la ruta de acceso del archivo, a partir de la raíz, y la convierte en la única de IDENTIFICACIÓN, anteponiendo el «root:«. Lo que puede determinar la ruta de acceso mediante la eliminación de la "/document/root:» parte de la uri.getPath(), la creación de un archivo real camino por hacer algo como esto:

    public void onActivityResult(int requestCode, int resultCode, Intent data) {
    //check resultcodes and such, then...
    uri = data.getData();
    if (uri.getAuthority().equals("com.example.provider"))  {
    String path = Environment.getExternalStorageDirectory(0.toString()
    .concat("/")
    .concat(uri.getPath().substring("/document/root:".length())));
    doSomethingWithThePath(path); }
    else {
    //another provider (maybe a cloud-based service such as GDrive)
    //created this uri.  So handle it, or don't.  You can allow specific
    //local filesystem providers, filter non-filesystem path results, etc.
    }

    Sé. Es vergonzoso, pero funcionó. De nuevo, esto depende de el uso que su propio documentos de proveedor en su aplicación para generar el documento de IDENTIFICACIÓN.

    (También, hay una mejor manera de construir el camino que no suponga «/» es el separador de ruta, etc. Pero usted consigue la idea.)

    • Para responder a mí mismo con una aún más loco de pensar, si la aplicación ya está manejo file:// intenciones desde un archivo externo selector, también se puede comprobar a la autoridad, como en el ejemplo anterior para asegurarse de que es de su proveedor personalizado, y si es así, usted podría también utilizar la ruta de acceso a «forjar» un nuevo file:// intención de utilizar la ruta de acceso extrajo, a continuación, StartActivity() y deje que su aplicación a la recogida. Lo sé, es terrible.
  15. 0

    Esto funcionó muy bien para mí:

    else if(requestCode == GALLERY_ACTIVITY_NEW && resultCode == Activity.RESULT_OK)
    {
    Uri uri = data.getData();
    Log.i(TAG, "old uri =  " + uri);
    dumpImageMetaData(uri);
    try {
    ParcelFileDescriptor parcelFileDescriptor =
    getContentResolver().openFileDescriptor(uri, "r");
    FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
    Log.i(TAG, "File descriptor " + fileDescriptor.toString());
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeFileDescriptor(fileDescriptor, null, options);
    options.inSampleSize =
    BitmapHelper.calculateInSampleSize(options,
    User.PICTURE_MAX_WIDTH_IN_PIXELS,
    User.PICTURE_MAX_HEIGHT_IN_PIXELS);
    options.inJustDecodeBounds = false;
    Bitmap bitmap = BitmapFactory.decodeFileDescriptor(fileDescriptor, null, options);
    imageViewPic.setImageBitmap(bitmap);
    ByteArrayOutputStream stream = new ByteArrayOutputStream();
    bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
    //get byte array here
    byte[] picData = stream.toByteArray();
    ParseFile picFile = new ParseFile(picData);
    user.setProfilePicture(picFile);
    }
    catch(FileNotFoundException exc)
    {
    Log.i(TAG, "File not found: " + exc.toString());
    }
    }
    • olvidar el dumpImageMetaData(uri); es innecesario
  16. 0

    De construcción en Paul Burke respuesta he enfrentado muchos problemas para resolver tarjeta SD externa de la URI de la ruta ya que la mayoría de la propuesta de «built-in» funciones de caminos de retorno que no se resuelven a los archivos.

    Sin embargo, este es mi enfoque de su
    //TODO manejar no primaria volúmenes
    .

    String resolvedPath = "";
    File[] possibleExtSdComposites = context.getExternalFilesDirs(null);
    for (File f : possibleExtSdComposites) {
    //Reset final path
    resolvedPath = "";
    //Construct list of folders
    ArrayList<String> extSdSplit = new ArrayList<>(Arrays.asList(f.getPath().split("/")));
    //Look for folder "<your_application_id>"
    int idx = extSdSplit.indexOf(BuildConfig.APPLICATION_ID);
    //ASSUMPTION: Expected to be found at depth 2 (in this case ExtSdCard's root is /storage/0000-0000/) - e.g. /storage/0000-0000/Android/data/<your_application_id>/files
    ArrayList<String> hierarchyList = new ArrayList<>(extSdSplit.subList(0, idx - 2));
    //Construct list containing full possible path to the file
    hierarchyList.add(tail);
    String possibleFilePath = TextUtils.join("/", hierarchyList);
    //If file is found --> success
    if (idx != -1 && new File(possibleFilePath).exists()) {
    resolvedPath = possibleFilePath;
    break;
    }
    }
    if (!resolvedPath.equals("")) {
    return resolvedPath;
    } else {
    return null;
    }

    Nota depende de jerarquía que puede ser diferente en cada fabricante del teléfono – no he probado todos (que ha funcionado bien hasta el momento en el Xperia Z3 API 23 y Samsung Galaxy A3 API 23).

    Por favor confirmar si es que no funciona bien en otros lugares.

  17. -1

    @paul burke respuesta funciona bien para la cámara y galería de fotos para la API de nivel 19 y encima, pero no funciona si su proyecto Android mínima del SDK se establece debajo de los 19 años, y algunas respuestas de referencia de arriba no funcionan para la galería y la cámara. Bueno, he modificado @paul burke código que funciona para la API de nivel inferior a 19. A continuación está el código.

    public static String getPath(final Context context, final Uri uri) {
    final boolean isKitKat = Build.VERSION.SDK_INT >=
    Build.VERSION_CODES.KITKAT;
    Log.i("URI",uri+"");
    String result = uri+"";
    //DocumentProvider
    //if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
    if (isKitKat && (result.contains("media.documents"))) {
    String[] ary = result.split("/");
    int length = ary.length;
    String imgary = ary[length-1];
    final String[] dat = imgary.split("%3A");
    final String docId = dat[1];
    final String type = dat[0];
    Uri contentUri = null;
    if ("image".equals(type)) {
    contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
    }
    else if ("video".equals(type)) {
    }
    else if ("audio".equals(type)) {
    }
    final String selection = "_id=?";
    final String[] selectionArgs = new String[] {
    dat[1]
    };
    return getDataColumn(context, contentUri, selection, selectionArgs);
    }
    else
    if ("content".equalsIgnoreCase(uri.getScheme())) {
    return getDataColumn(context, uri, null, null);
    }
    //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 column_index = cursor.getColumnIndexOrThrow(column);
    return cursor.getString(column_index);
    }
    }
    finally {
    if (cursor != null)
    cursor.close();
    }
    return null;
    }
    • Recibo de java.lang.IllegalArgumentException: Ninguna de las columnas solicitadas pueden ser proporcionados al momento de seleccionar un Google Doc imagen
    • Me estoy haciendo la misma Excepción. Encontraste una solución?
  18. -4

    La respuesta a tu pregunta es que usted necesita tener permisos. Escriba el siguiente código en su manifest.xml archivo:

    <uses-sdk  android:minSdkVersion="8"   android:targetSdkVersion="18" />
    <uses-permission android:name="android.permission.READ_CONTACTS" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
    <uses-permission android:name="android.permission.WRITE_OWNER_DATA"></uses-permission>
    <uses-permission android:name="android.permission.READ_OWNER_DATA"></uses-permission>`

    Que trabajó para mí…

Dejar respuesta

Please enter your comment!
Please enter your name here