mirror of
https://github.com/nextcloud/talk-android
synced 2025-06-19 11:39:42 +01:00
Some work
Signed-off-by: Mario Danic <mario@lovelyhq.com>
This commit is contained in:
parent
526e4d1f9e
commit
f26c38444b
@ -20,21 +20,39 @@
|
||||
|
||||
package com.nextcloud.talk.activities;
|
||||
|
||||
import android.Manifest;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import com.bluelinelabs.conductor.Conductor;
|
||||
import com.bluelinelabs.conductor.Router;
|
||||
import com.bluelinelabs.conductor.RouterTransaction;
|
||||
import com.bluelinelabs.conductor.changehandler.SimpleSwapChangeHandler;
|
||||
import com.gun0912.tedpermission.PermissionListener;
|
||||
import com.gun0912.tedpermission.TedPermission;
|
||||
import com.nextcloud.talk.R;
|
||||
import com.nextcloud.talk.application.NextcloudTalkApplication;
|
||||
import com.nextcloud.talk.controllers.CallController;
|
||||
import com.nextcloud.talk.utils.bundle.BundleBuilder;
|
||||
import com.nextcloud.talk.webrtc.MagicPeerConnectionObserver;
|
||||
import com.nextcloud.talk.webrtc.MagicSdpObserver;
|
||||
|
||||
import org.webrtc.AudioSource;
|
||||
import org.webrtc.AudioTrack;
|
||||
import org.webrtc.Camera1Enumerator;
|
||||
import org.webrtc.CameraEnumerator;
|
||||
import org.webrtc.IceCandidate;
|
||||
import org.webrtc.Logging;
|
||||
import org.webrtc.MediaConstraints;
|
||||
import org.webrtc.MediaStream;
|
||||
import org.webrtc.PeerConnection;
|
||||
import org.webrtc.PeerConnectionFactory;
|
||||
import org.webrtc.SessionDescription;
|
||||
import org.webrtc.SurfaceViewRenderer;
|
||||
import org.webrtc.VideoCapturer;
|
||||
import org.webrtc.VideoRenderer;
|
||||
import org.webrtc.VideoSource;
|
||||
import org.webrtc.VideoTrack;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import autodagger.AutoInjector;
|
||||
import butterknife.BindView;
|
||||
@ -44,14 +62,29 @@ import butterknife.ButterKnife;
|
||||
public class CallActivity extends AppCompatActivity {
|
||||
private static final String TAG = "CallActivity";
|
||||
|
||||
@BindView(R.id.controller_container)
|
||||
ViewGroup container;
|
||||
@BindView(R.id.pip_video_view)
|
||||
SurfaceViewRenderer pipVideoView;
|
||||
|
||||
private Router router;
|
||||
@BindView(R.id.fullscreen_video_view)
|
||||
SurfaceViewRenderer fullScreenVideoView;
|
||||
|
||||
private String roomToken;
|
||||
private String userDisplayName;
|
||||
|
||||
PeerConnectionFactory peerConnectionFactory;
|
||||
MediaConstraints audioConstraints;
|
||||
MediaConstraints videoConstraints;
|
||||
MediaConstraints sdpConstraints;
|
||||
VideoSource videoSource;
|
||||
VideoTrack localVideoTrack;
|
||||
AudioSource audioSource;
|
||||
AudioTrack localAudioTrack;
|
||||
|
||||
VideoRenderer localRenderer;
|
||||
VideoRenderer remoteRenderer;
|
||||
|
||||
PeerConnection localPeer, remotePeer;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
@ -70,26 +103,221 @@ public class CallActivity extends AppCompatActivity {
|
||||
roomToken = getIntent().getExtras().getString("roomToken", "");
|
||||
userDisplayName = getIntent().getExtras().getString("userDisplayName", "");
|
||||
|
||||
router = Conductor.attachRouter(this, container, savedInstanceState);
|
||||
|
||||
if (!router.hasRootController()) {
|
||||
BundleBuilder bundleBuilder = new BundleBuilder(new Bundle());
|
||||
bundleBuilder.putString("roomToken", roomToken);
|
||||
bundleBuilder.putString("userDisplayName", userDisplayName);
|
||||
PermissionListener permissionlistener = new PermissionListener() {
|
||||
@Override
|
||||
public void onPermissionGranted() {
|
||||
start();
|
||||
call();
|
||||
}
|
||||
|
||||
router.setRoot(RouterTransaction.with(new CallController(bundleBuilder.build()))
|
||||
.popChangeHandler(new SimpleSwapChangeHandler())
|
||||
.pushChangeHandler((new SimpleSwapChangeHandler())));
|
||||
@Override
|
||||
public void onPermissionDenied(ArrayList<String> deniedPermissions) {
|
||||
}
|
||||
};
|
||||
|
||||
TedPermission.with(this)
|
||||
.setPermissionListener(permissionlistener)
|
||||
.setDeniedMessage("If you reject permission,you can not use this service\n\nPlease turn on permissions at [Setting] > [Permission]")
|
||||
.setPermissions(android.Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO,
|
||||
Manifest.permission.MODIFY_AUDIO_SETTINGS, Manifest.permission.ACCESS_NETWORK_STATE,
|
||||
Manifest.permission.ACCESS_WIFI_STATE, Manifest.permission.INTERNET)
|
||||
.check();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private VideoCapturer createVideoCapturer() {
|
||||
VideoCapturer videoCapturer;
|
||||
videoCapturer = createCameraCapturer(new Camera1Enumerator(false));
|
||||
return videoCapturer;
|
||||
}
|
||||
|
||||
private VideoCapturer createCameraCapturer(CameraEnumerator enumerator) {
|
||||
final String[] deviceNames = enumerator.getDeviceNames();
|
||||
|
||||
// First, try to find front facing camera
|
||||
Logging.d(TAG, "Looking for front facing cameras.");
|
||||
for (String deviceName : deviceNames) {
|
||||
if (enumerator.isFrontFacing(deviceName)) {
|
||||
Logging.d(TAG, "Creating front facing camera capturer.");
|
||||
VideoCapturer videoCapturer = enumerator.createCapturer(deviceName, null);
|
||||
|
||||
if (videoCapturer != null) {
|
||||
return videoCapturer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Front facing camera not found, try something else
|
||||
Logging.d(TAG, "Looking for other cameras.");
|
||||
for (String deviceName : deviceNames) {
|
||||
if (!enumerator.isFrontFacing(deviceName)) {
|
||||
Logging.d(TAG, "Creating other camera capturer.");
|
||||
VideoCapturer videoCapturer = enumerator.createCapturer(deviceName, null);
|
||||
|
||||
if (videoCapturer != null) {
|
||||
return videoCapturer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void start() {
|
||||
//Initialize PeerConnectionFactory globals.
|
||||
//Params are context, initAudio,initVideo and videoCodecHwAcceleration
|
||||
PeerConnectionFactory.initializeAndroidGlobals(this, true, true,
|
||||
false);
|
||||
|
||||
//Create a new PeerConnectionFactory instance.
|
||||
PeerConnectionFactory.Options options = new PeerConnectionFactory.Options();
|
||||
peerConnectionFactory = new PeerConnectionFactory(options);
|
||||
|
||||
//Now create a VideoCapturer instance. Callback methods are there if you want to do something! Duh!
|
||||
VideoCapturer videoCapturerAndroid = createVideoCapturer();
|
||||
|
||||
//Create MediaConstraints - Will be useful for specifying video and audio constraints.
|
||||
audioConstraints = new MediaConstraints();
|
||||
videoConstraints = new MediaConstraints();
|
||||
|
||||
//Create a VideoSource instance
|
||||
videoSource = peerConnectionFactory.createVideoSource(videoCapturerAndroid);
|
||||
localVideoTrack = peerConnectionFactory.createVideoTrack("100", videoSource);
|
||||
|
||||
//create an AudioSource instance
|
||||
audioSource = peerConnectionFactory.createAudioSource(audioConstraints);
|
||||
localAudioTrack = peerConnectionFactory.createAudioTrack("101", audioSource);
|
||||
|
||||
//create a videoRenderer based on SurfaceViewRenderer instance
|
||||
localRenderer = new VideoRenderer(pipVideoView);
|
||||
// And finally, with our VideoRenderer ready, we
|
||||
// can add our renderer to the VideoTrack.
|
||||
localVideoTrack.addRenderer(localRenderer);
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void call() {
|
||||
//we already have video and audio tracks. Now create peerconnections
|
||||
List<PeerConnection.IceServer> iceServers = new ArrayList<>();
|
||||
iceServers.add(new PeerConnection.IceServer("stun:stun.nextcloud.com:443"));
|
||||
|
||||
//create sdpConstraints
|
||||
sdpConstraints = new MediaConstraints();
|
||||
sdpConstraints.mandatory.add(new MediaConstraints.KeyValuePair("offerToReceiveAudio", "true"));
|
||||
sdpConstraints.mandatory.add(new MediaConstraints.KeyValuePair("offerToReceiveVideo", "true"));
|
||||
sdpConstraints.optional.add(new MediaConstraints.KeyValuePair("internalSctpDataChannels", "true"));
|
||||
sdpConstraints.optional.add(new MediaConstraints.KeyValuePair("DtlsSrtpKeyAgreement", "true"));
|
||||
|
||||
//creating localPeer
|
||||
localPeer = peerConnectionFactory.createPeerConnection(iceServers, sdpConstraints,
|
||||
new MagicPeerConnectionObserver() {
|
||||
@Override
|
||||
public void onIceCandidate(IceCandidate iceCandidate) {
|
||||
super.onIceCandidate(iceCandidate);
|
||||
onIceCandidateReceived(localPeer, iceCandidate);
|
||||
}
|
||||
});
|
||||
|
||||
//creating remotePeer
|
||||
remotePeer = peerConnectionFactory.createPeerConnection(iceServers, sdpConstraints,
|
||||
new MagicPeerConnectionObserver() {
|
||||
|
||||
@Override
|
||||
public void onIceCandidate(IceCandidate iceCandidate) {
|
||||
super.onIceCandidate(iceCandidate);
|
||||
onIceCandidateReceived(remotePeer, iceCandidate);
|
||||
}
|
||||
|
||||
public void onAddStream(MediaStream mediaStream) {
|
||||
super.onAddStream(mediaStream);
|
||||
gotRemoteStream(mediaStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onIceGatheringChange(PeerConnection.IceGatheringState iceGatheringState) {
|
||||
super.onIceGatheringChange(iceGatheringState);
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
//creating local mediastream
|
||||
MediaStream stream = peerConnectionFactory.createLocalMediaStream("102");
|
||||
stream.addTrack(localAudioTrack);
|
||||
stream.addTrack(localVideoTrack);
|
||||
localPeer.addStream(stream);
|
||||
|
||||
//creating Offer
|
||||
localPeer.createOffer(new MagicSdpObserver(){
|
||||
@Override
|
||||
public void onCreateSuccess(SessionDescription sessionDescription) {
|
||||
//we have localOffer. Set it as local desc for localpeer and remote desc for remote peer.
|
||||
//try to create answer from the remote peer.
|
||||
super.onCreateSuccess(sessionDescription);
|
||||
localPeer.setLocalDescription(new MagicSdpObserver(), sessionDescription);
|
||||
remotePeer.setRemoteDescription(new MagicSdpObserver(), sessionDescription);
|
||||
remotePeer.createAnswer(new MagicSdpObserver() {
|
||||
@Override
|
||||
public void onCreateSuccess(SessionDescription sessionDescription) {
|
||||
//remote answer generated. Now set it as local desc for remote peer and remote desc for local peer.
|
||||
super.onCreateSuccess(sessionDescription);
|
||||
remotePeer.setLocalDescription(new MagicSdpObserver(), sessionDescription);
|
||||
localPeer.setRemoteDescription(new MagicSdpObserver(), sessionDescription);
|
||||
|
||||
}
|
||||
},new MediaConstraints());
|
||||
}
|
||||
},sdpConstraints);
|
||||
}
|
||||
|
||||
|
||||
private void hangup() {
|
||||
if (localPeer != null) {
|
||||
localPeer.close();
|
||||
localPeer = null;
|
||||
}
|
||||
|
||||
if (remotePeer != null) {
|
||||
remotePeer.close();
|
||||
remotePeer = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void gotRemoteStream(MediaStream stream) {
|
||||
//we have remote video stream. add to the renderer.
|
||||
final VideoTrack videoTrack = stream.videoTracks.getFirst();
|
||||
AudioTrack audioTrack = stream.audioTracks.getFirst();
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
remoteRenderer = new VideoRenderer(fullScreenVideoView);
|
||||
videoTrack.addRenderer(remoteRenderer);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public void onIceCandidateReceived(PeerConnection peer, IceCandidate iceCandidate) {
|
||||
//we have received ice candidate. We can set it to the other peer.
|
||||
if (peer == localPeer) {
|
||||
remotePeer.addIceCandidate(iceCandidate);
|
||||
} else {
|
||||
localPeer.addIceCandidate(iceCandidate);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
if (!router.handleBack()) {
|
||||
super.onBackPressed();
|
||||
}
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
hangup();
|
||||
}
|
||||
|
||||
private static int getSystemUiVisibility() {
|
||||
int flags = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN;
|
||||
flags |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
|
||||
|
Loading…
Reference in New Issue
Block a user