webview 那些事儿
来源:互联网 发布:淘宝关键词搜索量 编辑:程序博客网 时间:2024/05/17 18:42
快速开发时代,很多原生开发让位于套壳混合开发,webview这个之前没过多关注的控件成了核心,当然webview没想的那么简单,链接一放就完事了?
No! 首先要说下整体的框架,很多的项目都是fragement + webview 实现的 ,比如 首页 菜单 购物车 个人中心 四个 强烈建议还是用一个webview去处理 不要 每个fragement都new一个 webview 不然后期很麻烦的,当然如果加载的url 已经包含有底部导航栏了,那更好。下面开始遇到的问题:
首先就是对JavaScript的支持了:
WebSettings websetting = webview.getSettings();websetting.setJavaScriptEnabled(true); //与JS交互
紧接着就是 back返回按键,这里需要重写onkeydown方法了
@Overridepublic boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK && webview.canGoBack()) { webview.goBack();// 返回前一个页面 return true; } else { //提示退出应用 AlertDialog.Builder isExit = new AlertDialog.Builder(this); //设置对话框标题 isExit.setTitle("应用提醒"); //设置对话框消息 isExit.setMessage("确定要退出吗"); // 添加选择按钮并注册监听 isExit.setPositiveButton("确定", diaListener); //diaListener 是实例化Dialog的对象 isExit.setNegativeButton("取消", diaListener); //对话框显示 isExit.show(); } return super.onKeyDown(keyCode, event);}
这个是webview 在activity里的可以直接重写onkeydown方法,但有的webview是在fragement里的 那就需要:
webview.setOnKeyListener(new View.OnKeyListener() { @Override public boolean onKey(View view, int i, KeyEvent keyEvent) { if (keyEvent.getAction() == KeyEvent.ACTION_DOWN) { if (i == KeyEvent.KEYCODE_BACK && webview.canGoBack()) { //这里处理返回键事件 Log.d(" FRAGEMENT ","CAN GOBACK = " + webview.canGoBack()); webview_fuwu.goBack(); return true; } } return false; } });
当遇到第三方登录 如跳到 支付宝 QQ 微信 等 再按back键时,那么成功进入又一个webview的问题点 重定向问题 ,你back会变成刷新一样,出不去了,这里我是在对webview的重写方法
shouldOverrideUrlLoading
中处理
@Override public boolean shouldOverrideUrlLoading(WebView view, String url) { // TODO Auto-generated method stub Log.d(TAG, "加载的url==" + url); //view.loadUrl(url); return false ; });
把view.loadUrl(url); 注释掉
有时当反复点击了back键还是没返回,log信息报 UnimplementedWebViewApi: Unimplemented WebView method onKeyDown called from: android.webkit.WebView.onKeyDown(WebView.java:2178)
的,也可以用上面的方法 解决。
对一些加载失败的连接处理时:
@Overridepublic void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { Log.e("MianActivity", "ERROR == " + errorCode + "--->" + description + "---->" + failingUrl); //用javascript隐藏系统定义的404页面信息 String data = ""; view.loadUrl("javascript:document.body.innerHTML=\"" + data + "\""); if (errorCode == -10 && description.equals("net::ERR_UNKNOWN_URL_SCHEME") && failingUrl.equals("****")) { //也可以截获错误信息在这个做自定义的处理 // Callphone_showDialog(); } else if (errorCode == -10 && description.equals("net::ERR_UNKNOWN_URL_SCHEME") && failingUrl.equals("***")) { //自定义处理 }}
webview开发加载的毕竟是网页啊,要是断网了呢,空白啊,所以还要做缓存处理,这个方法在webview的
webview.setWebViewClient(new WebViewClient()之前
/** * 设置webview 缓存 */private void WebView_Set() { WebSettings websetting = webview.getSettings(); websetting.setJavaScriptEnabled(true); //与JS交互 websetting.setDomStorageEnabled(true); //开启DOM形式存储 websetting.setDatabaseEnabled(true); //开启数据库形式存储 String appCacheDir = this.getDir("cache", Context.MODE_PRIVATE).getPath(); //缓存数据的存储地址 websetting.setAppCachePath(appCacheDir); websetting.setAppCacheEnabled(true); //开启缓存功能 websetting.setCacheMode(WebSettings.LOAD_DEFAULT); //缓存模式 websetting.setAllowFileAccess(true);// 设置允许访问文件数据 websetting.setAppCacheMaxSize(1024 * 1024 * 8); //设置缓存文件大小}
网上也说缓存模式设置这样:
websetting.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); //缓存模式
两者的区别为:
LOAD_DEFAULT,根据cache-control决定是否从网络上取数据
LOAD_CACHE_ELSE_NETWORK,只要本地有,无论是否过期,或者no-cache,都使用缓存中的数据
LOAD_CACHE_ELSE_NETWORK,只要本地有,无论是否过期,或者no-cache,都使用缓存中的数据
使用LOAD_CACHE_ELSE_NETWORK会出现,比如你加购物车了,但到购物车去看没有的现象
webview除了加载url的setWebViewClient 外还有一个专用辅助方法
webview.setWebChromeClient(new WebChromeClient() {});
用于处理弹框 警示信息 图片 文件选择处理等, 因为js里面的alert confirm 事件即使有setjavascriptenabled(true) 但仍是不识别的,同样需要在setWebChromeClient里面重写,用android的方法显示:
@Overridepublic boolean onJsAlert(WebView view, String url, String message, JsResult result) { Log.d(TAG, "url =" + url + "----message=" + message + "-----result==" + result); final JsResult jr = result; if (message.contains("*******")) { // SweetAlertDialog 自定义的一个dialog SweetAlertDialog sd = new SweetAlertDialog(MainActivity.this, SweetAlertDialog.CUSTOM_IMAGE_TYPE); sd.setTitleText("***********"); sd.setConfirmText("确定"); sd.setCancelable(false); sd.setCanceledOnTouchOutside(false); sd.setConfirmClickListener(new SweetAlertDialog.OnSweetClickListener() { @Override public void onClick(SweetAlertDialog sDialog) { jr.confirm(); sDialog.dismiss(); } }); sd.show(); }else { //处理其他alert事件 }
@Overridepublic boolean onJsConfirm(final WebView view, String url, String message, JsResult result) { Log.d(TAG, "url =" + url + "----message=" + message + "-----result==" + result); final JsResult jr = result; if (message.contains("***********")) { // SweetAlertDialog 是我自定义的一个dialog SweetAlertDialog sd = new SweetAlertDialog(MainActivity.this, SweetAlertDialog.WARNING_TYPE); sd.setTitleText("************?"); // .setContentText("Won't be able to recover this file!") sd.setCancelText("取消"); sd.setConfirmText("确定"); sd.showCancelButton(true); sd.setCancelable(false); sd.setCanceledOnTouchOutside(false); sd.setCancelClickListener(new SweetAlertDialog.OnSweetClickListener() { @Override public void onClick(SweetAlertDialog sDialog) { // reuse previous dialog instance, keep widget user state, reset them if you need sDialog.dismiss(); jr.cancel(); } }); sd.setConfirmClickListener(new SweetAlertDialog.OnSweetClickListener() { @Override public void onClick(SweetAlertDialog sDialog) { jr.confirm(); Toast.makeText(MainActivity.this, "移出成功", Toast.LENGTH_SHORT).show(); sDialog.dismiss(); } }); sd.show(); return true; }
对于webview上传文件图片同样在setWebViewChromeClient中写入方法:
//3.0++版本public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) { Log.d(TAG, "3.0++"); openFileChooserImpl(uploadMsg);}//3.0--版本public void openFileChooser(ValueCallback<Uri> uploadMsg) { Log.d(TAG, "3.0"); openFileChooserImpl(uploadMsg);}public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) { Log.d(TAG, "4.1"); openFileChooserImpl(uploadMsg);}@Overridepublic boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) { Log.d(TAG, "5.0++"); onenFileChooseImpleForAndroid(filePathCallback); return true;}
android在5.0之后才将webview打开文件图片方法固定,所以会有两个不同的方法,android会自己根据版本选择 下面代码会给出
这里重点说下android4.4版本的上传路径的重新获取和android4.4.4打开文件或图片取消的情况
getRealPathFromURL( ) 是对选中的图片或文件路径的重新修改,不然上传会卡在哪里,
onActivityResult( ) 是当打开文件或图片列表时,用户按back键取消返回时,传入intent 为空,所以将mUploadMessage.onReceiveValue(null) 也赋予null值,才可正常返回,
public ValueCallback<Uri> mUploadMessage;private void openFileChooserImpl(ValueCallback<Uri> uploadMsg) { mUploadMessage = uploadMsg; Intent i = new Intent(Intent.ACTION_GET_CONTENT); i.addCategory(Intent.CATEGORY_OPENABLE); i.setType("image/*"); startActivityForResult(Intent.createChooser(i, "File Chooser"), FILECHOOSER_RESULTCODE);}public ValueCallback<Uri[]> mUploadMessageForAndroid5;private void onenFileChooseImpleForAndroid(ValueCallback<Uri[]> filePathCallback) { mUploadMessageForAndroid5 = filePathCallback; Intent contentSelectionIntent = new Intent(Intent.ACTION_GET_CONTENT); contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE); contentSelectionIntent.setType("image/*"); Intent chooserIntent = new Intent(Intent.ACTION_CHOOSER); chooserIntent.putExtra(Intent.EXTRA_INTENT, contentSelectionIntent); chooserIntent.putExtra(Intent.EXTRA_TITLE, "Image Chooser"); startActivityForResult(chooserIntent, FILECHOOSER_RESULTCODE_FOR_ANDROID_5);}@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent intent) { if (requestCode == FILECHOOSER_RESULTCODE) { if (null == mUploadMessage) return; if (intent == null) { Toast.makeText(MainActivity.this, "已取消", Toast.LENGTH_SHORT).show(); mUploadMessage.onReceiveValue(null); mUploadMessage = null; return; } Log.e(TAG, "requestCode=" + requestCode + "resultCode=" + resultCode + "intent.getdata()=="); if (Build.VERSION.SDK_INT == 19) { String realPathFromURI = getRealPathFromURI(intent.getData()); File file = new File(realPathFromURI); if (file.exists()) { Uri uri = Uri.fromFile(file); Log.e(TAG, "文件uri-->" + uri); Toast.makeText(MainActivity.this, "图片上传中...", Toast.LENGTH_SHORT).show(); mUploadMessage.onReceiveValue(uri); } } mUploadMessage = null; } else if (requestCode == FILECHOOSER_RESULTCODE_FOR_ANDROID_5) { if (null == mUploadMessageForAndroid5) return; Uri result = (intent == null || resultCode != RESULT_OK) ? null : intent.getData(); if (result != null) { Toast.makeText(MainActivity.this, "图片上传中...", Toast.LENGTH_SHORT).show(); mUploadMessageForAndroid5.onReceiveValue(new Uri[]{result}); } else { mUploadMessageForAndroid5.onReceiveValue(new Uri[]{}); } mUploadMessageForAndroid5 = null; }}public String getRealPathFromURI(Uri contentUri) { String res = null; String[] proj = {MediaStore.Images.Media.DATA}; Cursor cursor = MainActivity.this.getContentResolver().query(contentUri, proj, null, null, null); if (cursor.moveToFirst()) { int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); res = cursor.getString(column_index); } cursor.close(); return res;}
这些都是项目中遇到的吧,不大也不小,记录下来,也希望能帮助到有同样问题的你。
阅读全文
1 0
- webview 那些事儿
- WebView与H5那些事儿
- Android之使用WebView的那些事儿
- WebView与H5那些事儿(=)
- WebView性能优化的那些事儿……
- 那些事儿
- 【产品那些事儿】产品经理那些事儿
- 西工大:那些人儿、那些事儿
- 明朝的那些事儿
- 明朝那些事儿
- '符号连接'那些事儿
- 《明朝那些事儿》读书笔记
- 去年那些事儿?
- Java编程那些事儿
- 广告匹配那些事儿
- Lighttpd那些事儿
- 依赖注入那些事儿
- Oracle 的那些事儿
- MySQL解压安装步骤
- 删除时bug:Unknown return value type: java.lang.Integer
- thinkphp5+workerman+layim 在线客服系统
- Save your cats Aizu
- linux常用命令 ls等
- webview 那些事儿
- 数据库优化方法借鉴
- Ubuntu报错修复方法
- StringUtils用法+StringUtils详细介绍
- 【机器学习】神经网络
- 在linux中使用python实现oracle进程的均衡负载
- java.lang.String.isEmpty()
- 欢迎使用CSDN-markdown编辑器
- 安卓设计模式の策略模式