【问题标题】:Android: Get file name and extension of any fileAndroid:获取任何文件的文件名和扩展名
【发布时间】:2019-05-21 00:14:40
【问题描述】:

我遇到的问题是,我无法从搭载 Android 9 的智能手机上选择的文件中提取文件扩展名。该问题不会出现在搭载 Android 8 或更低版本的设备上。

当用户选择了任何类型的文件时,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();
                    path = FileUtils.getPath(getApplicationContext().getContentResolver(), uri);
                    name = path.substring(path.lastIndexOf("."));
                    extension = path.substring(path.lastIndexOf(".") + 1);
                }
                break;
            }
        }
    }

getPath() 来自 FileUtils 类 (from this repo) 通过 URI 评估文件是哪种文件,但负责这种情况的是以下部分:

public static String getPath(final ContentResolver cr, final Uri uri) {
    if (isDownloadsDocument(uri)) {
        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++) {
            res = getDataColumn(cr, uris.get(i), null, null);
            if (res != null) return res;
        }
    }
}

getDataColumn()查询保存文件物理路径的文件列:

public static String getDataColumn(ContentResolver cr,
                                   Uri uri, String selection,
                                   String[] selectionArgs) {
    Cursor cursor = null;
    final String[] projection = {"_data"};
    String col = "";

    try {
        cursor = cr.query(uri, projection, selection, selectionArgs,null);
        if (cursor != null && cursor.moveToFirst()) {
            final int column_index = cursor.getColumnIndexOrThrow("_data");
            col = cursor.getString(column_index);
        }
    }finally{ if (cursor != null) cursor.close();}
    return col;
}

当我测试它时,我得到的路径看起来像:E/AddItemActivity: result, path: /storage/emulated/0/Download/SampleVideo_176x144_1mb.3gp。 但在 Android 9 中,路径始终是空的。

【问题讨论】:

    标签: android android-emulator


    【解决方案1】:

    对于解决方案,我使用 MediaStore 来提取所选文件的名称和扩展名。所以我将onActivityResult 中的代码替换为以下代码:

    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) filename=uri.getPath();
      else{
        cursor.moveToFirst();
        int idx = cursor.getColumnIndex(MediaStore.Files.FileColumns.DISPLAY_NAME);
        filename = cursor.getString(idx);
        cursor.close();
      }
    
      String name = filename.substring(0,filename.lastIndexOf("."));
      String extension = filename.substring(filename.lastIndexOf(".")+1);
    }
    

    因此,使用MediaStore.File.FileColumns.DISPLAY_NAME 可以从使用文件选择器选择的任何文件中获取文件名和扩展名。

    【讨论】:

    • 从其他应用程序下载文件时会失败。 Uri 不一定要提供文件名或扩展名。
    • 实际上使用文件选择器从 Intent data 获取 Uri 不会失败。
    【解决方案2】:
    fun Uri.getFileNameWithExtension(context: Context): String? {
        val name = this.path?.let { path -> File(path).name }.orEmpty()
        val extension = MimeTypeMap.getSingleton()
            .getExtensionFromMimeType(getMimeType(context)).orEmpty()
        
        return if (name.isNotEmpty() && extension.isNotEmpty()) "$name.$extension" else null
    }
    
    fun Uri.getMimeType(context: Context): String? {
        return when (scheme) {
            ContentResolver.SCHEME_CONTENT -> context.contentResolver.getType(this)
            ContentResolver.SCHEME_FILE -> MimeTypeMap.getSingleton().getMimeTypeFromExtension(
                MimeTypeMap.getFileExtensionFromUrl(toString()).toLowerCase(Locale.US)
            )
            else -> null
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-10-23
      • 2014-01-10
      • 1970-01-01
      • 2014-04-14
      • 2012-06-07
      • 2016-09-01
      • 1970-01-01
      相关资源
      最近更新 更多