web-dev-qa-db-fra.com

Convertissez le contenu: // URI en chemin réel dans Android 4.4

J'ai essayé une solution (voir ci-dessous) qui fonctionne bien, sauf dans Android 4.4, l'appel de startActivityForResult()] appelle une activité intitulée "Ouvrir à partir de", qui a "Récente". , "Images", "Téléchargements", ainsi que plusieurs applications parmi lesquelles choisir. Lorsque je choisis "Images" et que je tente de résoudre l'URI de contenu renvoyé (à l'aide du code ci-dessous), l'appel à cursor.getString() renvoie null. Si je choisis exactement le même fichier à l'aide de l'application Gallery, cursor.getString() renvoie un chemin d'accès au fichier. Je ne l'ai testé qu'aux niveaux 16 et 19 de l'API. Tout fonctionne comme prévu dans le point 16. Aussi loin que 19 disparaisse. , Je dois choisir la galerie ou une autre application, sinon cela ne fonctionne pas.

private 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();
        String path = cursor.getString(column_index);

        return path;
    } finally {
        if (cursor != null) {
            cursor.close();
        }
    }
}
60
Raging Software

Le chemin d'accès au fichier provient de MediaProvider, DownloadsProvider et ExternalStorageProvider, tout en utilisant la méthode non officielle ContentProvider que vous avez mentionnée.

   /**
 * 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 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());
}

sourceaFileChooser

93
Kishan Vaghela

Convertissez le contenu: // URI en chemin réel dans Android 4.4

Il n’existe aucun moyen fiable de le faire sur une version Android version. Un content:// _ Uri n’a pas à représenter un fichier sur le système de fichiers, encore moins celui qui vous pouvez accéder.

Les modifications apportées par Android 4.4 pour offrir la structure de stockage augmentent simplement la fréquence à laquelle vous rencontrerez les valeurs content://Uri.

Si vous obtenez un content://Uri, veuillez le consommer en utilisant un ContentResolver et des méthodes telles que openInputStream() et openOutputStream().

44
CommonsWare

J'ai également été confronté à ce problème, mais dans mon cas, je voulais spécifier un Uri en béton à la Galerie afin que je puisse utiliser crop ultérieurement. On dirait que dans le nouveau navigateur de documents de KitKat, nous ne pouvons plus le faire à moins de choisir la galerie dans le tiroir de navigation et, comme vous l'avez dit, d'ouvrir l'image ou le fichier directement à partir de là.

Dans le cas Uri, vous pouvez toujours récupérer le chemin lors de l’ouverture du navigateur de documents.

    Intent dataIntent= new Intent(Intent.ACTION_GET_CONTENT);
    dataIntent.setType("image/*"); //Or whatever type you need

Et puis dans onActivityResult:

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == ACTIVITY_SELECT_IMAGE && resultCode == RESULT_OK) {
        myUri = data.getData();
        String path = myUri.getPath();
        openPath(myUri);

    }
}

Si vous devez ensuite ouvrir un fichier avec ce chemin, vous devez simplement utiliser un résolveur de contenu:

public void openPath(Uri uri){
    InputStream is = null;
    try {
        is = getContentResolver().openInputStream(uri);
        //Convert your stream to data here
        is.close();

    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}
9
Makerhack

Il est introduit dans ne API Google . Vous pouvez essayer ceci:

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;
}
7
FireBear

Si vous avez vraiment besoin d'un chemin de fichier. Commencez par récupérer les données à l'aide de ContentResolver. Ensuite, vous pouvez enregistrer les données dans un fichier temporaire et utiliser ce chemin.

(J'ai dû utiliser une bibliothèque avec un objet File dans un paramètre de fonction.)

1
fatihpense

Merci à @FireBear, j'ai modifié la réponse maintenant on obtiendra le chemin du fichier multimédia

String filePath = saveBitmap (activité, getBitmapFromUri (imageUri), "tmpFile"). GetPath ();

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

    private File saveBitmap(Context context, Bitmap bitmap, String name) {
        File filesDir = context.getFilesDir();
        File imageFile = new File(filesDir, name + ".jpg");
        OutputStream os;
        try {
            os = new FileOutputStream(imageFile);
            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, os);
            os.flush();
            os.close();
        } catch (Exception e) {
            //Log.e(getClass().getSimpleName(), "Error writing bitmap", e);
        }
        return imageFile;
    }
0
Shshank Bhong