注册 登录  
 加关注

网易博客网站关停、迁移的公告:

将从2018年11月30日00:00起正式停止网易博客运营
查看详情
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

罔少年

QQ 332256483

 
 
 

日志

 
 

webViewjavascripBridge setWebViewClient冲突  

2015-08-11 15:25:15|  分类: android |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
采用webViewjavascripBridge  做js和java的通信后,发现如果webView使用了setWebViewClient(new WebViewClient(){});那么通信就会中断。

查看BridgeWebView.class的源码,可以看到重写了setWebViewClient()方法
 private void init() {
this.setVerticalScrollBarEnabled(false);
this.setHorizontalScrollBarEnabled(false);
this.getSettings().setJavaScriptEnabled(true);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
WebView.setWebContentsDebuggingEnabled(true);
}
this.setWebViewClient(new BridgeWebViewClient()); //重写BridgeWebViewClient()
}
查看BridgeWebViewClient类,最后发现是onPageFinished()在作怪
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);

if (toLoadJs != null) {
BridgeUtil.webViewLoadLocalJs(view, toLoadJs);
}

//
if (startupMessage != null) {
for (Message m : startupMessage) {
dispatchMessage(m);
}
startupMessage = null;
}
}

所以我就想到那何不直接把webViw.setWebViewClient(new WebViewClient(){});改成webViw.setWebViewClient(new BridgeWebViewClient(){});呢?

结果发现,BridgeWebViewClient这是个内部类,无法直接new,所以只能把BridgeWebViewClient和BridgeWebView这两个类分开。

新建一个BridgeWebViewClient.class 写一个构造函数,把webView传进去
public class BridgeWebViewClient extends WebViewClient {

BridgeWebView mBridgeWebView = null;
public BridgeWebViewClient(BridgeWebView bridgeWebView) {
mBridgeWebView = bridgeWebView;
}
	......
}
重写后的BridgeWebView.class
package com.zjcpo.jsbridge.jsBridge;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.os.Build;
import android.os.Looper;
import android.os.SystemClock;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.webkit.WebView;
import android.webkit.WebViewClient;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@SuppressLint("SetJavaScriptEnabled")
public class BridgeWebView extends WebView implements WebViewJavascriptBridge {

private final String TAG = "BridgeWebView";

String toLoadJs = "WebViewJavascriptBridge.js";
Map<String, CallBackFunction> responseCallbacks = new HashMap<String, CallBackFunction>();
Map<String, BridgeHandler> messageHandlers = new HashMap<String, BridgeHandler>();
BridgeHandler defaultHandler = new DefaultHandler();

List<Message> startupMessage = new ArrayList<Message>();
long uniqueId = 0;

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

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

public BridgeWebView(Context context) {
super(context);
init();
}

/**
* @param handler default handler,handle messages send by js without assigned handler name,
* if js message has handler name, it will be handled by named handlers registered by native
*/
public void setDefaultHandler(BridgeHandler handler) {
this.defaultHandler = handler;
}

private void init() {
this.setVerticalScrollBarEnabled(false);
this.setHorizontalScrollBarEnabled(false);
this.getSettings().setJavaScriptEnabled(true);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
WebView.setWebContentsDebuggingEnabled(true);
}
this.setWebViewClient(new BridgeWebViewClient(this));
}

public void handlerReturnData(String url) {
String functionName = BridgeUtil.getFunctionFromReturnUrl(url);
CallBackFunction f = responseCallbacks.get(functionName);
String data = BridgeUtil.getDataFromReturnUrl(url);
if (f != null) {
f.onCallBack(data);
responseCallbacks.remove(functionName);
return;
}
}


@Override
public void send(String data) {
send(data, null);
}

@Override
public void send(String data, CallBackFunction responseCallback) {
doSend(null, data, responseCallback);
}

private void doSend(String handlerName, String data, CallBackFunction responseCallback) {
Message m = new Message();
if (!TextUtils.isEmpty(data)) {
m.setData(data);
}
if (responseCallback != null) {
String callbackStr = String.format(BridgeUtil.CALLBACK_ID_FORMAT, ++uniqueId + (BridgeUtil.UNDERLINE_STR + SystemClock.currentThreadTimeMillis()));
responseCallbacks.put(callbackStr, responseCallback);
m.setCallbackId(callbackStr);
}
if (!TextUtils.isEmpty(handlerName)) {
m.setHandlerName(handlerName);
}
queueMessage(m);
}

private void queueMessage(Message m) {
if (startupMessage != null) {
startupMessage.add(m);
} else {
dispatchMessage(m);
}
}

public void dispatchMessage(Message m) {
String messageJson = m.toJson();
//escape special characters for json string
messageJson = messageJson.replaceAll("(\\\\)([^utrn])", "\\\\\\\\$1$2");
messageJson = messageJson.replaceAll("(?<=[^\\\\])(\")", "\\\\\"");
String javascriptCommand = String.format(BridgeUtil.JS_HANDLE_MESSAGE_FROM_JAVA, messageJson);
if (Thread.currentThread() == Looper.getMainLooper().getThread()) {
this.loadUrl(javascriptCommand);
}
}

public void flushMessageQueue() {
if (Thread.currentThread() == Looper.getMainLooper().getThread()) {
loadUrl(BridgeUtil.JS_FETCH_QUEUE_FROM_JAVA, new CallBackFunction() {

@Override
public void onCallBack(String data) {
// deserializeMessage
List<Message> list = null;
try {
list = Message.toArrayList(data);
} catch (Exception e) {
e.printStackTrace();
return;
}
if (list == null || list.size() == 0) {
return;
}
for (int i = 0; i < list.size(); i++) {
Message m = list.get(i);
String responseId = m.getResponseId();
// 是否是response
if (!TextUtils.isEmpty(responseId)) {
CallBackFunction function = responseCallbacks.get(responseId);
String responseData = m.getResponseData();
function.onCallBack(responseData);
responseCallbacks.remove(responseId);
} else {
CallBackFunction responseFunction = null;
// if had callbackId
final String callbackId = m.getCallbackId();
if (!TextUtils.isEmpty(callbackId)) {
responseFunction = new CallBackFunction() {
@Override
public void onCallBack(String data) {
Message responseMsg = new Message();
responseMsg.setResponseId(callbackId);
responseMsg.setResponseData(data);
queueMessage(responseMsg);
}
};
} else {
responseFunction = new CallBackFunction() {
@Override
public void onCallBack(String data) {
// do nothing
}
};
}
BridgeHandler handler;
if (!TextUtils.isEmpty(m.getHandlerName())) {
handler = messageHandlers.get(m.getHandlerName());
} else {
handler = defaultHandler;
}
handler.handler(m.getData(), responseFunction);
}
}
}
});
}
}

public void loadUrl(String jsUrl, CallBackFunction returnCallback) {
this.loadUrl(jsUrl);
responseCallbacks.put(BridgeUtil.parseFunctionName(jsUrl), returnCallback);
}

/**
* register handler,so that javascript can call it
*
* @param handlerName
* @param handler
*/
public void registerHandler(String handlerName, BridgeHandler handler) {
if (handler != null) {
messageHandlers.put(handlerName, handler);
}
}

/**
* call javascript registered handler
*
* @param handlerName
* @param data
* @param callBack
*/
public void callHandler(String handlerName, String data, CallBackFunction callBack) {
doSend(handlerName, data, callBack);
}
}
重写后的BridgeWebViewClient.class
package com.zjcpo.jsbridge.jsBridge;

import android.graphics.Bitmap;
import android.webkit.WebView;
import android.webkit.WebViewClient;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;

/**
* Created by jiemiao.zhang on 2015/8/11.
*/
public class BridgeWebViewClient extends WebViewClient {

BridgeWebView mBridgeWebView = null;
public BridgeWebViewClient(BridgeWebView bridgeWebView) {
mBridgeWebView = bridgeWebView;
}

@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
try {
url = URLDecoder.decode(url, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
if (url.startsWith(BridgeUtil.YY_RETURN_DATA)) { // 如果是返回数据
mBridgeWebView.handlerReturnData(url);
return true;
} else if (url.startsWith(BridgeUtil.YY_OVERRIDE_SCHEMA)) { //
mBridgeWebView.flushMessageQueue();
return true;
} else {
return super.shouldOverrideUrlLoading(view, url);
}
}

@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
}

@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);

if (mBridgeWebView.toLoadJs != null) {
BridgeUtil.webViewLoadLocalJs(view, mBridgeWebView.toLoadJs);
}

//
if (mBridgeWebView.startupMessage != null) {
for (Message m : mBridgeWebView.startupMessage) {
mBridgeWebView.dispatchMessage(m);
}
mBridgeWebView.startupMessage = null;
}
}

@Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
super.onReceivedError(view, errorCode, description, failingUrl);
}
}
Activity.class使用
webView.setWebViewClient(new BridgeWebViewClient(webView) {
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
}

@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
}

@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
return super.shouldOverrideUrlLoading(view, url);
}
});

所以只要3步就行
1、新建BridgeWebViewClient.class
2、把BridgeWebView.class的BridgeWebViewClient类分离
3、在activity的webView.setWebViewClient(new BridgeWebViewClient(webView){});


  评论这张
 
阅读(257)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018