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

Dans mon application l'utilisateur de sélectionner un fichier audio à 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 parcourir 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 le populaire gestionnaire de fichiers application Astro, j'obtiens ce qui suit:

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

ce dernier est beaucoup plus accessible pour moi de travailler avec, mais bien sûr je veux que l'application ait la fonctionnalité avec le fichier audio que l'utilisateur choisit indépendamment du programme qu'ils utilisent pour parcourir leur collection. Alors ma question Est, y a-t-il un moyen de transformer L'URI de style content:// en un URI file:// ? Sinon, que recommanderiez-vous pour moi à résoudre ce problème? Voici le code qui appelle le chooser, 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 le suivant avec le contenu URI:

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

puis faire quelques trucs FileInputStream avec ce fichier.

87
demandé sur ROMANIA_engineer 2011-04-14 04:54:26

6 réponses

il suffit d'utiliser getContentResolver().openInputStream(uri) pour obtenir un InputStream d'une URI.

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

119
répondu Jason LeBrun 2012-03-15 13:50:04

vous pouvez utiliser le résolveur de contenu pour obtenir un chemin file:// à partir du 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);
39
répondu nobre 2015-10-01 14:55:35

essayer de gérer L'URI Avec contenu:// schéma en appelant ContentResolver.query() n'est pas une bonne solution. Sur HTC Desire en cours d'exécution 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

5
répondu Darth Raven 2017-05-23 12:34:45

si vous avez un Uri de contenu avec content://com.externalstorage... vous pouvez utiliser cette méthode pour obtenir le chemin absolu d'un dossier ou d'un fichier sur 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 chaque partie D'Uri utilise println. Les valeurs retournées pour ma carte SD et ma mémoire principale sont listées ci-dessous. Vous pouvez accéder et supprimer si le fichier est sur la mémoire mais je n'ai pas été en mesure de supprimer le fichier de la carte SD en utilisant cette méthode, seulement lire ou opene d image utilisant ce chemin absolu. Si vous avez trouver une solution pour supprimer en utilisant cette méthode, s'il vous plaît partager. 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 obtenir Uri avec file:/// après l'utilisation du chemin d'accès

DocumentFile documentFile = DocumentFile.fromFile(new File(path));
documentFile.getUri() // will return a Uri with file Uri
5
répondu Thracian 2018-03-06 14:12:31

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

vérifier le schéma d'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 l'uri vidéo en tableau d'octets , mais ce n'est pas lié à la question, Je viens de copier mon code complet pour montrer l'utilisation de FileInputStream et InputStream que les deux travaillent même dans mon code.

j'ai utilisé le contexte variable qui est getActivity () dans mon Fragment et en activité il est tout simplement ActivityName.ce

context=getActivity(); / / en Fragment

context=ActivityName.this; / / en activité

1
répondu Umar Ata 2018-02-05 11:28:50

vous devez utiliser getContentResolver().openInputStream(uri) pour obtenir un InputStream d'une URI. Parce qu'il est très simple et facile à comprendre. Pour plus openInputStream(android.net.Uri)

-1
répondu Harneet Singh 2017-10-23 15:06:36