Веб-браузер Android, поле ввода файла filechooser не отображается

Я должен отображать веб-страницу в веб-представлении в приложении. Страница содержит HTML-форму, где одним из полей является файл. Итак, что-то вроде...

<input type="file" name="file">

Если я открою страницу в браузере и нажму кнопку "Выбрать файл", появится окно выбора файла, и все будет хорошо, но когда я нажму кнопку "Выбрать файл" в веб-просмотре, ничего не произойдет:/

Есть идеи, как сделать эту работу?

2 ответа

Решение

WebView по умолчанию не открывает средство выбора файлов. Однако можно сделать эту работу. WebChromeClient имеет скрытый метод openFileChooser, который необходимо переопределить, чтобы открыть окно выбора файлов, а затем вернуть результат в WebView. По словам гуру, никогда не следует использовать скрытые методы Android SDK, так что это не очень хорошее решение и, вероятно, не должно использоваться в корпоративных приложениях. Однако стандартный браузер Android делает именно так. Немного больше информации о том, как я переопределил этот метод, в моем вопросе. Если кому-то нужен источник, дайте мне знать, я опубликую его где-нибудь.

Можно ли загружать файлы через веб-просмотр?

Эта функция доступна в версии 1.3.0 и новее. Для более старых версий приложения это возможно, но вам нужно добавить дополнительный код, чтобы он работал. Добавьте следующий код в ваш файл AndroidManifest.xml. Разместите его ниже других элементов разрешения использования:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

Скопируйте / вставьте этот Java-класс MediaUtility.java в проект. Поместите его в каталог com / robotemplates / webviewapp / utility.

Откройте файл MainFragment.java во фрагментном пакете. Найдите метод renderView() и замените "webView.setWebChromeClient(new WebChromeClient());" следующим кодом:

webView.setWebChromeClient(new WebChromeClient()
{
    public void openFileChooser(ValueCallback<Uri> filePathCallback)
    {
        mFilePathCallback4 = filePathCallback;
        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        intent.setType("*/*");
        startActivityForResult(Intent.createChooser(intent, "File Chooser"), REQUEST_FILE_PICKER);
    }

    public void openFileChooser(ValueCallback filePathCallback, String acceptType)
    {
        mFilePathCallback4 = filePathCallback;
        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        intent.setType("*/*");
        startActivityForResult(Intent.createChooser(intent, "File Chooser"), REQUEST_FILE_PICKER);
    }

    public void openFileChooser(ValueCallback<Uri> filePathCallback, String acceptType, String capture)
    {
        mFilePathCallback4 = filePathCallback;
        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        intent.setType("*/*");
        startActivityForResult(Intent.createChooser(intent, "File Chooser"), REQUEST_FILE_PICKER);
    }

    @Override
    public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams)
    {
        mFilePathCallback5 = filePathCallback;
        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        intent.setType("*/*");
        startActivityForResult(Intent.createChooser(intent, "File Chooser"), REQUEST_FILE_PICKER);
        return true;
    }
});

Наконец, добавьте следующий код где-нибудь внутри объекта MainFragment (например, ниже этой строки "private boolean mLocal = false;"):

private static final int REQUEST_FILE_PICKER = 1;
private ValueCallback<Uri> mFilePathCallback4;
private ValueCallback<Uri[]> mFilePathCallback5;

@Override
public void onActivityResult(int requestCode, int resultCode, Intent intent)
{
    if(requestCode==REQUEST_FILE_PICKER)
    {
        if(mFilePathCallback4!=null)
        {
            Uri result = intent==null || resultCode!=Activity.RESULT_OK ? null : intent.getData();
            if(result!=null)
            {
                String path = MediaUtility.getPath(getActivity(), result);
                Uri uri = Uri.fromFile(new File(path));
                mFilePathCallback4.onReceiveValue(uri);
            }
            else
            {
                mFilePathCallback4.onReceiveValue(null);
            }
        }
        if(mFilePathCallback5!=null)
        {
            Uri result = intent==null || resultCode!=Activity.RESULT_OK ? null : intent.getData();
            if(result!=null)
            {
                String path = MediaUtility.getPath(getActivity(), result);
                Uri uri = Uri.fromFile(new File(path));
                mFilePathCallback5.onReceiveValue(new Uri[]{ uri });
            }
            else
            {
                mFilePathCallback5.onReceiveValue(null);
            }
        }

        mFilePathCallback4 = null;
        mFilePathCallback5 = null;
    }
}

Не забудьте добавить необходимый импорт: "import android.webkit.ValueCallback;", "import com.robotemplates.webviewapp.utility.MediaUtility;", "import java.io.File;". Если проблема не устранена, попробуйте добавить правило в сценарий Proguard: https://code.google.com/p/android/issues/detail?id=62220.

Другие вопросы по тегам