Webview兼容h5的localstorage以及input file标签
来源:互联网 发布:unity3d最全资源合集 编辑:程序博客网 时间:2024/06/06 18:17
首先我先描述一下我遇到的问题,在我把h5的项目嵌入安卓原生的外壳时,由于h5的
代码涉及到他们自己本地的存储,所以在我点击h5页面上的按钮后,页面没有任何响应,
在排查一顿之后,发像是因为没有兼容他们的localstorage,要实现兼容其实很简单
//兼容h5的localStorage settings.setDomStorageEnabled(true); settings.setAppCacheMaxSize(1024*1024*8); String path = getApplicationContext().getCacheDir().getAbsolutePath();//把内部私有缓存目录'/data/data/包名/cache/'作为webview的appcache的缓存路径 settings.setAppCachePath(path); settings.setAllowFileAccess(true); settings.setAppCacheEnabled(true);
还有一个就是h5的项目中利用inputfile标签实现了调用系统相机以及图库的功能,而我们
安卓如果不做任何处理,原生的webview其实不能支持这样的功能,要支持这样的功能,主要
需要重写WebChromeClient,自己实现几个方法:
// For Android 3.0+ @SuppressWarnings({"rawtypes"}) public void openFileChooser(ValueCallback uploadMsg, String acceptType) { vCbFileChooser = uploadMsg; /*Intent i = new Intent(Intent.ACTION_GET_CONTENT); i.addCategory(Intent.CATEGORY_OPENABLE); i.setType("image/*"); MainActivity.this.startActivityForResult( Intent.createChooser(i,"文件选择"), FILECHOOSER_RESULTCODE );*/ selPic(); } // For Android 3.0+ @SuppressWarnings({"unused", "rawtypes"}) public void openFileChooser(ValueCallback uploadMsg) { openFileChooser(uploadMsg, ""); } //For Android 4.1 @SuppressWarnings({"unused", "rawtypes"}) public void openFileChooser(ValueCallback uploadMsg, String acceptType, String capture) { openFileChooser(uploadMsg, acceptType); } // For Lollipop 5.0+ Devices @SuppressWarnings("unchecked") @TargetApi(Build.VERSION_CODES.LOLLIPOP) public boolean onShowFileChooser( WebView mWebView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams ) { if (vCbFileChooser != null) { vCbFileChooser.onReceiveValue(null); vCbFileChooser = null; } vCbFileChooser = filePathCallback; selPic(); return true; }
完整代码如下,我也尽量做了一些优化,提高加载h5时的渲染速度
public class MainActivity extends AppCompatActivity {
WebView wv_webview;ImageView iv_start;//String url="http://wxtest.51hbx.com/wap/FQcarInfo.html";//服务器//String url="http://10.1.100.121/wap/FQcarInfo.html";//庆庆String url="http://test.51hbx.com:2043/wap/FQcarInfo.html";//小飞//String url="http://test.51hbx.com:2043/wap/adultrisks.html?productId=7";//小飞WebSettings settings;AlertDialog loadingDialog;boolean hasTouch=true;boolean hasRequest=false;boolean firstTime=true;//记录是否是首次加载,避免显示空白页String urlPrevious="";//记录上一次的urlString urlPreviousStart="";//记录上一次的url,//保存状态@Overrideprotected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); wv_webview.saveState(outState);}@SuppressLint("SetJavaScriptEnabled")@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); wv_webview= (WebView) findViewById(R.id.wv_webview); iv_start= (ImageView) findViewById(R.id.iv_start); settings = wv_webview.getSettings(); //js交互 wv_webview.setVerticalScrollbarOverlay(true); //设置webview支持js settings.setJavaScriptEnabled(true); settings.setAllowFileAccess(true); settings.setAllowContentAccess(true); settings.setDefaultTextEncodingName("UTF -8");//设置默认为utf-8 initCacheStrategies(settings);//配置缓存 initMyConfiguration(settings);//初始化部分配置,优化 if (null!=savedInstanceState) { wv_webview.restoreState(savedInstanceState); } else { // contain_wv.loadData(list.get(0).getContent(), "text/html;charset=UTF-8", null); wv_webview.loadUrl(url); } wv_webview.addJavascriptInterface(new JsInterface(this),"AndroidWebView"); //添加客户端支持 wv_webview.setWebChromeClient(new MyWebChromeClient()); wv_webview.setWebViewClient(new WebViewClient(){ @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { if (url.equals(urlPrevious)) { urlPrevious=url; return false; } else { urlPrevious=url; view.loadUrl(url); Log.e("==shouldOverride=","======="+url); return super.shouldOverrideUrlLoading(view, url); //return false; } } @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { super.onPageStarted(view, url, favicon); Log.e("===0====","===onPageStarted==="+url+":"+GapsTimes.effectiveTime(400)); if (!firstTime) { /*if (!url.equals(urlPreviousStart)) {*/ LoadingUtils.showDialogMethod(MainActivity.this); /*}*/ } else { firstTime=false; } urlPreviousStart=url; } @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); if (!wv_webview.getSettings().getLoadsImagesAutomatically()){ wv_webview.getSettings().setLoadsImagesAutomatically(true); } LoadingUtils.displayLoadingDialog(); } @Override public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) { super.onReceivedError(view, request, error); LoadingUtils.displayLoadingDialog(); } //加载页面资源会调用,每加载一次就会调用一次 @Override public void onLoadResource(WebView view, String url) { super.onLoadResource(view, url); Log.e("===1====","===onLoadResource==="); } });}private void initMyConfiguration(WebSettings settings) { //解决webview加载网页不显示图片 if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.LOLLIPOP) { settings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW); } if (Build.VERSION.SDK_INT>=19) { wv_webview.getSettings().setLoadsImagesAutomatically(true); } else { wv_webview.getSettings().setLoadsImagesAutomatically(false); } //提高渲染的优先级 settings.setRenderPriority(WebSettings.RenderPriority.HIGH); settings.setBlockNetworkImage(true);}@Overridepublic void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig);}//配置webview的缓存private void initCacheStrategies(WebSettings settings) { //配置浏览器的缓存 /*settings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); //配置h5的缓存 settings.setAppCacheEnabled(true); String path = getApplicationContext().getCacheDir().getPath();//把内部私有缓存目录'/data/data/包名/cache/'作为webview的appcache的缓存路径 settings.setAppCachePath(path); settings.setAppCacheMaxSize(5*1024*1024);*/ //另一种组合 //设置缓存模式 /*settings.setCacheMode(WebSettings.LOAD_DEFAULT); //开启 DOM storage API 功能 settings.setDomStorageEnabled(true);*/ //兼容h5的localStorage settings.setDomStorageEnabled(true); settings.setAppCacheMaxSize(1024*1024*8); String path = getApplicationContext().getCacheDir().getAbsolutePath();//把内部私有缓存目录'/data/data/包名/cache/'作为webview的appcache的缓存路径 settings.setAppCachePath(path); settings.setAllowFileAccess(true); settings.setAppCacheEnabled(true);}private class JsInterface { private Context mContext; public JsInterface(Context context) { this.mContext = context; } //在js中调用window.AndroidWebView.showInfoFromJs(name),便会触发此方法。 @JavascriptInterface public void showInfoFromJs(String name) { Toast.makeText(mContext, name, Toast.LENGTH_SHORT).show(); }}@Overridepublic boolean onKeyDown(int keyCode, KeyEvent event) { if ((keyCode==KeyEvent.KEYCODE_BACK)&&wv_webview.canGoBack()) { wv_webview.goBack(); return true; } return super.onKeyDown(keyCode, event);}@Overrideprotected void onDestroy() { super.onDestroy(); wv_webview.stopLoading(); wv_webview.destroy(); wv_webview=null;}private final static int FILECHOOSER_RESULTCODE = 2;private final static int TAKEPHOTO_RESULTCODE = 1;private ValueCallback<Uri[]> vCbFileChooser;String pathTakePhoto="";Uri uriTakePhoto;public class MyWebChromeClient extends WebChromeClient { @Override public void onProgressChanged(WebView view, int newProgress) { super.onProgressChanged(view, newProgress); Log.e("==onProgressChanged==", "======" + newProgress); if (newProgress >= 100) { iv_start.setVisibility(View.GONE); //解除数据阻止 settings.setBlockNetworkImage(false); } } // For Android 3.0+ @SuppressWarnings({"rawtypes"}) public void openFileChooser(ValueCallback uploadMsg, String acceptType) { vCbFileChooser = uploadMsg; /*Intent i = new Intent(Intent.ACTION_GET_CONTENT); i.addCategory(Intent.CATEGORY_OPENABLE); i.setType("image/*"); MainActivity.this.startActivityForResult( Intent.createChooser(i,"文件选择"), FILECHOOSER_RESULTCODE );*/ selPic(); } // For Android 3.0+ @SuppressWarnings({"unused", "rawtypes"}) public void openFileChooser(ValueCallback uploadMsg) { openFileChooser(uploadMsg, ""); } //For Android 4.1 @SuppressWarnings({"unused", "rawtypes"}) public void openFileChooser(ValueCallback uploadMsg, String acceptType, String capture) { openFileChooser(uploadMsg, acceptType); } // For Lollipop 5.0+ Devices @SuppressWarnings("unchecked") @TargetApi(Build.VERSION_CODES.LOLLIPOP) public boolean onShowFileChooser( WebView mWebView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams ) { if (vCbFileChooser != null) { vCbFileChooser.onReceiveValue(null); vCbFileChooser = null; } vCbFileChooser = filePathCallback; selPic(); return true; }}@SuppressWarnings("unused")private void selPic() { if (!checkSDcard()){return;} String[] selectPicTypeStr = { "拍照","选择照片" }; AlertDialog alertDialog = new AlertDialog.Builder(this) .setItems( selectPicTypeStr, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { switch (which) { case 0://拍照 chkPrivBeforeTakePhoto(); break; case 1://选择图片文件 choosePicFile(); break; default: break; } } } ).setOnCancelListener( new DialogInterface.OnCancelListener() { @SuppressWarnings("unchecked") @Override public void onCancel(DialogInterface dialog) { if (null != vCbFileChooser) { vCbFileChooser.onReceiveValue(null); vCbFileChooser = null; } } } ).show();}private static final int PERMISSIONS_REQUEST_CODE_TAKE_PHOTO = 1;@SuppressWarnings("unchecked")private void chkPrivBeforeTakePhoto() { if( ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED ) { if (null != vCbFileChooser) { vCbFileChooser.onReceiveValue(null); vCbFileChooser = null; } new AlertDialog .Builder(this) .setTitle("提示信息") .setMessage("该功能需要您接受应用对一些关键权限(拍照)的申请,如之前拒绝过,可到手机系统的应用管理授权设置界面再次设置。") .setPositiveButton("确认", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { ActivityCompat.requestPermissions(MainActivity.this, new String[]{ Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE }, PERMISSIONS_REQUEST_CODE_TAKE_PHOTO); } }) .show(); } else { chooseTakePhoto(); }}private void chooseTakePhoto() { pathTakePhoto = Environment.getExternalStorageDirectory().getPath() + "/mbossclient/camera/temp/" + (System.currentTimeMillis() + ".jpg"); File vFile = new File(pathTakePhoto); if (!vFile.exists()) {//必须确保文件夹路径存在,否则拍照后无法完成回调 File vDirPath = vFile.getParentFile(); vDirPath.mkdirs(); } else { if (vFile.exists()) { vFile.delete(); } } Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); uriTakePhoto = Uri.fromFile(vFile); intent.putExtra(MediaStore.EXTRA_OUTPUT, uriTakePhoto); startActivityForResult(intent, TAKEPHOTO_RESULTCODE);}private boolean checkSDcard() { boolean flag = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED); if(!flag){Toast.makeText(this, "请插入手机存储卡再使用本功能", Toast.LENGTH_SHORT).show();} return flag;}/** * 选择文件 */private void choosePicFile(){ Intent i = new Intent(Intent.ACTION_GET_CONTENT); i.addCategory(Intent.CATEGORY_OPENABLE); i.setType("image/*"); MainActivity.this.startActivityForResult( Intent.createChooser(i,"文件选择"), FILECHOOSER_RESULTCODE );}@SuppressLint("NewApi")@SuppressWarnings("unchecked")@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent intent) { if (requestCode == FILECHOOSER_RESULTCODE) {//从文件选择器选择照片 if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { if(null == vCbFileChooser) {return;} vCbFileChooser.onReceiveValue(WebChromeClient.FileChooserParams.parseResult(resultCode, intent)); vCbFileChooser = null; } else { if(null == vCbFileChooser) {return;} Uri result = (intent == null || resultCode != RESULT_OK)? null:intent.getData(); vCbFileChooser.onReceiveValue(new Uri[]{result}); vCbFileChooser = null; } } else if(requestCode == TAKEPHOTO_RESULTCODE){ if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { if(null == vCbFileChooser) {return;} if(null == uriTakePhoto) { vCbFileChooser.onReceiveValue(null); vCbFileChooser = null; return; } addImageGallery(pathTakePhoto); Uri[] uris = new Uri[1]; uris[0] = uriTakePhoto; vCbFileChooser.onReceiveValue(uris); vCbFileChooser = null; uriTakePhoto = null; pathTakePhoto = null; } else { if(null == vCbFileChooser) {return;} if(null == uriTakePhoto) { vCbFileChooser.onReceiveValue(null); vCbFileChooser = null; return; } addImageGallery(pathTakePhoto); vCbFileChooser.onReceiveValue(new Uri[]{uriTakePhoto}); vCbFileChooser = null; uriTakePhoto = null; pathTakePhoto = null; } } super.onActivityResult(requestCode, resultCode, intent);}/** * 解决拍照后在相册中找不到的问题 */private void addImageGallery(String path) { if (null == path || "".equals(path)) { return; } File file = new File(pathTakePhoto); ContentValues values = new ContentValues(); values.put(MediaStore.Images.Media.DATA, file.getAbsolutePath()); values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg"); getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);}
}
阅读全文
0 0
- Webview兼容h5的localstorage以及input file标签
- Android WebView 不支持 H5 input type="file" 解决方法
- Android WebView 支持H5图片上传<input type="file">
- Android WebView 不支持 H5 input type="file" 解决方法
- Android WebView H5页面 input type =“file”解决方法
- Android WebView 不支持 H5 input type="file" 解决方法
- Android Webview H5交互之LocalStorage
- input标签type="file"的格式要求,以及文件阅读,图片上传前的显示
- js/html中input、text、redio、checkbox、file、option以及textarea标签的使用
- h5新标签兼容写法
- H5标签video兼容IE8
- 自定义input的file标签形状
- type=“file”的input标签美化
- HTML中input:file标签的使用
- webview中input file伪造无刷新上传(兼容Android和IOS)
- WebView实现html文件选择(input type=file),兼容安卓6.0
- 面试总结(2):H5新标签的兼容写法
- 安卓WebView控件完美支持h5 的video标签
- mysql5.7创建用户授权删除用户撤销授权
- 增删改查CURD(数据库助手)
- Myeclipse卡死,无响应,加载慢
- java序
- 图片代码
- Webview兼容h5的localstorage以及input file标签
- 【直播系列之二】快速接入PC端直播功能
- 基础练习 十六进制转十进制
- 四、MySQL互为主从配置
- AR 广告大屏UI界面搭建一
- (二)php操作符与控制结构
- 云计算与大数据互利互进 加码云计算安全成破题关键
- 大数运算_string类的简单应用
- PHP面向对象的三大特征: 继承,封装,多态