Android 自定义WebView 原生接入及WebView JavascriptInterface

来源:互联网 发布:淘宝开网店的流程 编辑:程序博客网 时间:2024/05/16 10:50

一、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的引用,不能回收,必然会造成一些内存泄露。

1 0
原创粉丝点击