[webview_flutter] not working choose file (input type file)

Steps to Reproduce

Run simple index.html with tag <input type="file"> in webview_flutter
Try to click to input (choose file) and nothing happens

I have this issue too.
Does anybody have found a solution yet?

I having similiar issues too. I can not select the add media button in my webview and also the choose select button also not function.. other thing are fine..😢

I have this issue too on Android. but run on iOS fine.

The input option does not work with the plugin for me too. :cry:

Hey, I have a workaround for this. This will take another plugin though. :smile:
The plugin: https://github.com/fluttercommunity/flutter_webview_plugin
The code:
        child: WebviewScaffold(
          url: _url,
          withLocalStorage: true,
        ),
      ),

this is an issue with native android webviews.  it is not directly related to flutter (a bug within flutter), although fixing it would require the flutter team to write some code to implement the feature as the webview_flutter plugin acts as a passthrough to the native webviews.
you can see a discussion around the android native problem at:
https://stackoverflow.com/questions/5907369/file-upload-in-webview
agreed that this does not affect iOS as the native iOS implementation does not suffer from the same limitation as the android implementation.
i would love to see this get fixed as I spent a ton of time implementing something on a webpage with javascript that you can't do easily in flutter only to have it not work due to the inability to upload files.  i guess i could technically put a flutter widget above the webview to do the upload and then have the webview take over, but that would create a pretty tricky/possibly ugly experience.

Hey, I have a workaround for this. This will take another plugin though. 😄
The plugin: https://github.com/fluttercommunity/flutter_webview_plugin
The code:
        child: WebviewScaffold(
          url: _url,
          withLocalStorage: true,
        ),
      ),

This plugin doesn't allow you to draw widget on top of webview you need to close the webview to show popup and everything. Also, the "input" tag works fine without "withlocalstorage:true" "withlocalstorage" is used to render HTML/js from the local storage.

this is an issue with native android webviews. it is not directly related to flutter (a bug within flutter), although fixing it would require the flutter team to write some code to implement the feature as the webview_flutter plugin acts as a passthrough to the native webviews.
you can see a discussion around the android native problem at:
https://stackoverflow.com/questions/5907369/file-upload-in-webview
agreed that this does not affect iOS as the native iOS implementation does not suffer from the same limitation as the android implementation.
i would love to see this get fixed as I spent a ton of time implementing something on a webpage with javascript that you can't do easily in flutter only to have it not work due to the inability to upload files. i guess i could technically put a flutter widget above the webview to do the upload and then have the webview take over, but that would create a pretty tricky/possibly ugly experience.

Hi,
You have a small problem in your link. It is not formatted with the correct link.
About the problem, this happens only on Android. If someone wants to try to implement the solution, you can fork the plugin here.

any update for this bug?

I have fixed this bug and testing.
maybe i can make a PR.

Any update?

Maybe this plugin help to solve the problem https://github.com/Sh1d0w/multi_image_picker

Maybe this plugin help to solve the problem https://github.com/Sh1d0w/multi_image_picker

I don't think this will be helpfull inside the webview.

I guess there is no single person come up with a comprehensive solution :D
For those who need a temporary solution until flutter team adds the file input support:
1- download latest the flutter_webview_plugin and webview_flutter plugins from pub.dev
2- copy the the file selection part from flutter_webview_plugin to webview_flutter
3- replace your old version of webview_flutter in pubspec.yaml with this new one
for ex:
  webview_flutter:
    path: ../webview_flutter-0.3.19+3/

Same Problem, Wondering When we can find a solution.

wating for fixing this problem,I met this problem for many days but have no idea to resolve

Same problem

will they fix this issue soon?

use this flutter_webview_plugin
its work for me .. can for input type file

Steps to Reproduce

Run simple index.html with tag <input type="file"> in webview_flutter
Try to click to input (choose file) and nothing happens

This issue is only in Android devices

same problem any updates?
I can't upload file in webview page

Same problem.
Is there any update?

I solve the problem by hide() or show() webView when I push page or back page

Same problem.
Is there any update?

Same problem.
Is there any update?

I solve the problem by hide() or show() webView when I push page or back page

Same problem.
Is there any update?

Same problem.
Is there any update?

I solve the problem by hide() or show() webView when I push page or back page

how?

same problem

I have solved this problem.
https://github.com/libo1223/plugins/tree/master/packages/webview_flutter
If it is useful, please star

@libo1223  Could You please merge with  yenole:master and publish your plugin to pub.dev?

@libo1223  Will You publish this plugin to pub.dev?

@libo1223 Please check "git status", you have some missing files there... :)

sorry，i have pushed now。

@libo1223 @VladyslavBondarenko
我也在Android 10上遇到了webview_flutter里密码输入框不能成功唤起键盘的问题，只有密码输入框,只在Android 10上！！！ 如果你们解决了希望能告知一下，谢谢
相关log如下:
I also encountered the problem that the password input box in webview_flutter cannot successfully evoke the keyboard on Android 10, only the password input box, only on Android 10! ! !   If you solve it, I hope you can let me know, thank you
The relevant log is as follows:
error log:
E/InputMethodManager(32318): b/117267690: Failed to get fallback IMM with expected displayId=415 actual IMM#displayId=0 view=io.flutter.plugins.webviewflutter.InputAwareWebView{11e0c8d VFED..C.. .F...... 0,0-1080,1971} W/InputMethodManager(32318): startInputReason = 3 E/InputMethodManager(32318): b/117267690: Failed to get fallback IMM with expected displayId=415 actual IMM#displayId=0 view=io.flutter.plugins.webviewflutter.InputAwareWebView{11e0c8d VFED..C.. .F...... 0,0-1080,1971} I/InputMethodManager(32318): showSoftInput E/InputMethodManager(32318): b/117267690: Failed to get fallback IMM with expected displayId=415 actual IMM#displayId=0 view=io.flutter.plugins.webviewflutter.InputAwareWebView{11e0c8d VFED..C.. .F...... 0,0-1080,1971} I/flutter (32318): ViewStateModel---constructor--->ServiceModel E/InputMethodManager(32318): b/117267690: Failed to get fallback IMM with expected displayId=415 actual IMM#displayId=0 view=io.flutter.plugins.webviewflutter.InputAwareWebView{11e0c8d VFED..C.. ......ID 0,0-1080,1971} E/InputMethodManager(32318): b/117267690: Failed to get fallback IMM with expected displayId=415 actual IMM#displayId=0 view=io.flutter.plugins.webviewflutter.InputAwareWebView{11e0c8d VFED..C.. ......ID 0,0-1080,1971} W/InputMethodManager(32318): startInputReason = 3 I/DecorView[](32318):  old windowMode:0 new windoMode:1 W/libEGL  (32318): EGLNativeWindowType 0x6f17e9ced0 disconnect failed I/HiTouch_HiTouchSensor(32318): HiTouch restricted: Sub windows restricted. D/HiTouch_PressGestureDetector(32318): onAttached, package=com.fujian.daily, windowType=2037, mHiTouchRestricted=true D/mali_winsys(32318): EGLint new_window_surface(egl_winsys_display *, void *, EGLSurface, EGLConfig, egl_winsys_surface **, EGLBoolean) returns 0x3000 D/OpenGLRenderer(32318): disableOutlineDraw is true I/flutter (32318): ViewStateModel---constructor--->ServiceModel E/InputMethodManager(32318): b/117267690: Failed to get fallback IMM with expected displayId=416 actual IMM#displayId=0 view=io.flutter.plugins.webviewflutter.InputAwareWebView{11e0c8d VFED..C.. ......ID 0,0-1080,1059} E/InputMethodManager(32318): b/117267690: Failed to get fallback IMM with expected displayId=416 actual IMM#displayId=0 view=io.flutter.plugins.webviewflutter.InputAwareWebView{11e0c8d VFED..C.. ......ID 0,0-1080,1059} W/InputMethodManager(32318): startInputReason = 3 I/DecorView[](32318):  old windowMode:0 new windoMode:1 W/libEGL  (32318): EGLNativeWindowType 0x6f17e9ced0 disconnect failed I/HiTouch_HiTouchSensor(32318): HiTouch restricted: Sub windows restricted. D/HiTouch_PressGestureDetector(32318): onAttached, package=com.fujian.daily, windowType=2037, mHiTouchRestricted=true D/mali_winsys(32318): EGLint new_window_surface(egl_winsys_display *, void *, EGLSurface, EGLConfig, egl_winsys_surface **, EGLBoolean) returns 0x3000 D/OpenGLRenderer(32318): disableOutlineDraw is true
flutter doctor -v
`[✓] Flutter (Channel stable, v1.17.2, on Mac OS X 10.15.1 19B88, locale
zh-Hans-CN)
• Flutter version 1.17.2 at /Users/wangxin/Library/flutter/flutter
• Framework revision 5f21edf8b6 (12 days ago), 2020-05-28 12:44:12 -0700
• Engine revision b851c71829
• Dart version 2.8.3
[!] Android toolchain - develop for Android devices (Android SDK version 28.0.3)
• Android SDK at /Users/wangxin/Library/Android/sdk
• Platform android-29, build-tools 28.0.3
• Java binary at: /Applications/Android
Studio.app/Contents/jre/jdk/Contents/Home/bin/java
• Java version OpenJDK Runtime Environment (build
1.8.0_212-release-1586-b4-5784211)
! Some Android licenses not accepted.  To resolve this, run: flutter doctor
--android-licenses
[✓] Xcode - develop for iOS and macOS (Xcode 11.2.1)
• Xcode at /Applications/Xcode.app/Contents/Developer
• Xcode 11.2.1, Build version 11B500
• CocoaPods version 1.9.0
[✓] Android Studio (version 3.6)
• Android Studio at /Applications/Android Studio.app/Contents
• Flutter plugin version 45.1.1
• Dart plugin version 192.8052
• Java version OpenJDK Runtime Environment (build
1.8.0_212-release-1586-b4-5784211)
[!] IntelliJ IDEA Ultimate Edition (version 2019.1.2)
• IntelliJ at /Applications/IntelliJ IDEA.app
✗ Flutter plugin not installed; this adds Flutter specific functionality.
✗ Dart plugin not installed; this adds Dart specific functionality.
• For information about installing plugins, see
https://flutter.dev/intellij-setup/#installing-the-plugins
[✓] Connected device (1 available)
• ELE AL00 • GBGDU19821001370 • android-arm64 • Android 10 (API 29)
! Doctor found issues in 2 categories.`

入框无法成功触发Android 10上的键盘，只有密码输入框仅适用于Android 10！！！如果您解决了问题

这个问题我最近也很头大，我主要是为了解决search的问题。然后发现所有input都有问题，password的比较严重。我在尝试着看懂InputAwareWebView和ThreadedInputConnectionProxyAdapterView这两个文件。可惜的是我可能还是太菜了，需要花很多时间来解决。

@libo1223   是这个问题不好解决，键盘相关的，一个是密码输入框Android 10不能唤起键盘，一个是在其他输入的地方键盘起来了网页上下滚动的时候体验有点差。 寄希望于官方吧，  我刚看到另外一个地方说要换到master分支可能没问题，我准备试试

@libo1223 是这个问题不好解决，键盘相关的，一个是密码输入框Android 10不能唤起键盘，一个是在其他输入的地方键盘起来了网页上下滚动的时候体验有点差。 寄希望于官方吧， 我刚看到另外一个地方说要换到master分支可能没问题，我准备试试

我这边是原生密码键盘一闪而过，然后调起flutter的键盘，但是在flutter的键盘上输入，无法在input上显示，我也不确定他是否获取到了输入的值，就显示来看是没有。mix3 android 10.
顺便一提，我之前测了dev版本，问题还是存在，但是select的问题解决了。等官方解决的话是在太慢了，而且升级flutter后很多接口不一样了。如果master能解决的话请务必通知我一声

This issue not get any progress so long. There is a workaround : transfer to flutter_webview_plugin.
Then I am able to pick files. And if need to prevent navigation -- just set invalidUrlRegex in WebviewScaffold. And get the blocked url launch in statechange listener like:
flutterWebviewPlugin.onStateChanged.listen((event) {       if (event.type == WebViewState.abortLoad) {           //get the abortedLoad url here with event.url           ...        }   }
Hope it helps.

Using @libo1223 's code as a base I have managed to get a completely working solution for the file upload where it will prompt the user to either take a picture from the camera or choose from the native files app (this can be changed of course). It doesn't require making a custom layout for the intents. Here are the steps to make it work:
Open External Libraries > Flutter Plugins > webview_flutter > android > src.main> java.io. ...> FlutterWebView.java and add
    context1 = context;
    webView.setWebChromeClient ( new WebChromeClient () {
      @Override
      public  boolean onShowFileChooser (
              WebView webView, ValueCallback<Uri[]> filePathCallback,
              FileChooserParams fileChooserParams) {

        // Successfully jump to newActivity! ! ! Very nice
         // jump to newActivity to open the folder operation
        Intent intent = new Intent(context1, newActivity. class );
        newActivity.getfilePathCallback(filePathCallback);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context1.startActivity(intent);
        return true;
      }

      public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) {
        callback.invoke(origin, true, false);
      }

    });

after the line webView = new InputAwareWebView(context, containerView); and make sure to add the relative imports and variable declarations. After the imports and declarations the InputAwareWebView line was at line 54 (webview_flutter version 0.3.22+1).
Next, right click on the java.io. ... folder and create a new file, calling it newActivity.java. Inside this put all this code:
package io.flutter.plugins.webviewflutter;

import android.app.Activity;
import android.app.Dialog;
import android.content.ClipData;
import android.content.ComponentName;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.AssetFileDescriptor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Parcelable;
import android.provider.MediaStore;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.webkit.ValueCallback;

import androidx.annotation.Nullable;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class newActivity extends Activity {
    private static ValueCallback<Uri[]> mUploadMessages;
    private Object Utils;
    private File outputFile;
    private Uri mOutputFileUri;
    private Uri image;

    public static void getfilePathCallback(ValueCallback<Uri[]> filePathCallback){
        mUploadMessages = filePathCallback;
    }

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

        openImageIntent();
    }

    private Uri outputFileUri;

    private void openImageIntent() {
        try {
            outputFile = File.createTempFile("tmp", ".jpg", getCacheDir());
        } catch (IOException pE) {
            pE.printStackTrace();
        }
        File imageStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "FolderName");

        if (!imageStorageDir.exists()) {
            imageStorageDir.mkdirs();
        }
        File file = new File(imageStorageDir + File.separator + "IMG_" + String.valueOf(System.currentTimeMillis()) + ".jpg");
        mOutputFileUri = Uri.fromFile(file);

        // Camera.
        final Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, mOutputFileUri);

        // Filesystem.
        final Intent fileIntent = new Intent();
        fileIntent.setType("*/*");
        fileIntent.setAction(Intent.ACTION_GET_CONTENT);
        fileIntent.addCategory(Intent.CATEGORY_OPENABLE);

        // Chooser of filesystem options.
        final Intent chooserIntent = Intent.createChooser(fileIntent, "Select Source");

        // Add the camera options.
        chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Parcelable[]{captureIntent});
        startActivityForResult(chooserIntent, 42);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
        super.onActivityResult(requestCode, resultCode, intent);
        Uri[] results = null;
        try {
            if (resultCode != RESULT_OK) {
                results = null;
            } else {
                if (intent != null) {
                    String dataString = intent.getDataString();
                    ClipData clipData = intent.getClipData();
                    if (clipData != null) {
                        results = new Uri[clipData.getItemCount()];
                        for (int i = 0; i < clipData.getItemCount(); i++) {
                            ClipData.Item item = clipData.getItemAt(i);
                            results[i] = item.getUri();
                        }
                    }
                    if (dataString != null) {
                        results = new Uri[]{Uri.parse(dataString)};
                    }
                } else {
                    results = new Uri[]{mOutputFileUri};
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        mUploadMessages.onReceiveValue(results);
        mUploadMessages = null;
        finish();
    }
}

In the fileIntent.setType("*/*"); line you can change the MIME type for a specific type of file to fit your needs, like image/*.
Lastly, add
<activity
            android:name="io.flutter.plugins.webviewflutter.newActivity"
            android:theme="@android:style/Theme.Translucent.NoTitleBar"/>

in your app's AndroidManifest and that's all!
Now in the webview when you click a file upload button it should prompt for either camera or files, and upload correctly. Tested on SM-G975F running Android 10.

Issue is reproducibel on latest dev channel (1.20.0-0.0.pre) and with latest version of webview_flutter. Tapping on Choose file button does nothing.

flutter doctor -v
[✓] Flutter (Channel dev, 1.20.0-0.0.pre, on Mac OS X 10.15.2 19C57, locale en-US)
    • Flutter version 1.20.0-0.0.pre at /Users/deeptibelsare/Documents/Fluttersdk/flutter
    • Framework revision d9653445f4 (8 days ago), 2020-06-09 18:43:03 -0400
    • Engine revision e8c13aa012
    • Dart version 2.9.0 (build 2.9.0-14.0.dev 5c1376615e)

[!] Android toolchain - develop for Android devices (Android SDK version 29.0.3)
    • Android SDK at /Users/deeptibelsare/Library/Android/sdk
    • Platform android-29, build-tools 29.0.3
    • ANDROID_HOME = /Users/deeptibelsare/Library/Android/sdk
    • ANDROID_SDK_ROOT = /Users/deeptibelsare/Library/Android/sdk
    • Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 1.8.0_212-release-1586-b4-5784211)
    ✗ Android license status unknown.
      Try re-installing or updating your Android SDK Manager.
      See https://developer.android.com/studio/#downloads or visit https://flutter.dev/docs/get-started/install/macos#android-setup for detailed instructions.

[✓] Xcode - develop for iOS and macOS (Xcode 11.3)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Xcode 11.3, Build version 11C29
    • CocoaPods version 1.9.3

[✓] Android Studio (version 3.6)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin version 45.1.1
    • Dart plugin version 192.7761
    • Java version OpenJDK Runtime Environment (build 1.8.0_212-release-1586-b4-5784211)

[✓] Connected device (1 available)
    • Android SDK built for x86 • emulator-5554 • android-x86 • Android 8.1.0 (API 27) (emulator)

! Doctor found issues in 1 category.

The solution of @tneotia seems to work. Can this be merged into the webview_flutter library?

There is a workaround : transfer to powerful flutter_inappwebview.
@override
Widget build(BuildContext context) {
  return MaterialApp(
    home: Scaffold(
      appBar: AppBar(
        title: const Text('InAppWebView Example'),
      ),
      body: InAppWebView(
        initialUrl: "https://flutter.dev/",
        initialHeaders: {},
        onWebViewCreated: (InAppWebViewController controller) {
          webView = controller;
        },
        onLoadStart: (InAppWebViewController controller, String url) {
          setState(() {
            this.url = url;
          });
        },
        onLoadStop: (InAppWebViewController controller, String url) async {
          setState(() {
            this.url = url;
          });
        },
        onProgressChanged: (InAppWebViewController controller, int progress) {
          setState(() {
            this.progress = progress / 100;
          });
        },
      ),
    ),
  );
}

Using @libo1223 's code as a base I have managed to get a completely working solution for the file upload where it will prompt the user to either take a picture from the camera or choose from the native files app (this can be changed of course). It doesn't require making a custom layout for the intents. Here are the steps to make it work:
Open External Libraries > Flutter Plugins > webview_flutter > android > src.main> java.io. ...> FlutterWebView.java and add
    context1 = context;
    webView.setWebChromeClient ( new WebChromeClient () {
      @Override
      public  boolean onShowFileChooser (
              WebView webView, ValueCallback<Uri[]> filePathCallback,
              FileChooserParams fileChooserParams) {

        // Successfully jump to newActivity! ! ! Very nice
         // jump to newActivity to open the folder operation
        Intent intent = new Intent(context1, newActivity. class );
        newActivity.getfilePathCallback(filePathCallback);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context1.startActivity(intent);
        return true;
      }

      public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) {
        callback.invoke(origin, true, false);
      }

    });

after the line webView = new InputAwareWebView(context, containerView); and make sure to add the relative imports and variable declarations (check here just to make sure). After the imports and declarations the InputAwareWebView line was at line 54 (webview_flutter version 0.3.22+1).
Next, right click on the java.io. ... folder and create a new file, calling it newActivity.java. Inside this put all this code:
package io.flutter.plugins.webviewflutter;

import android.app.Activity;
import android.app.Dialog;
import android.content.ClipData;
import android.content.ComponentName;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.AssetFileDescriptor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Parcelable;
import android.provider.MediaStore;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.webkit.ValueCallback;

import androidx.annotation.Nullable;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class newActivity extends Activity {
    private static ValueCallback<Uri[]> mUploadMessages;
    private Object Utils;
    private File outputFile;
    private Uri mOutputFileUri;
    private Uri image;

    public static void getfilePathCallback(ValueCallback<Uri[]> filePathCallback){
        mUploadMessages = filePathCallback;
    }

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

        openImageIntent();
    }

    private Uri outputFileUri;

    private void openImageIntent() {
        try {
            outputFile = File.createTempFile("tmp", ".jpg", getCacheDir());
        } catch (IOException pE) {
            pE.printStackTrace();
        }
        File imageStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "FolderName");

        if (!imageStorageDir.exists()) {
            imageStorageDir.mkdirs();
        }
        File file = new File(imageStorageDir + File.separator + "IMG_" + String.valueOf(System.currentTimeMillis()) + ".jpg");
        mOutputFileUri = Uri.fromFile(file);

        // Camera.
        final Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, mOutputFileUri);

        // Filesystem.
        final Intent fileIntent = new Intent();
        fileIntent.setType("*/*");
        fileIntent.setAction(Intent.ACTION_GET_CONTENT);
        fileIntent.addCategory(Intent.CATEGORY_OPENABLE);

        // Chooser of filesystem options.
        final Intent chooserIntent = Intent.createChooser(fileIntent, "Select Source");

        // Add the camera options.
        chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Parcelable[]{captureIntent});
        startActivityForResult(chooserIntent, 42);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
        super.onActivityResult(requestCode, resultCode, intent);
        Uri[] results = null;
        try {
            if (resultCode != RESULT_OK) {
                results = null;
            } else {
                if (intent != null) {
                    String dataString = intent.getDataString();
                    ClipData clipData = intent.getClipData();
                    if (clipData != null) {
                        results = new Uri[clipData.getItemCount()];
                        for (int i = 0; i < clipData.getItemCount(); i++) {
                            ClipData.Item item = clipData.getItemAt(i);
                            results[i] = item.getUri();
                        }
                    }
                    if (dataString != null) {
                        results = new Uri[]{Uri.parse(dataString)};
                    }
                } else {
                    results = new Uri[]{mOutputFileUri};
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        mUploadMessages.onReceiveValue(results);
        mUploadMessages = null;
        finish();
    }
}

In the fileIntent.setType("*/*"); line you can change the MIME type for a specific type of file to fit your needs, like image/*.
After that, add
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

and
<activity
            android:name="io.flutter.plugins.webviewflutter.newActivity"
            android:theme="@android:style/Theme.Translucent.NoTitleBar"/>

in your app's AndroidManifest, and follow the steps in the the package permission_handler to set up the iOS Podfile. Then add
<key>NSPhotoLibraryUsageDescription</key>
<string>YOUR_REASON_HERE</string>

in your app's Info.plist.
Finally, you'll need to prompt the user for file access - you can either do this OS specific so it asks only when the file input is clicked or you could do it through Flutter, which I did. Use the package permission_handler again and add this code wherever:
bool storage = Platform.isAndroid ? await Permission.storage.isGranted : await Permission.photos.isGranted;
    if (!storage) {
      Platform.isAndroid? await Permission.storage.request() : await Permission.photos.request();
    }

Now in the webview when you click a file upload button it should prompt for either camera or files, and upload correctly. Tested on SM-G975F running Android 10.
Leave a thumbs up if this helped!

With your code:
-I can select a file and upload to HTML page.
-I can open the camera, but after taking the photo, Is not possible to upload it to HTML page.

This has been fixed in Flutter 1.22/ WebView 1.0 - use hybrid composition in the Flutter WebView plugin.
https://github.com/flutter/plugins/tree/master/packages/webview_flutter#using-hybrid-composition

This has been fixed in Flutter 1.22/ WebView 1.0 - use hybrid composition in the Flutter WebView plugin.
https://github.com/flutter/plugins/tree/master/packages/webview_flutter#using-hybrid-composition

WebView 1.0 version doesn't work.
Please refer to this plugin's way, thanks:     https://github.com/fluttercommunity/flutter_webview_plugin/blob/4862bd987cf8ce6695d8d280ab407d57e5ae30f0/android/src/main/java/com/flutter_webview_plugin/WebviewManager.java#L213

Using @libo1223 's code as a base I have managed to get a completely working solution for the file upload where it will prompt the user to either take a picture from the camera or choose from the native files app (this can be changed of course). It doesn't require making a custom layout for the intents. Here are the steps to make it work:
Open External Libraries > Flutter Plugins > webview_flutter > android > src.main> java.io. ...> FlutterWebView.java and add
    context1 = context;
    webView.setWebChromeClient ( new WebChromeClient () {
      @Override
      public  boolean onShowFileChooser (
              WebView webView, ValueCallback<Uri[]> filePathCallback,
              FileChooserParams fileChooserParams) {

        // Successfully jump to newActivity! ! ! Very nice
         // jump to newActivity to open the folder operation
        Intent intent = new Intent(context1, newActivity. class );
        newActivity.getfilePathCallback(filePathCallback);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context1.startActivity(intent);
        return true;
      }

      public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) {
        callback.invoke(origin, true, false);
      }

    });

after the line webView = new InputAwareWebView(context, containerView); and make sure to add the relative imports and variable declarations (check here just to make sure). After the imports and declarations the InputAwareWebView line was at line 54 (webview_flutter version 0.3.22+1).
Next, right click on the java.io. ... folder and create a new file, calling it newActivity.java. Inside this put all this code:
package io.flutter.plugins.webviewflutter;

import android.app.Activity;
import android.app.Dialog;
import android.content.ClipData;
import android.content.ComponentName;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.AssetFileDescriptor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Parcelable;
import android.provider.MediaStore;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.webkit.ValueCallback;

import androidx.annotation.Nullable;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class newActivity extends Activity {
    private static ValueCallback<Uri[]> mUploadMessages;
    private Object Utils;
    private File outputFile;
    private Uri mOutputFileUri;
    private Uri image;

    public static void getfilePathCallback(ValueCallback<Uri[]> filePathCallback){
        mUploadMessages = filePathCallback;
    }

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

        openImageIntent();
    }

    private Uri outputFileUri;

    private void openImageIntent() {
        try {
            outputFile = File.createTempFile("tmp", ".jpg", getCacheDir());
        } catch (IOException pE) {
            pE.printStackTrace();
        }
        File imageStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "FolderName");

        if (!imageStorageDir.exists()) {
            imageStorageDir.mkdirs();
        }
        File file = new File(imageStorageDir + File.separator + "IMG_" + String.valueOf(System.currentTimeMillis()) + ".jpg");
        mOutputFileUri = Uri.fromFile(file);

        // Camera.
        final Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, mOutputFileUri);

        // Filesystem.
        final Intent fileIntent = new Intent();
        fileIntent.setType("*/*");
        fileIntent.setAction(Intent.ACTION_GET_CONTENT);
        fileIntent.addCategory(Intent.CATEGORY_OPENABLE);

        // Chooser of filesystem options.
        final Intent chooserIntent = Intent.createChooser(fileIntent, "Select Source");

        // Add the camera options.
        chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Parcelable[]{captureIntent});
        startActivityForResult(chooserIntent, 42);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
        super.onActivityResult(requestCode, resultCode, intent);
        Uri[] results = null;
        try {
            if (resultCode != RESULT_OK) {
                results = null;
            } else {
                if (intent != null) {
                    String dataString = intent.getDataString();
                    ClipData clipData = intent.getClipData();
                    if (clipData != null) {
                        results = new Uri[clipData.getItemCount()];
                        for (int i = 0; i < clipData.getItemCount(); i++) {
                            ClipData.Item item = clipData.getItemAt(i);
                            results[i] = item.getUri();
                        }
                    }
                    if (dataString != null) {
                        results = new Uri[]{Uri.parse(dataString)};
                    }
                } else {
                    results = new Uri[]{mOutputFileUri};
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        mUploadMessages.onReceiveValue(results);
        mUploadMessages = null;
        finish();
    }
}

In the fileIntent.setType("*/*"); line you can change the MIME type for a specific type of file to fit your needs, like image/*.
After that, add
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

and
<activity
            android:name="io.flutter.plugins.webviewflutter.newActivity"
            android:theme="@android:style/Theme.Translucent.NoTitleBar"/>

in your app's AndroidManifest, and follow the steps in the the package permission_handler to set up the iOS Podfile. Then add
<key>NSPhotoLibraryUsageDescription</key>
<string>YOUR_REASON_HERE</string>

in your app's Info.plist.
Finally, you'll need to prompt the user for file access - you can either do this OS specific so it asks only when the file input is clicked or you could do it through Flutter, which I did. Use the package permission_handler again and add this code wherever:
bool storage = Platform.isAndroid ? await Permission.storage.isGranted : await Permission.photos.isGranted;
    if (!storage) {
      Platform.isAndroid? await Permission.storage.request() : await Permission.photos.request();
    }

Now in the webview when you click a file upload button it should prompt for either camera or files, and upload correctly. Tested on SM-G975F running Android 10.
Leave a thumbs up if this helped!

With your code:
-I can select a file and upload to HTML page.
-I can open the camera, but after taking the photo, Is not possible to upload it to HTML page.

i have the same problem...

Using @libo1223 's code as a base I have managed to get a completely working solution for the file upload where it will prompt the user to either take a picture from the camera or choose from the native files app (this can be changed of course). It doesn't require making a custom layout for the intents. Here are the steps to make it work:
Open External Libraries > Flutter Plugins > webview_flutter > android > src.main> java.io. ...> FlutterWebView.java and add
    context1 = context;
    webView.setWebChromeClient ( new WebChromeClient () {
      @Override
      public  boolean onShowFileChooser (
              WebView webView, ValueCallback<Uri[]> filePathCallback,
              FileChooserParams fileChooserParams) {

        // Successfully jump to newActivity! ! ! Very nice
         // jump to newActivity to open the folder operation
        Intent intent = new Intent(context1, newActivity. class );
        newActivity.getfilePathCallback(filePathCallback);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context1.startActivity(intent);
        return true;
      }

      public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) {
        callback.invoke(origin, true, false);
      }

    });

after the line webView = new InputAwareWebView(context, containerView); and make sure to add the relative imports and variable declarations (check here just to make sure). After the imports and declarations the InputAwareWebView line was at line 54 (webview_flutter version 0.3.22+1).
Next, right click on the java.io. ... folder and create a new file, calling it newActivity.java. Inside this put all this code:
package io.flutter.plugins.webviewflutter;

import android.app.Activity;
import android.app.Dialog;
import android.content.ClipData;
import android.content.ComponentName;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.AssetFileDescriptor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Parcelable;
import android.provider.MediaStore;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.webkit.ValueCallback;

import androidx.annotation.Nullable;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class newActivity extends Activity {
    private static ValueCallback<Uri[]> mUploadMessages;
    private Object Utils;
    private File outputFile;
    private Uri mOutputFileUri;
    private Uri image;

    public static void getfilePathCallback(ValueCallback<Uri[]> filePathCallback){
        mUploadMessages = filePathCallback;
    }

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

        openImageIntent();
    }

    private Uri outputFileUri;

    private void openImageIntent() {
        try {
            outputFile = File.createTempFile("tmp", ".jpg", getCacheDir());
        } catch (IOException pE) {
            pE.printStackTrace();
        }
        File imageStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "FolderName");

        if (!imageStorageDir.exists()) {
            imageStorageDir.mkdirs();
        }
        File file = new File(imageStorageDir + File.separator + "IMG_" + String.valueOf(System.currentTimeMillis()) + ".jpg");
        mOutputFileUri = Uri.fromFile(file);

        // Camera.
        final Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, mOutputFileUri);

        // Filesystem.
        final Intent fileIntent = new Intent();
        fileIntent.setType("*/*");
        fileIntent.setAction(Intent.ACTION_GET_CONTENT);
        fileIntent.addCategory(Intent.CATEGORY_OPENABLE);

        // Chooser of filesystem options.
        final Intent chooserIntent = Intent.createChooser(fileIntent, "Select Source");

        // Add the camera options.
        chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Parcelable[]{captureIntent});
        startActivityForResult(chooserIntent, 42);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
        super.onActivityResult(requestCode, resultCode, intent);
        Uri[] results = null;
        try {
            if (resultCode != RESULT_OK) {
                results = null;
            } else {
                if (intent != null) {
                    String dataString = intent.getDataString();
                    ClipData clipData = intent.getClipData();
                    if (clipData != null) {
                        results = new Uri[clipData.getItemCount()];
                        for (int i = 0; i < clipData.getItemCount(); i++) {
                            ClipData.Item item = clipData.getItemAt(i);
                            results[i] = item.getUri();
                        }
                    }
                    if (dataString != null) {
                        results = new Uri[]{Uri.parse(dataString)};
                    }
                } else {
                    results = new Uri[]{mOutputFileUri};
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        mUploadMessages.onReceiveValue(results);
        mUploadMessages = null;
        finish();
    }
}

In the fileIntent.setType("*/*"); line you can change the MIME type for a specific type of file to fit your needs, like image/*.
After that, add
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

and
<activity
            android:name="io.flutter.plugins.webviewflutter.newActivity"
            android:theme="@android:style/Theme.Translucent.NoTitleBar"/>

in your app's AndroidManifest, and follow the steps in the the package permission_handler to set up the iOS Podfile. Then add
<key>NSPhotoLibraryUsageDescription</key>
<string>YOUR_REASON_HERE</string>

in your app's Info.plist.
Finally, you'll need to prompt the user for file access - you can either do this OS specific so it asks only when the file input is clicked or you could do it through Flutter, which I did. Use the package permission_handler again and add this code wherever:
bool storage = Platform.isAndroid ? await Permission.storage.isGranted : await Permission.photos.isGranted;
    if (!storage) {
      Platform.isAndroid? await Permission.storage.request() : await Permission.photos.request();
    }

Now in the webview when you click a file upload button it should prompt for either camera or files, and upload correctly. Tested on SM-G975F running Android 10.
Leave a thumbs up if this helped!

With your code:
-I can select a file and upload to HTML page.
-I can open the camera, but after taking the photo, Is not possible to upload it to HTML page.

i have the same problem...

you can look it to fix. I run my demo now, and can't found any problem.
https://github.com/libo1223/plugins/commit/57af93947c8be6d8be28cb8bf6665bb70658b3f4

@libo1223 So if i want to use this plugin now, how to solve the choose file and input event problem ？

@libo1223 So if i want to use this plugin now, how to solve the choose file and input event problem ？

fork this , or change your code like this

@libo1223 Thank you! I also found some code #3225

@libo1223 Thank you! I also found some code #3225

To test @libo1223 solution, we need to change all these files? Like in this #3225 link?
packages/webview_flutter/android/src/main/AndroidManifest.xml
/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/Constants.java
/android/src/main/java/io/flutter/plugins/webviewflutter/FileChooserActivity.java
/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/Constants.java
/android/src/main/java/io/flutter/plugins/webviewflutter/FileChooserLauncher.java
and more...

@libo1223 Thank you! I also found some code #3225

To test @libo1223 solution, we need to change all these files? Like in this #3225 link?
packages/webview_flutter/android/src/main/AndroidManifest.xml
/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/Constants.java
/android/src/main/java/io/flutter/plugins/webviewflutter/FileChooserActivity.java
/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/Constants.java
/android/src/main/java/io/flutter/plugins/webviewflutter/FileChooserLauncher.java
and more...

You can use specific git commit in pubspec file.
Something like this:
webview_flutter:
    git:
      url: git@github.com:fesp/plugins.git
      path: packages/webview_flutter/
      ref: 42fdb08fe0d4bbbf7e0742a05e6343eb789e4b1d

@libo1223 Thank you! I also found some code #3225

To test @libo1223 solution, we need to change all these files? Like in this #3225 link?
packages/webview_flutter/android/src/main/AndroidManifest.xml
/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/Constants.java
/android/src/main/java/io/flutter/plugins/webviewflutter/FileChooserActivity.java
/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/Constants.java
/android/src/main/java/io/flutter/plugins/webviewflutter/FileChooserLauncher.java
and more...

You can use specific git commit in pubspec file.
Something like this:
webview_flutter:
    git:
      url: git@github.com:fesp/plugins.git
      path: packages/webview_flutter/
      ref: 42fdb08fe0d4bbbf7e0742a05e6343eb789e4b1d

Thank you @michaltrmac, it worked using like this:
webview_flutter:
    git:
      url: https://github.com/libo1223/plugins.git
      path: packages/webview_flutter

But even running the code from "\plugins-master\packages\webview_flutter\example"
It's returnning:
E/MediaStore(23322): Failed to insert image
E/MediaStore(23322): java.lang.SecurityException: Permission Denial: writing com.android.providers.media.MediaProvider uri content://media/external/images/media from pid=23322, uid=10170 requires android.permission.WRITE_EXTERNAL_STORAGE, or grantUriPermission()

When I press on

@libo1223 Thank you! I also found some code #3225

After changing all the code of webview_flutter like this code #3225
The app crash when I click on <input tipe="file">
W/System.err(12698): java.lang.NullPointerException: Attempt to invoke virtual method 'int android.content.Context.checkPermission(java.lang.String, int, int)' on a null object reference
W/System.err(12698): 	at androidx.core.content.ContextCompat.checkSelfPermission(ContextCompat.java:535)
W/System.err(12698): 	at io.flutter.plugins.webviewflutter.FileChooserLauncher.hasCameraPermission(FileChooserLauncher.java:60)
W/System.err(12698): 	at io.flutter.plugins.webviewflutter.FileChooserLauncher.start(FileChooserLauncher.java:65)
W/System.err(12698): 	at io.flutter.plugins.webviewflutter.FlutterWebView$FlutterWebChromeClient.onShowFileChooser(FlutterWebView.java:86)

@libo1223 Thank you! I also found some code #3225

After changing all the code of webview_flutter like this code #3225
The app crash when I click on <input tipe="file">
W/System.err(12698): java.lang.NullPointerException: Attempt to invoke virtual method 'int android.content.Context.checkPermission(java.lang.String, int, int)' on a null object reference
W/System.err(12698): 	at androidx.core.content.ContextCompat.checkSelfPermission(ContextCompat.java:535)
W/System.err(12698): 	at io.flutter.plugins.webviewflutter.FileChooserLauncher.hasCameraPermission(FileChooserLauncher.java:60)
W/System.err(12698): 	at io.flutter.plugins.webviewflutter.FileChooserLauncher.start(FileChooserLauncher.java:65)
W/System.err(12698): 	at io.flutter.plugins.webviewflutter.FlutterWebView$FlutterWebChromeClient.onShowFileChooser(FlutterWebView.java:86)

I had same problem with NullPointerException on checkPermission method and I resolved it by replacing Actvity with Context.
Check this commit https://github.com/michaltrmac/plugins/commit/9376b1e15998c2d46ac14ae3d41d913a3bcf0f93 for more info.
This work for my app.

@libo1223 Thank you! I also found some code #3225

After changing all the code of webview_flutter like this code #3225
The app crash when I click on <input tipe="file">
W/System.err(12698): java.lang.NullPointerException: Attempt to invoke virtual method 'int android.content.Context.checkPermission(java.lang.String, int, int)' on a null object reference
W/System.err(12698): 	at androidx.core.content.ContextCompat.checkSelfPermission(ContextCompat.java:535)
W/System.err(12698): 	at io.flutter.plugins.webviewflutter.FileChooserLauncher.hasCameraPermission(FileChooserLauncher.java:60)
W/System.err(12698): 	at io.flutter.plugins.webviewflutter.FileChooserLauncher.start(FileChooserLauncher.java:65)
W/System.err(12698): 	at io.flutter.plugins.webviewflutter.FlutterWebView$FlutterWebChromeClient.onShowFileChooser(FlutterWebView.java:86)

I had same problem with NullPointerException on checkPermission method and I resolved it by replacing Actvity with Context.
Check this commit michaltrmac/plugins@9376b1e for more info.
This work for my app.

Thank you @michaltrmac it worked well now. (I don't have idea how do you find these solutions)
There is only one problem for me. My html code is:
<input type="file" accept="image/*" capture>
Now it's possible to select a file. But I need the both option 1-Select a file, or 2-Take a picture.
The same as Chrome do.
Does anyone know how to do it?

@libo1223 Thank you! I also found some code #3225

After changing all the code of webview_flutter like this code #3225
The app crash when I click on <input tipe="file">
W/System.err(12698): java.lang.NullPointerException: Attempt to invoke virtual method 'int android.content.Context.checkPermission(java.lang.String, int, int)' on a null object reference
W/System.err(12698): 	at androidx.core.content.ContextCompat.checkSelfPermission(ContextCompat.java:535)
W/System.err(12698): 	at io.flutter.plugins.webviewflutter.FileChooserLauncher.hasCameraPermission(FileChooserLauncher.java:60)
W/System.err(12698): 	at io.flutter.plugins.webviewflutter.FileChooserLauncher.start(FileChooserLauncher.java:65)
W/System.err(12698): 	at io.flutter.plugins.webviewflutter.FlutterWebView$FlutterWebChromeClient.onShowFileChooser(FlutterWebView.java:86)

I had same problem with NullPointerException on checkPermission method and I resolved it by replacing Actvity with Context.
Check this commit michaltrmac/plugins@9376b1e for more info.
This work for my app.

Thank you @michaltrmac it worked well now. (I don't have idea how do you find these solutions)
There is only one problem for me. My html code is:
<input type="file" accept="image/*" capture>
Now it's possible to select a file. But I need the both option 1-Select a file, or 2-Take a picture.
The same as Chrome do.
Does anyone know how to do it?

@brnyza You have to request CAMERA permission.
Add
<uses-permission android:name="android.permission.CAMERA" />

to android/app/src/main/AndroidManifest.xml and use some plugin to request permissions in app.
I use this plugin https://pub.dev/packages/permission_handler and then in app request permission with code like this:
PermissionStatus status = await Permission.camera.status;
if (status.isUndetermined) {
    await Permission.camera.request();
}

I also fully uninstalled the app from phone and install it again.

@libo1223 Thank you! I also found some code #3225

After changing all the code of webview_flutter like this code #3225
The app crash when I click on <input tipe="file">
W/System.err(12698): java.lang.NullPointerException: Attempt to invoke virtual method 'int android.content.Context.checkPermission(java.lang.String, int, int)' on a null object reference
W/System.err(12698): 	at androidx.core.content.ContextCompat.checkSelfPermission(ContextCompat.java:535)
W/System.err(12698): 	at io.flutter.plugins.webviewflutter.FileChooserLauncher.hasCameraPermission(FileChooserLauncher.java:60)
W/System.err(12698): 	at io.flutter.plugins.webviewflutter.FileChooserLauncher.start(FileChooserLauncher.java:65)
W/System.err(12698): 	at io.flutter.plugins.webviewflutter.FlutterWebView$FlutterWebChromeClient.onShowFileChooser(FlutterWebView.java:86)

I had same problem with NullPointerException on checkPermission method and I resolved it by replacing Actvity with Context.
Check this commit michaltrmac/plugins@9376b1e for more info.
This work for my app.

Thank you @michaltrmac it worked well now. (I don't have idea how do you find these solutions)
There is only one problem for me. My html code is:
<input type="file" accept="image/*" capture>
Now it's possible to select a file. But I need the both option 1-Select a file, or 2-Take a picture.
The same as Chrome do.
Does anyone know how to do it?

@brnyza You have to request CAMERA permission.
Add
<uses-permission android:name="android.permission.CAMERA" />

to android/app/src/main/AndroidManifest.xml and use some plugin to request permissions in app.
I use this plugin https://pub.dev/packages/permission_handler and then in app request permission with code like this:
PermissionStatus status = await Permission.camera.status;
if (status.isUndetermined) {
    await Permission.camera.request();
}

I also fully uninstalled the app from phone and install it again.

@michaltrmac Thank you more one time, worked perfectly!

@libo1223  and @michaltrmac thank you so much, I have a problem. I applied the codes, but when I upload a picture from the camera, it does not load the page. When I choose it from the gallery, it loads without any problem. Do you have an opinion on this?

@libo1223 and @michaltrmac thank you so much, I have a problem. I applied the codes, but when I upload a picture from the camera, it does not load the page. When I choose it from the gallery, it loads without any problem. Do you have an opinion on this?

img upload but image type goes blank

since july 2019 checking this thread every month to see if the workarounds got polished and merged
and I am in awe that how such a crucial and small fix took this long and still not published

since july 2019 checking this thread every month to see if the workarounds got polished and merged
and I am in awe that how such a crucial and small fix took this long and still not published

I am still facing this issue, none of the above forks seem to work for me.

I am still facing the issue too.

I am still facing the issue too.

The problem is solved but not working on mi note 9 pro series phones

The problem is solved but not working on mi note 9 pro series phones

#hamed2f

#hamed2f

#۲۷۹۲۴

#۲۷۹۲۴

Any update in file upload ? Its one of the serious issue

Any update in file upload ? Its one of the serious issue

Using @libo1223 's code as a base I have managed to get a completely working solution for the file upload where it will prompt the user to either take a picture from the camera or choose from the native files app (this can be changed of course). It doesn't require making a custom layout for the intents. Here are the steps to make it work:
Open External Libraries > Flutter Plugins > webview_flutter > android > src.main> java.io. ...> FlutterWebView.java and add
    context1 = context;
    webView.setWebChromeClient ( new WebChromeClient () {
      @Override
      public  boolean onShowFileChooser (
              WebView webView, ValueCallback<Uri[]> filePathCallback,
              FileChooserParams fileChooserParams) {

        // Successfully jump to newActivity! ! ! Very nice
         // jump to newActivity to open the folder operation
        Intent intent = new Intent(context1, newActivity. class );
        newActivity.getfilePathCallback(filePathCallback);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context1.startActivity(intent);
        return true;
      }

      public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) {
        callback.invoke(origin, true, false);
      }

    });

after the line webView = new InputAwareWebView(context, containerView); and make sure to add the relative imports and variable declarations (check here just to make sure). After the imports and declarations the InputAwareWebView line was at line 54 (webview_flutter version 0.3.22+1).
Next, right click on the java.io. ... folder and create a new file, calling it newActivity.java. Inside this put all this code:
package io.flutter.plugins.webviewflutter;

import android.app.Activity;
import android.app.Dialog;
import android.content.ClipData;
import android.content.ComponentName;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.AssetFileDescriptor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Parcelable;
import android.provider.MediaStore;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.webkit.ValueCallback;

import androidx.annotation.Nullable;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class newActivity extends Activity {
    private static ValueCallback<Uri[]> mUploadMessages;
    private Object Utils;
    private File outputFile;
    private Uri mOutputFileUri;
    private Uri image;

    public static void getfilePathCallback(ValueCallback<Uri[]> filePathCallback){
        mUploadMessages = filePathCallback;
    }

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

        openImageIntent();
    }

    private Uri outputFileUri;

    private void openImageIntent() {
        try {
            outputFile = File.createTempFile("tmp", ".jpg", getCacheDir());
        } catch (IOException pE) {
            pE.printStackTrace();
        }
        File imageStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "FolderName");

        if (!imageStorageDir.exists()) {
            imageStorageDir.mkdirs();
        }
        File file = new File(imageStorageDir + File.separator + "IMG_" + String.valueOf(System.currentTimeMillis()) + ".jpg");
        mOutputFileUri = Uri.fromFile(file);

        // Camera.
        final Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, mOutputFileUri);

        // Filesystem.
        final Intent fileIntent = new Intent();
        fileIntent.setType("*/*");
        fileIntent.setAction(Intent.ACTION_GET_CONTENT);
        fileIntent.addCategory(Intent.CATEGORY_OPENABLE);

        // Chooser of filesystem options.
        final Intent chooserIntent = Intent.createChooser(fileIntent, "Select Source");

        // Add the camera options.
        chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Parcelable[]{captureIntent});
        startActivityForResult(chooserIntent, 42);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
        super.onActivityResult(requestCode, resultCode, intent);
        Uri[] results = null;
        try {
            if (resultCode != RESULT_OK) {
                results = null;
            } else {
                if (intent != null) {
                    String dataString = intent.getDataString();
                    ClipData clipData = intent.getClipData();
                    if (clipData != null) {
                        results = new Uri[clipData.getItemCount()];
                        for (int i = 0; i < clipData.getItemCount(); i++) {
                            ClipData.Item item = clipData.getItemAt(i);
                            results[i] = item.getUri();
                        }
                    }
                    if (dataString != null) {
                        results = new Uri[]{Uri.parse(dataString)};
                    }
                } else {
                    results = new Uri[]{mOutputFileUri};
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        mUploadMessages.onReceiveValue(results);
        mUploadMessages = null;
        finish();
    }
}

In the fileIntent.setType("*/*"); line you can change the MIME type for a specific type of file to fit your needs, like image/*.
After that, add
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

and
<activity
            android:name="io.flutter.plugins.webviewflutter.newActivity"
            android:theme="@android:style/Theme.Translucent.NoTitleBar"/>

in your app's AndroidManifest, and follow the steps in the the package permission_handler to set up the iOS Podfile. Then add
<key>NSPhotoLibraryUsageDescription</key>
<string>YOUR_REASON_HERE</string>

in your app's Info.plist.
Finally, you'll need to prompt the user for file access - you can either do this OS specific so it asks only when the file input is clicked or you could do it through Flutter, which I did. Use the package permission_handler again and add this code wherever:
bool storage = Platform.isAndroid ? await Permission.storage.isGranted : await Permission.photos.isGranted;
    if (!storage) {
      Platform.isAndroid? await Permission.storage.request() : await Permission.photos.request();
    }

Now in the webview when you click a file upload button it should prompt for either camera or files, and upload correctly. Tested on SM-G975F running Android 10.
Leave a thumbs up if this helped!

With your code:
-I can select a file and upload to HTML page.
-I can open the camera, but after taking the photo, Is not possible to upload it to HTML page.

i have the same problem...

you can look it to fix. I run my demo now, and can't found any problem.
libo1223/plugins@57af939

I followed the same steps you mentioned but got this error
Launching lib/main.dart on sdk gphone x86 arm in debug mode...
Running Gradle task 'assembleDebug'...
/home/paras/AndroidStudioProjects/inspireip_app/android/app/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebViewClient.java:5: error: cannot find symbol
public FlutterWebViewClient(MethodChannel methodChannel) {
^
symbol:   class MethodChannel
location: class FlutterWebViewClient
Note: /home/paras/AndroidStudioProjects/inspireip_app/android/app/src/main/java/io/flutter/plugins/newActivity.java uses or overrides a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
1 error
FAILURE: Build failed with an exception.

What went wrong:
Execution failed for task ':app:compileDebugJavaWithJavac'.

Compilation failed; see the compiler error output for details.

Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

Get more help at https://help.gradle.org

BUILD FAILED in 6s
Exception: Gradle task assembleDebug failed with exit code 1

Using @libo1223 's code as a base I have managed to get a completely working solution for the file upload where it will prompt the user to either take a picture from the camera or choose from the native files app (this can be changed of course). It doesn't require making a custom layout for the intents. Here are the steps to make it work:
Open External Libraries > Flutter Plugins > webview_flutter > android > src.main> java.io. ...> FlutterWebView.java and add
    context1 = context;
    webView.setWebChromeClient ( new WebChromeClient () {
      @Override
      public  boolean onShowFileChooser (
              WebView webView, ValueCallback<Uri[]> filePathCallback,
              FileChooserParams fileChooserParams) {

        // Successfully jump to newActivity! ! ! Very nice
         // jump to newActivity to open the folder operation
        Intent intent = new Intent(context1, newActivity. class );
        newActivity.getfilePathCallback(filePathCallback);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context1.startActivity(intent);
        return true;
      }

      public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) {
        callback.invoke(origin, true, false);
      }

    });

after the line webView = new InputAwareWebView(context, containerView); and make sure to add the relative imports and variable declarations (check here just to make sure). After the imports and declarations the InputAwareWebView line was at line 54 (webview_flutter version 0.3.22+1).
Next, right click on the java.io. ... folder and create a new file, calling it newActivity.java. Inside this put all this code:
package io.flutter.plugins.webviewflutter;

import android.app.Activity;
import android.app.Dialog;
import android.content.ClipData;
import android.content.ComponentName;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.AssetFileDescriptor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Parcelable;
import android.provider.MediaStore;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.webkit.ValueCallback;

import androidx.annotation.Nullable;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class newActivity extends Activity {
    private static ValueCallback<Uri[]> mUploadMessages;
    private Object Utils;
    private File outputFile;
    private Uri mOutputFileUri;
    private Uri image;

    public static void getfilePathCallback(ValueCallback<Uri[]> filePathCallback){
        mUploadMessages = filePathCallback;
    }

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

        openImageIntent();
    }

    private Uri outputFileUri;

    private void openImageIntent() {
        try {
            outputFile = File.createTempFile("tmp", ".jpg", getCacheDir());
        } catch (IOException pE) {
            pE.printStackTrace();
        }
        File imageStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "FolderName");

        if (!imageStorageDir.exists()) {
            imageStorageDir.mkdirs();
        }
        File file = new File(imageStorageDir + File.separator + "IMG_" + String.valueOf(System.currentTimeMillis()) + ".jpg");
        mOutputFileUri = Uri.fromFile(file);

        // Camera.
        final Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, mOutputFileUri);

        // Filesystem.
        final Intent fileIntent = new Intent();
        fileIntent.setType("*/*");
        fileIntent.setAction(Intent.ACTION_GET_CONTENT);
        fileIntent.addCategory(Intent.CATEGORY_OPENABLE);

        // Chooser of filesystem options.
        final Intent chooserIntent = Intent.createChooser(fileIntent, "Select Source");

        // Add the camera options.
        chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Parcelable[]{captureIntent});
        startActivityForResult(chooserIntent, 42);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
        super.onActivityResult(requestCode, resultCode, intent);
        Uri[] results = null;
        try {
            if (resultCode != RESULT_OK) {
                results = null;
            } else {
                if (intent != null) {
                    String dataString = intent.getDataString();
                    ClipData clipData = intent.getClipData();
                    if (clipData != null) {
                        results = new Uri[clipData.getItemCount()];
                        for (int i = 0; i < clipData.getItemCount(); i++) {
                            ClipData.Item item = clipData.getItemAt(i);
                            results[i] = item.getUri();
                        }
                    }
                    if (dataString != null) {
                        results = new Uri[]{Uri.parse(dataString)};
                    }
                } else {
                    results = new Uri[]{mOutputFileUri};
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        mUploadMessages.onReceiveValue(results);
        mUploadMessages = null;
        finish();
    }
}

In the fileIntent.setType("*/*"); line you can change the MIME type for a specific type of file to fit your needs, like image/*.
After that, add
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

and
<activity
            android:name="io.flutter.plugins.webviewflutter.newActivity"
            android:theme="@android:style/Theme.Translucent.NoTitleBar"/>

in your app's AndroidManifest, and follow the steps in the the package permission_handler to set up the iOS Podfile. Then add
<key>NSPhotoLibraryUsageDescription</key>
<string>YOUR_REASON_HERE</string>

in your app's Info.plist.
Finally, you'll need to prompt the user for file access - you can either do this OS specific so it asks only when the file input is clicked or you could do it through Flutter, which I did. Use the package permission_handler again and add this code wherever:
bool storage = Platform.isAndroid ? await Permission.storage.isGranted : await Permission.photos.isGranted;
    if (!storage) {
      Platform.isAndroid? await Permission.storage.request() : await Permission.photos.request();
    }

Now in the webview when you click a file upload button it should prompt for either camera or files, and upload correctly. Tested on SM-G975F running Android 10.
Leave a thumbs up if this helped!

With your code:
-I can select a file and upload to HTML page.
-I can open the camera, but after taking the photo, Is not possible to upload it to HTML page.

i have the same problem...

you can look it to fix. I run my demo now, and can't found any problem.
libo1223/plugins@57af939

I followed the same steps you mentioned but got this error
Launching lib/main.dart on sdk gphone x86 arm in debug mode...
Running Gradle task 'assembleDebug'...
/home/paras/AndroidStudioProjects/inspireip_app/android/app/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebViewClient.java:5: error: cannot find symbol
public FlutterWebViewClient(MethodChannel methodChannel) {
^
symbol:   class MethodChannel
location: class FlutterWebViewClient
Note: /home/paras/AndroidStudioProjects/inspireip_app/android/app/src/main/java/io/flutter/plugins/newActivity.java uses or overrides a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
1 error
FAILURE: Build failed with an exception.

What went wrong:
Execution failed for task ':app:compileDebugJavaWithJavac'.

Compilation failed; see the compiler error output for details.

Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

Get more help at https://help.gradle.org

BUILD FAILED in 6s
Exception: Gradle task assembleDebug failed with exit code 1

The Version of the Flutter is upgraded, so my code maybe have error. Unfortunately, I don't study flutter now. But the key of the issues is override the function what is
webView.setWebChromeClient ( new WebChromeClient () {
      @Override
      public  boolean onShowFileChooser (
              WebView webView, ValueCallback<Uri[]> filePathCallback,
              FileChooserParams fileChooserParams) {

        // Successfully jump to newActivity! ! ! Very nice
         // jump to newActivity to open the folder operation
        Intent intent = new Intent(context1, newActivity. class );
        newActivity.getfilePathCallback(filePathCallback);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context1.startActivity(intent);
        return true;
      }

      public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) {
        callback.invoke(origin, true, false);
      }

    });

The Version of the Flutter is upgraded, so my code maybe have error. Unfortunately, I don't study flutter now. But the key of the issues is override the function what is
webView.setWebChromeClient ( new WebChromeClient () {
      @Override
      public  boolean onShowFileChooser (
              WebView webView, ValueCallback<Uri[]> filePathCallback,
              FileChooserParams fileChooserParams) {

        // Successfully jump to newActivity! ! ! Very nice
         // jump to newActivity to open the folder operation
        Intent intent = new Intent(context1, newActivity. class );
        newActivity.getfilePathCallback(filePathCallback);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context1.startActivity(intent);
        return true;
      }

      public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) {
        callback.invoke(origin, true, false);
      }

    });

All, I will try to update my tutorial to fix the file chooser tomorrow, but no promises 😉
Personally I have migrated to flutter_inappwebview because it fits my needs better, but I'll try to help all y'all out who depend on this plugin and this functionality.

All, I will try to update my tutorial to fix the file chooser tomorrow, but no promises 😉
Personally I have migrated to flutter_inappwebview because it fits my needs better, but I'll try to help all y'all out who depend on this plugin and this functionality.

Alright all, I have solved the file upload issue again with the following code. Tested on Galaxy S8 Android 9, release mode and debug mode with uploading website as https://pasteboard.co and webview_flutter: ^1.0.7. Tested both standard rendering method and new hybrid composition rendering method.
Instructions

Open External Libraries > Flutter Plugins > webview_flutter > android > src.main> java.io. ...> FlutterWebView.java.
Inside the imports add:

import android.content.Intent;
import android.net.Uri;
import android.webkit.ValueCallback;

Add Context context1; as a variable in public class FlutterWebView.
Inside the private class FlutterWebChromeClient below onCreateWindow() add:

@Override
    public boolean onShowFileChooser(
            WebView webView, ValueCallback<Uri[]> filePathCallback,
            WebChromeClient.FileChooserParams fileChooserParams) {
      Intent intent = new Intent(context1, newActivity.class);
      newActivity.getfilePathCallback(filePathCallback);
      intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
      context1.startActivity(intent);
      return true;
    }

Inside FlutterWebView() right around the line webView.getSettings().<something> (around line 110 in code), add:

context1 = context;
webView.getSettings().setAllowContentAccess(true);
webView.getSettings().setAllowFileAccess(true);

Finally, create your newActivity.java file in the same directory, copy the code from here.

Now you are done with the webview_flutter code. For reference, FlutterWebView.java should be around 438 lines total.
In your own app,

In AndroidManifest, add:

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

Above the .MainActivity declaration in AndroidManifest add:

<activity
            android:name="io.flutter.plugins.webviewflutter.newActivity"
            android:theme="@android:style/Theme.Translucent.NoTitleBar"/>

The last thing left to do is in Dart. Use the permission_handler plugin (or something similar, for these instructions I am using that) to request for your permissions at runtime like so:
await Permission.camera.request();
await Permission.storage.request();

These requests return bool, so you can check whether the user granted or denied the permission and perform actions accordingly.

Let's try to keep this thread clean and avoid quoting my huge post, this is why I put it in a dropdown - but I'm not sure if GitHub will preserve the dropdown when quoted. Let me know of any issues and I may be able to take care of them, and leave a thumbs up if it worked for you!

Alright all, I have solved the file upload issue again with the following code. Tested on Galaxy S8 Android 9, release mode and debug mode with uploading website as https://pasteboard.co and webview_flutter: ^1.0.7. Tested both standard rendering method and new hybrid composition rendering method.
Instructions

Open External Libraries > Flutter Plugins > webview_flutter > android > src.main> java.io. ...> FlutterWebView.java.
Inside the imports add:

import android.content.Intent;
import android.net.Uri;
import android.webkit.ValueCallback;

Add Context context1; as a variable in public class FlutterWebView.
Inside the private class FlutterWebChromeClient below onCreateWindow() add:

@Override
    public boolean onShowFileChooser(
            WebView webView, ValueCallback<Uri[]> filePathCallback,
            WebChromeClient.FileChooserParams fileChooserParams) {
      Intent intent = new Intent(context1, newActivity.class);
      newActivity.getfilePathCallback(filePathCallback);
      intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
      context1.startActivity(intent);
      return true;
    }

Inside FlutterWebView() right around the line webView.getSettings().<something> (around line 110 in code), add:

context1 = context;
webView.getSettings().setAllowContentAccess(true);
webView.getSettings().setAllowFileAccess(true);

Finally, create your newActivity.java file in the same directory, copy the code from here.

Now you are done with the webview_flutter code. For reference, FlutterWebView.java should be around 438 lines total.
In your own app,

In AndroidManifest, add:

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

Above the .MainActivity declaration in AndroidManifest add:

<activity
            android:name="io.flutter.plugins.webviewflutter.newActivity"
            android:theme="@android:style/Theme.Translucent.NoTitleBar"/>

The last thing left to do is in Dart. Use the permission_handler plugin (or something similar, for these instructions I am using that) to request for your permissions at runtime like so:
await Permission.camera.request();
await Permission.storage.request();

These requests return bool, so you can check whether the user granted or denied the permission and perform actions accordingly.

Let's try to keep this thread clean and avoid quoting my huge post, this is why I put it in a dropdown - but I'm not sure if GitHub will preserve the dropdown when quoted. Let me know of any issues and I may be able to take care of them, and leave a thumbs up if it worked for you!

@Paras-Gupta790 you thumbs down so what issue did you have with the above? I can try and fix it...

@Paras-Gupta790 you thumbs down so what issue did you have with the above? I can try and fix it...

This is not working at my end. I am using dropzone for file uploading. When I click on the dropzone, the file chooser doesn't open.

This is not working at my end. I am using dropzone for file uploading. When I click on the dropzone, the file chooser doesn't open.

This is not working at my end. I am using dropzone for file uploading. When I click on the dropzone, the file chooser doesn't open.

What is the URL? Is it https://www.dropzonejs.com?

This is not working at my end. I am using dropzone for file uploading. When I click on the dropzone, the file chooser doesn't open.

What is the URL? Is it https://www.dropzonejs.com?

Yes

Yes

Okay I will look into it in a few hours and update the tutorial above if necessary.

Okay I will look into it in a few hours and update the tutorial above if necessary.

Sure. Thank you so much.

Sure. Thank you so much.

@tneotia - If you can share the complete code of WebviewFlutter.java, then it will be great for all the developers working in this ddomain.

@tneotia - If you can share the complete code of WebviewFlutter.java, then it will be great for all the developers working in this ddomain.

@Paras-Gupta790 working great for me:
https://user-images.githubusercontent.com/50850142/106361889-d7123d00-62ed-11eb-8cfe-dd19e73ba9a8.mp4
Nevertheless I will redo my instructions above to instead provide a gist of the FlutterWebView file.

@Paras-Gupta790 working great for me:
https://user-images.githubusercontent.com/50850142/106361889-d7123d00-62ed-11eb-8cfe-dd19e73ba9a8.mp4
Nevertheless I will redo my instructions above to instead provide a gist of the FlutterWebView file.

Can you please share the code, I guess I am doing something wrong

Can you please share the code, I guess I am doing something wrong

Here is my code -
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'package:url_launcher/url_launcher.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
          body: SafeArea(
            child : WebView(
              initialUrl: 'https://user-profile.com',
              javascriptMode: JavascriptMode.unrestricted,
              navigationDelegate: (NavigationRequest request) {
                if (request.url.contains("mailto:")) {
                  launch(request.url);
                  return NavigationDecision.prevent;
                }
                // if (request.url.contains("download")) {
                //   launch(request.url);
                //   return NavigationDecision.prevent;
                // }
                return NavigationDecision.navigate;
              },
            ),
          )
      ),
    );
  }
}

Here is my code -
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'package:url_launcher/url_launcher.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
          body: SafeArea(
            child : WebView(
              initialUrl: 'https://user-profile.com',
              javascriptMode: JavascriptMode.unrestricted,
              navigationDelegate: (NavigationRequest request) {
                if (request.url.contains("mailto:")) {
                  launch(request.url);
                  return NavigationDecision.prevent;
                }
                // if (request.url.contains("download")) {
                //   launch(request.url);
                //   return NavigationDecision.prevent;
                // }
                return NavigationDecision.navigate;
              },
            ),
          )
      ),
    );
  }
}

@Paras-Gupta790 and all others, I have solved the file upload issue again with the following code. Tested on Galaxy S8 Android 9, release mode and debug mode with uploading website as https://pasteboard.co and https://dropzonejs.com, and webview_flutter: ^1.0.7. Tested both standard rendering method and new hybrid composition rendering method. Both images and file upload should function correctly now.
Instructions

Open External Libraries > Flutter Plugins > webview_flutter > android > src.main> java.io. ...> FlutterWebView.java.
Replace code in this file from the code here.
Create a newActivity.java file in the same directory, copy the code from here.

In your own app,

In AndroidManifest, add:

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

If you don't want the camera choosing capability you can leave out the camera permission.
2. Above the .MainActivity declaration in AndroidManifest add:
<activity
            android:name="io.flutter.plugins.webviewflutter.newActivity"
            android:theme="@android:style/Theme.Translucent.NoTitleBar"/>

The last thing left to do is in Dart. Use the permission_handler plugin (or something similar, for these instructions I am using that) to request for your permissions at runtime like so:
await Permission.camera.request();
await Permission.storage.request();

These requests return bool, so you can check whether the user granted or denied the permission and perform actions accordingly. Again, if you don't want the camera choosing functionality you don't need to request for the camera permission.
Depending on how the website is set up, you may need to use JavascriptMode.unrestricted:
WebView(
    initialUrl: your_url,
    javascriptMode: JavascriptMode.unrestricted,
    //any other parameters
),

Let's try to keep this thread clean and avoid quoting my huge post, this is why I put it in a dropdown - but I'm not sure if GitHub will preserve the dropdown when quoted. Let me know of any issues and I may be able to take care of them, and leave a thumbs up if it worked for you!

@Paras-Gupta790 and all others, I have solved the file upload issue again with the following code. Tested on Galaxy S8 Android 9, release mode and debug mode with uploading website as https://pasteboard.co and https://dropzonejs.com, and webview_flutter: ^1.0.7. Tested both standard rendering method and new hybrid composition rendering method. Both images and file upload should function correctly now.
Instructions

Open External Libraries > Flutter Plugins > webview_flutter > android > src.main> java.io. ...> FlutterWebView.java.
Replace code in this file from the code here.
Create a newActivity.java file in the same directory, copy the code from here.

In your own app,

In AndroidManifest, add:

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

If you don't want the camera choosing capability you can leave out the camera permission.
2. Above the .MainActivity declaration in AndroidManifest add:
<activity
            android:name="io.flutter.plugins.webviewflutter.newActivity"
            android:theme="@android:style/Theme.Translucent.NoTitleBar"/>

The last thing left to do is in Dart. Use the permission_handler plugin (or something similar, for these instructions I am using that) to request for your permissions at runtime like so:
await Permission.camera.request();
await Permission.storage.request();

These requests return bool, so you can check whether the user granted or denied the permission and perform actions accordingly. Again, if you don't want the camera choosing functionality you don't need to request for the camera permission.
Depending on how the website is set up, you may need to use JavascriptMode.unrestricted:
WebView(
    initialUrl: your_url,
    javascriptMode: JavascriptMode.unrestricted,
    //any other parameters
),

Let's try to keep this thread clean and avoid quoting my huge post, this is why I put it in a dropdown - but I'm not sure if GitHub will preserve the dropdown when quoted. Let me know of any issues and I may be able to take care of them, and leave a thumbs up if it worked for you!

Here is my code -

Looks fine, you probably made a mistake in the java files, I updated the instructions above.

Here is my code -

Looks fine, you probably made a mistake in the java files, I updated the instructions above.

Is the path of files correct or not?
Path of file ->

/AndroidStudioProjects/profile_app/android/app/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebView.java

Is the path of files correct or not?
Path of file ->

/AndroidStudioProjects/profile_app/android/app/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebView.java

No that doesn't look right, you shouldn't have an existing file there in that directory I think. Mine is like so:

C:\flutter.pub-cache\hosted\pub.dartlang.org\webview_flutter-1.0.7\android\src\main\java\io\flutter\plugins\webviewflutter\FlutterWebView.java

In android studio you access this like so:

No that doesn't look right, you shouldn't have an existing file there in that directory I think. Mine is like so:

C:\flutter.pub-cache\hosted\pub.dartlang.org\webview_flutter-1.0.7\android\src\main\java\io\flutter\plugins\webviewflutter\FlutterWebView.java

In android studio you access this like so:

WHere we have to do these modifications? -

The last thing left to do is in Dart. Use the permission_handler plugin (or something similar, for these instructions I am using that) to request for your permissions at runtime like so:
await Permission.camera.request();
await Permission.storage.request();
These requests return bool, so you can check whether the user granted or denied the permission and perform actions accordingly. Again, if you don't want the camera choosing functionality you don't need to request for the camera permission.

WHere we have to do these modifications? -

The last thing left to do is in Dart. Use the permission_handler plugin (or something similar, for these instructions I am using that) to request for your permissions at runtime like so:
await Permission.camera.request();
await Permission.storage.request();
These requests return bool, so you can check whether the user granted or denied the permission and perform actions accordingly. Again, if you don't want the camera choosing functionality you don't need to request for the camera permission.

Anytime before the user will click file upload will work. I don't know of a way to detect when a user has clicked on file upload, but you could put that code in initState or something to make it work.

Anytime before the user will click file upload will work. I don't know of a way to detect when a user has clicked on file upload, but you could put that code in initState or something to make it work.

Not working at my end. When I click on the dropzone it throws me an error and asks me to send the bug report for analysis.
I have added these permissions here -
`import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:permission_handler/permission_handler.dart';
void main() {
Permission.camera.request();
Permission.storage.request();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: SafeArea(
child : WebView(
initialUrl: 'https://user-profile.com',
javascriptMode: JavascriptMode.unrestricted,
navigationDelegate: (NavigationRequest request) {
if (request.url.contains("mailto:")) {
launch(request.url);
return NavigationDecision.prevent;
}
// if (request.url.contains("download")) {
//   launch(request.url);
//   return NavigationDecision.prevent;
// }
return NavigationDecision.navigate;
},
),
)
),
);
}
}
`

Not working at my end. When I click on the dropzone it throws me an error and asks me to send the bug report for analysis.
I have added these permissions here -
`import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:permission_handler/permission_handler.dart';
void main() {
Permission.camera.request();
Permission.storage.request();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: SafeArea(
child : WebView(
initialUrl: 'https://user-profile.com',
javascriptMode: JavascriptMode.unrestricted,
navigationDelegate: (NavigationRequest request) {
if (request.url.contains("mailto:")) {
launch(request.url);
return NavigationDecision.prevent;
}
// if (request.url.contains("download")) {
//   launch(request.url);
//   return NavigationDecision.prevent;
// }
return NavigationDecision.navigate;
},
),
)
),
);
}
}
`

2 questions:

What is the error you get?
Do the permission request dialogs show when the app starts?

2 questions:

What is the error you get?
Do the permission request dialogs show when the app starts?

What is the error you get? - App got crashed and the message is the app keeps stopping.
Do the permission request dialogs show when the app starts?  - No

What is the error you get? - App got crashed and the message is the app keeps stopping.
Do the permission request dialogs show when the app starts?  - No

Do the permission request dialogs show when the app starts? - No

This is the issue then. I think you cannot request for the permissions before runApp. Try putting them in a spot like this:
@override
      Widget build(BuildContext context) {
Permission.camera.request();
   Permission.storage.request();
return MaterialApp(
...
)
}

This is definitely not ideal, ie don't use in production I'm just suggesting this to you for testing.

Do the permission request dialogs show when the app starts? - No

This is the issue then. I think you cannot request for the permissions before runApp. Try putting them in a spot like this:
@override
      Widget build(BuildContext context) {
Permission.camera.request();
   Permission.storage.request();
return MaterialApp(
...
)
}

This is definitely not ideal, ie don't use in production I'm just suggesting this to you for testing.

yeah, working now. Thanks a lot @tneotia.
1 more question -

Is there any way we can add downloading files capability in the android applications build using the same plugin?

yeah, working now. Thanks a lot @tneotia.
1 more question -

Is there any way we can add downloading files capability in the android applications build using the same plugin?

Is there any way we can add downloading files capability in the android applications build using the same plugin?

This unfortunately I have not worked on, but the plugin I use (flutter_inappwebview) has this functionality. If you really want to keep using webview_flutter you can do some workarounds:

Use url_launcher plugin and detect your download URL, then open browser to download the file.
Use dio plugin and make a DOWNLOAD request when your download URL is detected:

response = await dio.download("https://www.google.com/", "./xx.html");

Is there any way we can add downloading files capability in the android applications build using the same plugin?

This unfortunately I have not worked on, but the plugin I use (flutter_inappwebview) has this functionality. If you really want to keep using webview_flutter you can do some workarounds:

Use url_launcher plugin and detect your download URL, then open browser to download the file.
Use dio plugin and make a DOWNLOAD request when your download URL is detected:

response = await dio.download("https://www.google.com/", "./xx.html");

none of the workarounds above is eligible in the long term
can somebody at least add a callback for this and create pull request

For me it is opening the camera and taking snap but doesn't show images in viewer in the above mentioned site. And when i use reader in js it doesn't get into reader.onload nor into on error function. Can anyone help me this

Yeah I'm still trying to figure it out with @Paras-Gupta790 but no luck yet.. it is definitely working on my Samsung S8 debug mode. I don't understand why it wouldn't work on other devices.

This has been fixed in Flutter 1.22/ WebView 1.0 - use hybrid composition in the Flutter WebView plugin.
https://github.com/flutter/plugins/tree/master/packages/webview_flutter#using-hybrid-composition

@blasten can you please re-open this issue? As you can see from all the comments, it's not fixed, even with hybrid composition. You can try it by opening this URL in a webview: https://www.w3schools.com/tags/tryit.asp?filename=tryhtml5_input_type_file

I have verified that this doesn't work although I remember seeing it working

The very same issue occurred to me when i was trying to webview in android. And i replaced the code in mainactivity as shown. Can you take this as a reference
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.AlertDialogLayout;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Debug;
import android.os.Environment;
import android.os.Parcelable;
import android.provider.MediaStore;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.Window;
import android.webkit.GeolocationPermissions;
import android.webkit.JavascriptInterface;
import android.webkit.JsResult;
import android.webkit.PermissionRequest;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebResourceError;
import android.webkit.WebResourceRequest;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ProgressBar;
import android.widget.Toast;
import java.io.File;
import java.io.IOException;
import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationCallback;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationResult;
import com.google.android
.gms.location
.LocationServices;
import android.os.Looper;
import android.provider.Settings;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import android.Manifest;
import android.annotation.SuppressLint;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import android.widget.TextView;
import android.widget.Toast;
import android.content.Context;
import android.content.Intent;
public class MainActivity extends AppCompatActivity {
WebView web;
ProgressBar progressBar;
final Context myApp = this;
public Context context;
private static final String TAG = MainActivity.class.getSimpleName();
private static final int FILECHOOSER_RESULTCODE = 1;
private ValueCallback mUploadMessage;
private Uri mCapturedImageURI = null;
// the same for Android 5.0 methods only
private ValueCallback<Uri[]> mFilePathCallback;
private String mCameraPhotoPath;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    web = findViewById(R.id.webView);
    progressBar = findViewById(R.id.progress);
    WebSettings webSettings = web.getSettings();
    webSettings.setJavaScriptEnabled(true);
    webSettings.setCacheMode(webSettings.LOAD_NO_CACHE);
    web.addJavascriptInterface(new WebAppInterface(getBaseContext()), "Android");
    webSettings.setDomStorageEnabled(true);
    webSettings.setAllowContentAccess(true);
    webSettings.setAllowFileAccess(true);
    webSettings.setGeolocationEnabled(true);
    if(Build.VERSION.SDK_INT >= 21){
        webSettings.setMixedContentMode(0);
        web.setLayerType(View.LAYER_TYPE_HARDWARE, null);
    }else {
        web.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
    }
    web.setWebChromeClient(new WebChromeClient(){
        @Override
        public boolean onJsConfirm(WebView view, String url, String message, final JsResult result) {
            new AlertDialog.Builder(myApp)
                    .setTitle("Confirm")
                    .setMessage(message)
                    .setPositiveButton(android.R.string.ok,
                            new DialogInterface.OnClickListener()
                            {
                                public void onClick(DialogInterface dialog, int which)
                                {
                                    result.confirm();
                                }
                            })
                    .setNegativeButton(android.R.string.cancel,
                            new DialogInterface.OnClickListener()
                            {
                                public void onClick(DialogInterface dialog, int which)
                                {
                                    result.cancel();
                                }
                            })
                    .create()
                    .show();

            return true;
        }

        @Override
        public boolean onJsAlert(WebView view, String url, String message, final JsResult result){
            new AlertDialog.Builder(myApp)
                    .setTitle("Alert")
                    .setMessage(message)
                    .setPositiveButton(android.R.string.ok,
                            new DialogInterface.OnClickListener()
                            {
                                public void onClick(DialogInterface dialog, int which)
                                {
                                    result.confirm();
                                }
                            })
                    .create()
                    .show();
            return true;
        }

        @Override
        public void onPermissionRequest(final PermissionRequest request){
            MainActivity.this.runOnUiThread(new Runnable() {
                @TargetApi(Build.VERSION_CODES.M)
                @Override
                public void run() {
                    if(request.getOrigin().toString().equals("file:///")){
                        request.grant(request.getResources());
                    }
                    else {
                        request.deny();
                    }

                }
            });

        }

        public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) {
            callback.invoke(origin, true, false);
            //check for permissions or show your dialog etc
        }

        @Override
        public boolean onShowFileChooser(
                WebView webView, ValueCallback<Uri[]> filePathCallback,
                WebChromeClient.FileChooserParams fileChooserParams) {
            if (mFilePathCallback != null) {
                mFilePathCallback.onReceiveValue(null);
            }
            mFilePathCallback = filePathCallback;

            Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
                Log.d("from camera", "testing the function");
                // create the file where the photo should go
                File photoFile = null;
                try {
                    photoFile = createImageFile();
                    takePictureIntent.putExtra("PhotoPath", mCameraPhotoPath);
                } catch (IOException ex) {
                    // Error occurred while creating the File
                    Log.e(TAG, "Unable to create Image File", ex);
                }

                // continue only if the file was successfully created
                if (photoFile != null) {
                    mCameraPhotoPath = "file:" + photoFile.getAbsolutePath();
                    Log.d(TAG, mCameraPhotoPath.toString());
                    //Log.d(TAG, mCapturedImageURI.toString());
                    takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
                            Uri.fromFile(photoFile));
                    Log.d("Extraout", MediaStore.EXTRA_OUTPUT);
                    Log.d("URI", Uri.fromFile(photoFile).toString());
                } else {
                    takePictureIntent = null;
                }
            }

            Intent contentSelectionIntent = new Intent(Intent.ACTION_GET_CONTENT);
            contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE);
            contentSelectionIntent.setType("image/*");

            Intent[] intentArray;
            if (takePictureIntent != null) {
                intentArray = new Intent[]{takePictureIntent};
            } else {
                intentArray = new Intent[0];
            }

            Intent chooserIntent = new Intent(Intent.ACTION_CHOOSER);
            chooserIntent.putExtra(Intent.EXTRA_INTENT, contentSelectionIntent);
            Log.d("ContentSelection", contentSelectionIntent.toString());
            chooserIntent.putExtra(Intent.EXTRA_TITLE, getString(R.string.image_chooser));
            chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentArray);

            startActivityForResult(chooserIntent, FILECHOOSER_RESULTCODE);

            return true;
        }

        private File createImageFile() throws IOException {
            File imageStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "DirectoryNameHere");
            //File imageStorageDir = new File();

            Log.d("IMagedriectory", imageStorageDir.toString());
            if (!imageStorageDir.exists()) {
                imageStorageDir.mkdirs();
            }

            // create an image file name
            imageStorageDir = new File(imageStorageDir + File.separator + "IMG_" + String.valueOf(System.currentTimeMillis()) + ".jpg");
            Log.d("direct exists", imageStorageDir.toString());
            return imageStorageDir;
        }

        // openFileChooser for Android 3.0+
        public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
            mUploadMessage = uploadMsg;

            try {
                File imageStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "DirectoryNameHere");
                Log.d("IMagedriectory2", imageStorageDir.toString());

                if (!imageStorageDir.exists()) {
                    imageStorageDir.mkdirs();
                }

                File file = new File(imageStorageDir + File.separator + "IMG_" + String.valueOf(System.currentTimeMillis()) + ".jpg");

                mCapturedImageURI = Uri.fromFile(file); // save to the private variable

                final Intent captureIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
                captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, mCapturedImageURI);
                // captureIntent.putExtra(MediaStore.EXTRA_SCREEN_ORIENTATION, ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

                Intent i = new Intent(Intent.ACTION_GET_CONTENT);
                i.addCategory(Intent.CATEGORY_OPENABLE);
                i.setType("image/*");

                Intent chooserIntent = Intent.createChooser(i, getString(R.string.image_chooser));
                chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Parcelable[]{captureIntent});

                startActivityForResult(chooserIntent, FILECHOOSER_RESULTCODE);
            } catch (Exception e) {
                Toast.makeText(getBaseContext(), "Camera Exception:" + e, Toast.LENGTH_LONG).show();
            }

        }

        // openFileChooser for Android < 3.0
        public void openFileChooser(ValueCallback<Uri> uploadMsg) {
            openFileChooser(uploadMsg, "");
        }

        // openFileChooser for other Android versions
        /* may not work on KitKat due to lack of implementation of openFileChooser() or onShowFileChooser()
           https://code.google.com/p/android/issues/detail?id=62220
           however newer versions of KitKat fixed it on some devices */
        public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
            openFileChooser(uploadMsg, acceptType);
        }
    });
    web.setWebViewClient(new WebViewClient(){
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            return false;
        }

        @Override
        public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
            view.loadUrl("about:blank");
            progressBar.setVisibility(View.GONE);
            openactivity_no_internet(error);
        }

        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon){
            super.onPageStarted(view, url, favicon);
            Log.d("url tag", url);
            if (url == "https://www.dropzonejs.com/") {  //https://www.dropzonejs.com/
                progressBar.setVisibility(View.VISIBLE);
            }
        }

        @Override
        public void onPageFinished(WebView view, String url){
            super.onPageFinished(view, url);
            progressBar.setVisibility(View.GONE);
        }
    });
    web.loadUrl("https://www.dropzonejs.com/");
}

// return here when file selected from camera or from SD Card

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {

    // code for all versions except of Lollipop
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {

        if (requestCode == FILECHOOSER_RESULTCODE) {
            if (null == this.mUploadMessage) {
                return;
            }

            Uri result = null;

            try {
                if (resultCode != RESULT_OK) {
                    result = null;
                } else {
                    // retrieve from the private variable if the intent is null
                    result = data == null ? mCapturedImageURI : data.getData();
                }
            } catch (Exception e) {
                Toast.makeText(getApplicationContext(), "activity :" + e, Toast.LENGTH_LONG).show();
            }

            mUploadMessage.onReceiveValue(result);
            mUploadMessage = null;
        }

    } // end of code for all versions except of Lollipop

    // start of code for Lollipop only
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {

        if (requestCode != FILECHOOSER_RESULTCODE || mFilePathCallback == null) {
            super.onActivityResult(requestCode, resultCode, data);
            return;
        }

        Uri[] results = null;

        // check that the response is a good one
        if (resultCode == Activity.RESULT_OK) {
            if (data == null || data.getData() == null) {
                // if there is not data, then we may have taken a photo
                if (mCameraPhotoPath != null) {
                    results = new Uri[]{Uri.parse(mCameraPhotoPath)};
                }
            } else {
                String dataString = data.getDataString();
                if (dataString != null) {
                    results = new Uri[]{Uri.parse(dataString)};
                }
            }
        }

        mFilePathCallback.onReceiveValue(results);
        mFilePathCallback = null;

    } // end of code for Lollipop only
}

public void openactivity_no_internet(WebResourceError error){
    Intent intent = new Intent(this, NoIntenetActivity.class);
    intent.putExtra("error",error.toString());
    startActivity(intent);
    overridePendingTransition(0, 0);
}

}

@Paras-Gupta790 and all others, I have solved the file upload issue again with the following code. Tested on Galaxy S8 Android 9, release mode and debug mode with uploading website as https://pasteboard.co and https://dropzonejs.com, and webview_flutter: ^1.0.7. Tested both standard rendering method and new hybrid composition rendering method. Both images and file upload should function correctly now.
Instructions
Let's try to keep this thread clean and avoid quoting my huge post, this is why I put it in a dropdown - but I'm not sure if GitHub will preserve the dropdown when quoted. Let me know of any issues and I may be able to take care of them, and leave a thumbs up if it worked for you!

@tneotia The solution you gave (by editing code in the java file) worked for me but not completely. If I try to upload an image using Camera, this is what happens:

Camera app gets opened
I click a photograph and click on the tick (✔ ) icon.
But, when I try to upload the image I clicked, it says no file is selected.

Also, FYI, I'm not using the "Permission" plugin to ask for permission. My app already asks for camera permission after you install it and open for the first time.

Yeah @Paras-Gupta790 is having a similar issue, the camera opens and takes the snap, but the upload is unsuccessful. Still trying to work it out but I feel this is stretching beyond my expertise.

Ohhh. It's alright. Thanks though! Just in case you find any solution, please do let me know. It'd would be really helpful.
@Paras-Gupta790 did you happen to solve the issue yet?

Not yet. Me and @tneotia are working on this issue but not able to figure out the solution yet.

ohhh.
Guys, by the way, I just got to know that camera upload is working in a different mobile (Samsung M21), if that's of any help to you to figure out.
Let me know if you need any extra hand for help. I'll be happy to help! 😄

https://github.com/flutter/plugins/pull/3225/files this solution worked for me.
extension defined at this file "packages/webview_flutter/android/src/main/res/values/strings.xml"
I didn't change "packages/webview_flutter/pubspec.yaml" file.
i using  "webview_flutter: ^1.0.7"
thank you @libo1223

i worked on that same , but i couldn't solve my error.
Here is my Code :
import 'package:flutter/material.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'dart:async';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
Permission.camera.request();
Permission.storage.request();
return MaterialApp(
title: 'Door Steps Markets',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Padding(
padding: const EdgeInsets.only(top: 25.0),
child: Container(
child: WebView(
initialUrl: 'https://doorstepsmarkets.com',
javascriptMode: JavascriptMode.unrestricted,
      ),
    ),
  ),
);

}
}

any good news?

@Paras-Gupta790 and all others, I have solved the file upload issue again with the following code. Tested on Galaxy S8 Android 9, release mode and debug mode with uploading website as https://pasteboard.co and https://dropzonejs.com, and webview_flutter: ^1.0.7. Tested both standard rendering method and new hybrid composition rendering method. Both images and file upload should function correctly now.
Instructions

Open External Libraries > Flutter Plugins > webview_flutter > android > src.main> java.io. ...> FlutterWebView.java.
Replace code in this file from the code here.
Create a newActivity.java file in the same directory, copy the code from here.

In your own app,

In AndroidManifest, add:

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

If you don't want the camera choosing capability you can leave out the camera permission.
2. Above the .MainActivity declaration in AndroidManifest add:
<activity
            android:name="io.flutter.plugins.webviewflutter.newActivity"
            android:theme="@android:style/Theme.Translucent.NoTitleBar"/>

The last thing left to do is in Dart. Use the permission_handler plugin (or something similar, for these instructions I am using that) to request for your permissions like so:
await Permission.camera.request();
await Permission.storage.request();

These requests return bool, so you can check whether the user granted or denied the permission and perform actions accordingly. Again, if you don't want the camera choosing functionality you don't need to request for the camera permission.
Depending on how the website is set up, you may need to use JavascriptMode.unrestricted:
WebView(
    initialUrl: your_url,
    javascriptMode: JavascriptMode.unrestricted,
    //any other parameters
),

Let's try to keep this thread clean and avoid quoting my huge post, this is why I put it in a dropdown - but I'm not sure if GitHub will preserve the dropdown when quoted. Let me know of any issues and I may be able to take care of them, and leave a thumbs up if it worked for you!

I've followed everything in the instructions but after taking photo by camera the app crashes, does this happen to anyone too?

Thanks, @yeeemayy. Will try this.
One more thing - This will ask for user permissions at the beginning. Can we ask for user permissions whenever he tries to upload documents?

Correct me if i'm wrong, it seems impossible to keep asking for permission after user granted the permission once. On the other hand, if user permanently denied the permission request, there's no way we can request again but to prompt user to grant permission in app settings.

According to Google guidelines - The app requests runtime permissions in context, when the functionality is requested, rather than upfront during app startup.
We can check before asking permissions based on the status, which is either undetermined, granted, denied, restricted or permanentlyDenied. But IDk how to ask for permissions when the user tries to upload image (i.e. when the functionality is requested)

https://github.com/flutter/plugins/pull/3225/files this solution worked for me.
extension defined at this file "packages/webview_flutter/android/src/main/res/values/strings.xml"
I didn't change "packages/webview_flutter/pubspec.yaml" file.
i using "webview_flutter: ^1.0.7"
thank you @libo1223

Yes, by applying the code changes from https://github.com/flutter/plugins/pull/3225 (Add file choose on Android), now the webview can handle file-input field correctly. I'm using webview_flutter: 2.0.0-nullsafety.3
However, please take note that the code changes will throw java.lang.IllegalArgumentException if you're using a plugin called "flutter_downloader". After removed flutter_downloader from pubspec.yaml, it is working flawlessly.
Thanks to the code contributor, @fesp

yes this works great, but is there any way to assign a controller with it just as we can with flutter_inappwebview so that we can call javascript functions?

flutter_inappwebview works just fine with input type file so if you currently use that no need to switch to flutter_webview_plugin.

hello @tneotia ...im newbie in dart language..
in my project app,im using inappwebview plugin...in my problem,this plugin cannot show keyboard after fullscreen inappwebview..
can you help me?
thanks

i had solved this problem by adding this line of code in the initState of the class which have the WebViewPage
add this code.
void initState() {
super.initState();
WidgetsFlutterBinding.ensureInitialized();
if (Platform.isAndroid) WebView.platform = SurfaceAndroidWebView();
}

hello @tneotia ...im newbie in dart language..
in my project app,im using inappwebview plugin...in my problem,this plugin cannot show keyboard after fullscreen inappwebview..
can you help me?
thanks

I haven't experienced this issue at all, I use the webview fullscreen and the keyboard shows.

thankyou mr tanay...
and then,i migrate to inappwebview plugin...can you help in the same problem...?
Dari: "Mohamed khira" @.>
Ke: "flutter/flutter" @.>
Cc: "Bintang Aditya" @.>, "Comment" @.>
Terkirim: Senin, 5 April 2021 22:46:51
Subjek: Re: [flutter/flutter] [webview_flutter] not working choose file (input type file) (#27924)
i had solved this problem by adding this line of code in the initState of the class which have the WebViewPage
add this code.
void initState() {
super.initState();
WidgetsFlutterBinding.ensureInitialized();
if (Platform.isAndroid) WebView.platform = SurfaceAndroidWebView();
}
—
You are receiving this because you commented.
Reply to this email directly, [ https://github.com/flutter/flutter/issues/27924#issuecomment-813463766 | view it on GitHub ] , or [ https://github.com/notifications/unsubscribe-auth/ATPC2FUBY4VDRBMUNHBUNFLTHHLOXANCNFSM4GXMEGSA | unsubscribe ] .

Thanks mr Mkhira...
sorry,im using inappwebview plugin...
webview.platform cannot found in this plugin...can you help me?

i had solved this problem by adding this line of code in the initState of the class which have the WebViewPage
add this code.
void initState() {
super.initState();
WidgetsFlutterBinding.ensureInitialized();
if (Platform.isAndroid) WebView.platform = SurfaceAndroidWebView();
}

Thanks mr Mkhira...
sorry,im using inappwebview plugin...
webview.platform cannot found in this plugin...can you help me?

Hi. I got few app crashes when the user selected camera option to upload an image. And it happened in only in one device repeatedly (Samsung M21)
below are the logs. Could you help? @tneotia @Paras-Gupta790 @yeeemayy
Fatal Exception: java.lang.RuntimeException: Unable to resume activity {com.forwoodsafety.safetyapps/io.flutter.plugins.webviewflutter.newActivity}: java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=42, result=0, data=null} to activity {com.forwoodsafety.safetyapps/io.flutter.plugins.webviewflutter.newActivity}: java.lang.NullPointerException: Attempt to invoke interface method 'void android.webkit.ValueCallback.onReceiveValue(java.lang.Object)' on a null object reference
       at android.app.ActivityThread.performResumeActivity(ActivityThread.java:4864)
       at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:4901)
       at android.app.servertransaction.ResumeActivityItem.execute(ResumeActivityItem.java:52)
       at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:176)
       at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97)
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2307)
       at android.os.Handler.dispatchMessage(Handler.java:106)
       at android.os.Looper.loop(Looper.java:246)
       at android.app.ActivityThread.main(ActivityThread.java:8506)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1139)

Caused by java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=42, result=0, data=null} to activity {com.forwoodsafety.safetyapps/io.flutter.plugins.webviewflutter.newActivity}: java.lang.NullPointerException: Attempt to invoke interface method 'void android.webkit.ValueCallback.onReceiveValue(java.lang.Object)' on a null object reference
       at android.app.ActivityThread.deliverResults(ActivityThread.java:5506)
       at android.app.ActivityThread.performResumeActivity(ActivityThread.java:4851)
       at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:4901)
       at android.app.servertransaction.ResumeActivityItem.execute(ResumeActivityItem.java:52)
       at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:176)
       at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97)
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2307)
       at android.os.Handler.dispatchMessage(Handler.java:106)
       at android.os.Looper.loop(Looper.java:246)
       at android.app.ActivityThread.main(ActivityThread.java:8506)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1139)

Caused by java.lang.NullPointerException: Attempt to invoke interface method 'void android.webkit.ValueCallback.onReceiveValue(java.lang.Object)' on a null object reference
       at io.flutter.plugins.webviewflutter.newActivity.onActivityResult(newActivity.java:80)
       at android.app.Activity.dispatchActivityResult(Activity.java:8541)
       at android.app.ActivityThread.deliverResults(ActivityThread.java:5499)
       at android.app.ActivityThread.performResumeActivity(ActivityThread.java:4851)
       at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:4901)
       at android.app.servertransaction.ResumeActivityItem.execute(ResumeActivityItem.java:52)
       at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:176)
       at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97)
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2307)
       at android.os.Handler.dispatchMessage(Handler.java:106)
       at android.os.Looper.loop(Looper.java:246)
       at android.app.ActivityThread.main(ActivityThread.java:8506)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602)