一、WebView原生接入:
Android webview继承自AbsoluteLayout,可以在其中放入一些子View,如下所示的布局文件:
<TextView
android:id="@+id/hello"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"/>
<WebView
android:id="@+id/webview"
android:layout_below="@+id/hello"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:id="@+id/hello_webview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World In WebView"/>
/>
</WebView>
如果需要加载线上的地址需要配置网络权限,清单中加入:
//添加网络权限
<uses-permission android:name="android.permission.INTERNET" />
在Activity等中使用:
WebView mWebView = (WebView) findViewById(R.id.webview);
mWebView.loadUrl("http://www.baidu.com");
注意:loadUrl()必须在主线程中执行
webview的一些自定义的行为,请按照上一节中的行为进行自定义,例如在当前的webview页面中打开一个新链接:
public boolean shouldOverrideUrlLoading(WebView view, String url) {
//拦截某个URL,并按照业务需求进行处理。
view.loadUrl(url);
return true;
}
一般会对webview进行自定义,然后在代码的布局文件中引入自己的自定义WebView,如下:
public class MyWebView extends WebView{
public PaWebView(Context context) {
super(context);
initWebView();
}
public PaWebView(Context context, AttributeSet attrs){
super(context, attrs);
initWebView();
}
/**
* 初始化webview
*/
@TargetApi(Build.VERSION_CODES.FROYO)
private void initWebView(){
WebSettings webSettings = getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setSupportZoom(false);
webSettings.setUseWideViewPort(true);
webSettings.setLoadWithOverviewMode(true);
webSettings.setSavePassword(false);
webSettings.setDomStorageEnabled(true);
removeSecurityRisk();
}
/**
* 移除风险接口
*/
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
private void removeSecurityRisk(){
//移除操作系统开放的存在安全漏洞的对象
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB){
removeJavascriptInterface("searchBoxJavaBridge_") ;
removeJavascriptInterface("accessibility");
removeJavascriptInterface("accessibilityTraversal");
}
}
二:JavascriptInterface
Native需要开启JS支持,并提供一个接口,其中native接口的名字(NativeGetH5Interface)和与交互的接口名字(nativegeth5)可以和H5约定好,例如:
webSettings.setJavaScriptEnabled(true);
mWebView.addJavascriptInterface(NativeGetH5Interface(), "nativegeth5");
public class NativeGetH5Interface{
BaseActivity mActivity;
public PaHaoFangInterface(BaseActivity a) {
mActivity = a;
}
@JavascriptInterface
public String osVersion() {
return DeviceInfo.VersionName;
}
......
上述方法看似很完美,实际上问题重重,Android API 4.4以前,谷歌的webview存在安全漏洞,网页通过Js方法遍历代码中通过addjavascriptInterface注入进来的类的所有方法并从中获取到getClass方法,进而通过反射获取到Runtime对象,调用Runtime对象的exec方法执行一些操作,恶意的Js代码如下:
function execute(cmdArgs) {
for (var obj in window) {
if ("getClass" in window[obj]) {
alert(obj);
return window[obj].getClass().forName("java.lang.Runtime") .getMethod("getRuntime",null).invoke(null,null).exec(cmdArgs);
}
}
}
官方从4.4开始要求被Js调用的方法添加@JavascriptInterface注解,否则无效。低版本可以与前端约定一套协议,使用Js的prompt方法进行解决,除此之外,为了避免WebView加载任意url,也需要对url进行白名单检测。Android碎片化太严重也是一个需要对WebView做兼容的不得不面对的问题,WebView的内核在4.4版本进行了改变,由webkit改为chromium,除了上述所说的问题,WebView还有一个众所周知的问题,Activity与WebView关联后,WebView内部的一些操作的执行在新线程中,这些时间无法确定,而可能导致WebView一直持有Activity的引用,不能回收,必然会造成一些内存泄露。
本文介绍了如何在Android中实现WebView的原生接入,包括设置网络权限和主线程加载URL。同时,讨论了JavaScriptInterface的安全问题,如API 4.4以前的安全漏洞,以及如何使用@JavascriptInterface注解进行修复。此外,提到了WebView的兼容性问题,特别是不同版本内核差异导致的内存泄漏风险,并建议进行URL白名单检测。
4266

被折叠的 条评论
为什么被折叠?



