Android WebSocket实践

您所在的位置:网站首页 websocket安卓客户端工具 Android WebSocket实践

Android WebSocket实践

2024-01-24 03:41| 来源: 网络整理| 查看: 265

既生HTTP何生WebSockt

与服务端交互的协议中,HTTP只能被动接收客户端请求,然后响应。而WebSocket在客户端与服务端建立连接以后,服务端可以主动发消息给客户端。这就是WebSocket的特点。

应用

因为服务端可以主动发消息的特性,WebSocket在以下场景使用非常多: 1、推送 2、聊天室 3、开发工具 4...

大部分功能依赖于产品的业务,投入使用可能比较困难,而开发工具是开发人员可以肆意发挥的地方!

ReactNative中WebSocket的使用

ReactNative开发过程中,pc端可以控制android端重新加载、打印堆栈等等。这些的实现都依赖于WebSocket。

com.facebook.react.packagerconnection.ReconnectingWebSocket实现了WebSocket的连接,使用了okhttp。

final public class ReconnectingWebSocket extends WebSocketListener { public ReconnectingWebSocket( String url, MessageCallback messageCallback, ConnectionCallback connectionCallback) { super(); mUrl = url; mMessageCallback = messageCallback; mConnectionCallback = connectionCallback; mHandler = new Handler(Looper.getMainLooper()); } public void connect() { if (mClosed) { throw new IllegalStateException("Can't connect closed client"); } OkHttpClient httpClient = new OkHttpClient.Builder() .connectTimeout(10, TimeUnit.SECONDS) .writeTimeout(10, TimeUnit.SECONDS) .readTimeout(0, TimeUnit.MINUTES) // Disable timeouts for read .build(); Request request = new Request.Builder().url(mUrl).build(); httpClient.newWebSocket(request, this); } }

JSPackagerClient包装了ReconnectingWebSocket,在onMessage回调处分发服务端下发的命令:

final public class JSPackagerClient implements ReconnectingWebSocket.MessageCallback { private ReconnectingWebSocket mWebSocket; public JSPackagerClient( String clientId, PackagerConnectionSettings settings, Map requestHandlers, @Nullable ReconnectingWebSocket.ConnectionCallback connectionCallback) { super(); Uri.Builder builder = new Uri.Builder(); builder.scheme("ws") .encodedAuthority(settings.getDebugServerHost()) .appendPath("message") .appendQueryParameter("device", AndroidInfoHelpers.getFriendlyDeviceName()) .appendQueryParameter("app", settings.getPackageName()) .appendQueryParameter("clientid", clientId); String url = builder.build().toString(); mWebSocket = new ReconnectingWebSocket(url, this, connectionCallback); mRequestHandlers = requestHandlers; } @Override public void onMessage(String text) { try { JSONObject message = new JSONObject(text); int version = message.optInt("version"); String method = message.optString("method"); Object id = message.opt("id"); Object params = message.opt("params"); if (version != PROTOCOL_VERSION) { FLog.e( TAG, "Message with incompatible or missing version of protocol received: " + version); return; } if (method == null) { abortOnMessage(id, "No method provided"); return; } RequestHandler handler = mRequestHandlers.get(method); if (handler == null) { abortOnMessage(id, "No request handler for method: " + method); return; } if (id == null) { handler.onNotification(params); } else { handler.onRequest(params, new ResponderImpl(id)); } } catch (Exception e) { FLog.e(TAG, "Handling the message failed", e); } } }

命令的具体执行在RequestHandler。注入RequestHandler的时机在DevServerHelper#openPackagerConnection

public void openPackagerConnection( final String clientId, final PackagerCommandListener commandListener) { if (mPackagerClient != null) { FLog.w(ReactConstants.TAG, "Packager connection already open, nooping."); return; } new AsyncTask() { @Override protected Void doInBackground(Void... backgroundParams) { Map handlers = new HashMap(); handlers.put("reload", new NotificationOnlyHandler() { @Override public void onNotification(@Nullable Object params) { commandListener.onPackagerReloadCommand(); } }); handlers.put("devMenu", new NotificationOnlyHandler() { @Override public void onNotification(@Nullable Object params) { commandListener.onPackagerDevMenuCommand(); } }); handlers.put("captureHeap", new RequestOnlyHandler() { @Override public void onRequest(@Nullable Object params, Responder responder) { commandListener.onCaptureHeapCommand(responder); } }); handlers.putAll(new FileIoHandler().handlers()); ConnectionCallback onPackagerConnectedCallback = new ConnectionCallback() { @Override public void onConnected() { commandListener.onPackagerConnected(); } @Override public void onDisconnected() { commandListener.onPackagerDisconnected(); } }; mPackagerClient = new JSPackagerClient( clientId, mSettings.getPackagerConnectionSettings(), handlers, onPackagerConnectedCallback); mPackagerClient.init(); return null; } }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } Android客户端实现一个WebSocket Server

大部分使用WebSocket的开发工具,服务端都是pc,Android端都是一个client。经过okhttp的封装,实现client非常简单。

github上找到了两个java websocket server的库,Java-WebSocket和AndroidAsync。尝试写了一下Demo,最终只跑通了AndroidAsync,github:github.com/PortgasAce/…

Server的主要代码:

AsyncHttpClient.getDefaultInstance().websocket(get, "my-protocol", new WebSocketConnectCallback() { @Override public void onCompleted(Exception ex, WebSocket webSocket) { if (ex != null) { ex.printStackTrace(); return; } webSocket.send("a string"); // webSocket.send(new byte[10]); webSocket.setStringCallback(new StringCallback() { public void onStringAvailable(String s) { System.out.println("I got a string: " + s); } }); webSocket.setDataCallback(new DataCallback() { public void onDataAvailable(DataEmitter emitter, ByteBufferList byteBufferList) { System.out.println("I got some bytes!"); // note that this data has been read byteBufferList.recycle(); } }); } });

上面是github的readme,注释了一行webSocket.send(new byte[10]);,否则websocket连接会断掉。

参考

知乎WebSocket原理:www.zhihu.com/question/20…

阮一峰WebSocket教程:www.ruanyifeng.com/blog/2017/0…

Java-WebSocket:github.com/TooTallNate…

AndroidAsync:github.com/koush/Andro…



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3