最近在使用webview_flutter遇到在内嵌的h5中有上传文件的需求,但是官方的webview_flutter并没有对Android做相关的适配。做过Android的应该知道在Android源生中使用webview内嵌H5需要对上传文件的功能做相关的适配处理,否则会报错。由于webview_flutter内部还是使用Android源生的webview来展示H5,所以如果项目中有这方面需求还是需要自己处理。

1.我们要拿到webview_flutter插件的源码:
这里我是在flutter插件缓存中拷贝的(官网上可以下载,但是我没拿到最新的源码不知道是什么原因)
2.将webview_flutter插件源码复制的项目中去:
在项目根目录下创建一个文件夹放本地插件。

在pubspec.yaml中修改依赖:

dependencies:  flutter:    sdk: flutter  flutter_localizations:    sdk: flutter  # WebView插件 https://github.com/flutter/plugins/tree/master/packages/webview_flutter  webview_flutter:    path: plugins/webview_flutter

然后找到插件Android的实现代码:
修改WebViewFactory.java的相关实现:

public final class WebViewFactory extends PlatformViewFactory {  private final BinaryMessenger messenger;  private final View containerView;  private  FlutterWebView flutterWebView;  WebViewFactory(BinaryMessenger messenger, View containerView) {    super(StandardMessageCodec.INSTANCE);    this.messenger = messenger;    this.containerView = containerView;  }  @SuppressWarnings("unchecked")  @Override  public PlatformView create(Context context, int id, Object args) {    Map<String, Object> params = (Map<String, Object>) args;    flutterWebView=new FlutterWebView(context, messenger, id, params, containerView);    return flutterWebView;  }  public FlutterWebView getFlutterWebView() {    return flutterWebView;  }}

修改WebViewFlutterPlugin.java相关实现:

public class WebViewFlutterPlugin implements FlutterPlugin, PluginRegistry.ActivityResultListener , ActivityAware {  private FlutterCookieManager flutterCookieManager;  public static Activity activity; private WebViewFactory factory;  public WebViewFlutterPlugin() {}  public static void registerWith(Registrar registrar) {    registrar        .platformViewRegistry()        .registerViewFactory(            "plugins.flutter.io/webview",            new WebViewFactory(registrar.messenger(), registrar.view()));    new FlutterCookieManager(registrar.messenger());  }  @Override  public void onAttachedToEngine(FlutterPluginBinding binding) {    BinaryMessenger messenger = binding.getBinaryMessenger();    factory=new WebViewFactory(messenger, null);    binding        .getFlutterEngine()        .getPlatformViewsController()        .getRegistry()        .registerViewFactory(            "plugins.flutter.io/webview",factory);    flutterCookieManager = new FlutterCookieManager(messenger);  }  @Override  public void onDetachedFromEngine(FlutterPluginBinding binding) {    if (flutterCookieManager == null) {      return;    }    activity=null;    flutterCookieManager.dispose();    flutterCookieManager = null;  }  @Override  public boolean onActivityResult(int requestCode, int resultCode, Intent data) {    Log.v("userlogin","onActivityResult in plugin");    if (factory!=null&&factory.getFlutterWebView()!=null){        return factory.getFlutterWebView().activityResult(requestCode,resultCode,data);    }    return false;  }  @Override  public void onAttachedToActivity(ActivityPluginBinding binding) {      activity=binding.getActivity();    binding.addActivityResultListener(this);  }  @Override  public void onDetachedFromActivityForConfigChanges() {  }  @Override  public void onReattachedToActivityForConfigChanges(ActivityPluginBinding binding) {  }  @Override  public void onDetachedFromActivity() {  }}

在FlutterWebView.java中适配上传文件,通过 webView.setWebChromeClient监听h5选择文件的操作并拦截,然后打开文件管理选择要上传的文件,最后将文件返回给H5.

     webView.setWebChromeClient(new WebChromeClient() {                // For Android < 3.0        public void openFileChooser(ValueCallback<Uri> valueCallback) {          uploadMessage = valueCallback;          openImageChooserActivity();        }        // For Android  >= 3.0        public void openFileChooser(ValueCallback valueCallback, String acceptType) {          uploadMessage = valueCallback;          openImageChooserActivity();        }        //For Android  >= 4.1        public void openFileChooser(ValueCallback<Uri> valueCallback, String acceptType, String capture) {          uploadMessage = valueCallback;          openImageChooserActivity();        }        // For Android >= 5.0        @Override        public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {          uploadMessageAboveL = filePathCallback;          openImageChooserActivity();          return true;        }        @RequiresApi(api = Build.VERSION_CODES.KITKAT)        @Override        public void onProgressChanged(WebView view, int newProgress) {                  }      });
private void openImageChooserActivity() {    Intent i = new Intent(Intent.ACTION_GET_CONTENT);    i.addCategory(Intent.CATEGORY_OPENABLE);    i.setType("video/*;image/*;application/*;text/*;audio/*;");    if (WebViewFlutterPlugin.activity!=null){      WebViewFlutterPlugin.activity.startActivityForResult(Intent.createChooser(i, "选择文件"), FILE_CHOOSER_RESULT_CODE);    }else {      Log.v("userlogin","activity is null");    }  }  public static final int RESULT_OK = -1;  public boolean activityResult(int requestCode, int resultCode, Intent data) {    Log.v("userlogin","回到onActivityResult");    if (requestCode == FILE_CHOOSER_RESULT_CODE) {      if (null == uploadMessage && null == uploadMessageAboveL) {        return false;      }      Uri result = data == null || resultCode != RESULT_OK ? null : data.getData();      if (uploadMessageAboveL != null) {        onActivityResultAboveL(requestCode, resultCode, data);      } else if (uploadMessage != null) {        uploadMessage.onReceiveValue(result);        uploadMessage = null;      }    }    return false;  }  @TargetApi(Build.VERSION_CODES.LOLLIPOP)  private void onActivityResultAboveL(int requestCode, int resultCode, Intent intent) {    if (requestCode != FILE_CHOOSER_RESULT_CODE || uploadMessageAboveL == null)    {      return;    }    Uri[] results = null;    if (resultCode == Activity.RESULT_OK) {      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)};        }      }    }    uploadMessageAboveL.onReceiveValue(results);    uploadMessageAboveL = null;  }

感兴趣的同学可以结合另一个插件:flutter_webview_plugin
来结合flutter_webview_plugin中上传文件的适配打造一个完美的webview_flutter。

相关代码:
https://github.com/qq1057119720/flutter_fish_local/tree/master/plugins/webview_flutter

更多相关文章

  1. Android(安卓)Studio 更换debug.keystore问题
  2. 双击运行Android模拟器、创建SDcard、AVD、安装APK文件、上传文
  3. Android存储选项简析
  4. Android(安卓)RenderScript 的使用基础篇
  5. Android(安卓)项目编译过程
  6. APPS大乱斗:4大Android文件浏览器横评(一)
  7. android apk安装原理分析
  8. android四层框架
  9. NPM 和webpack 的基础使用

随机推荐

  1. android之组件4
  2. Android Studio 出现 Error: NDK integra
  3. Android APP 设置启动的第一张图片
  4. ubuntu 编译 ffmpeg For Android
  5. android一键清除最近应用按钮
  6. Android外接扫码枪监听普通输入事件
  7. android音乐播放器(2)
  8. 判断Android客户端网络是否连接
  9. Android(安卓)之 在内存中读/取数据
  10. Android Studio关闭双击Shift打开全局搜