Как добавить icecandidate в sdp?

Сервер требует наличие icecandidatte в sdp. Но когда я отправляю sdp, в нем нет icecandidate. Cразу после отправки sdp я вижу сформированные icecandidate. Не могу понять, как поменять код, чтобы icecandidate отправлялись в sdp. Далее прилагаю код основной активити и sdp:

   public class MainActivity extends AppCompatActivity {

    private final int MY_PERMISSIONS_REQUEST_CAMERA = 100;
    private final int MY_PERMISSIONS_REQUEST_RECORD_AUDIO = 101;
    private final int MY_PERMISSIONS_REQUEST = 102;
    public static final MediaType JSON = MediaType.get("application/json; charset=utf-8");
    private PeerConnection localPeer, remotePeer;
    private PeerConnectionFactory peerConnectionFactory;
    private VideoRenderer remoteRenderer;
    private VideoTrack localVideoTrack;
    private String socketAddress = "http://193.XXX.XX.XX:XXXXX/offer";
    private OkHttpClient webSocket1;
    private WebSocket ws1;
    private OkHttpClient webSocket2;
    private WebSocket ws2;
    EglBase rootEglBase;
    @BindView(R.id.start_call)
    Button start_call;
    @BindView(R.id.init_call)
    Button init_call;
    @BindView(R.id.end_call)
    Button end_call;
    @BindView(R.id.remote_gl_surface_view)
    SurfaceViewRenderer remoteVideoView;
    @BindView(R.id.local_gl_surface_view)
    SurfaceViewRenderer localVideoView;
    private enum MessageType { MESSAGE, LEAVE }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        askForPermissions();
        ButterKnife.bind(this);
    }
    public void setRemoteDescription(SessionDescription sessionDescription) {
        localPeer.setRemoteDescription(new CustomSdpObserver("localSetRemoteDesc"), sessionDescription);
    }

    public void askForPermissions() {
        if ((ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
                != PackageManager.PERMISSION_GRANTED) &&
                (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO)
                        != PackageManager.PERMISSION_GRANTED)) {
            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO},
                    MY_PERMISSIONS_REQUEST);
        } else if (ContextCompat.checkSelfPermission(this,
                Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.RECORD_AUDIO},
                    MY_PERMISSIONS_REQUEST_RECORD_AUDIO);

        } else if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
                != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.CAMERA},
                    MY_PERMISSIONS_REQUEST_CAMERA);
        }
    }



    public void start(View view) throws JSONException {
        start_call.setEnabled(false);
        init_call.setEnabled(true);
        localVideoView.setMirror(true);
        remoteVideoView.setMirror(true);
        EglBase rootEglBase = EglBase.create();
        localVideoView.init(rootEglBase.getEglBaseContext(), null);
        localVideoView.setZOrderMediaOverlay(true);
        remoteVideoView.init(rootEglBase.getEglBaseContext(), null);
        remoteVideoView.setZOrderMediaOverlay(true);
        PeerConnectionFactory.InitializationOptions initializationOptions =
                PeerConnectionFactory.InitializationOptions.builder(this)
                        .createInitializationOptions();
        PeerConnectionFactory.initialize(initializationOptions);

//Create a new PeerConnectionFactory instance - using Hardware encoder and decoder.
        PeerConnectionFactory.Options options = new PeerConnectionFactory.Options();
        DefaultVideoEncoderFactory defaultVideoEncoderFactory = new DefaultVideoEncoderFactory(
                rootEglBase.getEglBaseContext(), /* enableIntelVp8Encoder */false, /* enableH264HighProfile */true);
        DefaultVideoDecoderFactory defaultVideoDecoderFactory = new DefaultVideoDecoderFactory(rootEglBase.getEglBaseContext());
        peerConnectionFactory = PeerConnectionFactory.builder()
                .setOptions(options)
                .setVideoEncoderFactory(defaultVideoEncoderFactory)
                .setVideoDecoderFactory(defaultVideoDecoderFactory)
                .createPeerConnectionFactory();
        VideoCapturer videoGrabberAndroid = createVideoGrabber();


        VideoSource videoSource = peerConnectionFactory.createVideoSource(videoGrabberAndroid);
        localVideoTrack =
                peerConnectionFactory.createVideoTrack("100", videoSource);




        videoGrabberAndroid.startCapture(1000, 1000, 30);

        final VideoRenderer localRenderer = new VideoRenderer(localVideoView);
        localVideoTrack.addRenderer(localRenderer);

        MediaConstraints sdpConstraints = new MediaConstraints();
        sdpConstraints.mandatory.add(new MediaConstraints.KeyValuePair("offerToReceiveVideo", "true"));

        createLocalPeerConnection(sdpConstraints);
        createLocalSocket();

        MediaStream stream = peerConnectionFactory.createLocalMediaStream("PIFXfZsA0IWyPxA3kFprHM6dGzVM9lM6aQjq");
        stream.addTrack(localVideoTrack);
        localPeer.addStream(stream);

        createLocalOffer(sdpConstraints);
    }

    public void createLocalPeerConnection(MediaConstraints sdpConstraints) {
        final List<PeerConnection.IceServer> iceServers = new ArrayList<>();
        PeerConnection.IceServer peerIceServer = PeerConnection.IceServer.builder("turn:XXXXXXX=udp")
                .setUsername("sXXXXXXXXXXXXXXXXXXXXX=")
                .setPassword("XXXXXXXXXXXXXXXXXXXXXX")

                .createIceServer();
        iceServers.add(peerIceServer);

        localPeer = peerConnectionFactory.createPeerConnection(iceServers, sdpConstraints, new CustomPeerConnectionObserver("localPeerCreation") {
            @Override
            public void onIceCandidate(IceCandidate iceCandidate) {
                super.onIceCandidate(iceCandidate);
                try {
                    JSONObject json = new JSONObject();
                    json.put("type", "candidate");
                    json.put("candidate", iceCandidate.sdp);
                    json.put("video_transform", "mask");
                    json.put("exercise_id", "2");

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

    public void createLocalSocket() {
        Request request = new Request.Builder()
                .url(socketAddress)
                .build();
        AsyncHttpURLConnection listener =
                new AsyncHttpURLConnection("POST", socketAddress, localPeer.toString(), new AsyncHttpURLConnection.AsyncHttpEvents() {
                    @Override
                    public void onHttpError(String errorMessage) {
                    }

                    @Override
                    public void onHttpComplete(String response) {

                        try {
                            JSONObject roomJson = new JSONObject(response);
                            String result = roomJson.getString("COMPLETE");
                            ws2.send(roomJson.toString());
                            if (!result.equals("SUCCESS")) {
                            }
                        } catch (JSONException e) {
                            return;
                        }

                    }
                });
        listener.send();
        OkHttpClient.Builder okHttpClientBuilder = new OkHttpClient.Builder();

        webSocket1 = okHttpClientBuilder.build();
        ws1 = webSocket1.newWebSocket(request, listener);
        webSocket1.dispatcher().executorService().shutdown();
    }


    public void call(View view) {
        start_call.setEnabled(false);
        init_call.setEnabled(false);
        end_call.setEnabled(true);

        createRemotePeerConnection();
        createRemoteSocket();
    }

    public void createRemotePeerConnection() {
        final List<PeerConnection.IceServer> iceServers = new ArrayList<>();
        PeerConnection.IceServer
                iceServer = PeerConnection.IceServer.builder("turnXXXXXXX=udp")
                .setUsername("XXXXXXXXXXXXXXXXXXXX")
                .setPassword("XXXXXXXXXXXXXXXXXX")
                .createIceServer();
        iceServers.add(iceServer);

        MediaConstraints sdpConstraints = new MediaConstraints();
        sdpConstraints.mandatory.add(new MediaConstraints.KeyValuePair("offerToReceiveVideo", "true"));
        remotePeer = peerConnectionFactory.createPeerConnection(iceServers, sdpConstraints, new CustomPeerConnectionObserver("remotePeerCreation") {

            @Override
            public void onIceCandidate(IceCandidate iceCandidate) {
                super.onIceCandidate(iceCandidate);
                try {
                    JSONObject json = new JSONObject();
                    json.put("type", "candidate");
                    json.put("id", iceCandidate.sdpMid);
                    json.put("candidate", iceCandidate.sdp);
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
            public void onAddStream(MediaStream mediaStream) {
                super.onAddStream(mediaStream);
                gotRemoteStream(mediaStream);
            }

            @Override
            public void onIceGatheringChange(PeerConnection.IceGatheringState iceGatheringState) {
                super.onIceGatheringChange(iceGatheringState);

            }
        });
    }
    public void createLocalOffer(MediaConstraints sdpConstraints) {
        localPeer.createOffer(new CustomSdpObserver("localCreateOffer") {
            @Override
            public void onCreateSuccess(SessionDescription sessionDescription) {
                super.onCreateSuccess(sessionDescription);
                localPeer.setLocalDescription(new CustomSdpObserver("localSetLocalDesc"), sessionDescription);
                try {
                    Map<String, String> sdp = new HashMap<>();
                    sdp.put("desc", sessionDescription.description);
                    JSONObject json = new JSONObject();
                    json.put("sdp", sessionDescription.description);
                    json.put("type", sessionDescription.type);
                    json.put("video_transform", "mask");
                    json.put("exercise_id", "5");
                    sendPostMessage(MessageType.MESSAGE, socketAddress, sdp.toString());
                    sendPostMessage(MessageType.MESSAGE, socketAddress, json.toString());
                    JSONObject json1 = new JSONObject();
                    json1.put("start", "true");
                    sendPostMessage(MessageType.MESSAGE, socketAddress, json1.toString());
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
        }, sdpConstraints);
    }
    public void createRemoteSocket() {
        Request request = new Request.Builder().url(socketAddress).build();
        AsyncHttpURLConnection listener =
                new AsyncHttpURLConnection("POST", socketAddress, remotePeer.toString(), new AsyncHttpURLConnection.AsyncHttpEvents() {
                    @Override
                    public void onHttpError(String errorMessage) {
                    }

                    @Override
                    public void onHttpComplete(String response) {
                        try {
                            JSONObject roomJson = new JSONObject(response);
                            String result = roomJson.getString("COMPLETE");
                            ws2.send(roomJson.toString());
                            if (!result.equals("SUCCESS")) {
                            }
                        } catch (JSONException e) {
                            return;
                        }

                    }
                });
        listener.send();
        OkHttpClient.Builder okHttpClientBuilder = new OkHttpClient.Builder();
        webSocket2 = okHttpClientBuilder.build();
        ws2 = webSocket2.newWebSocket(request, listener);
        listener.setWebSocket(ws2);
        webSocket2.dispatcher().executorService().shutdown();
    }

    public void hangup(View view) {
        ws1.send("bye");
        ws2.send("bye");
        localPeer.close();
        remotePeer.close();
        localPeer = null;
        remotePeer = null;
        start_call.setEnabled(true);
        init_call.setEnabled(false);
        end_call.setEnabled(false);
    }

    public VideoCapturer createVideoGrabber() {
        VideoCapturer videoCapturer;
        videoCapturer = createCameraGrabber(new Camera1Enumerator(false));
        return videoCapturer;
    }

    public VideoCapturer createCameraGrabber(CameraEnumerator enumerator) {
        final String[] deviceNames = enumerator.getDeviceNames();

        for (String deviceName : deviceNames) {
            if (enumerator.isFrontFacing(deviceName)) {
                VideoCapturer videoCapturer = enumerator.createCapturer(deviceName, null);

                if (videoCapturer != null) {
                    return videoCapturer;
                }
            }
        }

        for (String deviceName : deviceNames) {
            if (!enumerator.isFrontFacing(deviceName)) {
                VideoCapturer videoCapturer = enumerator.createCapturer(deviceName, null);
                if (videoCapturer != null) {
                    return videoCapturer;
                }
            }
        }

        return null;
    }
    private void gotRemoteStream(MediaStream stream) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                try {
                    remoteRenderer = new VideoRenderer(remoteVideoView);
                    remoteVideoView.setVisibility(View.VISIBLE);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }
    private void sendPostMessage(
            final MessageType messageType, final String url, @Nullable final String message) {
        String logInfo = url;
        if (message != null) {
            logInfo += ". Message: " + message;
        }
        Log.d(TAG, "C->GAE: " + logInfo);
        AsyncHttpURLConnection httpConnection =
                new AsyncHttpURLConnection("POST", url, message, new AsyncHttpURLConnection.AsyncHttpEvents() {
                    @Override
                    public void onHttpError(String errorMessage) {
                        Log.d(TAG, "C<-GAE: " + errorMessage);
                    }

                    @Override
                    public void
                    onHttpComplete(String response) {
                        if (messageType == MessageType.MESSAGE) {
                            try {
                                JSONObject roomJson = new JSONObject(response);
                                Log.d(TAG, "C<-GAE: " + roomJson);
                                String result = roomJson.getString("complete");
                                ws2.send(roomJson.toString());
                                if (!result.equals("SUCCESS")) {
                                }
                            } catch (JSONException e) {
                                return;
                            }
                        }
                    }
                });
        httpConnection.send();
    }
}

SDP, который я отправляю:

{   v=0
    o=- 5019693990448584856 2 IN IP4 127.0.0.1
    s=-
    t=0 0
    a=group:BUNDLE video
    a=msid-semantic: WMS PIFXfZsA0IWyPxA3kFprHM6dGzVM9lM6aQjq
    m=video 9 UDP/TLS/RTP/SAVPF 96 97 98 99 100 101 127
    c=IN IP4 0.0.0.0
    a=rtcp:9 IN IP4 0.0.0.0
    a=ice-ufrag:4wF2
    a=ice-pwd:6OUJcsZSraUSzOifM28FUvIX
    a=ice-options:trickle renomination
    a=fingerprint:sha-256 8B:1B:C0:15:96:9B:B2:FA:F5:C7:3E:05:B6:EB:A7:10:A1:85:35:B8:A4:40:E6:54:C1:40:80:EA:1B:8E:12:F0
    a=setup:actpass
    a=mid:video
    a=extmap:2 urn:ietf:params:rtp-hdrext:toffset
    a=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
    a=extmap:4 urn:3gpp:video-orientation
    a=extmap:5 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
    a=extmap:6 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay
    a=extmap:7 http://www.webrtc.org/experiments/rtp-hdrext/video-content-type
    a=extmap:8 http://www.webrtc.org/experiments/rtp-hdrext/video-timing
    a=sendrecv
    a=rtcp-mux
    a=rtcp-rsize
    a=rtpmap:96 VP8/90000
    a=rtcp-fb:96 goog-remb
    a=rtcp-fb:96 transport-cc
    a=rtcp-fb:96 ccm fir
    a=rtcp-fb:96 nack
    a=rtcp-fb:96 nack pli
    a=rtpmap:97 rtx/90000
    a=fmtp:97 apt=96
    a=rtpmap:98 VP9/90000
    a=rtcp-fb:98 goog-remb
    a=rtcp-fb:98 transport-cc
    a=rtcp-fb:98 ccm fir
    a=rtcp-fb:98 nack
    a=rtcp-fb:98 nack pli
    a=rtpmap:99 rtx/90000
    a=fmtp:99 apt=98
    a=rtpmap:100 red/90000
    a=rtpmap:101 rtx/90000
    a=fmtp:101 apt=100
    a=rtpmap:127 ulpfec/90000
    a=ssrc-group:FID 2141423954 286339792
    a=ssrc:2141423954 cname:Ove/zZBrf3D1xV56
    a=ssrc:2141423954 msid:PIFXfZsA0IWyPxA3kFprHM6dGzVM9lM6aQjq 100
    a=ssrc:2141423954 mslabel:PIFXfZsA0IWyPxA3kFprHM6dGzVM9lM6aQjq
    a=ssrc:2141423954 label:100
    a=ssrc:286339792 cname:Ove/zZBrf3D1xV56
    a=ssrc:286339792 msid:PIFXfZsA0IWyPxA3kFprHM6dGzVM9lM6aQjq 100
    a=ssrc:286339792 mslabel:PIFXfZsA0IWyPxA3kFprHM6dGzVM9lM6aQjq
    a=ssrc:286339792 label:100
    }

Ответы (0 шт):