Android WebView与javaScript交互

操作前提
webview.getSettings().setJavaScriptEnabled(true);

通过webView调用JavaScript方法
webView.loadUrl("javascript:METHOD")
或者 webView.evaluateJavaScript("javascript:METHOD",CallBack) //只能在4.4以上调用,效率高,能拿到返回结果

loadUrl在4.4之前的系统中会导致网页重载,4.4以后无影响
如果调用的方法有参数的话,javascript是弱类型,如果参数是字符串形式,则需要使用单引号’'进行包括,如果包含\之类的符号,则需要转义,使用\

JavaScript调用Java方法
webView.addJavaScriptInterface("接口对象","接口名字"); //这个名字给js端当做对象来调用内部方法
然后在接口对象类里面给所有JavaScript可以调用的Java方法添加@JavaScriptInterface注解,加注解是防止h5进行攻击,因为没有注解的话,h5可以持有对象,可以调用对象的任何方法,私有的可以通过对象拿到Class进行反射调用

webview内存泄漏问题解决
在销毁过程中需保证 先执行webView的onDetachedFromWindow 然后执行destroy()释放webview
onDestroy()中

 if (mWebView != null) {
    
    
      ViewParent parent = mWebView.getParent();
      if (parent != null) {
    
    
         ((ViewGroup) parent).removeView(mWebView);
      }
      mWebView.removeAllViews();
      mWebView.destroy();  //如果只写这一行代码,则不能保证onDetachedFromWindo会执行, 导致内存泄漏,因为这个方法内部判断了if(!isDestroyed){执行释放逻辑}
      mWebView = null;
   }

注:webview字体大小不随系统字体大小解决方法 webSettings.setTextZoom(100);

JSBridge库

下面是基于JSBridge库的封装

public abstract class BaseWebView extends BridgeWebView {
    
    
    public BaseWebView(Context context, AttributeSet attrs) {
    
    
        super(context, attrs);
        setWebAttr();
        registerDefaultHandlers();
    }

    public BaseWebView(Context context, AttributeSet attrs, int defStyle) {
    
    
        super(context, attrs, defStyle);
        setWebAttr();
        registerDefaultHandlers();
    }

    public BaseWebView(Context context) {
    
    
        super(context);
        setWebAttr();
        registerDefaultHandlers();
    }

    protected void setWebAttr() {
    
    
        WebSettings settings = this.getSettings();
        settings.setDomStorageEnabled(true);
        setWebChromeClient(new WebChromeClient() {
    
    
            @Override
            public void onReceivedTitle(WebView view, String title) {
    
    
                BaseWebView.this.onReceivedTitle(title);
                super.onReceivedTitle(view, title);
            }

            @Override
            public void onProgressChanged(WebView view, int newProgress) {
    
    
                BaseWebView.this.onProgressChanged(newProgress);
                super.onProgressChanged(view, newProgress);
            }
        });
    }

    protected abstract void registerDefaultHandlers();

    protected abstract void onReceivedTitle(String title);

    protected abstract void onProgressChanged(int progress);
}
public class DefaultWebView extends BaseWebView implements OpenNativePageHandler.Callback {
    
    

    public interface Callback {
    
    
        boolean openNativePage(JSONObject param);

        void onReceivedError(WebView view);

        void onReceivedTitle(String title);

        void onProgressChanged(int progress);
    }

    public static abstract class SimpleCallBack implements Callback {
    
    
        public void onReceivedError(WebView view) {
    
    
        }

        public void onReceivedTitle(String title) {
    
    
        }

        public void onProgressChanged(int progress) {
    
    

        }
    }

    private static final String WEBVIEW_VERSION = "0";
    private Callback mCallback;

    public DefaultWebView(Context context, AttributeSet attrs) {
    
    
        super(context, attrs);
    }

    public DefaultWebView(Context context, AttributeSet attrs, int defStyle) {
    
    
        super(context, attrs, defStyle);
    }

    public DefaultWebView(Context context) {
    
    
        super(context);
    }

    public Callback getCallback() {
    
    
        return mCallback;
    }

    public void setCallback(Callback callback) {
    
    
        this.mCallback = callback;
    }

    @Override
    protected void registerDefaultHandlers() {
    
    
    	//这些是提前注册好的handler,供h5在需要的时候调用
        this.registerHandler("getInfo", new GetInfoHandler());
        this.registerHandler("getLocation", new GetLocationHandler());
        this.registerHandler("openNativePage", new OpenNativePageHandler(this));
    }

    @Override
    protected void onReceivedTitle(String title) {
    
    
        if (mCallback != null) {
    
    
            mCallback.onReceivedTitle(title);
        }
    }

    @Override
    protected void onProgressChanged(int progress) {
    
    
        if (mCallback != null) {
    
    
            mCallback.onProgressChanged(progress);
        }
    }

    public Map<String, String> getDefaultHeaders() {
    
    
        Map<String, String> headers = new HashMap<>();
        JSONObject utk = new JSONObject();
        try {
    
    
            User user = ServerHandler.getCurrentUser();
            if (user != null) {
    
    
                Integer userId = user.getUserId();
                if (userId != null) {
    
    
                    utk.put("id", String.valueOf(userId));
                }
                String atk = user.getAtk();
                if (atk != null) {
    
    
                    utk.put("atk", atk);
                }
            }

            if (ColorVConst.DEVICE_ID != null) {
    
    
                utk.put("udid", ColorVConst.DEVICE_ID);
            }
            utk.put("webview_ver", WEBVIEW_VERSION);
        } catch (JSONException e) {
    
    
            e.printStackTrace();
        }

        headers.put("utk", utk.toString());
        return headers;
    }

    public void loadUrl(String url) {
    
    
        super.loadUrl(url, getDefaultHeaders());
    }

    @Override
    public boolean openNativePage(JSONObject param) {
    
    
        if (mCallback != null) {
    
    
            return mCallback.openNativePage(param);
        }
        return false;
    }

    @Override
    public boolean showMoreBtn(int type, boolean showMore) {
    
    
        if (mCallback != null) {
    
    
            return mCallback.showMoreBtn(type, showMore);
        }
        return false;
    }

    @Override
    protected BridgeWebViewClient generateBridgeWebViewClient() {
    
    
        return new MyBridgeWebViewClient(this);
    }

    class MyBridgeWebViewClient extends BridgeWebViewClient {
    
    
        public MyBridgeWebViewClient(BridgeWebView webView) {
    
    
            super(webView);
        }

        @Override
        public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
    
    
            super.onReceivedError(view, request, error);
            if (mCallback != null) {
    
    
                mCallback.onReceivedError(view);
            }
        }

        @Override
        public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
    
    
            super.onReceivedError(view, errorCode, description, failingUrl);
            if (mCallback != null) {
    
    
                mCallback.onReceivedError(view);
            }
        }

        @Override
        @TargetApi(Build.VERSION_CODES.LOLLIPOP)
        public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
    
    
            LogUtils.println("web view request url: " + request.getUrl());
            LogUtils.println("web view request url: " + request.getMethod());
            Map<String, String> headers = request.getRequestHeaders();
            if (headers != null && headers.size() > 0) {
    
    
                LogUtils.println("web view headers start-----------");
                for (String key : headers.keySet()) {
    
    
                    String value = headers.get(key);
                    LogUtils.println("web view header " + key + ": " + value);
                }
                LogUtils.println("web view headers end-----------");
            }
            return super.shouldInterceptRequest(view, request);
        }

        @Override
        public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
    
    
            LogUtils.println("web view request url: " + url);
            return super.shouldInterceptRequest(view, url);
        }
    }
}

public abstract class BaseHandler implements BridgeHandler {
    
    

    private static final String DEFAULT_ERROR_MESSAGE="出错了";

    private static final String ERROR_MESSAGE_KEY = "error_message";
    private static final String ERROR_CODE_KEY = "error_code";

    protected void handlerError(String errorMsg,int errorCode, CallBackFunction function)
    {
    
    
        JSONObject jsonObject = new JSONObject();

        try {
    
    
            if (errorMsg != null) {
    
    
                jsonObject.put(ERROR_MESSAGE_KEY, errorMsg);
            }
            else {
    
    
                jsonObject.put(ERROR_MESSAGE_KEY,DEFAULT_ERROR_MESSAGE);
            }
            jsonObject.put(ERROR_CODE_KEY,errorCode);
        } catch (JSONException e) {
    
    
            e.printStackTrace();
        }

        if (function != null) {
    
    
            function.onCallBack(jsonObject.toString());
        }
    }

    protected void handlerError(String errorMsg,CallBackFunction function)
    {
    
    
        this.handlerError(errorMsg,0,function);
    }

    protected void handlerError(CallBackFunction function)
    {
    
    
        this.handlerError(null,0,function);
    }
}

public class GetInfoHandler extends BaseHandler {
    
    

    @Override
    public void handler(String data, CallBackFunction function) {
    
    
        JSONObject info = new JSONObject();
        try {
    
    
            //塞入数据
        } catch (Exception e) {
    
    
            e.printStackTrace();
            this.handlerError(e.getLocalizedMessage(),function);
            return;
        }

        function.onCallBack(info.toString());
    }
}

猜你喜欢

转载自blog.csdn.net/qq_33666539/article/details/84624941