Android: получить URI файла из URI контента? - PullRequest
101 голосов
/ 14 апреля 2011

В моем приложении пользователь должен выбрать аудиофайл, который затем обрабатывает приложение.Проблема в том, что для того, чтобы приложение делало то, что я хочу, с аудиофайлами, мне нужен URI в формате файла.Когда я использую собственный музыкальный проигрыватель Android для поиска аудиофайла в приложении, URI является URI контента, который выглядит следующим образом:

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

Однако, используя популярное приложение для управления файлами Astro, я получаюследующее:

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

С последним мне гораздо удобнее работать, но, конечно, я хочу, чтобы приложение имело функциональность с аудиофайлом, который выбирает пользователь, независимо от программы, которую он использует для просмотра своих файлов.коллекция.Итак, мой вопрос, есть ли способ конвертировать URI в стиле content:// в URI file://?В противном случае, что бы вы посоветовали мне решить эту проблему?Вот код, который вызывает селектор, для справки:

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);

Я делаю следующее с URI содержимого:

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

Затем выполняем некоторые вещи FileInputStream с указанным файлом.

Ответы [ 5 ]

131 голосов
/ 14 апреля 2011

Просто используйте getContentResolver().openInputStream(uri), чтобы получить InputStream из URI.

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

40 голосов
/ 26 сентября 2012

Вы можете использовать Content Resolver, чтобы получить путь file:// из 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);
6 голосов
/ 23 октября 2017

Если у вас есть контент Uri с content://com.externalstorage..., вы можете использовать этот метод, чтобы получить абсолютный путь к папке или файлу на Android 19 или выше .

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

Вы можетепроверьте, что каждая часть Uri использует println.Возвращенные значения для моей SD-карты и основной памяти устройства перечислены ниже.Вы можете получить доступ и удалить файл, если файл находится в памяти, но я не смог удалить файл с SD-карты , используя этот метод, только читать или открывать изображение, используя этот абсолютный путь.Если вы нашли решение для удаления с помощью этого метода, пожалуйста, поделитесь.SD CARD

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

ОСНОВНАЯ ПАМЯТЬ

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

Если вы хотите получить Uri с file:/// после получения пути, используйте

DocumentFile documentFile = DocumentFile.fromFile(new File(path));
documentFile.getUri() // will return a Uri with file Uri
6 голосов
/ 19 марта 2015

Попытка обработать URI с помощью схемы content: // путем вызова ContentResolver.query() не является хорошим решением.В HTC Desire под управлением 4.2.2 вы можете получить NULL в качестве результата запроса.

Почему бы вместо этого не использовать ContentResolver?https://stackoverflow.com/a/29141800/3205334

2 голосов
/ 05 февраля 2018

Ну, я немного опоздал с ответом, но мой код проверен

Проверка схемы от 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);
        }

В ответе выше я преобразовал видео URI в массив байтов, но это не имеет отношения к вопросу, Я просто скопировал свой полный код, чтобы показать использование FileInputStream и InputStream, так как оба кода работают одинаково в моем коде.

Я использовал переменную context, которая называется getActivity () в моем фрагменте, а в Activity это просто ActivityName.this

context=getActivity(); // во фрагменте

context=ActivityName.this; // в деятельности

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...