2015-11-25 14 views
7

Node.jsサーバーで実行されているWebRTCサーバーのクライアントとしてアンドロイドアプリケーションを実行しています。 アプリの現在の状態はビデオ通話はできますが、DataChannelでメッセージを送信することはできません。DataChannel.state()は常にwebRTCを返します。

ここに、アンドロイドアプリの完全なコードがあります。

Home.java

public class Home extends Activity { 

    public List<PeerConnection.IceServer> iceServers; 
    private GLSurfaceView videoView; 
    public static SocketIO socket; 
    ArrayList<String> userIDs = new ArrayList<>(); 
    private static final String FIELD_TRIAL_VP9 = "WebRTC-SupportVP9/Enabled/"; 
    String RoomId = ""; 
    String sreverURL = "http://xx.xx.xx.xx:xxxx/"; 
    private EditText roomid; 
    private VideoRenderer.Callbacks remote_view; 
    private VideoRenderer.Callbacks local_view; 
    protected PeerConnectionFactory factory; 
    PeerConnectionFactory.Options options = null; 
    Events pc_events; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_home); 
     videoView = (GLSurfaceView) findViewById(R.id.glview_call_remote); 
     VideoRendererGui.setView(videoView, new Runnable() { 
      @Override 
      public void run() { 
       createPeerConnectionFactory(); 
      } 
     }); 

     remote_view = VideoRendererGui.create(0, 0, 100, 100, ScalingType.SCALE_ASPECT_FIT, false); 
     local_view = VideoRendererGui.create(0, 0, 100, 100, ScalingType.SCALE_ASPECT_FILL, true); 
     iceServers = new ArrayList<>(); 
     IceServer icc = new IceServer("stun:stun.l.google.com:19302", "", ""); 
     iceServers.add(icc); 
     roomid = (EditText) findViewById(R.id.roomId); 
     Random rand = new Random(); 
     roomid.setText("" + rand.nextInt(9999)); 
     pc_events = new peerEventHandler(); 
    } 

    private void createPeerConnectionFactory() { 
     runOnUiThread(new Runnable() { 
      @Override 
      public void run() { 
       PeerConnectionFactory.initializeFieldTrials(FIELD_TRIAL_VP9); 
       PeerConnectionFactory.initializeAndroidGlobals(Home.this, true, true, true, VideoRendererGui.getEGLContext()); 
       try { 
        factory = new PeerConnectionFactory(); 
       } catch (Exception e) { 
        e.printStackTrace(); 
       } 
      } 
     }); 
    } 

    public void ondail(View view) { 

     try { 

      try { 
       SocketIO.setDefaultSSLSocketFactory(SSLContext.getDefault()); 
      } catch (NoSuchAlgorithmException e1) { 
       e1.printStackTrace(); 
      } 

      socket = new SocketIO(); 

      socket.connect(sreverURL, new IOCallback() { 

       @Override 
       public void onMessage(JSONObject json, IOAcknowledge ack) { 
       } 
       @Override 
       public void onMessage(String data, IOAcknowledge ack) { 
       } 
       @Override 
       public void onError(SocketIOException socketIOException) { 
        socketIOException.printStackTrace(); 
       } 
       @Override 
       public void onDisconnect() { 
       } 
       @Override 
       public void onConnect() { 
        showToast("Connected to " + sreverURL); 
       } 
       @Override 
       public void on(final String event, IOAcknowledge ack, final Object... args) { 

        Log.e("Socked.on", event + ", " + args); 
        switch (getEvent(event)) { 

         case LOG : 
          break; 
         case MESSAGE : 
          if (args instanceof Object[]) { 
           pc_events.setMessage(args[0].toString()); 
          } else { 
           pc_events.setMessage(args.toString()); 
          } 
          break; 
         case CREATED : 
          runOnUiThread(new Runnable() { 
           public void run() { 
            showToast("Room Created " + args[0]); 
           } 
          }); 
          break; 
         case BROADCAST : 
          break; 
         case JOIN : 
          break; 
         case EMIT : 
          Log.e("Socked.onEMIT", args.toString()); 
          startCall(); 
          pc_events.createOffer(); 
          break; 

         case ERROR : 
          Log.e("Socked.onERROR", args.toString()); 
          break; 

         default : 

          break; 
        } 
       } 
      }); 

      try { 
       RoomId = roomid.getText().toString(); 
      } catch (Exception e) { 
      } 

      socket.emit("create or join", RoomId); 

     } catch (MalformedURLException e) { 

      e.printStackTrace(); 
     } 

    } 

    public void oncancel(View view) { 

    } 

    public SocketEvent getEvent(String eventString) { 

     SocketEvent eventType; 

     try { 

      if (eventString.contains("log")) { 
       eventType = SocketEvent.LOG; 
      } else if (eventString.contains("created")) { 
       eventType = SocketEvent.CREATED; 
      } else if (eventString.contains("emit():")) { 
       eventType = SocketEvent.EMIT; 
      } 

      else if (eventString.contains("broadcast():")) { 
       eventType = SocketEvent.BROADCAST; 
      } else if (eventString.contains("message")) { 
       eventType = SocketEvent.MESSAGE; 
      } else if (eventString.toLowerCase().substring(0, 20).contains("join")) { 
       eventType = SocketEvent.JOIN; 
      } else { 
       eventType = SocketEvent.ERROR; 
      } 

     } catch (Exception e) { 
      eventType = SocketEvent.ERROR; 
     } 

     return eventType; 

    } 

    public static interface Events { 

     public void peerConnectionEvent(VideoRenderer.Callbacks localRender, VideoRenderer.Callbacks remoteRender); 

     public void setFactory(PeerConnectionFactory factory); 

     public void setMessage(String message); 
     public void createOffer(); 

     public void sendMessage(String msg); 
    } 

    private void startCall() { 

     pc_events.setFactory(factory); 

     pc_events.peerConnectionEvent(remote_view, local_view); 

    } 

    public void showToast(final String message) { 

     runOnUiThread(new Runnable() { 
      public void run() { 
       Toast.makeText(Home.this, message, Toast.LENGTH_SHORT).show(); 
      } 
     }); 
    } 

    public void makeOffer(View v) { 
     pc_events.sendMessage("Hello"); 
    } 

} 

peerEventHandler.java

public class peerEventHandler implements Events { 

    private PeerConnection peerConnection; 
    private PeerConnectionFactory factory; 
    PCObserver pcObserver = new PCObserver(); 
    public LooperExecutor executor; 

    private MediaStream mediaStream; 

    private VideoSource videoSource; 
    private DcObserver dc_observer; 
    public static final String VIDEO_TRACK_ID = "ARDAMSv0"; 
    public static final String AUDIO_TRACK_ID = "ARDAMSa0"; 

    private VideoCapturerAndroid videoCapturer; 
    private VideoTrack localVideoTrack; 
    private VideoTrack remoteVideoTrack; 
    public boolean preferIsac = false; 
    public boolean videoCallEnabled = true; 
    public boolean preferH264 = false; 

    private SessionDescription localSdp; 

    private final SDPObserver sdpObserver = new SDPObserver(); 

    public boolean isInitiator = false; 
    private MediaConstraints sdpMediaConstraints; 

    private VideoRenderer.Callbacks remote_view; 
    private VideoRenderer.Callbacks local_view; 
    private DataChannel dataChannel; 

    @Override 
    public void peerConnectionEvent(Callbacks remoteRender, Callbacks localRender) { 

     this.remote_view = remoteRender; 
     this.local_view = localRender; 
     creatPeerConnection(); 

    } 

    public void creatPeerConnection() { 

     executor = new LooperExecutor(); 
     executor.requestStart(); 

     MediaConstraints pcConstraints = new MediaConstraints(); 
     MediaConstraints videoConstraints = new MediaConstraints(); 
     MediaConstraints audioConstraints = new MediaConstraints(); 
     sdpMediaConstraints = new MediaConstraints(); 

     creatPcConstrains(pcConstraints); 
     creatvideoConstraints(videoConstraints); 
     creatsdpMediaConstraints(sdpMediaConstraints); 

     List<PeerConnection.IceServer> iceServers = new ArrayList<PeerConnection.IceServer>(); 

     IceServer iceServer = new IceServer("stun:stun.l.google.com:19302", "", ""); 

     iceServers.add(iceServer); 

     PeerConnection.RTCConfiguration rtcConfig = new PeerConnection.RTCConfiguration(iceServers); 

     rtcConfig.tcpCandidatePolicy = PeerConnection.TcpCandidatePolicy.DISABLED; 
     rtcConfig.bundlePolicy = PeerConnection.BundlePolicy.BALANCED; 
     rtcConfig.rtcpMuxPolicy = PeerConnection.RtcpMuxPolicy.NEGOTIATE; 

     peerConnection = factory.createPeerConnection(rtcConfig, pcConstraints, pcObserver); 

     Logging.enableTracing("logcat:", EnumSet.of(Logging.TraceLevel.TRACE_DEFAULT), Logging.Severity.LS_WARNING); 

     mediaStream = factory.createLocalMediaStream("ARDAMS"); 

     String cameraDeviceName = CameraEnumerationAndroid.getDeviceName(0); 
     String frontCameraDeviceName = CameraEnumerationAndroid.getNameOfFrontFacingDevice(); 

     cameraDeviceName = frontCameraDeviceName; 

     videoCapturer = VideoCapturerAndroid.create(cameraDeviceName, null); 

     videoSource = factory.createVideoSource(videoCapturer, videoConstraints); 

     localVideoTrack = factory.createVideoTrack(VIDEO_TRACK_ID, videoSource); 
     localVideoTrack.setEnabled(true); 
     localVideoTrack.addRenderer(new VideoRenderer(local_view)); 
     mediaStream.addTrack(factory.createAudioTrack(AUDIO_TRACK_ID, factory.createAudioSource(audioConstraints))); 
     mediaStream.addTrack(localVideoTrack); 
     peerConnection.addStream(mediaStream); 

     dataChannel = peerConnection.createDataChannel("sendDataChannel", new DataChannel.Init()); 
     dc_observer = new DcObserver(); 
     dataChannel.registerObserver(dc_observer); 

    } 

    @Override 
    public void createOffer() { 
     executor.execute(new Runnable() { 
      @Override 
      public void run() { 
       if (peerConnection != null) { 
        isInitiator = true; 
        peerConnection.createOffer(sdpObserver, sdpMediaConstraints); 
       } 
      } 
     }); 

    } 

    public void createAnswer() { 
     executor.execute(new Runnable() { 
      @Override 
      public void run() { 
       if (peerConnection != null) { 
        isInitiator = false; 
        peerConnection.createAnswer(sdpObserver, sdpMediaConstraints); 
       } 
      } 
     }); 
    } 

    private class PCObserver implements PeerConnection.Observer { 

     @Override 
     public void onAddStream(final MediaStream stream) { 

      Log.e("onAddStream", "onAddStream"); 
      executor.execute(new Runnable() { 
       @Override 
       public void run() { 
        if (peerConnection == null) { 
         return; 
        } 
        if (stream.audioTracks.size() > 1 || stream.videoTracks.size() > 1) { 
         // /reportError("Weird-looking stream: " + stream); 
         return; 
        } 
        if (stream.videoTracks.size() == 1) { 
         remoteVideoTrack = stream.videoTracks.get(0); 
         remoteVideoTrack.setEnabled(true); 
         remoteVideoTrack.addRenderer(new VideoRenderer(remote_view)); 
         VideoRendererGui.update(local_view, 75, 70, 60, 60, ScalingType.SCALE_ASPECT_FIT, true); 
         VideoRendererGui.update(remote_view, 0, 0, 200, 200, ScalingType.SCALE_ASPECT_FILL, false); 
        } 
       } 
      }); 



     } 

     @Override 
     public void onDataChannel(final DataChannel dc) { 
      executor.execute(new Runnable() { 
       @Override 
       public void run() { 
        dataChannel = dc; 
        String channelName = dataChannel.label(); 
        dataChannel.registerObserver(new DcObserver()); 
       } 
      }); 
     } 

     @Override 
     public void onIceCandidate(IceCandidate candidate) { 

      SocketIO socket = Home.socket; 

      JSONObject json = new JSONObject(); 
      try { 

       json.putOpt("type", "candidate"); 
       json.putOpt("label", candidate.sdpMLineIndex); 
       json.putOpt("id", candidate.sdpMid); 
       json.putOpt("candidate", candidate.sdp); 

      } catch (JSONException e) { 
       e.printStackTrace(); 
      } 

      socket.emit("message", json); 
     } 

     @Override 
     public void onIceConnectionChange(IceConnectionState arg0) { 
     } 

     @Override 
     public void onIceConnectionReceivingChange(boolean arg0) { 
     } 

     @Override 
     public void onIceGatheringChange(IceGatheringState arg0) { 
     } 

     @Override 
     public void onRemoveStream(MediaStream arg0) { 
     } 

     @Override 
     public void onRenegotiationNeeded() { 
     } 

     @Override 
     public void onSignalingChange(SignalingState arg0) { 
     } 

    } 

    public void creatPcConstrains(MediaConstraints pcConstraints) { 
     pcConstraints.optional.add(new KeyValuePair("DtlsSrtpKeyAgreement", "true")); 
     pcConstraints.optional.add(new KeyValuePair("RtpDataChannels", "true")); 
     pcConstraints.optional.add(new KeyValuePair("internalSctpDataChannels", "true")); 
    } 
    public void creatvideoConstraints(MediaConstraints videoConstraints) { 

     String MAX_VIDEO_WIDTH_CONSTRAINT = "maxWidth"; 
     String MIN_VIDEO_WIDTH_CONSTRAINT = "minWidth"; 
     String MAX_VIDEO_HEIGHT_CONSTRAINT = "maxHeight"; 
     String MIN_VIDEO_HEIGHT_CONSTRAINT = "minHeight"; 
     String MAX_VIDEO_FPS_CONSTRAINT = "maxFrameRate"; 
     String MIN_VIDEO_FPS_CONSTRAINT = "minFrameRate"; 

     int videoWidth = 0; 
     int videoHeight = 0; 

     if ((videoWidth == 0 || videoHeight == 0) && true && MediaCodecVideoEncoder.isVp8HwSupported()) { 
      videoWidth = 1280; 
      videoHeight = 1280; 
     } 

     if (videoWidth > 0 && videoHeight > 0) { 
      videoWidth = Math.min(videoWidth, 1280); 
      videoHeight = Math.min(videoHeight, 1280); 
      videoConstraints.mandatory.add(new KeyValuePair(MIN_VIDEO_WIDTH_CONSTRAINT, Integer.toString(videoWidth))); 
      videoConstraints.mandatory.add(new KeyValuePair(MAX_VIDEO_WIDTH_CONSTRAINT, Integer.toString(videoWidth))); 
      videoConstraints.mandatory.add(new KeyValuePair(MIN_VIDEO_HEIGHT_CONSTRAINT, Integer.toString(videoHeight))); 
      videoConstraints.mandatory.add(new KeyValuePair(MAX_VIDEO_HEIGHT_CONSTRAINT, Integer.toString(videoHeight))); 
     } 

     int videoFps = 30; 

     videoConstraints.mandatory.add(new KeyValuePair(MIN_VIDEO_FPS_CONSTRAINT, Integer.toString(videoFps))); 
     videoConstraints.mandatory.add(new KeyValuePair(MAX_VIDEO_FPS_CONSTRAINT, Integer.toString(videoFps))); 

    } 
    public void creataudioConstraints(MediaConstraints pcConstraints) { 
     pcConstraints.optional.add(new KeyValuePair("DtlsSrtpKeyAgreement", "true")); 
     pcConstraints.optional.add(new KeyValuePair("RtpDataChannels", "true")); 
     pcConstraints.optional.add(new KeyValuePair("internalSctpDataChannels", "true")); 
    } 
    public void creatsdpMediaConstraints(MediaConstraints sdpMediaConstraints) { 

     sdpMediaConstraints.mandatory.add(new KeyValuePair("OfferToReceiveAudio", "true")); 

     sdpMediaConstraints.mandatory.add(new KeyValuePair("OfferToReceiveVideo", "true")); 

    } 

    private class SDPObserver implements SdpObserver { 

     @Override 
     public void onCreateFailure(String arg0) { 
      System.out.print(arg0); 
     } 

     @Override 
     public void onCreateSuccess(SessionDescription origSdp) { 
      if (localSdp != null) { 
       return; 
      } 
      localSdp = origSdp; 
      setLocalDescription(origSdp); 
     } 

     @Override 
     public void onSetFailure(String arg0) { 
     } 

     @Override 
     public void onSetSuccess() { 

      executor.execute(new Runnable() { 
       @Override 
       public void run() { 
        if (peerConnection == null) { 
         return; 
        } 
        if (isInitiator) { 
         if (peerConnection != null) { 
          JSONObject json = new JSONObject(); 
          try { 
           json.putOpt("type", localSdp.type.toString().toLowerCase()); 
           json.putOpt("sdp", localSdp.description); 
          } catch (JSONException e) { 
           e.printStackTrace(); 
          } 
          Home.socket.emit("message", json); 
         } 
        } else { 
         // createAnswer(); 
        } 
       } 
      }); 

     } 

    } 
    public void addRemoteIceCandidate(final IceCandidate candidate) { 
     executor.execute(new Runnable() { 
      @Override 
      public void run() { 
       peerConnection.addIceCandidate(candidate); 
      } 
     }); 
    } 

    public void setLocalDescription(final SessionDescription sdp) { 
     executor.execute(new Runnable() { 
      @Override 
      public void run() { 
       if (peerConnection == null) { 
        return; 
       } 
       peerConnection.setLocalDescription(sdpObserver, sdp); 
      } 
     }); 
    } 

    public void setRemoteDescription(final SessionDescription sdp) { 
     executor.execute(new Runnable() { 
      @Override 
      public void run() { 
       if (peerConnection == null) { 
        return; 
       } 

       peerConnection.setRemoteDescription(sdpObserver, sdp); 
      } 
     }); 
    } 

    @Override 
    public void setFactory(PeerConnectionFactory factory) { 
     this.factory = factory; 
    } 

    public void onWebSocketMessage(final String msg) { 

     try { 
      Log.e("onWebSocketMessage", msg); 
      JSONObject json = new JSONObject(msg); 
      json = new JSONObject(msg); 
      String type = json.optString("type"); 
      if (type.equals("candidate")) { 
       IceCandidate candidate = new IceCandidate(json.getString("id"), json.getInt("label"), json.getString("candidate")); 
       addRemoteIceCandidate(candidate); 
      } else if (type.equals("answer")) { 
       isInitiator = false; 
       SessionDescription sdp = new SessionDescription(SessionDescription.Type.fromCanonicalForm(type), json.getString("sdp")); 
       setRemoteDescription(sdp); 
      } else if (type.equals("offer")) { 
       SessionDescription sdp = new SessionDescription(SessionDescription.Type.fromCanonicalForm(type), json.getString("sdp")); 
       setRemoteDescription(sdp); 
      } else if (type.equals("bye")) { 
      } else { 
      } 

     } catch (JSONException e) { 

     } 
    } 

    @Override 
    public void setMessage(String message) { 
     if (message.toString().contains("got user media") || message.toString().contains("bye")) { 

     } else 
      onWebSocketMessage(message); 

    } 

    private class DcObserver implements DataChannel.Observer { 

     @Override 
     public void onMessage(DataChannel.Buffer buffer) { 

      ByteBuffer data = buffer.data; 
      byte[] bytes = new byte[data.remaining()]; 
      data.get(bytes); 
      String command = new String(bytes); 

      Log.e("onMessage ", command); 

     } 

     @Override 
     public void onStateChange() { 
      Log.e("onStateChange ", "onStateChange"); 
     } 

     @Override 
     public void onBufferedAmountChange(long arg0) { 
      Log.e("onMessage ", "" + arg0); 

     } 
    } 

    @Override 
    public void sendMessage(String msg) { 
     ByteBuffer buffer = ByteBuffer.wrap(msg.getBytes()); 
     boolean sent = dataChannel.send(new DataChannel.Buffer(buffer, false)); 
     if (sent) { 
      Log.e("Message sent", "" + sent); 
     } 
    } 
} 

任意のコメントや提案を歓迎している;)

+1

RtpDataChannels制約を削除できる点を除いて、データチャネルを追加するコードはわかりやすく見えます。データチャネルがSCTPで動作することを思い出してください。 –

+0

ありがとう@GuySすぐにお試しになります。 –

+0

ありがとう@GuySサーバーの端に少し変更がありましたが、あなたのヒントはうまくいきました。私はそれを受け入れ、他の人を助けるかもしれないように答えとして投稿できますか? –

答えて

2

のWebRTCデータチャネルは、あなたができるようになりましたSCTPを介して動作しますRtpDataChannels制約を削除します。

関連する問題