Skip to content

Commit 863bd9e

Browse files
committed
fix(Android): onClose event not firing on both sockets
1 parent 7acf25d commit 863bd9e

File tree

7 files changed

+99
-119
lines changed

7 files changed

+99
-119
lines changed

android/src/main/java/com/asterinet/react/tcpsocket/TcpReceiverTask.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ protected Void doInBackground(Pair<TcpSocketClient, TcpReceiverTask.OnDataReceiv
3636
bufferCount = in.read(buffer);
3737
if (bufferCount > 0) {
3838
receiverListener.onData(socketId, Arrays.copyOfRange(buffer, 0, bufferCount));
39+
} else if (bufferCount == -1) {
40+
clientSocket.close();
3941
}
4042
}
4143
} catch (IOException ioe) {

android/src/main/java/com/asterinet/react/tcpsocket/TcpSocketClient.java

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package com.asterinet.react.tcpsocket;
22

3-
import android.content.Context;
43
import android.net.Network;
54
import android.os.AsyncTask;
65
import android.util.Pair;
@@ -14,6 +13,7 @@
1413
public class TcpSocketClient {
1514
private TcpReceiverTask receiverTask;
1615
private Socket socket;
16+
private TcpReceiverTask.OnDataReceivedListener mReceiverListener;
1717

1818
protected Integer id;
1919

@@ -44,13 +44,15 @@ public TcpSocketClient(final TcpReceiverTask.OnDataReceivedListener receiverList
4444
socket.bind(new InetSocketAddress(localInetAddress, localPort));
4545
socket.connect(new InetSocketAddress(remoteInetAddress, port));
4646
receiverTask = new TcpReceiverTask();
47+
mReceiverListener = receiverListener;
4748
receiverTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, new Pair<>(this, receiverListener));
4849
}
4950

5051
public TcpSocketClient(final TcpReceiverTask.OnDataReceivedListener receiverListener, final Integer id, final Socket socket) {
5152
this.id = id;
5253
this.socket = socket;
5354
receiverTask = new TcpReceiverTask();
55+
mReceiverListener = receiverListener;
5456
receiverTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, new Pair<>(this, receiverListener));
5557
}
5658

@@ -66,7 +68,7 @@ public Socket getSocket() {
6668
/**
6769
* Sends data from the socket
6870
*
69-
* @param data
71+
* @param data data to be sent
7072
*/
7173
public void write(final byte[] data) throws IOException {
7274
if (socket != null && !socket.isClosed()) {
@@ -78,16 +80,21 @@ public void write(final byte[] data) throws IOException {
7880
/**
7981
* Shuts down the receiver task, closing the socket.
8082
*/
81-
public void close() throws IOException {
82-
if (receiverTask != null && !receiverTask.isCancelled()) {
83-
// stop the receiving task
84-
receiverTask.cancel(true);
85-
}
83+
public void close() {
84+
try {
85+
if (receiverTask != null && !receiverTask.isCancelled()) {
86+
// stop the receiving task
87+
receiverTask.cancel(true);
88+
}
8689

87-
// close the socket
88-
if (socket != null && !socket.isClosed()) {
89-
socket.close();
90-
socket = null;
90+
// close the socket
91+
if (socket != null && !socket.isClosed()) {
92+
socket.close();
93+
mReceiverListener.onClose(getId(), null);
94+
socket = null;
95+
}
96+
} catch (IOException e) {
97+
mReceiverListener.onClose(getId(), e.getMessage());
9198
}
9299
}
93100
}

android/src/main/java/com/asterinet/react/tcpsocket/TcpSocketModule.java

Lines changed: 33 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,17 @@
2323
import java.net.Inet6Address;
2424
import java.net.InetAddress;
2525
import java.net.InetSocketAddress;
26-
import java.net.UnknownHostException;
2726
import java.util.concurrent.CountDownLatch;
2827

28+
import androidx.annotation.NonNull;
29+
import androidx.annotation.Nullable;
30+
2931
public class TcpSocketModule extends ReactContextBaseJavaModule implements TcpReceiverTask.OnDataReceivedListener {
3032

3133
private final ReactApplicationContext mReactContext;
32-
private SparseArray<TcpSocketClient> socketClients = new SparseArray<>();
33-
private SparseArray<Network> mNetworkMap = new SparseArray<>();
34+
private final SparseArray<TcpSocketClient> socketClients = new SparseArray<>();
35+
private final SparseArray<Network> mNetworkMap = new SparseArray<>();
3436
private Network mSelectedNetwork;
35-
private boolean shuttingDown = false;
3637

3738
public static final String TAG = "TcpSockets";
3839

@@ -42,7 +43,7 @@ public TcpSocketModule(ReactApplicationContext reactContext) {
4243
}
4344

4445
@Override
45-
public String getName() {
46+
public @NonNull String getName() {
4647
return TAG;
4748
}
4849

@@ -52,18 +53,21 @@ private void sendEvent(String eventName, WritableMap params) {
5253
.emit(eventName, params);
5354
}
5455

55-
private void selectNetwork(final String iface, final String ipAddress) throws InterruptedException {
56-
/**
57-
* Returns a network given its interface name:
58-
* "wifi" -> WIFI
59-
* "cellular" -> Cellular
60-
* etc...
61-
*/
56+
/**
57+
* Returns a network given its interface name:
58+
* "wifi" -> WIFI
59+
* "cellular" -> Cellular
60+
* etc...
61+
*/
62+
private void selectNetwork(@Nullable final String iface, @Nullable final String ipAddress) throws InterruptedException {
63+
if (iface == null) return;
6264
mSelectedNetwork = null;
63-
Network cachedNetwork = mNetworkMap.get(ipAddress.hashCode());
64-
if (cachedNetwork != null){
65-
mSelectedNetwork = cachedNetwork;
66-
return;
65+
if (ipAddress != null){
66+
Network cachedNetwork = mNetworkMap.get(ipAddress.hashCode());
67+
if (cachedNetwork != null){
68+
mSelectedNetwork = cachedNetwork;
69+
return;
70+
}
6771
}
6872
final CountDownLatch awaitingNetwork = new CountDownLatch(1); // only needs to be counted down once to release waiting threads
6973
final ConnectivityManager cm = (ConnectivityManager) mReactContext.getSystemService(Context.CONNECTIVITY_SERVICE);
@@ -75,7 +79,7 @@ private void selectNetwork(final String iface, final String ipAddress) throws In
7579
@Override
7680
public void onAvailable(Network network) {
7781
mSelectedNetwork = network;
78-
if (!ipAddress.equals("0.0.0.0"))
82+
if (ipAddress != null && !ipAddress.equals("0.0.0.0"))
7983
mNetworkMap.put(ipAddress.hashCode(), mSelectedNetwork);
8084
awaitingNetwork.countDown(); // Stop waiting
8185
}
@@ -92,17 +96,17 @@ public void onUnavailable() {
9296
mSelectedNetwork = null;
9397
break;
9498
}
95-
if (mSelectedNetwork!= null && !ipAddress.equals("0.0.0.0"))
99+
if (mSelectedNetwork!= null && ipAddress != null && !ipAddress.equals("0.0.0.0"))
96100
mNetworkMap.put(ipAddress.hashCode(), mSelectedNetwork);
97101
}
98102

99103
/**
100104
* Creates a TCP Socket and establish a connection with the given host
101105
*
102-
* @param cId
103-
* @param host
104-
* @param port
105-
* @param options
106+
* @param cId socket ID
107+
* @param host socket IP address
108+
* @param port socket port to be bound
109+
* @param options extra options
106110
*/
107111
@ReactMethod
108112
public void connect(final Integer cId, final String host, final Integer port, final ReadableMap options) {
@@ -128,12 +132,9 @@ protected void doInBackgroundGuarded(Void... params) {
128132
client = new TcpSocketClient(TcpSocketModule.this, cId, host, port, localAddress, localPort, mSelectedNetwork);
129133
socketClients.put(cId, client);
130134
onConnect(cId, host, port);
131-
} catch (IOException e) {
132-
onError(cId, e.getMessage());
133-
} catch (InterruptedException e) {
135+
} catch (Exception e) {
134136
onError(cId, e.getMessage());
135137
}
136-
return;
137138
}
138139
}.execute();
139140
}
@@ -158,7 +159,6 @@ protected void doInBackgroundGuarded(Void... params) {
158159
if (callback != null) {
159160
callback.invoke();
160161
}
161-
return;
162162
}
163163
}.execute();
164164
}
@@ -168,18 +168,12 @@ public void end(final Integer cId) {
168168
new GuardedAsyncTask<Void, Void>(mReactContext.getExceptionHandler()) {
169169
@Override
170170
protected void doInBackgroundGuarded(Void... params) {
171-
try {
172-
TcpSocketClient socketClient = socketClients.get(cId);
173-
if (socketClient == null){
174-
return;
175-
}
176-
socketClient.close();
177-
onClose(cId, null);
178-
socketClients.remove(cId);
179-
} catch (IOException e) {
180-
onClose(cId, e.getMessage());
171+
TcpSocketClient socketClient = socketClients.get(cId);
172+
if (socketClient == null) {
173+
return;
181174
}
182-
return;
175+
socketClient.close();
176+
socketClients.remove(cId);
183177
}
184178
}.execute();
185179
}
@@ -198,10 +192,8 @@ protected void doInBackgroundGuarded(Void... params) {
198192
TcpSocketServer server = new TcpSocketServer(socketClients, TcpSocketModule.this, cId, host, port);
199193
socketClients.put(cId, server);
200194
onConnect(cId, host, port);
201-
} catch (UnknownHostException uhe) {
195+
} catch (Exception uhe) {
202196
onError(cId, uhe.getMessage());
203-
} catch (IOException ioe) {
204-
onError(cId, ioe.getMessage());
205197
}
206198
}
207199
}.execute();
@@ -211,9 +203,6 @@ protected void doInBackgroundGuarded(Void... params) {
211203

212204
@Override
213205
public void onConnect(Integer id, String host, int port) {
214-
if (shuttingDown) {
215-
return;
216-
}
217206
WritableMap eventParams = Arguments.createMap();
218207
eventParams.putInt("id", id);
219208
WritableMap addressParams = Arguments.createMap();
@@ -226,9 +215,6 @@ public void onConnect(Integer id, String host, int port) {
226215

227216
@Override
228217
public void onData(Integer id, byte[] data) {
229-
if (shuttingDown) {
230-
return;
231-
}
232218
WritableMap eventParams = Arguments.createMap();
233219
eventParams.putInt("id", id);
234220
eventParams.putString("data", Base64.encodeToString(data, Base64.NO_WRAP));
@@ -238,9 +224,6 @@ public void onData(Integer id, byte[] data) {
238224

239225
@Override
240226
public void onClose(Integer id, String error) {
241-
if (shuttingDown) {
242-
return;
243-
}
244227
if (error != null) {
245228
onError(id, error);
246229
}
@@ -253,9 +236,6 @@ public void onClose(Integer id, String error) {
253236

254237
@Override
255238
public void onError(Integer id, String error) {
256-
if (shuttingDown) {
257-
return;
258-
}
259239
WritableMap eventParams = Arguments.createMap();
260240
eventParams.putInt("id", id);
261241
eventParams.putString("error", error);
@@ -265,9 +245,6 @@ public void onError(Integer id, String error) {
265245

266246
@Override
267247
public void onConnection(Integer serverId, Integer clientId, InetSocketAddress socketAddress){
268-
if (shuttingDown) {
269-
return;
270-
}
271248
WritableMap eventParams = Arguments.createMap();
272249
eventParams.putInt("id", serverId);
273250

android/src/main/java/com/asterinet/react/tcpsocket/TcpSocketPackage.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,17 @@
88
import com.facebook.react.bridge.NativeModule;
99
import com.facebook.react.bridge.ReactApplicationContext;
1010
import com.facebook.react.uimanager.ViewManager;
11-
import com.facebook.react.bridge.JavaScriptModule;
11+
12+
import androidx.annotation.NonNull;
1213

1314
public class TcpSocketPackage implements ReactPackage {
1415
@Override
15-
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
16+
public @NonNull List<NativeModule> createNativeModules(@NonNull ReactApplicationContext reactContext) {
1617
return Arrays.<NativeModule>asList(new TcpSocketModule(reactContext));
1718
}
1819

1920
@Override
20-
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
21+
public @NonNull List<ViewManager> createViewManagers(@NonNull ReactApplicationContext reactContext) {
2122
return Collections.emptyList();
2223
}
2324
}

0 commit comments

Comments
 (0)