您的位置:首页 > 移动开发

Android 内嵌WebView之选择文件上传及扩展

2016-12-30 14:31 465 查看

Android 内嵌WebView之选择文件上传及填坑记录

Android 内嵌WebView之选择文件上传及填坑记录

前言

实现
开发中遇到的问题

功能的具体实现

总结

扩展

前言

今天老大给我提了个醒,年前的一个问题还没解决…然而我早已忘记… 既然说了,那么咱就研究研究这问题。

问题是关于内嵌webView时网页内无法调用系统的拍照功能/文件选择功能。于是我写起一个demo试试,发现确实无法调起来,而浏览器上可以正常使用,恩…那就是我们支持的不够咯~

这不,发现带有input type = file标签的Html页面通过webVie显示就无法正常功能做,那么我们要做的是在webView中增加对这类js的支持…

实现

1.我们先写一个简单的demo, 通过webView打开一个有调用打开文件功能的网页(文末附源码)

WebView mWeb = (WebView) findViewById(R.id.webView);
WebSettings settings = mWeb.getSettings();
mWeb.requestFocusFromTouch();
settings.setJavaScriptEnabled(true);   //支持js
settings.setAllowFileAccess(true);     //设置可以访问文件

mWeb.loadUrl("file:///android_asset/getFile.html");


开发中遇到的问题

点击打开webView时跳转至系统自带的浏览器/第三方浏览器
解决办法:覆盖WebView的WebViewClient对象。

mWeb.setWebViewClient(new WebViewClient(){
public boolean shouldOverrideUrlLoading(WebView view, String url){
view.loadUrl(url);
return true;
}
});
同时扩展一下:在不做任何处理下按系统返回键,整个Browser回调用finis()销毁,而一般我们是希望按历史记录逐步回退,那么这个时候我们需要在当前Activity中消费掉Back事件。

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && mWeb.canGoBack()){
mWeb.goBack();
return true;
}
return super.onKeyDown(keyCode, event);
}


注:这里我们将Html文件放到assets目录下

功能的具体实现

通过Google大法终于找出常用的解决办法。

【重写WebVie的webChromeClien覆盖OpenFileChooser方法】

Android在不同版本中调用相机的方法不同:

Android 3.0 以下
public void openFileChooser(ValueCallback<Uri> uploadMsg)

Android 3.0以上
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType)

Androi 4.4以下
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture)

Android 5.0以上
public boolean onShowFileChooser(WebView mWebView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams)


代码如下:

mWeb.setWebChromeClient(new MyWebChromeClient());

private class MyWebChromeClient extends WebChromeClient {

//  Android 3.0 以下
@SuppressWarnings("unused")
public void openFileChooser(ValueCallback<Uri> uploadMsg) {
openFileChooser(uploadMsg, null);
}

// Android 3.0以上
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
openFileChooser(uploadMsg, acceptType, null);
}

// Androi 4.4以下
@SuppressWarnings("unused")
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
openFileInput(uploadMsg, null, false);
}

//  Android 5.0以上
@SuppressWarnings("all")
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) {
if (Build.VERSION.SDK_INT >= 21) {
final boolean allowMultiple = fileChooserParams.getMode() == WebChromeClient.FileChooserParams.MODE_OPEN_MULTIPLE;//是否支持多选
openFileInput(null, filePathCallback, allowMultiple);
return true;
} else {
return false;
}
}
}

@SuppressLint("NewApi")
protected void openFileInput(final ValueCallback<Uri> fileUploadCallbackFirst, final ValueCallback<Uri[]> fileUploadCallbackSecond, final boolean allowMultiple) {
//Android 5.0以下版本
if (mFileUploadCallbackLowVersion != null) {
mFileUploadCallbackLowVersion.onReceiveValue(null);
}
mFileUploadCallbackLowVersion = fileUploadCallbackFirst;

//Android 5.0及以上版本
if (mFileUploadCallbackHighVersion != null) {
mFileUploadCallbackHighVersion.onReceiveValue(null);
}
mFileUploadCallbackHighVersion = fileUploadCallbackSecond;

Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);

if (allowMultiple) {
if (Build.VERSION.SDK_INT >= 18) {
i.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
}
}
i.setType(mFileTypes);
startActivityForResult(Intent.createChooser(i, "选择文件"), REQUEST_CODE_FILE_PICKER);
}


最后我们在Acitivity的onActivityResult()方法中处理,不管请求是否成功,我们都要在onReceiveValue()传nul,否则html中的j执行一次就不会再执行即我们点击不会在有响应了。

public void onActivityResult(final int requestCode, final int resultCode, final Intent intent) {
if (requestCode == REQUEST_CODE_FILE_PICKER) {
if (resultCode == Activity.RESULT_OK) {
if (intent != null) {
//Android 5.0以下版本
if (mFileUploadCallbackLowVersion != null) {
mFileUploadCallbackLowVersion.onReceiveValue(intent.getData());
mFileUploadCallbackLowVersion = null;
} else if (mFileUploadCallbackHighVersion !=
b074
null) {//Android 5.0及以上版本
Uri[] dataUris = null;

try {
if (intent.getDataString() != null) {
dataUris = new Uri[]{Uri.parse(intent.getDataString())};
} else {
if (Build.VERSION.SDK_INT >= 16) {
if (intent.getClipData() != null) {
final int numSelectedFiles = intent.getClipData().getItemCount();

dataUris = new Uri[numSelectedFiles];

for (int i = 0; i < numSelectedFiles; i++) {
dataUris[i] = intent.getClipData().getItemAt(i).getUri();
}
}
}
}
} catch (Exception ignored) {
}
mFileUploadCallbackHighVersion.onReceiveValue(dataUris);
mFileUploadCallbackHighVersion = null;
}
}
} else {
//这里mFileUploadCallbackFirst跟mFileUploadCallbackSecond在不同系统版本下分别持有了
//WebView对象,在用户取消文件选择器的情况下,需给onReceiveValue传null返回值
//否则WebView在未收到返回值的情况下,无法进行任何操作,文件选择器会失效
if (mFileUploadCallbackLowVersion != null) {
mFileUploadCallbackLowVersion.onReceiveValue(null);
mFileUploadCallbackLowVersion = null;
} else if (mFileUploadCallbackHighVersion != null) {
mFileUploadCallbackHighVersion.onReceiveValue(null);
mFileUploadCallbackHighVersion = null;
}
}
}
}


总结

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设置节点 webview

10. webSettings.setBuiltInZoomControls(true); //设置支持缩放

11.setJavaScriptCanOpenWindowsAutomatically(true); //支持通过JS打开新窗口

12.setLoadWithOverviewMode(true); // 缩放至屏幕的大小

13.setLoadsImagesAutomatically(true); //支持自动加载图片


扩展

现在对于许多APP的开放方案已经从原生开发趋向于混合(Hybrid)开发的方式,我们应该去学习Java与JavaScript的交互;

React Native 结合了 Web 应用和 Native 应用的优势,可以使用 JavaScript 来开发 iOS 和 Android 原生应用。在 JavaScript 中用 React 抽象操作系统原生的 UI 组件,代替 DOM 元素来渲染等。

React Native 使你能够使用基于 JavaScript 和 React 一致的开发体验在本地平台上构建世界一流的应用程序体验。

我们都应该学习学习!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android webview