如何获取Android中任何文件的文件名和扩展名

时间:2018-12-20 13:01:29

标签: android android-studio android-emulator

实际上,我正在使用一个应用程序,用户可以选择任何文件,然后将文件上传到服务器上。该用户必须输入该文件的名称,并且在上载该文件时,该文件将在列表中显示,其中包含键入的名称和文件类型(.exe,.svg,任何文件类型)。

我遇到的问题是,我无法从使用Android 9的智能手机上选择的文件中提取文件扩展名。该问题在装有Android 8和更低版本的设备上或在装有Android 9的平板电脑上没有出现。使用Android Studios模拟器测试该应用。

文件选择器从以下意图开始:

        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。在这种方法中,我从FileUtils类调用getPath,因此可以提取文件扩展名。

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

FileUtils类(the class is from this repo)中的getPath方法通过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的智能手机模拟器时,路径始终是空的。

提前谢谢!

2 个答案:

答案 0 :(得分:1)

对于该解决方案,我拒绝使用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设备。

答案 1 :(得分:1)

TypeError: Cannot read property 'rows' of undefined