将 fileChooserParams 中的 mime 类型转换为 Intent.setType 的正确格式

Posted

技术标签:

【中文标题】将 fileChooserParams 中的 mime 类型转换为 Intent.setType 的正确格式【英文标题】:Convert mime types in fileChooserParams to the right format for Intent.setType 【发布时间】:2019-08-22 04:22:14 【问题描述】:

我正在尝试使用 android 中的 WebView 上传文件。

这是the code 正在使用中:

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public boolean onShowFileChooser(WebView webView, final ValueCallback<Uri[]> filePathsCallback, final WebChromeClient.FileChooserParams fileChooserParams) 
    Intent intent = fileChooserParams.createIntent();
    LOG.d(LOG_TAG, "mime types: " + Arrays.toString(fileChooserParams.getAcceptTypes()));
    // PRINTS [.jpg,.png,.tiff,.jpeg,.tif,.pdf] !!        
    try 
        parentEngine.cordova.startActivityForResult(new CordovaPlugin() 
            @Override
            public void onActivityResult(int requestCode, int resultCode, Intent intent) 
                // ...
            
        , intent, FILECHOOSER_RESULTCODE);
     catch (ActivityNotFoundException e) 
      // ...
    
    return true;

问题是当我必须使用的外部库 (ng-file-upload) 触发该方法的执行时,在 fileChooserParams 中作为参数传递的 mime 类型是:[.jpg,.png,.tiff,.jpeg,.tif,.pdf]。我在list of allowed mime types 中看不到其中的大部分内容。

因此,我在 LogCat 中发现了这个错误: No activity found to handle file chooser intent.: android.content.ActivityNotFoundException: No Activity found to handle Intent act=android.intent.action.GET_CONTENT cat=[android.intent.category.OPENABLE] typ=.jpg,.png,.tiff,.jpeg,.tif,.pdf

如果我只是添加intent.setType("image/* application/pdf");,一切都会按预期工作!

现在问题是:在我想提交给cordova-android 的贡献者的Merge Request 中,我如何安全地将fileChooserParams 转换为正确的格式?

【问题讨论】:

【参考方案1】:

我解决了在my PR 中添加以下两行:

intent.setType("image/*");
intent.putExtra(Intent.EXTRA_MIME_TYPES, fileChooserParams.getAcceptTypes());

结果:

2019-04-01 00:18:00.501 32500-32500/my.app.bundle.id D/SystemWebChromeClient: : fileChooserParams.getAcceptTypes(): [.jpg,.png,.tiff,.jpeg,.tif,.pdf]

2019-04-01 00:18:00.503 2225-2921/system_process I/ActivityManager: START u0 act=android.intent.action.GET_CONTENT cat=[android.intent.category.OPENABLE] typ=image/* cmp=com.android.documentsui/.picker.PickActivity (has extras) from uid 10105

我希望它会被接受。

【讨论】:

我切换到其他解决方案,因为这会强制选择器将图像作为首选。它可能在其他 Cordova 应用程序中存在问题(例如音乐选择器)。【参考方案2】:

我使用此代码改进了解决方案:

   // Validation utility for mime types
    private List<String> extractValidMimeTypes(String[] mimeTypes) 
        List<String> results = new ArrayList<String>();
        List<String> mimes;
        if (mimeTypes.length() == 1 && mimeTypes[0].contains(",")) 
            mimes = Arrays.asList(mimeTypes[0].split(","));
         else 
            mimes = Arrays.asList(mimeTypes);
        
        MimeTypeMap mtm = MimeTypeMap.getSingleton();
        for (String mime : mimes) 
            if (mime != null && mime.trim().startsWith(".")) 
                String extensionWithoutDot = mime.trim().substring(1, mime.trim().length());
                String derivedMime = mtm.getMimeTypeFromExtension(extensionWithoutDot);
                if (derivedMime != null && !results.contains(derivedMime)) 
                    // adds valid mime type derived from the file extension
                    results.add(derivedMime);
                
             else if (mtm.getExtensionFromMimeType(mime) != null && !results.contains(mime)) 
                // adds valid mime type checked agains file extensions mappings
                results.add(mime);
            
        
        return results;
    


public boolean onShowFileChooser(WebView webView, final ValueCallback<Uri[]> filePathsCallback, final WebChromeClient.FileChooserParams fileChooserParams) 
    Intent intent = fileChooserParams.createIntent();
    List<String> validMimeTypes = extractValidMimeTypes(fileChooserParams.getAcceptTypes());
    if (validMimeTypes.isEmpty()) 
        intent.setType(DEFAULT_MIME_TYPE);
     else 
        intent.setType(String.join(" ", validMimeTypes));
    
    ...

更多详情请查看我的Pull Request。

【讨论】:

以上是关于将 fileChooserParams 中的 mime 类型转换为 Intent.setType 的正确格式的主要内容,如果未能解决你的问题,请参考以下文章

音乐中的do、re、mi、fa、sol是哪些音?

将存储为 hh24miss 的时间转换为 hh24:mi:ss

如何将存储为 VARCHAR2 的日期转换为 'MM/DD/YYYY HH24:MI:SS'?

将 YYYY-MM-DDTHH24:MI:SEC.milliseconds 时间戳插入 Oracle

整数划分问题

整数划分