索马里海盗
索马里海盗
  • 发布:2017-01-08 21:57
  • 更新:2021-07-27 09:28
  • 阅读:14176

分享下android的websocket解决方案

分类:5+ SDK

分享下android的websocket结局方案
先占个坑
明天写

  • 2017.1.9
  • 最近在做一个外勤应用,里面要做即时通讯,最终选择的是自己写websocket封装协议,没有使用融云这些,原因是系统会给用户私有云部署,同时也不想太依赖于第三方
  • ios下面的websocket是没有任何问题的
  • 但是android上是有问题的 虽然官方说4.4以上支持,但是经测试 我的一台4.4的机器也是不支持,服务端报错是 protocol error
  • 我们做应用的 除非是公司品牌特别牛像微信支付宝这类,否则你放弃了4.4一下的用户,他们也就放弃了你
    网上找了很久,其中也搜到这里 http://ask.dcloud.net.cn/article/302
    也尝试了下不是很好
    最好只好自己尝试解决
    目标有三个
    1:使用第三方websocket js库 这样代码改动基本是最小的
    2:自己写一个dcloud插件

第一个方案 找了很多 包括jwebsocket socket.io
最后发现问题依旧,原因就不说了
开始尝试第二个方案
但是看了半天dcloud的文档,发现自己写一个插件的复杂度太大,主要是官方很多地方文档描述不清
随后静下心来,我本身就是在原生的基础上来加的h5+sdk,所以可以尝试原生与js混合通信的方式
写到这里 我再次吐槽一下,我也用过apicloud,里面我觉得最好的一个是apicloud与原生之间的一个事件通知,不需要使用webview,随手写随手通知

回归正题

原有的js中websocke的部分,需要完成3个事情:
1 websocket初始化连接
2 发送消息
3 接受消息

所以我们只需要在java中写一个辅助类
1在需要的时候初始化连接
2可以接受js的发送请求,将数据发出
3在收到消息时候通知js

下面贴代码
js部分

function createWs() {  
		var WsUrl = ws_host + getMemberId();  
		if(mui.os.ios) {  
			if('WebSocket' in window) {  
				debug("WebSocket")  
				wsClient = new WebSocket(WsUrl);  
			} else if('MozWebSocket' in window) {  
				debug("MozWebSocket")  
				wsClient = new MozWebSocket(WsUrl);  
			}  
			wsClient.onopen = function() {  
				onOpen()  
			};  
			wsClient.onclose = function() {  
				onClose()  
			};  
			wsClient.onmessage = function(evt) {  
				onMessage(evt)  
			};  
			wsClient.onerror = function() {  
				onError()  
			};  
		} else if(mui.os.android) {  
			var Toolkit = plus.android.importClass("com.HBuilder.integrate.WsHelper");  
			if(Toolkit) {  
				//var wifiInfo = new Toolkit();  
				Toolkit.webConnect(WsUrl);  
			} else {  
				plus.nativeUI.alert("IM服务器连接失败");  
			}  
		}  
  
	}

原理一看就明白,如果是ios 则使用html5的websocket,如果是案桌,就使用原生的方法去创建websocket
下面是java原生,java原生有很多websocket客户端库,我这里用的是AndroidAsync
java 实现初始化websocket连接,以及实现向js通讯消息

public static void webConnect(final String url) {  
  
        if (webSocket == null) {  
            try {  
                AsyncHttpClient.getDefaultInstance().websocket(url, null, new AsyncHttpClient.WebSocketConnectCallback() {  
                    @Override  
                    public void onCompleted(Exception ex, WebSocket _webSocket) {  
                        webSocket = _webSocket;  
//发送心跳  
                        webSocket.send("{\"messageType\":3}");  
                        webSocket.setStringCallback(new WebSocket.StringCallback() {  
                            @Override  
                            public void onStringAvailable(String s) {  
                                Log.d("qwe", "hello");  
                                //获取webview  
                                ArrayList<IWebview> ss = SDK.obtainAllIWebview();  
                                for (IWebview iWebview : ss) {  
                                    if (iWebview.getOriginalUrl().equals("messageList.html")) {  
                                        iWebview.evalJS("wsRecive('" + s + "')");  
                                        // JSUtil.broadcastWebviewEvent(iWebview, iWebview.getWebviewUUID(), "wsRecive", s);  
                                        //JSUtil.execCallback(iWebview, "wsRecive", s, JSUtil.OK, false);  
                                        break;  
                                    }  
                                }  
                            }  
                        });  
                        webSocket.setClosedCallback(new CompletedCallback() {  
                            @Override  
                            public void onCompleted(Exception ex) {  
                                try {  
                                    if (ex != null)  
                                        Log.e("WebSocket", "Error");  
                                } finally {  
                                    if (tryTime <= 3) {  
                                        tryTime += 1;  
                                        webConnect(url);  
                                    }  
                                }  
                            }  
                        });  
                    }  
                });  
            }  
            finally {  
                if (tryTime <= 3) {  
                    tryTime += 1;  
                    webConnect(url);  
                }  
            }  
  
        } else {  
            webSocket.send("{\"messageType\":3}");  
        }  
    }

这里又要吐槽一下,官方的h5+sdk文档实在是太糟糕,花了很长时间才摸索出来,主要是获取指定的webview 这点没有apicloud做得好 ,apicloud后台java发起一个事件,前面任何一个页面都可以监听,5+sdk我找了半天没有找到,可能也有但是不知道在哪里
首先查找所有的webview,然后调用这个页面的js方法

  ArrayList<IWebview> ss = SDK.obtainAllIWebview();  
                                for (IWebview iWebview : ss) {  
                                    if (iWebview.getOriginalUrl().equals("messageList.html")) {  
                                        iWebview.evalJS("wsRecive('" + s + "')");  
                                        break;  
                                    }  
                                }

下面是js发送消息

function sendMsg(msg) {  
  
		if(mui.os.ios) {  
			//缓存本地  
			if(wsClient.readyState == WebSocket.OPEN) {  
				wsClient.send(JSON.stringify(msg));  
				_msg = null;  
			} else {  
				_msg = msg;  
				createWs();  
			}  
		} else if(mui.os.android) {  
			var Toolkit = plus.android.importClass("com.HBuilder.integrate.WsHelper");  
			if(Toolkit) {  
				//var wifiInfo = new Toolkit();  
				Toolkit.sendMsg(JSON.stringify(msg));  
			} else {  
				plus.nativeUI.alert("IM服务器连接失败");  
			}  
		}  
  
	}

也是先要判断,如果ios就走h5直接发送,否则就走原生android发送

public static void sendMsg(String msg) {  
        if (webSocket != null && webSocket.isOpen()) {  
            webSocket.send(msg);  
        }  
    }

至此,android的websocket完美解决,无论多少版本,统一走底层
思路不一定是最好的 欢迎加我微信(ming-lsard)交流
希望有更好的解决思路一起分享
谢谢大家

本文未经许可,禁止转载,只发在dcloud官方论坛

7 关注 分享
BoredApe lhyh yuhezheng 前端的程序狗 1***@qq.com l***@163.com 1***@qq.com

要回复文章请先登录注册

huangr_001

huangr_001

你可以试试插件市场的这款GoEasy_websocket插件,对安卓和ios的APP兼容性很好,同时也支持各种小程序。你们也可以试试:[https://ext.dcloud.net.cn/plugin?id=1334](https://ext.dcloud.net.cn/plugin?id=1334)
2021-07-27 09:28
1***@qq.com

1***@qq.com

太感谢了
2019-07-10 09:33
QTD

QTD

回复 Danny :
我用Hbuilder创建的app项目,里面创建了websocket,但是在连接的时候,显示连接一场,open根本没有到后台,,虚心求教!
2018-03-15 10:20
freedemon

freedemon

占坑
2018-02-09 09:50
夜帝

夜帝

可以离线推送吗?
2018-01-24 11:00
移动达人

移动达人

官方加入对WebSocket的默认支持就好了,不然安卓机器不同系统版本支持不一致,问题实在太多。
2017-10-08 23:36
猫猫猫猫

猫猫猫猫

不错,当发现部分安卓4.4也出问题的时候,就得采用插件方式。
2017-07-19 10:26
前端的程序狗

前端的程序狗

有完整的代码吗
2017-02-24 16:11
Danny

Danny

淘汰Android4.4以下机器,限定APP运行环境,直接用WebSocket,无需任何解决方案
2017-01-09 08:58
四阿哥

四阿哥

mark
2017-01-08 22:07