(FRONT) FRONT (2025)

WebRTC Service.  Return to WebRTC service  

   1:  package com.voipplus.mmsclient.WebRTC;
   2:  
   3:  import android.app.Service;
   4:  import android.content.Intent;
   5:  import android.os.Binder;
   6:  import android.os.IBinder;
   7:  import android.util.Log;
   8:  
   9:  import java.util.concurrent.CopyOnWriteArrayList;
  10:  
  11:  import livekit.org.webrtc.AudioTrack;
  12:  import livekit.org.webrtc.DataChannel;
  13:  import livekit.org.webrtc.IceCandidate;
  14:  import livekit.org.webrtc.PeerConnection;
  15:  import livekit.org.webrtc.SessionDescription;
  16:  import livekit.org.webrtc.VideoTrack;
  17:  import okhttp3.WebSocket;
  18:  
  19:  public class WebRTCService extends Service {
  20:      private static final String TAG = "WebRTCService";
  21:  
  22:      private final CopyOnWriteArrayList<WebRTCEventListener> eventListeners = new CopyOnWriteArrayList<>();
  23:      private final IBinder binder = new LocalBinder();
  24:      private WebRTCState webRTCState = WebRTCState.IDLE;
  25:      private PeerConnectionManager peerConnectionManager;
  26:      private SignalingManager signalingManager;
  27:      private DataChannelManager dataChannelManager;
  28:  
  29:  
  30:      @Override
  31:      public int onStartCommand(Intent intent, int flags, int startId) {
  32:          WebRTCUtils.debugInfo(TAG, "🟢 WebRTCService Started.", webRTCState, safeGetPeerConnection(), safeGetDataChannel(), safeGetWebSocket(), getSafeSignalinServerUrl());
  33:  
  34:          // ✅ Check if the intent has a signaling server URL
  35:          if (intent != null && intent.hasExtra("SIGNALING_SERVER_URL")) {
  36:              String signalingUrl = intent.getStringExtra("SIGNALING_SERVER_URL");
  37:              WebRTCUtils.debugInfo(TAG, "🔗 Received Signaling Server URL: " + signalingUrl, webRTCState, safeGetPeerConnection(), safeGetDataChannel(), safeGetWebSocket(), getSafeSignalinServerUrl());
  38:  
  39:              if (signalingUrl != null) {
  40:                  setSignalingServerUrl(signalingUrl); // ✅ Set the signaling server URL dynamically
  41:              }
  42:          } else {
  43:              WebRTCUtils.debugInfo(TAG, "⚠️ No signaling URL provided.", webRTCState, safeGetPeerConnection(), safeGetDataChannel()), safeGetWebSocket(), getSafeSignalinServerUrl());
  44:          }
  45:  
  46:          return START_STICKY; // ✅ Keep service running unless explicitly stopped
  47:      }
  48:  
  49:      // 1️⃣ Service Lifecycle & Binding
  50:      //region Service Lifecycle & Binding
  51:  
  52:      public WebRTCService() {
  53:          WebRTCUtils.debugInfo(TAG, "🟢 WebRTCService Constructor Called.", webRTCState, safeGetPeerConnection(), safeGetDataChannel(), safeGetWebSocket(), getSafeSignalinServerUrl());
  54:      }
  55:  
  56:      @Override
  57:      public void onCreate() {
  58:          super.onCreate();
  59:          WebRTCUtils.debugInfo(TAG, "🟢 WebRTCService Created.", webRTCState, safeGetPeerConnection(), safeGetDataChannel(), safeGetWebSocket(), getSafeSignalinServerUrl());
  60:          peerConnectionManager = new PeerConnectionManager(this);
  61:          signalingManager = new SignalingManager(this);
  62:          dataChannelManager = new DataChannelManager(this);
  63:      }
  64:  
  65:      // ✅ LocalBinder for the service
  66:      public class LocalBinder extends Binder {
  67:          public WebRTCService getService() {
  68:              return WebRTCService.this;
  69:          }
  70:      }@Override
  71:      public IBinder onBind(Intent intent) {
  72:          WebRTCUtils.debugInfo(TAG, "🔗 onBind: WebRTC Service bound to client.", webRTCState, safeGetPeerConnection(), safeGetDataChannel(), safeGetWebSocket(), getSafeSignalinServerUrl());
  73:          return binder;  // ✅ Return the LocalBinder instance
  74:      }
  75:      //endregion
  76:  
  77:      // 2️⃣ State Management
  78:      //region State Management
  79:  
  80:      public void updateWebRTCState(WebRTCState state) {
  81:          WebRTCUtils.debugInfo(TAG, "updateWebRTCState: State=" + state, webRTCState, safeGetPeerConnection(), safeGetDataChannel(), safeGetWebSocket(), getSafeSignalinServerUrl());
  82:          this.webRTCState = state;
  83:      }
  84:  
  85:      public WebRTCState getWebRTCState() {
  86:          WebRTCUtils.debugInfo(TAG, "getWebRTCState: Called. Returning webRTCState=" + webRTCState, webRTCState, safeGetPeerConnection(), safeGetDataChannel(), safeGetWebSocket(), getSafeSignalinServerUrl());
  87:          return webRTCState;
  88:      }
  89:  
  90:      public void printState(String TAG, String message) {
  91:          WebRTCUtils.debugInfo(TAG, message, webRTCState, safeGetPeerConnection(), safeGetDataChannel(), safeGetWebSocket(), getSafeSignalinServerUrl());
  92:      }
  93:      //endregion
  94:  
  95:      // 3️⃣ PeerConnection & Signaling Management
  96:      //region PeerConnection & Signaling Management
  97:  
  98:      public void setSignalingServerUrl(String url) {
  99:          WebRTCUtils.debugInfo(TAG, "🔗 Setting WebSocket URL: " + url, webRTCState, safeGetPeerConnection(), safeGetDataChannel(), safeGetWebSocket(), getSafeSignalinServerUrl());
 100:          signalingManager.setSignalingServerUrl(url);
 101:      }
 102:  
 103:      public void createOffer() {
 104:          WebRTCUtils.debugInfo(TAG, "createOffer: Called.", webRTCState, safeGetPeerConnection(), safeGetDataChannel(), safeGetWebSocket(), getSafeSignalinServerUrl());
 105:          peerConnectionManager.createOffer();
 106:      }
 107:  
 108:      public void handleRemoteAnswer(SessionDescription remoteSessionDescription) {
 109:          WebRTCUtils.debugInfo(TAG, "handleRemoteAnswer: Called.", webRTCState, safeGetPeerConnection(), safeGetDataChannel(), safeGetWebSocket(), getSafeSignalinServerUrl());
 110:          peerConnectionManager.handleRemoteAnswer(remoteSessionDescription);
 111:      }
 112:  
 113:      public void addIceCandidate(IceCandidate candidate) {
 114:          WebRTCUtils.debugInfo(TAG, "addIceCandidate: Called.", webRTCState, safeGetPeerConnection(), safeGetDataChannel(), safeGetWebSocket(), getSafeSignalinServerUrl());
 115:          peerConnectionManager.addIceCandidate(candidate);
 116:      }
 117:  
 118:      public void closeConnection() {
 119:          WebRTCUtils.debugInfo(TAG, "closeConnection: Called.", webRTCState, safeGetPeerConnection(), safeGetDataChannel(), safeGetWebSocket(), getSafeSignalinServerUrl());
 120:          peerConnectionManager.closeConnection();
 121:      }
 122:  
 123:      public void sendIceCandidateToSignalingServer(IceCandidate iceCandidate) {
 124:          WebRTCUtils.debugInfo(TAG, "sendIceCandidateToSignalingServer: ICE Candidate=" + iceCandidate.sdp, webRTCState, safeGetPeerConnection(), safeGetDataChannel(), safeGetWebSocket(), getSafeSignalinServerUrl());
 125:          signalingManager.sendIceCandidateToSignalingServer(iceCandidate);
 126:      }
 127:  
 128:      public void startRenegotiation() {
 129:          WebRTCUtils.debugInfo(TAG, "startRenegotiation: Attempting to restart ICE", webRTCState, safeGetPeerConnection(), safeGetDataChannel(), safeGetWebSocket(), getSafeSignalinServerUrl());
 130:          peerConnectionManager.startRenegotiation();
 131:      }
 132:      //endregion
 133:  
 134:      // 4️⃣ Event Listener Management
 135:      //region Event Listener Management
 136:  
 137:      public void addWebRTCEventListener(WebRTCEventListener listener) {
 138:          if (!eventListeners.contains(listener)) {
 139:              eventListeners.add(listener);
 140:              WebRTCUtils.debugInfo(TAG, "✅ WebRTCEventListener added. Current listeners: " + eventListeners.size(), webRTCState, safeGetPeerConnection(), safeGetDataChannel(), safeGetWebSocket(), getSafeSignalinServerUrl());
 141:          }
 142:      }
 143:  
 144:      public void removeWebRTCEventListener(WebRTCEventListener listener) {
 145:          if (eventListeners != null) {
 146:              eventListeners.remove(listener);
 147:              WebRTCUtils.debugInfo(TAG, "❌ removeWebRTCEventListener: Removed listener=" + listener, webRTCState, safeGetPeerConnection(), safeGetDataChannel(), safeGetWebSocket(), getSafeSignalinServerUrl());
 148:          }
 149:      }
 150:  
 151:      public void notifyListeners(String event, Object value) {
 152:          WebRTCUtils.debugInfo(TAG, "🔔 notifyListeners: " + event + " -> " + value, webRTCState, safeGetPeerConnection(), safeGetDataChannel(), safeGetWebSocket(), getSafeSignalinServerUrl());
 153:          for (WebRTCEventListener listener : eventListeners) {
 154:              switch (event) {
 155:                  case "onIceCandidate":
 156:                      listener.onIceCandidate((IceCandidate) value);
 157:                      break;
 158:                  case "onDataChannel":
 159:                      listener.onDataChannel((DataChannel) value);
 160:                      break;
 161:                  case "onCallStarted":
 162:                      listener.onCallStarted((SessionDescription) value);
 163:                      break;
 164:                  case "onCallEnded":
 165:                      listener.onCallEnded();
 166:                      break;
 167:                  default:
 168:                      WebRTCUtils.debugInfo(TAG, "⚠️ Unknown event: " + event, webRTCState, safeGetPeerConnection(), safeGetDataChannel(), safeGetWebSocket(), getSafeSignalinSeerverUrl());
 169:              }
 170:          }
 171:      }
 172:      //endregion
 173:  
 174:      // 5️⃣ DataChannel & Media Stream Handling
 175:      //region DataChannel & Media Stream Handling
 176:  
 177:      public void onDataChannelOpened(DataChannel dataChannel) {
 178:          WebRTCUtils.debugInfo(TAG, "onDataChannelOpened: DataChannel opened=" + dataChannel.label(), webRTCState, safeGetPeerConnection(), safeGetDataChannel(), safeGetWebSocket(), getSafeSignalinServerUrl());
 179:          dataChannelManager.onDataChannelOpened(dataChannel);
 180:      }
 181:  
 182:      public void notifyMediaStreamAdded(AudioTrack audioTrack, VideoTrack videoTrack) {
 183:          WebRTCUtils.debugInfo(TAG, "notifyMediaStreamAdded: Audio=" + (audioTrack != null) + ", Video=" + (videoTrack != null), webRTCState, safeGetPeerConnection(), safeGetDataChannel(), safeGetWebSocket(), getSafeSignalinServerUrl());
 184:          for (WebRTCEventListener listener : eventListeners) {
 185:              listener.onMediaStreamAdded(audioTrack, videoTrack);
 186:          }
 187:      }
 188:      //endregion
 189:  
 190:      // 6️⃣ Peer Connection State Updates
 191:      //region Peer Connection State Updates
 192:  
 193:      public void updatePeerConnectionState(PeerConnection.PeerConnectionState newState) {
 194:          WebRTCUtils.debugInfo(TAG, "updatePeerConnectionState: PeerConnectionState=" + newState, webRTCState, safeGetPeerConnection(), safeGetDataChannel(), safeGetWebSocket(), getSafeSignalinServerUrl());
 195:          peerConnectionManager.updatePeerConnectionState(newState);}
 196:  
 197:      public void updateWebRTCState(PeerConnection.SignalingState signalingState) {
 198:          WebRTCUtils.debugInfo(TAG, "updateWebRTCState: SignalingState=" + signalingState, webRTCState, safeGetPeerConnection(), safeGetDataChannel(), safeGetWebSocket(), getSafeSignalinServerUrl());
 199:          switch (signalingState) {
 200:              case STABLE:
 201:                  webRTCState = WebRTCState.WEBSOCKET_CONNECTED;
 202:                  break;
 203:              case HAVE_LOCAL_OFFER:
 204:                  webRTCState = WebRTCState.CREATING_OFFER;
 205:                  break;
 206:              case HAVE_REMOTE_OFFER:
 207:                  webRTCState = WebRTCState.WAITING_FOR_ANSWER;
 208:                  break;
 209:              default:
 210:                  webRTCState = WebRTCState.ERROR;
 211:          }
 212:      }
 213:  
 214:      public void updateWebRTCState(PeerConnection.IceConnectionState iceConnectionState) {
 215:          WebRTCUtils.debugInfo(TAG, "updateWebRTCState: IceConnectionState=" + iceConnectionState, webRTCState, safeGetPeerConnection(), safeGetDataChannel(), safeGetWebSocket(), getSafeSignalinServerUrl());
 216:          if (iceConnectionState == PeerConnection.IceConnectionState.CONNECTED) {
 217:              webRTCState = WebRTCState.ESTABLISHED;
 218:          } else if (iceConnectionState == PeerConnection.IceConnectionState.DISCONNECTED) {
 219:              webRTCState = WebRTCState.IDLE;
 220:          }
 221:      }
 222:      //endregion
 223:  
 224:      // 7️⃣ Safe Getters for Dependencies
 225:      //region Safe Getters for Dependencies
 226:  
 227:      public PeerConnection safeGetPeerConnection() {
 228:          return (peerConnectionManager != null) ? peerConnectionManager.getPeerConnection() : null;
 229:      }
 230:  
 231:      public DataChannel safeGetDataChannel() {
 232:          return (dataChannelManager != null) ? dataChannelManager.getDataChannel() : null;
 233:      }
 234:  
 235:      public SignalingManager safeGetSignalingManager() {
 236:          return (signalingManager != null) ? signalingManager :null;
 237:      }
 238:  
 239:      public WebSocket safeGetWebSocket() {
 240:          return (signalingManager != null) ? signalingManager.getWebSocket() : null;
 241:      }
 242:  
 243:      public String getSafeSignalinServerUrl() {
 244:          return (signalingManager != null) ? signalingManager.getSignalingServerUrl() : null;
 245:      }
 246:  
 247:      public PeerConnectionManager getPeerConnectionManager() {
 248:          return peerConnectionManager;
 249:      }
 250:  
 251:      public SignalingManager getSignalingManager() {
 252:          return signalingManager;
 253:      }
 254:  
 255:      public DataChannelManager getDataChannelManager() {
 256:          return dataChannelManager;
 257:      }
 258:      //endregion
 259:  }
 260:  

Return to WebRTC service




Android context:




Testing context:



Comments ( )
Link to this page: http://www.vb-net.com/AndroidMosaic/Service.htm
< THANKS ME>