javascript - Crosswalk Cordova Android 多文件选择

标签 javascript android html cordova crosswalk

我有一个使用 cordova 和 angularjs 构建的混合应用程序,对于 Android,我使用人行横道运行该应用程序。

我一直在网上搜索 html5 文件输入的解决方案,以允许选择多个文件。

我正在使用以下元素进行文件选择:

<input type="file" multiple="multiple" name="files[]" />

我正在运行 Android Lollipop 版本 5.1.1 和 Crosswalk 版本 20,我还测试了 Crosswalk 版本 18 和 19。 Chrome 安装在我运行最新版本的设备上,但我认为这没有什么不同。

当我点击上面的输入元素时,我得到了预期的对话框,要求我从我的文档或相机中进行选择。如果我选择从我的文档中选择,那么我只能选择单个文件,在本例中是图像。对于我可以从中选择图像的每个应用程序都是如此,因此默认的 android“图像”、“视频”、“音频”等和外部应用程序(如 Google 相册)都只允许我一次选择一个文件.

在下图中,您可以看到列出的文件,长按每个图 block 不会将文件添加到多项选择中。

enter image description here

这适用于应用程序的 IOS 版本。

在浏览了我可以在网上找到的所有 Material 后,运行 Chrome 49+ 的 Android 5+ 似乎支持 multiple 属性。

我不确定这是人行横道浏览器实现问题还是 Android 操作系统问题,还是其他原因?任何人都可以建议。

编辑

只是为了确认这在使用或不使用人行横道的情况下都不起作用。

最佳答案

经过几周的努力解决这个问题,我终于让它工作了(Cordova 没有人行横道)。这是在 Windows 中使用 Cordova 工具完成的,因此请原谅下面的文件规范。

第 1 步: 将 platforms\Android\CordovaLib\AndroidManifest.xml 中的 minSdkVersion 更改为 21 说明: onShowFileChooser API 是在 LOLLIPOP (API 21) 中引入的。它允许返回 url[] 而不是 showFileChooser 在早期 API 版本中返回的 url。仅当您将 API 更改为 21 或更高时才会调用此方法。

第 2 步:更新/替换 onActivityResult 方法以检索多个文件。 在使用 fileChooserParams 创建 Intent 后附加以下内容以允许选择多个文件:

    intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);

位置: platforms\android\CordovaLib\src\org\apache\cordova\engine\SystemWebChromeClient.java

第 3 步:使用 intent.getClipData() 更新相应的 onActivityResult 方法以返回多个 url。

注意事项:

  1. 为所有调用启用多重上传。您可以根据 fileChooserParams 模式更新 Intent 。
  2. 在默认情况下可用于人行横道的选择器中禁用相机作为源。

最终代码:

Uri photoUri;

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public boolean onShowFileChooser(WebView webView, final ValueCallback<Uri[]> filePathsCallback, final WebChromeClient.FileChooserParams fileChooserParams) {
    // Check and use MIME Type.
    String mimeType = "*/*";
    int ACTION_CODE = FILECHOOSER_RESULTCODE;
    try {
        if (fileChooserParams.getAcceptTypes().length > 0) {
            mimeType = fileChooserParams.getAcceptTypes()[0];
        } else {
            mimeType = "*/*";
        }
    } catch (Exception e) {
        mimeType = "*/*";
    };

    // Check if Mutiple is specified 
    Boolean selectMultiple = false;
    if (fileChooserParams.getMode() == WebChromeClient.FileChooserParams.MODE_OPEN_MULTIPLE) {
        selectMultiple = true;
    };

    Intent intent = new Intent();
    intent.setAction(Intent.ACTION_GET_CONTENT);
    intent.addCategory(Intent.CATEGORY_OPENABLE);
    if (selectMultiple) { intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true); };
    intent.setType(mimeType);
    ACTION_CODE = FILECHOOSER_RESULTCODE;
    final Intent chooserIntent = Intent.createChooser(intent, "Select Source");

    // Add camera intent to the chooser if image and send URI to return full image 
    if (mimeType.equals("image/*")) {
        photoUri = null;
        try {
            File photoFile = createImageFile();
            photoUri = Uri.fromFile(photoFile);
        }
        catch (Exception ex) {
            photoUri = null;
        }
        if (photoUri != null) {
            Intent camIntent = new Intent();
            camIntent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
            camIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
            camIntent.putExtra("return-data", true);
            chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent [] {camIntent} );
        }
    }

    try {
        parentEngine.cordova.startActivityForResult(new CordovaPlugin() {
            @Override
            public void onActivityResult(int requestCode, int resultCode, Intent intent) {
                if (resultCode ==  Activity.RESULT_OK && intent != null) {
                    if (intent.getData() != null)
                    {
                        Uri[] result = WebChromeClient.FileChooserParams.parseResult(resultCode, intent);
                        filePathsCallback.onReceiveValue(result);
                    }
                    else
                    {
                        if (intent.getClipData() != null) {
                            final int numSelectedFiles = intent.getClipData().getItemCount();
                            Uri[] result = new Uri[numSelectedFiles];
                            for (int i = 0; i < numSelectedFiles; i++) {
                                result[i] = intent.getClipData().getItemAt(i).getUri();
                            }
                            filePathsCallback.onReceiveValue(result);
                        }
                        else {
                            filePathsCallback.onReceiveValue(null);
                        }
                    }
                }
                else if(resultCode ==  Activity.RESULT_OK && (intent == null || intent.getData() == null )) {
                    Uri[] result = new Uri[1];
                    result[0] = photoUri;
                    filePathsCallback.onReceiveValue(result);
                } else {
                    filePathsCallback.onReceiveValue(null);
                }
            }
        }, chooserIntent, ACTION_CODE);
    } catch (ActivityNotFoundException e) {
        Log.w("No activity found to handle file chooser intent.", e);
        filePathsCallback.onReceiveValue(null);
    }
    return true;
}

关于javascript - Crosswalk Cordova Android 多文件选择,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39390781/

相关文章:

javascript - for 循环和词法环境中的闭包

javascript - 加载函数 onclick

android - google-api-services-translate 和 google-cloud-translate 做同样的事情吗?

javascript - 褪色图片被javascript下拉菜单干扰

javascript - 显示选定 ID 的问题

javascript - Pan Responder 根本无法在 Android 上运行

android - Exoplayer - 如何在重复模式下防止重新缓冲?

android - 为 Android 应用程序设置系统属性

javascript - 如何使用 javascript 为 p 标记中的 innerhtml 内容换行

html - 使用 CSS 在第三行之后放置一个元素