Как получить имя файла и расширение любого файла в Android - PullRequest
0 голосов
/ 20 декабря 2018

На самом деле я работаю над приложением, в котором пользователь может выбрать любой файл, который загружается на сервер.Этот пользователь должен ввести имя для этого файла, и когда файл загружен, файл отображается в списке с введенным именем и типом файла (.exe, .svg, любой тип файла).

Проблема, с которой я столкнулся, заключается в том, что я не могу извлечь расширение файла из файлов, выбранных на смартфоне с Android 9. Проблема не возникает на устройствах с Android 8 и менее или на планшетах с Android 9Я тестирую приложение только с Android Studios Emulator.

Выбор файла начинается со следующего намерения:

        intent.setType("*/*");
        intent.setAction(Intent.ACTION_GET_CONTENT);
        intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        Intent target = Intent.createChooser(intent, "Select Picture");

        startActivityForResult(target, PICKFILE_REQUEST_CODE);

Когда пользователь выбрал любой тип файла, вызывается onActivityResult.В этом методе я вызываю getPath из класса FileUtils, чтобы извлечь расширение файла.

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    Uri uri = new Uri.Builder().build();
    if (resultCode == RESULT_OK) {
        switch (requestCode) {
            case PICKFILE_REQUEST_CODE: {
                String path = new File(data.getData().getPath()).getAbsolutePath();

                if (path != null) {
                    uri = data.getData();
                    Context context = this.getApplicationContext();
                    path = FileUtils.getPath(context.getContentResolver(),uri);
                    name = path.substring(path.lastIndexOf("."));
                    extension = path.substring(path.lastIndexOf(".") + 1);
                }
                break;
            }
        }
    }

Метод getPath из класса FileUtils ( класс из этого репозитория ) оценивает файлчерез URI, какой это тип документа, но ответственным за этот случай является следующая часть:

public static String getPath(final ContentResolver contentResolver, final Uri uri) {

    //some irrelevant code ..

        // DownloadsProvider
        else if (isDownloadsDocument(uri)) {
            // depending on the device, the downloads folder can have different names
            final String id = DocumentsContract.getDocumentId(uri);

            final List<Uri> uris = new ArrayList<>();
            uris.add(ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(id)));
            uris.add(ContentUris.withAppendedId(Uri.parse("content://downloads/my_downloads"), Long.valueOf(id)));
            uris.add(ContentUris.withAppendedId(Uri.parse("content://downloads/all_downloads"), Long.valueOf(id)));

            String res;
            for(int i = 0; i < uris.size(); i++) {
                try {
                    res = getDataColumn(contentResolver, uris.get(i), null, null);
                    if(res != null)
                        return res;
                } catch (Exception e) {}
            }
        }

Метод getDataColumn запрашивает столбец файла, в котором сохранен физический путь файла:

public static String getDataColumn(ContentResolver contentResolver, Uri uri, String selection,
                                   String[] selectionArgs) {

    Cursor cursor = null;
    final String column = "_data";
    final String[] projection = {column};
    String col = "";

    try {
        cursor = contentResolver.query(uri, projection, selection, selectionArgs,null);
        if (cursor != null && cursor.moveToFirst()) {

            final int column_index = cursor.getColumnIndexOrThrow(column);
            col = cursor.getString(column_index);
        }
    }finally {
        if (cursor != null)
            cursor.close();
    }
    return col;
}

Когда я тестирую приложение с любым эмулятором смартфона (кроме тех, что на Android 9), путь, который я получаю, выглядит, например, следующим образом: E / AddItemActivity: результат, путь: / storage / emulated / 0 / Download / SampleVideo_176x144_1mb.3gp Но когда дело доходит до эмулятора смартфона с Android 9, путь всегда пуст.

Заранее спасибо!

1 Ответ

0 голосов
/ 21 декабря 2018

Для решения я отклонил путь с классом FileUtils и использовал MediaStore, чтобы извлечь имя и расширение для выбранного файла.Поэтому я заменил код в onActivityResult следующим кодом:

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    Uri uri = new Uri.Builder().build();
    if (resultCode == RESULT_OK) {
        switch (requestCode) {
            case PICKFILE_REQUEST_CODE: {
                String path = new File(data.getData().getPath()).getAbsolutePath();

                if (path != null) {
                    uri = data.getData();

                    String filename;
                    Cursor cursor = getContentResolver().query(uri, null, null, null, null);
                    if (cursor == null) { // Source is Dropbox or other similar local file path
                        filename = uri.getPath();
                    } else {
                        cursor.moveToFirst();
                        int idx = cursor.getColumnIndex(MediaStore.Files.FileColumns.DISPLAY_NAME);
                        filename = cursor.getString(idx);
                        cursor.close();
                    }

                    name = filename.substring(filename.lastIndexOf("."));
                    extension = filename.substring(filename.lastIndexOf(".") + 1);
               }
        break;
        }
   }
}

Так что с MediaStore.File.FileColumns.DISPLAY_NAME можно получить имя и расширение файла из любого файла, выбранного с помощью средства выбора файлов.Это работает с любым устройством Android с любой версией Android.

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