Android Test. Return to main page
1: package com.voipplus.mmsclient;
2:
3: import android.content.ComponentName;
4: import android.content.Context;
5: import android.content.;
6: import android.content.ServiceConnection;
7: import android.content.res.AssetManager;
8: import android.os.IBinder;
9: import android.util.Log;
10:
11: import androidx.test.core.app.ApplicationProvider;
12: import androidx.test.platform.app.InstrumentationRegistry;
13:
14: import com.voipplus.mmsclient.WebRTC.WebRTCEventListener;
15: import com.voipplus.mmsclient.WebRTC.WebRTCService;
16: import com.voipplus.mmsclient.WebRTC.WebRTCServiceStarter;
17: import com.voipplus.mmsclient.WebRTC.WebRTCState;
18: import com.voipplus.mmsclient.WebRTC.WebRTCUtils;
19:
20: import org.junit.After;
21: import org.junit.Before;
22: import org.junit.Test;
23: import org.mockito.Mock;
24:
25: import java.io.ByteArrayOutputStream;
26: import java.io.IOException;
27: import java.io.InputStream;
28: import java.nio.ByteBuffer;
29: import java.util.concurrent.CountDownLatch;
30: import java.util.concurrent.TimeUnit;
31:
32: import livekit.org.webrtc.AudioTrack;
33: import livekit.org.webrtc.DataChannel;
34: import livekit.org.webrtc.IceCandidate;
35: import livekit.org.webrtc.MediaStream;
36: import livekit.org.webrtc.PeerConnection;
37: import livekit.org.webrtc.SessionDescription;
38: import livekit.org.webrtc.VideoTrack;
39: import okhttp3.OkHttpClient;
40: import okhttp3.Request;
41: import okhttp3.Response;
42: import okhttp3.WebSocket;
43: import okhttp3.WebSocketListener;
44:
45: public class WebRTCServiceTest {
46: private static final String TAG = "WebRTCServiceTest";
47: private static final String REAL_WEB_SOCKET_URL = "ws://10.0.2.2:3000";
48: private WebRTCService webRTCService;
49: private CountDownLatch serviceConnectionLatch;
50: private DataChannel dataChannel;
51: private WebSocket webSocket;
52: private WebRTCServiceStarter webRTCServiceStarter;
53: private ServiceConnection serviceConnection;
54:
55: @Mock
56: private WebRTCEventListener webRTCEventListener;
57:
58: //region Setup and Teardown
59: @Before
60: public void setUp() throws Exception {
61: Log.d(TAG, "🛠️ setUp: Starting test setup");
62:
63: Context context = ApplicationProvider.getApplicationContext();
64: serviceConnectionLatch = new CountDownLatch(1); // Ensure service is connected before proceeding
65:
66: // Define Service Connection
67: serviceConnection = new ServiceConnection() {
68: @Override
69: public void onServiceConnected(ComponentName name, IBinder binder) {
70: Log.d(TAG, "🔗 onServiceConnected: WebRTCService connected");
71:
72: WebRTCService.LocalBinder localBinder = (WebRTCService.LocalBinder) binder;
73: webRTCService = localBinder.getService();
74:
75: if (webRTCService == null) {
76: Log.e(TAG, "❌ webRTCService is NULL after binding!");
77: throw new IllegalStateException("❌ webRTCService is NULL after binding. Cannot continue.");
78: } else {
79: Log.d(TAG, "✅ webRTCService initialized.");
80: webRTCService.printState("Test", "After service binding");
81: }
82:
83: serviceConnectionLatch.countDown(); // Notify that service is ready
84: }
85:
86: @Override
87: public void onServiceDisconnected(ComponentName name) {
88: Log.d(TAG, "🔴 onServiceDisconnected: WebRTCService disconnected");
89: webRTCService = null;
90: }
91: };
92:
93: // 🚀 Start the WebRTC Service FIRST
94: serviceIntent = new (context, WebRTCService.class);
95: serviceIntent.putExtra("SIGNALING_SERVER_URL", REAL_WEB_SOCKET_URL);
96: context.startService(serviceIntent);
97:
98: // 🔗 Now BIND to the Service
99: boolean bindSuccess = context.bindService(serviceIntent, serviceConnection, Context.BIND_AUTO_CREATE);
100: if (!bindSuccess) {
101: throw new IllegalStateException("❌ Failed to bind WebRTCService.");
102: }
103:
104: // ⏳ Wait for service to be connected
105: boolean serviceReady = serviceConnectionLatch.await(5, TimeUnit.SECONDS);
106: if (!serviceReady) {
107: throw new IllegalStateException("❌ Service binding timed out. WebRTCService not initialized.");
108: }
109:
110: // 🚨 If service is still null, fail early
111: if (webRTCService == null) {
112: throw new IllegalStateException("❌ webRTCService is NULL after binding. Cannot continue.");
113: }
114:
115: // ✅ **Now it's safe to call methods on 'webRTCService'**
116: WebRTCUtils.debugInfo(TAG, "✅ WebRTCService is fully initialized",
117: webRTCService.getWebRTCState(),
118: webRTCService.safeGetPeerConnection(),
119: webRTCService.safeGetDataChannel(),
120: webRTCService.safeGetWebSocket(),
121: webRTCService.getSafeSignalinServerUrl());
122:
123: // 🕵️♂️ Now wait for WebSocket AFTER service is initialized
124: waitForWebSocket();
125: }
126:
127:
128: @After
129: public void tearDown() {
130: Log.d(TAG, "tearDown: Method called");
131: if (webSocket != null) {
132: webSocket.close(1000, "Test complete");
133: }
134: }
135: private void waitForServiceInitialization() throws InterruptedException {
136: int attempts = 0;
137: int maxAttempts = 20; // Wait up to ~10 seconds (assuming 500ms delay)
138: long waitTimeMs = 500;
139:
140: while (attempts < maxAttempts) {
141: if (webRTCService != null && webRTCService.getWebRTCState() != WebRTCState.IDLE) {
142: WebRTCUtils.debugInfo(TAG, "✅ WebRTCService is initialized. Proceeding with test.", webRTCService.getWebRTCState(),
143: webRTCService.safeGetPeerConnection(), webRTCService.safeGetDataChannel(), webRTCService.safeGetWebSocket(), webRTCService.getSafeSignalinServerUrl());
144: return;
145: }
146: WebRTCUtils.debugInfo(TAG, "⏳ Waiting for WebRTCService to initialize... Attempt " + (attempts + 1), null, null, null, null, null);
147: Thread.sleep(waitTimeMs);
148: attempts++;
149: }
150:
151: throw new IllegalStateException("❌ Service binding timed out. WebRTCService not initialized.");
152: }
153:
154: //endregion
155:
156: //region WebSocket Management
157: @Before
158: public void initWebSocketConnection() {
159: webRTCService.printState(TAG, "initWebSocketConnection: Method called");
160: OkHttpClient client = new OkHttpClient();
161: Request request = new Request.Builder().url(REAL_WEB_SOCKET_URL).build();
162: webSocket = client.newWebSocket(request, new WebSocketListener() {
163: @Override
164: public void onOpen(WebSocket webSocket, Response response) {
165: webRTCService.printState(TAG, "WebSocket onOpen: WebSocket connection opened");
166: webRTCService.printState(TAG, "Local variables: webSocket=" + webSocket + ", response=" + response);
167: }
168:
169: @Override
170: public void onMessage(WebSocket webSocket, String text) {
171: webRTCService.printState(TAG, "WebSocket onMessage: Received message: " + text);
172: webRTCService.printState(TAG, "Local variables: text=" + text);
173: }
174:
175: @Override
176: public void onFailure(WebSocket webSocket, Throwable t, Response response) {
177: webRTCService.printState(TAG, "WebSocket onFailure: Error: " + t.getMessage());
178: webRTCService.printState(TAG, "Local variables: t=" + t + ", response=" + response);
179: }
180: });
181: }
182:
183: private void waitForWebSocket() throws InterruptedException {
184: int attempts = 0;
185: while (webRTCService == null || !webRTCService.getSignalingManager().isWebSocketConnected()) {
186: if (attempts++ > 20) {
187: if (webRTCService != null) {
188: webRTCService.printState(TAG,"❌ WebSocket initialization failed. Cannot proceed with SDP offer.");
189: } else {
190: Log.e(TAG, "❌ webRTCService is NULL in waitForWebSocket()");
191: }
192: return;
193: }
194: if (webRTCService != null) {
195: webRTCService.printState(TAG, "⏳ Waiting for WebSocket to be ready... Attempt " + attempts);
196: } else {
197: Log.e(TAG, "⏳ Waiting for WebSocket, but webRTCService is NULL. Attempt " + attempts);
198: }
199: Thread.sleep(500);
200: }
201: webRTCService.printState(TAG, "✅ WebSocket is ready. Proceeding with SDP offer.");
202: }
203: //endregion
204:
205: //region Test Methods
206: @Test
207: public void testSendTestMediaOverDataChannel() throws InterruptedException {
208: webRTCService.printState(TAG, "testSendTestMediaOverDataChannel: Starting test");
209:
210: // Ensure WebSocket is initialized
211: waitForWebSocket();
212:
213: webRTCService.createOffer();
214:
215: // Ensure WebRTCService is fully bound
216: if (webRTCService == null) {
217: webRTCService.printState(TAG, "❌ WebRTCService is not initialized.");
218: return;
219: }
220:
221: webRTCService.addWebRTCEventListener(new WebRTCEventListener() {
222: @Override
223: public void onSignalingChange(PeerConnection.SignalingState signalingState) {
224: webRTCService.printState(TAG, "🔄 onSignalingChange: State changed to " + signalingState);
225: }
226:
227: @Override
228: public void onIceConnectionChange(PeerConnection.IceConnectionState iceConnectionState) {
229: webRTCService.printState(TAG, "❄️ onIceConnectionChange: IceConnection state changed to " + iceConnectionState);
230: }
231:
232: @Override
233: public void onIceConnectionReceivingChange(boolean receiving) {
234: webRTCService.printState(TAG, "📡 onIceConnectionReceivingChange: Receiving=" + receiving);
235: }
236:
237: @Override
238: public void onIceGatheringChange(PeerConnection.IceGatheringState iceGatheringState) {
239: webRTCService.printState(TAG, "🧊 onIceGatheringChange: Gathering state changed to " + iceGatheringState);
240: }
241:
242: @Override
243: public void onIceCandidate(IceCandidate iceCandidate) {
244: webRTCService.printState(TAG, "📡 Sending ICE Candidate to peer: " + iceCandidate.sdp);
245: sendMessageToPeer("{"type": "candidate", "candidate": "" + iceCandidate.sdp + "", " +""sdpMid": "" + iceCandidate.sdpMid + "", "sdpMLineIndex": " + iceCandidate.sdpMLineIndex + "}");
246: }
247:
248: @Override
249: public void onAddStream(MediaStream mediaStream) {
250: webRTCService.printState(TAG, "🎥 onAddStream: Media stream added, ID=" + mediaStream.getId());
251: }
252:
253: @Override
254: public void onRemoveStream(MediaStream mediaStream) {
255: webRTCService.printState(TAG, "🛑 onRemoveStream: Media stream removed, ID=" + mediaStream.getId());
256: }
257:
258: @Override
259: public void onDataChannel(DataChannel channel) {
260: webRTCService.printState(TAG, "✅ onDataChannel: DataChannel opened. Label=" + channel.label());
261: dataChannel =channel;
262: }
263:
264: @Override
265: public void onRenegotiationNeeded() {
266: webRTCService.printState(TAG, "🔄 onRenegotiationNeeded: Renegotiation required.");
267: }
268:
269: @Override
270: public void onCallStarted(SessionDescription remoteDescription) {
271: webRTCService.printState(TAG, "📞 onCallStarted: Sending SDP Offer to test peer.");
272: sendMessageToPeer("{"type": "offer", "sdp": "" + remoteDescription.description + ""}");
273: }
274:
275: @Override
276: public void onCallEnded() {
277: webRTCService.printState(TAG, "🚫 onCallEnded: Call has ended.");
278: }
279:
280: @Override
281: public void onMediaStreamAdded(AudioTrack audioTrack, VideoTrack videoTrack) {
282: webRTCService.printState(TAG, "🎤🎥 onMediaStreamAdded: Audio track=" + (audioTrack != null) + ", Video track=" + (videoTrack != null));
283: }
284:
285: @Override
286: public void onError(String error) {
287: webRTCService.printState(TAG, "❌ onError: " +error);
288: }
289: });
290:
291: // Wait for DataChannel
292: int attempts = 0;
293: while (dataChannel == null || dataChannel.state() != DataChannel.State.OPEN) {
294: if (attempts++ > 30) {
295: webRTCService.printState(TAG, "❌ Failed to assign DataChannel within timeout.");
296: return;
297: }
298: webRTCService.printState(TAG, "⏳ Waiting for DataChannel... Attempt " + attempts);
299: Thread.sleep(1000);
300: }
301:
302: webRTCService.printState(TAG, "✅ DataChannel is now open. Sending test files.");
303: sendFileOverDataChannel("tst1.mp3");
304: sendFileOverDataChannel("tst1.mp4");
305: sendFileOverDataChannel("tst1.png");
306: sendFileOverDataChannel("tst1.txt");
307:
308: Thread.sleep(5000);
309: }
310: //endregion
311:
312: //region Data Channel and File Operations
313: private void sendFileOverDataChannel(String fileName) {
314: webRTCService.printState(TAG, "sendFileOverDataChannel: Method called with fileName=" + fileName);
315: if (dataChannel == null || dataChannel.state() != DataChannel.State.OPEN) {
316: webRTCService.printState(TAG, "DataChannel is not open. Cannot send file: " + fileName);
317: return;
318: }
319:
320: try {
321: AssetManager assetManager = InstrumentationRegistry.getInstrumentation().getContext().getAssets();
322: InputStream inputStream = assetManager.open(fileName);
323: ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
324:
325: byte[] buffer = new byte[4096];
326: int bytesRead;
327: while ((bytesRead = inputStream.read(buffer)) != -1) {
328: byteArrayOutputStream.write(buffer, 0, bytesRead);
329: }
330:
331: inputStream.close();
332: byte[] fileData = byteArrayOutputStream.toByteArray();
333: ByteBuffer byteBuffer = ByteBuffer.wrap(fileData);
334: DataChannel.Buffer dataBuffer = new DataChannel.Buffer(byteBuffer, false);
335:
336: webRTCService.printState(TAG, "Sending file over DataChannel: " + fileName);
337: webRTCService.printState(TAG, "Local variables: fileData=" + fileData + ", byteBuffer=" + byteBuffer + ", dataBuffer=" + dataBuffer);
338: dataChannel.send(dataBuffer);
339: webRTCService.printState(TAG, "File sent successfully: " + fileName);
340: } catch (IOException e) {
341: webRTCService.printState(TAG, "Failed to read file: " + fileName + ", Error: " + e.getMessage());
342: }
343: }
344: //endregion
345:
346: //region Helper Methods
347: private void sendMessageToPeer(String message) {
348: webRTCService.printState(TAG, "sendMessageToPeer: Method called with message=" + message);
349: if (webSocket == null) {
350: webRTCService.printState(TAG, "WebSocket is not initialized. Cannot send message.");
351: return;
352: }
353:
354: webRTCService.printState(TAG, "Sending message to test peer: " + message);
355: webRTCService.printState(TAG, "Local variables: message=" + message);
356: webSocket.send(message);
357: }
358: //endregion
359: }
360:
Return to main page
Android context:
Testing context:
Comments (
)
)
Link to this page:
http://www.vb-net.com/WebRTCMockitoTest/Test.htm
|
|