一、问题场景:

项目中遇到通过网页上传文件的需求,IOS直接是支持的,安卓端却没反应,有些机型甚至闪退。其实是Android的webview默认是不支持<input type="file"/>文件上传的。现在的前端页面需要处理的是:

1.打开本地文件选择器

2.用户选择需要上传的文件

3.处理用户选择的文件通知webview

4.前端提交表单上传文件

首先需要webview 对 JS 的支持,即 webview.getSettings().setJavaScriptEnable(true);其次要注意前端页面针对不同版本的android系统 webview内核会有不同,调用方法是不一样的。

二、问题解决:

1.需要授予的权限

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

2.针对不同系统的处理

webview.setWebChromeClient(new WebChromeClient() {// For Android < 3.0public void openFileChooser(ValueCallback<Uri> valueCallback) {uploadMessage = valueCallback;openImageChooserActivity();}// For Android  >= 3.0public void openFileChooser(ValueCallback valueCallback, String acceptType) {uploadMessage = valueCallback;openImageChooserActivity();}//For Android  >= 4.1public void openFileChooser(ValueCallback<Uri> valueCallback, String acceptType, String capture) {uploadMessage = valueCallback;openImageChooserActivity();}// For Android >= 5.0@Overridepublic boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) {uploadMessageAboveL = filePathCallback;openImageChooserActivity();return true;}});

三、完整代码:

package com.wwy.test.webview_takepicture_upload_demo;import android.annotation.TargetApi;
import android.app.Activity;
import android.content.ClipData;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;import com.wwy.mytest.webview_takepicture_upload_demo.R;public class WebViewActivity extends AppCompatActivity {private ValueCallback<Uri> uploadMessage;private ValueCallback<Uri[]> uploadMessageAboveL;private final static int FILE_CHOOSER_RESULT_CODE = 10000;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_web_view);WebView webview = (WebView) findViewById(R.id.web_view);WebSettings settings = webview.getSettings();settings.setUseWideViewPort(true);settings.setLoadWithOverviewMode(true);settings.setJavaScriptEnabled(true);// 1.设置WebChromeClient,重写文件上传回调webview.setWebChromeClient(new WebChromeClient() {// For Android < 3.0public void openFileChooser(ValueCallback<Uri> valueCallback) {uploadMessage = valueCallback;openImageChooserActivity();}// For Android  >= 3.0public void openFileChooser(ValueCallback valueCallback, String acceptType) {uploadMessage = valueCallback;openImageChooserActivity();}//For Android  >= 4.1public void openFileChooser(ValueCallback<Uri> valueCallback, String acceptType, String capture) {uploadMessage = valueCallback;openImageChooserActivity();}// For Android >= 5.0@Overridepublic boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) {uploadMessageAboveL = filePathCallback;openImageChooserActivity();return true;}});//加载本地网页String targetUrl = "file:///android_asset/takePicture-upload/index.html";webview.loadUrl(targetUrl);}// 2.回调方法触发本地选择文件private void openImageChooserActivity() {Intent i = new Intent(Intent.ACTION_GET_CONTENT);i.addCategory(Intent.CATEGORY_OPENABLE);
//        i.setType("image/*");//图片上传
//        i.setType("file/*");//文件上传i.setType("*/*");//文件上传startActivityForResult(Intent.createChooser(i, "Image Chooser"), FILE_CHOOSER_RESULT_CODE);}// 3.选择图片后处理@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);if (requestCode == FILE_CHOOSER_RESULT_CODE) {if (null == uploadMessage && null == uploadMessageAboveL) return;Uri result = data == null || resultCode != RESULT_OK ? null : data.getData();// 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;}} else {//这里uploadMessage跟uploadMessageAboveL在不同系统版本下分别持有了//WebView对象,在用户取消文件选择器的情况下,需给onReceiveValue传null返回值//否则WebView在未收到返回值的情况下,无法进行任何操作,文件选择器会失效if (uploadMessage != null) {uploadMessage.onReceiveValue(null);uploadMessage = null;} else if (uploadMessageAboveL != null) {uploadMessageAboveL.onReceiveValue(null);uploadMessageAboveL = null;}}}// 4. 选择内容回调到Html页面@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;}
}

注意:

1.最后我们在Acitivity的onActivityResult()方法中处理,不管请求是否成功,我们都要在onReceiveValue()传null,

否则html中的js执行一次就不会再执行,即我们点击不会在有响应了。

2.这个方法里可以选择上传的文件类型,可以限制为图片或者从文件夹中选择图片上传:

    private void openImageChooserActivity() {Intent i = new Intent(Intent.ACTION_GET_CONTENT);i.addCategory(Intent.CATEGORY_OPENABLE);
//        i.setType("image/*");//图片上传
//        i.setType("file/*");//文件上传i.setType("*/*");//文件上传startActivityForResult(Intent.createChooser(i, "Image Chooser"), FILE_CHOOSER_RESULT_CODE);}

(1)下图为 i.setType("*/*");

(2)下图为 i.setType("file/*");

四、引申其他一些设置

Android及iOS的webview的引擎都是webkit,对H5提供支持。webview有两个方法:setWebChromeClient 和setWebClientsetWebClient
WebChromeClient:辅助WebView处理Javascript的对话框,网站图标,网站title,加载进度等
WebViewClient就是帮助WebView处理各种通知、请求事件的。WebSetting常用方法总结:1.setJavaScriptEnabled(true); //支持js 2.setPluginsEnabled(true); //支持插件 3.setUseWideViewPort(false); //将图片调整到适合webview的大小 4.setSupportZoom(true); //支持缩放 5.setLayoutAlgorithm(LayoutAlgorithm.SINGLE_COLUMN); //支持内容重新布6.supportMultipleWindows(); //多窗口 7.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); //关闭webview中缓存 8.setAllowFileAccess(true); //设置可以访问文件 9.setNeedInitialFocus(true); //当webview调用requestFocus时为webview设置节点 webview10. webSettings.setBuiltInZoomControls(true); //设置支持缩放 11.setJavaScriptCanOpenWindowsAutomatically(true); //支持通过JS打开新窗口 12.setLoadWithOverviewMode(true); // 缩放至屏幕的大小 13.setLoadsImagesAutomatically(true); //支持自动加载图片

部分内容参考了https://www.jianshu.com/p/fea5e829b30a,里面有更多的webview常见问题有空可以看看。

Android webview支持H5页面通过js实现文件上传、图片上传相关推荐

  1. Android WebView 支持H5的定位Js

    1 //启用数据库 2 webSettings.setDatabaseEnabled(true); 3 String dir = this.getApplicationContext().getDir ...

  2. Android WebView 支持H5图片上传input type=file

    2019独角兽企业重金招聘Python工程师标准>>> Android WebView 缓存处理 Android WebView 支持H5图片上传<input type=&qu ...

  3. android webview中h5调用 拍照/相册 通用支持代码

    android webview中h5调用 拍照/相册 通用支持代码. 在webview的   WebChromeClient 中,重写 // For Android >= 5.0 @Overri ...

  4. android 双 webview,Android webview加载页面

    释放双眼,带上耳机,听听看~! Android webview加载页面 private WebView webView; public void init() { webView = (WebView ...

  5. 微信小程序web-view 外部引用h5页面调用摄像头录制视频 配有提示音

    微信小程序web-view 外部引用h5页面调用摄像头录制视频 配有提示音 1.目前的需求是什么 2.都踩了那些坑 1.小程序 2.h5语音提示 3.语音合成声音录制不进去,ios有时候是麦克风,有时 ...

  6. uni-app应用中控制webview的H5页面返回

    在uni-app中使用了webview之后, 由于项目完全由app内嵌h5完成, 所以无法控制app的物理返回键: 要实现这个功能,最主要的是完成应用与H5 的通讯问题. 1.H5向应用发送消息 首先 ...

  7. 三种方式让 Android WebView 支持文件下载

    三种方式让 Android WebView 支持文件下载 最近在开发的过程中遇到一个需求,那就是让 WebView 支持文件下载,比如说下载 apk.WebView 默认是不支持下载的,需要开发者自己 ...

  8. H5页面使用html2canvas实现div生成为图片,保存到手机

    在做微信公众号H5页面时,需求要求html页面生成base64图片,并保存到手机相册中.之前没做过,在网上搜了相关的资料.了解到了html2canvas.js. html2canvas首先将页面生成c ...

  9. h5页面怎么处理文件流_一种H5页面效果生成视频文件的方法及系统与流程

    本发明涉及计算机技术领域,尤其涉及一种H5页面效果生成视频文件的方法及系统. 背景技术: 现有的视频合成方法均是将视频需要合成的各个元素拆分出来,针对每个元素进行合成视频,复杂度高,一旦需要添加新的动 ...

最新文章

  1. 南开校长曹雪涛团队12篇论文被调查“可信性”,此前被举报实验图片有PS痕迹...
  2. 详解虚函数的实现过程之多重继承(3)
  3. Spring Security基于角色的权限管理
  4. Java教程:Java字符串替换实例
  5. Oracle用户密码使用特殊符号,例如(AND)、$(Dollar)、#(Pound)、*(Star)等
  6. 漫画:如何给女朋友解释什么是策略模式?
  7. 订阅发布可靠吗_华辉人力资源可靠吗?发布的招聘信息是否可靠?
  8. configtx.yaml中文注解
  9. 【树莓派之旅】第01期:一根网线搞定树莓派可视化界面
  10. Sublime Text3 插件:convertToUTF8
  11. 「双拼输入法安利」清欢实践了四个月,真的好用!
  12. 11.构建Ubuntu系统
  13. 使用ftp服务上传文件时553报错的解决(绝对有用)
  14. 微信8.0状态背景视频合集
  15. DDR controller控制器之AXI接口模块设计
  16. BeatSaber节奏光剑插件开发官方教程1-创建一个插件模板
  17. 静态扫描之Yara第一话--安装及使用Yara
  18. 前端题基础练习总结。。。。
  19. springboot校园餐厅点餐订餐选座系统
  20. TestDirector 8.0下载地址以及安装教程

热门文章

  1. 三极管BTJ与场效应管FET
  2. 生鲜小程序运营技巧 水果店小程序 临沂修齐网络
  3. -bash: ll: 未找到命令
  4. Unity Shader Early-Z技术
  5. 电力行业信息系统的尖,峰,平,谷的英文翻译
  6. python模型预测结果 取整_sklearn 文本分类器做预测时,如何拿到预测结果。。。...
  7. 搜索引擎的基本原理(以及MetaSeeker搜索引擎)
  8. java实现后台直接生成二维码图片并直接上传到七牛云上面
  9. windows 安装Eclipse win7为例
  10. wxhtmltopdf 图片路径问题_跳坑《一百零一》wx.downloadFile问题