最近刚好在用WebView对接一些接口设置,就写下来记录一下吧,希望能帮到遇到同样问题的人。
##一、基本设置 一般WebView不做多余配置,没有交互要求,只是很简单的载入网页的话,基本下面的配置就够用了
[代码]java代码:
1 2 3 4 5 6 | WebSettings mWebSettings = mWebView.getSettings(); mWebSettings.setSupportZoom(true); mWebSettings.setLoadWithOverviewMode(true); mWebSettings.setUseWideViewPort(true); mWebSettings.setDefaultTextEncodingName("GBK"); mWebSettings.setLoadsImagesAutomatically(true); |
上面可以看到,对于基本的使用,配置是很简单的,没什么太多需要自己注意的,接下来就是一些手机APP上载入网页的时候用得比较多的情况了,下面会一一列出。
##二、JS与APP交互 这种情况一般是比较常见的,就是JS网页调用APP的方法做一些本地事情,然后是APP调用JS的方法反馈一些情况什么的。
而要实现这个最重要的一个设置就是这个 mWebSettings.setJavaScriptEnabled(true); 要使能webview可以调用JS方法
1)APP调用JS方法
[代码]java代码:
1 2 3 | mWebView.loadUrl("javascript:test()");// 调用js函数无参数
mWebView.loadUrl("javascript:test(test)"); //test是js的函数test()的参数 |
2)JS调用APP方法 JS调用APP的方法也比较简单,只要添加JavascriptInterface方法接口即可
[代码]java代码:
1 | mWebView.addJavascriptInterface(mWebAppInterface, "AndroidWebAppInterface"); |
然后实现JS需要调用的方法,这里需要注意的就是安卓版本大于17的时候,需要在JS方法上加上注解
@JavascriptInterface
@JavascriptInterface
@JavascriptInterface
重要的事情说三遍
像这样
[代码]java代码:
1 2 3 4 5 6 | // 如果target 大于等于API 17,则需要加上如下注解 @JavascriptInterface public void showToast(String toast) { LogUtils.d(TAG, "toast = " + toast); Toast.makeText(mContext, toast, Toast.LENGTH_LONG).show(); } |
##三、HTML5数据存储(LocalStorage)
有时候网页需要自己保存一些关键数据,这个时候就需要用到像LocalStorage这些东西了,而安卓WebView默认是无法使用的,也是需要用户自己配置的,感觉好坑啊,IOS的直接加载啥都不用配置就都能用了,安卓直接用啥都不行,感觉被虐惨了。下面是关键配置,最最重要就是这个
mWebSettings.setDomStorageEnabled(true);mWebSettings.setDomStorageEnabled(true);mWebSettings.setDomStorageEnabled(true);
重要的事情说三遍
[代码]java代码:
1 2 3 4 5 | mWebSettings.setDomStorageEnabled(true); mWebSettings.setDatabaseEnabled(true); mWebSettings.setAppCacheEnabled(true); String appCachePath = getApplicationContext().getCacheDir().getAbsolutePath(); mWebSettings.setAppCachePath(appCachePath); |
##四、HTML5定位(获取当前地址)
存储完了,就该是定位了,有时候网页想自己直接获取定位地址,就需要用到定位配置了。当然该有的权限还是得自己加上,比如:
[代码]xml代码:
1 2 3 | <uses-permission android:name="android.permission.INTERNET"> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"></uses-permission></uses-permission></uses-permission> |
主要的配置就是需要复写WebChromeClient的三个方法
[代码]java代码:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 | @Override public void onReceivedIcon(WebView view, Bitmap icon) { super.onReceivedIcon(view, icon); }
@Override public void onGeolocationPermissionsHidePrompt() { super.onGeolocationPermissionsHidePrompt(); }
@Override public void onGeolocationPermissionsShowPrompt(final String origin, final GeolocationPermissions.Callback callback) { callback.invoke(origin, true, false);//注意个函数,第二个参数就是是否同意定位权限,第三个是是否希望内核记住 super.onGeolocationPermissionsShowPrompt(origin, callback); } |
基本加上上面的配置基本就OK了,没啥大问题。
##五、遇到的其它坑
1)多窗口的问题
html中的_bank标签就是新建窗口,在处理多窗口的时候需要配置下面的设置,不然可能点击没有反应
[代码]java代码:
1 2 | mWebSettings.setSupportMultipleWindows(true); mWebSettings.setJavaScriptCanOpenWindowsAutomatically(true); |
然后可以复写一下WebChromeClient的onCreateWindow方法
[代码]java代码:
1 2 3 4 5 6 7 8 | @Override public boolean onCreateWindow(WebView view, boolean isDialog, boolean isUserGesture, Message resultMsg) { WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj; transport.setWebView(mWebView); resultMsg.sendToTarget(); return true; } |
2)多页面在同一个WebView中打开,就是不新建activity或者调用系统浏览器打开,需要复写WebViewClient的shouldOverrideUrlLoading方法.
[代码]java代码:
1 2 3 4 5 | @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { view.loadUrl(url); return true; } |
3)WebView进行Http数据请求 这个相对也不复杂,主要是https坑比较大,加载数据基本用下面的就可以了
[代码]java代码:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | private void getWebData() { new Thread() { @Override public void run() { OkHttpClient okHttpClient = HttpClientSslHelper.getSslOkHttpClient(getApplicationContext(), AppApiContact.bServerDebug);//new OkHttpClient(); okHttpClient.setConnectTimeout(15, TimeUnit.SECONDS); Request request = new Request.Builder() .url(mWebUrl) .build(); try { Response response = okHttpClient.newCall(request).execute(); final String data = response.body().string(); LogUtils.d(TAG, "data = " + data); runOnUiThread(new Runnable() { @Override public void run() { if (StringHelper.notEmpty(data) && !isDestroy) {//页面销毁之后不做处理 // mWebView.loadData(data, "text/html; charset=UTF-8", null); mWebView.loadDataWithBaseURL(null, data, "text/html", "UTF-8", null); } } }); } catch (IOException e) { e.printStackTrace(); } } }.start(); } |
4)WebView进行HTTPS加密加载(这个坑貌似我还没解决,用的上面的第三种方法绕过去了)
5)JS调用安卓接口传输JSON格式数据 这个真是个大坑,以前一直没啥问题,直接传字符串数据结构就过来了,安卓也能直接解析,但是最近遇到安卓这边接受到数据死活不对,总是undefined值,也就是传输出问题了,后来反复排查才发现,需要对JSON数据字符串进行转义传输,不然就解析不到,也是无语了,例子如下
[代码]java代码:
01 02 03 04 05 06 07 08 09 10 11 12 13 | " { "title":"test title" } "
以前传这种字符串过来是可以正常解析的,也不知道发什么神经,突然不行了,必须做转义之后传这种才可以解析
" { \"title\":\"test title\" } " |
目前好像就遇到这些,等再遇到了再来更新吧,下面给出全部的配置
[代码]java代码:
001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047 048 049 050 051 052 053 054 055 056 057 058 059 060 061 062 063 064 065 066 067 068 069 070 071 072 073 074 075 076 077 078 079 080 081 082 083 084 085 086 087 088 089 090 091 092 093 094 095 096 097 098 099 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 | private void setUpViewComponent() { WebSettings mWebSettings = mWebView.getSettings(); mWebSettings.setSupportZoom(true); mWebSettings.setLoadWithOverviewMode(true); mWebSettings.setUseWideViewPort(true); mWebSettings.setJavaScriptEnabled(true); mWebSettings.setDefaultTextEncodingName("GBK"); mWebSettings.setSupportMultipleWindows(true); mWebSettings.setLoadsImagesAutomatically(true); mWebSettings.setDomStorageEnabled(true); mWebSettings.setDatabaseEnabled(true); mWebSettings.setAppCacheEnabled(true); String appCachePath = getApplicationContext().getCacheDir().getAbsolutePath(); mWebSettings.setAppCachePath(appCachePath); mWebSettings.setAllowFileAccess(true); if (AppApplication.getSdkVersion() >= 11) { mWebSettings.setDisplayZoomControls(false); } else { setZoomControlGone(mWebView); //Android 3.0(11) 以下使用以下方法 } mSwipeContainer.setOnRefreshListener(this); mWebAppInterface = new WebAppInterface(this); setWebViewListener(); }
private void setZoomControlGone(View view) { Class classType; Field field; try { classType = WebView.class; field = classType.getDeclaredField("mZoomButtonsController"); field.setAccessible(true); ZoomButtonsController mZoomButtonsController = new ZoomButtonsController( view); mZoomButtonsController.getZoomControls().setVisibility(View.GONE); try { field.set(view, mZoomButtonsController); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } catch (SecurityException e) { e.printStackTrace(); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (Exception ee) { ee.printStackTrace(); } }
private void setWebViewListener() { mWebView.addJavascriptInterface(mWebAppInterface, "AndroidWebAppInterface"); WebViewClient webClient = new CustWebViewClient(); mWebView.setWebViewClient(webClient); mWebView.setWebChromeClient(new WebChromeClient() { @Override public boolean onJsAlert(WebView view, String url, String message, JsResult result) { return super.onJsAlert(view, url, message, result); }
@Override public boolean onCreateWindow(WebView view, boolean isDialog, boolean isUserGesture, Message resultMsg) { return super.onCreateWindow(view, isDialog, isUserGesture, resultMsg); } });
mWebView.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View arg0) { return true; } }); }
private class CustomWebViewClient extends WebViewClient { public CustomWebViewClient() { super(); }
public boolean shouldOverrideUrlLoading(WebView view, String url) { // 重写此方法表明点击网页里面的链接还是在当前的Web view里跳转,不跳到浏览器那边 LogUtils.d(TAG, "url --" + url); view.loadUrl(url); return true; }
@Override public void onLoadResource(WebView view, String url) {
}
@Override public void onPageFinished(WebView view, String url) { mSwipeContainer.setRefreshing(false); }
@Override public void onPageStarted(WebView view, String url, Bitmap favicon) { mSwipeContainer.setRefreshing(true); } }
private void getWebData() { new Thread() { @Override public void run() { OkHttpClient okHttpClient = HttpClientSslHelper.getSslOkHttpClient(getApplicationContext(), AppApiContact.bServerDebug);//new OkHttpClient(); okHttpClient.setConnectTimeout(15, TimeUnit.SECONDS); Request request = new Request.Builder() .url(mWebUrl) .build(); try { Response response = okHttpClient.newCall(request).execute(); final String data = response.body().string(); LogUtils.d(TAG, "data = " + data); runOnUiThread(new Runnable() { @Override public void run() { if (StringHelper.notEmpty(data) && !isDestroy) {//页面销毁之后不做处理 // mWebView.loadData(data, "text/html; charset=UTF-8", null); mWebView.loadDataWithBaseURL(null, data, "text/html", "UTF-8", null); } } }); } catch (IOException e) { e.printStackTrace(); } } }.start(); |
共同学习,写下你的评论
评论加载中...
作者其他优质文章