mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-02-08 09:12:05 +08:00
Implement WebSocket module for Android. Fixes #2837
Summary: The JavaScript code for Android is same as the iOS counterpart, I just added few new lines and used arrow functions instead of binding `this`. Closes https://github.com/facebook/react-native/pull/2839 Reviewed By: @svcscm, @vjeux Differential Revision: D2498703 Pulled By: @mkonicek fb-gh-sync-id: 3fe958dd5af0efba00df07515f8e33b5d87eb05b
This commit is contained in:
committed by
facebook-github-bot-8
parent
57a7387d85
commit
f4857a6d42
@@ -0,0 +1,170 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
package com.facebook.react.modules.websocket;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import com.facebook.common.logging.FLog;
|
||||
import com.facebook.react.bridge.Arguments;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.bridge.ReactContext;
|
||||
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
||||
import com.facebook.react.bridge.ReactMethod;
|
||||
import com.facebook.react.bridge.WritableMap;
|
||||
import com.facebook.react.common.ReactConstants;
|
||||
import com.facebook.react.modules.core.DeviceEventManagerModule;
|
||||
|
||||
import com.squareup.okhttp.OkHttpClient;
|
||||
import com.squareup.okhttp.Request;
|
||||
import com.squareup.okhttp.Response;
|
||||
import com.squareup.okhttp.ws.WebSocket;
|
||||
import com.squareup.okhttp.ws.WebSocketCall;
|
||||
import com.squareup.okhttp.ws.WebSocketListener;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import okio.Buffer;
|
||||
import okio.BufferedSource;
|
||||
|
||||
public class WebSocketModule extends ReactContextBaseJavaModule {
|
||||
|
||||
private Map<Integer, WebSocket> mWebSocketConnections = new HashMap<>();
|
||||
private ReactContext mReactContext;
|
||||
|
||||
public WebSocketModule(ReactApplicationContext context) {
|
||||
super(context);
|
||||
mReactContext = context;
|
||||
}
|
||||
|
||||
private void sendEvent(String eventName, WritableMap params) {
|
||||
mReactContext
|
||||
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
|
||||
.emit(eventName, params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "WebSocketModule";
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void connect(final String url, final int id) {
|
||||
OkHttpClient client = new OkHttpClient();
|
||||
|
||||
client.setConnectTimeout(10, TimeUnit.SECONDS);
|
||||
client.setWriteTimeout(10, TimeUnit.SECONDS);
|
||||
// Disable timeouts for read
|
||||
client.setReadTimeout(0, TimeUnit.MINUTES);
|
||||
|
||||
Request request = new Request.Builder()
|
||||
.tag(id)
|
||||
.url(url)
|
||||
.build();
|
||||
|
||||
WebSocketCall.create(client, request).enqueue(new WebSocketListener() {
|
||||
|
||||
@Override
|
||||
public void onOpen(WebSocket webSocket, Response response) {
|
||||
mWebSocketConnections.put(id, webSocket);
|
||||
WritableMap params = Arguments.createMap();
|
||||
params.putInt("id", id);
|
||||
sendEvent("websocketOpen", params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClose(int code, String reason) {
|
||||
WritableMap params = Arguments.createMap();
|
||||
params.putInt("id", id);
|
||||
params.putInt("code", code);
|
||||
params.putString("reason", reason);
|
||||
sendEvent("websocketClosed", params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(IOException e, Response response) {
|
||||
notifyWebSocketFailed(id, e.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPong(Buffer buffer) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessage(BufferedSource bufferedSource, WebSocket.PayloadType payloadType) {
|
||||
String message;
|
||||
try {
|
||||
message = bufferedSource.readUtf8();
|
||||
} catch (IOException e) {
|
||||
notifyWebSocketFailed(id, e.getMessage());
|
||||
return;
|
||||
}
|
||||
try {
|
||||
bufferedSource.close();
|
||||
} catch (IOException e) {
|
||||
FLog.e(
|
||||
ReactConstants.TAG,
|
||||
"Could not close BufferedSource for WebSocket id " + id,
|
||||
e);
|
||||
}
|
||||
|
||||
WritableMap params = Arguments.createMap();
|
||||
params.putInt("id", id);
|
||||
params.putString("data", message);
|
||||
sendEvent("websocketMessage", params);
|
||||
}
|
||||
});
|
||||
|
||||
// Trigger shutdown of the dispatcher's executor so this process can exit cleanly
|
||||
client.getDispatcher().getExecutorService().shutdown();
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void close(int code, String reason, int id) {
|
||||
WebSocket client = mWebSocketConnections.get(id);
|
||||
if (client == null) {
|
||||
// This is a programmer error
|
||||
throw new RuntimeException("Cannot close WebSocket. Unknown WebSocket id " + id);
|
||||
}
|
||||
try {
|
||||
client.close(code, reason);
|
||||
mWebSocketConnections.remove(id);
|
||||
} catch (Exception e) {
|
||||
FLog.e(
|
||||
ReactConstants.TAG,
|
||||
"Could not close WebSocket connection for id " + id,
|
||||
e);
|
||||
}
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void send(String message, int id) {
|
||||
WebSocket client = mWebSocketConnections.get(id);
|
||||
if (client == null) {
|
||||
// This is a programmer error
|
||||
throw new RuntimeException("Cannot send a message. Unknown WebSocket id " + id);
|
||||
}
|
||||
try {
|
||||
client.sendMessage(
|
||||
WebSocket.PayloadType.TEXT,
|
||||
new Buffer().writeUtf8(message));
|
||||
} catch (IOException e) {
|
||||
notifyWebSocketFailed(id, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyWebSocketFailed(int id, String message) {
|
||||
WritableMap params = Arguments.createMap();
|
||||
params.putInt("id", id);
|
||||
params.putString("message", message);
|
||||
sendEvent("websocketFailed", params);
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,7 @@ import com.facebook.react.modules.fresco.FrescoModule;
|
||||
import com.facebook.react.modules.network.NetworkingModule;
|
||||
import com.facebook.react.modules.storage.AsyncStorageModule;
|
||||
import com.facebook.react.modules.toast.ToastModule;
|
||||
import com.facebook.react.modules.websocket.WebSocketModule;
|
||||
import com.facebook.react.uimanager.ViewManager;
|
||||
import com.facebook.react.views.drawer.ReactDrawerLayoutManager;
|
||||
import com.facebook.react.views.image.ReactImageManager;
|
||||
@@ -47,6 +48,7 @@ public class MainReactPackage implements ReactPackage {
|
||||
new AsyncStorageModule(reactContext),
|
||||
new FrescoModule(reactContext),
|
||||
new NetworkingModule(reactContext),
|
||||
new WebSocketModule(reactContext),
|
||||
new ToastModule(reactContext));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user