web-dev-qa-db-fra.com

Android: Obtenir un URI de fichier à partir d'un URI de contenu?

Dans mon application, l'utilisateur doit sélectionner un fichier audio que l'application gère ensuite. Le problème est que pour que l'application fasse ce que je veux qu'elle fasse avec les fichiers audio, j'ai besoin que l'URI soit au format de fichier. Lorsque j'utilise le lecteur de musique natif d'Android pour rechercher le fichier audio dans l'application, l'URI est un URI de contenu, qui ressemble à ceci:

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

Cependant, en utilisant l'application de gestion de fichiers Astro, je reçois ce qui suit:

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

Ce dernier est beaucoup plus accessible pour moi, mais je souhaite bien sûr que l'application dispose des fonctionnalités du fichier audio choisi par l'utilisateur, quel que soit le programme utilisé pour parcourir sa collection. Ma question est donc la suivante: existe-t-il un moyen de convertir le content:// URI de style dans un file:// URI? Sinon, que recommanderiez-vous pour résoudre ce problème? Voici le code qui appelle le sélecteur, pour référence:

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

Je fais ce qui suit avec l'URI de contenu:

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

Ensuite, faites des trucs FileInputStream avec ce fichier.

105
JMRboosties

Utilisez simplement getContentResolver().openInputStream(uri) pour obtenir un InputStream à partir d'un URI.

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

132
Jason LeBrun

Vous pouvez utiliser le résolveur de contenu pour obtenir un file:// chemin depuis le content:// URI:

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

Si vous avez un contenu Uri avec content://com.externalstorage... vous pouvez utiliser cette méthode pour obtenir le chemin absolu d’un dossier ou d’un fichier on Android 19 ou plus).

public static String getPath(final Context context, final Uri uri) {
    final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KitKat;

    // DocumentProvider
    if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
        System.out.println("getPath() uri: " + uri.toString());
        System.out.println("getPath() uri authority: " + uri.getAuthority());
        System.out.println("getPath() uri path: " + uri.getPath());

        // ExternalStorageProvider
        if ("com.Android.externalstorage.documents".equals(uri.getAuthority())) {
            final String docId = DocumentsContract.getDocumentId(uri);
            final String[] split = docId.split(":");
            final String type = split[0];
            System.out.println("getPath() docId: " + docId + ", split: " + split.length + ", type: " + type);

            // This is for checking Main Memory
            if ("primary".equalsIgnoreCase(type)) {
                if (split.length > 1) {
                    return Environment.getExternalStorageDirectory() + "/" + split[1] + "/";
                } else {
                    return Environment.getExternalStorageDirectory() + "/";
                }
                // This is for checking SD Card
            } else {
                return "storage" + "/" + docId.replace(":", "/");
            }

        }
    }
    return null;
}

Vous pouvez vérifier que chaque partie d'Uri utilise println. Les valeurs renvoyées pour la carte SD et la mémoire principale de l'appareil sont répertoriées ci-dessous. Vous pouvez accéder et supprimer si le fichier est en mémoire mais que je n’ai pas pu supprimer le fichier de la carte SD en utilisant cette méthode, uniquement en lecture ou en image à l’aide de ce chemin absolu. Si vous avez trouvé une solution à supprimer à l'aide de cette méthode, partagez-la. CARTE SD

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

MÉMOIRE PRINCIPALE

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

Si vous souhaitez avoir Uri avec file:/// après avoir utilisé le chemin

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

Essayer de gérer l'URI avec le schéma content: // en appelant ContentResolver.query() n'est pas une bonne solution. Sur HTC Desire sous 4.2.2, vous pouvez obtenir NULL comme résultat de requête.

Pourquoi ne pas utiliser ContentResolver à la place? https://stackoverflow.com/a/29141800/3205334

6
Darth Raven

Eh bien, je suis un peu en retard pour répondre, mais mon code est testé

schéma de vérification de uri:

 byte[] videoBytes;

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

Dans la réponse ci-dessus, j'ai converti le tableau uri vidéo en tableau d'octets, mais cela n'a rien à voir avec la question. Je viens de copier mon code complet pour montrer l'utilisation de FileInputStream et InputStream, car les deux fonctionnent de la même manière mon code.

J'ai utilisé le contexte de variable qui est getActivity () dans mon fragment et dans Activity, il s'agit simplement de NomActivité.

context=getActivity(); // dans le fragment

context=ActivityName.this; // en activité

3
Umar Ata