Crosswalk Cordova Android выбор нескольких файлов

У меня есть гибридное приложение, созданное с использованием Cordova и angularjs, для Android я запускаю приложение с помощью пешеходного перехода.

Я прочесывал Интернет, чтобы найти решение для ввода файла html5, позволяющее выбрать несколько файлов.

Я использую следующий элемент для выбора файла:

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

Я использую Android Lollipop версии 5.1.1 и Crosswalk версии 20, я также тестировал Crosswalk версии 18 и 19. Chrome установлен на моем устройстве с последней версией, хотя я не думаю, что это имеет значение.

Когда я щелкаю элемент ввода выше, я получаю ожидаемое диалоговое окно с просьбой выбрать из моих документов или камеры. Если я решу выбрать из своих документов, я смогу выбрать только отдельные файлы, в данном случае изображения. Это верно для каждого приложения, из которого я могу выбирать изображения, поэтому Android по умолчанию «Изображения», «Видео», «Аудио» и т. д., а также внешние приложения, такие как Google Фото. Все они позволяют мне выбирать только один файл за раз. .

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

введите здесь описание изображения

Это работает в версии приложения для IOS.

После изучения всех материалов, которые я могу найти в Интернете, кажется, что множественный атрибут поддерживается на Android 5+ с Chrome 49+.

Я не уверен, является ли это реализацией браузера пешеходного перехода, проблемой операционной системы Android или чем-то еще? Может кто посоветует.

Изменить

Просто чтобы подтвердить, что это не работает с использованием Crosswalk или без него.


person Lee Brindley    schedule 08.09.2016    source источник


Ответы (1)


После нескольких недель попыток разобраться в этом я, наконец, заработал (Кордова без пешеходного перехода). Это было сделано с помощью Cordova Tools в Windows, поэтому прошу прощения за спецификации файлов ниже.

Шаг 1. Измените minSdkVersion в файле platform\Android\CordovaLib\AndroidManifest.xml на 21. Объяснение: onShowFileChooser API был введен в LOLLIPOP (API 21). Это позволяет возвращать url[] вместо url, возвращаемого showFileChooser в более ранних версиях API. Это вызывается только тогда, когда вы меняете API на 21 или выше.

Шаг 2. Обновите/замените метод onActivityResult для получения нескольких файлов. Добавьте следующее после создания намерения с помощью fileChooserParams, чтобы разрешить выбор нескольких файлов:

    intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);

Расположение: платформы\android\CordovaLib\src\org\apache\cordova\engine\SystemWebChromeClient.java

Шаг 3. Обновите соответствующий метод onActivityResult, чтобы он возвращал несколько URL-адресов с помощью intent.getClipData().

Предупреждения:

  1. Включает мультизагрузку для всех вызовов. Вы можете обновить намерение на основе режима fileChooserParams.
  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;
}
person RIBH    schedule 15.10.2016
comment
это все еще предпочтительный метод? - person Thomas; 18.12.2017
comment
В идеале это должно быть исправлено в Кордове, однако я не очень хорошо знаком с механикой этого. Следовательно, если бы кто-то мог добровольно решить эту проблему в следующем выпуске, включая тестирование, это помогло бы всем. - person RIBH; 25.12.2017