Webrtc
Webrtc
activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.bumptech.glide.Glide;
import com.google.gson.Gson;
import com.idev.entalk.R;
import com.idev.entalk.base.BaseActivity;
import com.idev.entalk.model.CoLearner;
import com.idev.entalk.model.ConnectionStatus;
import com.idev.entalk.utils.Extra;
import com.idev.entalk.utils.Global;
import com.idev.entalk.utils.SimpleObserver;
import com.idev.entalk.utils.SimpleSdpObserver;
import com.idev.entalk.utils.SocketEvent;
import org.json.JSONException;
import org.json.JSONObject;
import org.webrtc.AudioSource;
import org.webrtc.AudioTrack;
import org.webrtc.Camera1Enumerator;
import org.webrtc.CameraEnumerator;
import org.webrtc.DefaultVideoDecoderFactory;
import org.webrtc.DefaultVideoEncoderFactory;
import org.webrtc.EglBase;
import org.webrtc.IceCandidate;
import org.webrtc.MediaConstraints;
import org.webrtc.MediaStream;
import org.webrtc.PeerConnection;
import org.webrtc.PeerConnectionFactory;
import org.webrtc.RtpReceiver;
import org.webrtc.SessionDescription;
import org.webrtc.SurfaceTextureHelper;
import org.webrtc.SurfaceViewRenderer;
import org.webrtc.VideoCapturer;
import org.webrtc.VideoDecoderFactory;
import org.webrtc.VideoEncoderFactory;
import org.webrtc.VideoSource;
import org.webrtc.VideoTrack;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;
import io.socket.client.Socket;
MediaStream localMediaStream;
MediaStream remoteMediaStream;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_calling);
setStatusBarLight();
try{
coLearner = (CoLearner)
getIntent().getExtras().get(Extra.EXTRA_CO_LEARNER);
if (coLearner == null) finish();
}
catch (Exception e){
finish();
}
if (Global.socket != null) {
this.socket = Global.socket;
Global.socket = null;
}
else finish();
statusView = findViewById(R.id.status_view);
profilePhotoView = findViewById(R.id.profile_photo_view);
userNameView = findViewById(R.id.user_name_view);
ratingView = findViewById(R.id.rating_count_view);
timestampView = findViewById(R.id.timestamp_view);
speakerBtn = findViewById(R.id.speaker_btn);
muteBtn = findViewById(R.id.mute_btn);
endBtn = findViewById(R.id.end_btn);
// peer connection
localVideoView = findViewById(R.id.local_rand);
remoteVideoView = findViewById(R.id.remote_rand);
rootEglBase = EglBase.create();
initVideos();
peerIceServers = getIceServers();
peerConnectionFactory = getPeerConnectionFactory();
startPeerConnectionCalling();
speakerBtn.setSelected(true);
muteBtn.setSelected(true);
muteBtn.setOnClickListener(view -> {
muteBtn.setSelected(!muteBtn.isSelected());
onVoiceSettingChange();
});
speakerBtn.setOnClickListener(view -> {
speakerBtn.setSelected(!speakerBtn.isSelected());
onVoiceSettingChange();
});
AtomicBoolean isClicked = new AtomicBoolean(false);
endBtn.setOnClickListener(view -> {
// if (isClicked.get()) return;
// isClicked.set(true);
// closeVoiceConversion(2000);
doCall();
});
updateUI();
startTimestampIncrease();
startVoiceConversion();
}
int timestamp = 0;
private void startTimestampIncrease() {
Handler handler = new Handler();
Runnable runnable = new Runnable() {
@Override
public void run() {
timestamp++;
int min = timestamp < 60 ? 0 : timestamp/60;
int sec = timestamp < 60 ? timestamp : timestamp - (min*60);
onTimestampChanged(min, sec);
handler.postDelayed((Runnable) this, 1000);
}
};
handler.postDelayed(runnable, 1000);
}
// signaling client
socket.on(SocketEvent.EVENT_SIGNAL_CALL_RECEIVED, args -> {
JSONObject s = (JSONObject) args[0];
if (s != null) runOnUiThread(()-> onOfferReceived(s));
});
socket.on(SocketEvent.EVENT_SIGNAL_ANSWER_RECEIVED, args -> {
JSONObject jsonObject = (JSONObject) args[0];
runOnUiThread(()-> onAnswerReceived(jsonObject));
});
socket.on(SocketEvent.EVENT_SIGNAL_ICE_CANDIDATE_RECEIVED, args -> {
JSONObject s = (JSONObject) args[0];
if (s != null) runOnUiThread(()-> onIceCandidateReceived(s));
});
}
private void onConnectionStatusChanged(ConnectionStatus status, boolean isMe){
if (status != null) return;
if (ConnectionStatus.RECONNECTED.equals(status.getConnection())){
statusView.setVisibility(View.INVISIBLE);
return;
}
if (statusView.getVisibility() != View.VISIBLE){
statusView.setVisibility(View.VISIBLE);
}
if (Objects.equals(status.getConnection(), ConnectionStatus.DISCONNECTED)){
statusView.setText("Disconnected");
}
else if (Objects.equals(status.getConnection(),
ConnectionStatus.RECONNECTING)){
statusView.setText("Reconnecting...");
}
else if (Objects.equals(status.getConnection(), ConnectionStatus.END)){
closeVoiceConversion(2000);
statusView.setText("End");
}
else statusView.setText(status.getConnection());
}
// @Override
// public void onBackPressed() {
//
// }
localMediaStream = peerConnectionFactory.createLocalMediaStream("102");
VideoSource videoSource;
AudioSource audioSource;
cameraCapture.initialize(SurfaceTextureHelper.create("SurfaceTextureHelper",
rootEglBase.getEglBaseContext()), this, videoSource.getCapturerObserver());
localVideoTrack = peerConnectionFactory.createVideoTrack("100",
videoSource);
cameraCapture.startCapture(1024, 720, 30);
localMediaStream.addTrack(localVideoTrack);
}
localVideoView.setMirror(true);
remoteVideoView.setMirror(true);
gotUserMedia = true;
createPeerConnection();
}
@NonNull
private List<PeerConnection.IceServer> getIceServers() {
List<PeerConnection.IceServer> iceServers = new ArrayList<>();
PeerConnection.IceServer.Builder iceServerBuilder =
PeerConnection.IceServer.builder("stun:stun1.l.google.com:19302");
iceServerBuilder.setTlsCertPolicy(PeerConnection.TlsCertPolicy.TLS_CERT_POLICY_INSE
CURE_NO_CHECK); //this does the magic.
PeerConnection.IceServer iceServer = iceServerBuilder.createIceServer();
iceServers.add(iceServer);
return iceServers;
}
@Override
public void onAddTrack(RtpReceiver receiver, MediaStream[]
mediaStreams) {
super.onAddTrack(receiver, mediaStreams);
if (mediaStreams.length == 0) return;
onRemoteMediaStream(mediaStreams[0]);
}
});
addStreamToLocalPeer();
}
if (mediaStream.audioTracks.size() != 0){
mediaStream.audioTracks.get(0).setEnabled(true);
}
if (mediaStream.videoTracks.size() != 0){
mediaStream.videoTracks.get(0).addSink(remoteVideoView);
}
}
// stream to other
// 100, 101 is media stream id/label
peerConnection.addTrack(localVideoTrack, Arrays.asList("100"));
peerConnection.addTrack(localAudioTrack, Arrays.asList("101"));
}
@Nullable
private VideoCapturer createCameraCapture(@NonNull CameraEnumerator enumerator)
{
String[] deviceNames = enumerator.getDeviceNames();
//find the front facing camera and return it.
for (String name : deviceNames){
if (enumerator.isFrontFacing(name)){
VideoCapturer videoCapturer = enumerator.createCapturer(name,
null);
if (videoCapturer != null){
return videoCapturer;
}
}
}
@Override
public void onCreateFailure(String s) {
super.onCreateFailure(s);
}
}, sdpConstraints);
}
try {
SessionDescription sd = new
SessionDescription(SessionDescription.Type.OFFER, data.getString("sdp"));
peerConnection.setRemoteDescription(new SimpleSdpObserver(), sd);
}
catch (JSONException e){
e.printStackTrace();
}
// do answer
doAnswer();
}
@Override
public void onCreateFailure(String s) {
super.onCreateFailure(s);
}
}, createSDPMediaConstraints());
}