mirror of
https://github.com/nextcloud/talk-android
synced 2025-06-19 19:49:33 +01:00
Reworked UI & Voice-only calls
Signed-off-by: Mario Danic <mario@lovelyhq.com>
This commit is contained in:
parent
1922673974
commit
f2aee50a74
@ -198,10 +198,12 @@ public class CallActivity extends AppCompatActivity {
|
||||
private String credentials;
|
||||
private List<MagicPeerConnectionWrapper> magicPeerConnectionWrapperList = new ArrayList<>();
|
||||
|
||||
private List<String> basicUISetupList = new ArrayList<>();
|
||||
private boolean videoOn = false;
|
||||
private boolean audioOn = false;
|
||||
|
||||
private boolean isMultiSession = false;
|
||||
private boolean isVoiceOnlyCall = false;
|
||||
|
||||
private Handler handler = new Handler();
|
||||
|
||||
@ -211,8 +213,6 @@ public class CallActivity extends AppCompatActivity {
|
||||
|
||||
private String baseUrl;
|
||||
|
||||
private boolean initialPermissionsCheck = true;
|
||||
|
||||
private SpotlightView spotlightView;
|
||||
|
||||
private static int getSystemUiVisibility() {
|
||||
@ -249,6 +249,7 @@ public class CallActivity extends AppCompatActivity {
|
||||
userEntity = Parcels.unwrap(getIntent().getExtras().getParcelable(BundleKeys.KEY_USER_ENTITY));
|
||||
callSession = getIntent().getExtras().getString(BundleKeys.KEY_CALL_SESSION, "0");
|
||||
credentials = ApiUtils.getCredentials(userEntity.getUsername(), userEntity.getToken());
|
||||
isVoiceOnlyCall = getIntent().getExtras().getBoolean(BundleKeys.KEY_CALL_VOICE_ONLY, false);
|
||||
|
||||
if (getIntent().getExtras().containsKey(BundleKeys.KEY_MODIFIED_BASE_URL)) {
|
||||
credentials = null;
|
||||
@ -442,6 +443,10 @@ public class CallActivity extends AppCompatActivity {
|
||||
toggleMedia(true, false);
|
||||
}
|
||||
|
||||
if (isVoiceOnlyCall && !inCall) {
|
||||
startCall();
|
||||
}
|
||||
|
||||
} else if (EffortlessPermissions.somePermissionPermanentlyDenied(this, PERMISSIONS_MICROPHONE)) {
|
||||
// Microphone permission is permanently denied so we cannot request it normally.
|
||||
OpenAppDetailsDialogFragment.show(
|
||||
@ -547,29 +552,39 @@ public class CallActivity extends AppCompatActivity {
|
||||
}
|
||||
|
||||
public void initViews() {
|
||||
if (cameraEnumerator.getDeviceNames().length < 2) {
|
||||
if (isVoiceOnlyCall) {
|
||||
cameraSwitchButton.setVisibility(View.GONE);
|
||||
}
|
||||
cameraControlButton.setVisibility(View.GONE);
|
||||
pipVideoView.setVisibility(View.GONE);
|
||||
} else {
|
||||
if (cameraEnumerator.getDeviceNames().length < 2) {
|
||||
cameraSwitchButton.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
// setting this to true because it's not shown by default
|
||||
pipVideoView.setMirror(true);
|
||||
pipVideoView.init(rootEglBase.getEglBaseContext(), null);
|
||||
pipVideoView.setZOrderMediaOverlay(true);
|
||||
// disabled because it causes some devices to crash
|
||||
pipVideoView.setEnableHardwareScaler(false);
|
||||
pipVideoView.setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_FIT);
|
||||
// setting this to true because it's not shown by default
|
||||
pipVideoView.setMirror(true);
|
||||
pipVideoView.init(rootEglBase.getEglBaseContext(), null);
|
||||
pipVideoView.setZOrderMediaOverlay(true);
|
||||
// disabled because it causes some devices to crash
|
||||
pipVideoView.setEnableHardwareScaler(false);
|
||||
pipVideoView.setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_FIT);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkPermissions() {
|
||||
EffortlessPermissions.requestPermissions(this, R.string.nc_permissions,
|
||||
R.string.nc_proceed, R.string.nc_empty, 100, PERMISSIONS_CALL);
|
||||
if (isVoiceOnlyCall) {
|
||||
onMicrophoneClick();
|
||||
} else {
|
||||
EffortlessPermissions.requestPermissions(this, R.string.nc_permissions,
|
||||
R.string.nc_proceed, R.string.nc_empty, 100, PERMISSIONS_CALL);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@AfterPermissionGranted(100)
|
||||
private void onPermissionsGranted() {
|
||||
if (EffortlessPermissions.hasPermissions(this, PERMISSIONS_CALL)) {
|
||||
if (!videoOn && !initialPermissionsCheck) {
|
||||
if (!videoOn && !isVoiceOnlyCall) {
|
||||
onCameraClick();
|
||||
}
|
||||
|
||||
@ -577,15 +592,13 @@ public class CallActivity extends AppCompatActivity {
|
||||
onMicrophoneClick();
|
||||
}
|
||||
|
||||
if (cameraEnumerator.getDeviceNames().length == 0) {
|
||||
cameraControlButton.setVisibility(View.GONE);
|
||||
}
|
||||
if (!isVoiceOnlyCall) {
|
||||
if (cameraEnumerator.getDeviceNames().length == 0) {
|
||||
cameraControlButton.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
if (cameraEnumerator.getDeviceNames().length > 1) {
|
||||
if (!initialPermissionsCheck) {
|
||||
if (cameraEnumerator.getDeviceNames().length > 1) {
|
||||
cameraSwitchButton.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
cameraSwitchButton.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -597,26 +610,27 @@ public class CallActivity extends AppCompatActivity {
|
||||
checkIfSomeAreApproved();
|
||||
}
|
||||
|
||||
initialPermissionsCheck = false;
|
||||
}
|
||||
|
||||
private void checkIfSomeAreApproved() {
|
||||
if (cameraEnumerator.getDeviceNames().length == 0) {
|
||||
cameraControlButton.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
if (cameraEnumerator.getDeviceNames().length > 1) {
|
||||
cameraSwitchButton.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
if (EffortlessPermissions.hasPermissions(this, PERMISSIONS_CAMERA) && !initialPermissionsCheck) {
|
||||
if (!videoOn) {
|
||||
onCameraClick();
|
||||
if (!isVoiceOnlyCall) {
|
||||
if (cameraEnumerator.getDeviceNames().length == 0) {
|
||||
cameraControlButton.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
if (cameraEnumerator.getDeviceNames().length > 1) {
|
||||
cameraSwitchButton.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
if (EffortlessPermissions.hasPermissions(this, PERMISSIONS_CAMERA)) {
|
||||
if (!videoOn) {
|
||||
onCameraClick();
|
||||
}
|
||||
} else {
|
||||
cameraControlButton.getFrontImageView().setImageResource(R.drawable.ic_videocam_off_white_24px);
|
||||
cameraControlButton.setAlpha(0.7f);
|
||||
cameraSwitchButton.setVisibility(View.GONE);
|
||||
}
|
||||
} else {
|
||||
cameraControlButton.getFrontImageView().setImageResource(R.drawable.ic_videocam_off_white_24px);
|
||||
cameraControlButton.setAlpha(0.7f);
|
||||
cameraSwitchButton.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
if (EffortlessPermissions.hasPermissions(this, PERMISSIONS_MICROPHONE)) {
|
||||
@ -634,11 +648,12 @@ public class CallActivity extends AppCompatActivity {
|
||||
|
||||
@AfterPermissionDenied(100)
|
||||
private void onPermissionsDenied() {
|
||||
initialPermissionsCheck = false;
|
||||
if (cameraEnumerator.getDeviceNames().length == 0) {
|
||||
cameraControlButton.setVisibility(View.GONE);
|
||||
} else if (cameraEnumerator.getDeviceNames().length == 1) {
|
||||
cameraSwitchButton.setVisibility(View.GONE);
|
||||
if (!isVoiceOnlyCall) {
|
||||
if (cameraEnumerator.getDeviceNames().length == 0) {
|
||||
cameraControlButton.setVisibility(View.GONE);
|
||||
} else if (cameraEnumerator.getDeviceNames().length == 1) {
|
||||
cameraSwitchButton.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
if (EffortlessPermissions.hasPermissions(this, PERMISSIONS_CAMERA) ||
|
||||
@ -685,11 +700,20 @@ public class CallActivity extends AppCompatActivity {
|
||||
//create sdpConstraints
|
||||
sdpConstraints = new MediaConstraints();
|
||||
sdpConstraints.mandatory.add(new MediaConstraints.KeyValuePair("OfferToReceiveAudio", "true"));
|
||||
sdpConstraints.mandatory.add(new MediaConstraints.KeyValuePair("OfferToReceiveVideo", "true"));
|
||||
String offerToReceiveVideoString = "true";
|
||||
|
||||
if (isVoiceOnlyCall) {
|
||||
offerToReceiveVideoString = "false";
|
||||
}
|
||||
|
||||
sdpConstraints.mandatory.add(new MediaConstraints.KeyValuePair("OfferToReceiveVideo",
|
||||
offerToReceiveVideoString));
|
||||
sdpConstraints.optional.add(new MediaConstraints.KeyValuePair("internalSctpDataChannels", "true"));
|
||||
sdpConstraints.optional.add(new MediaConstraints.KeyValuePair("DtlsSrtpKeyAgreement", "true"));
|
||||
|
||||
cameraInitialization();
|
||||
if (!isVoiceOnlyCall) {
|
||||
cameraInitialization();
|
||||
}
|
||||
microphoneInitialization();
|
||||
}
|
||||
|
||||
@ -1163,31 +1187,7 @@ public class CallActivity extends AppCompatActivity {
|
||||
|
||||
@Override
|
||||
public void onNext(GenericOverall genericOverall) {
|
||||
ncApi.leaveRoom(credentials, ApiUtils.getUrlForRoomParticipants(baseUrl, roomToken))
|
||||
.subscribeOn(Schedulers.newThread())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new Observer<GenericOverall>() {
|
||||
@Override
|
||||
public void onSubscribe(Disposable d) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNext(GenericOverall genericOverall) {
|
||||
finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable e) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onComplete() {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -1214,8 +1214,19 @@ public class CallActivity extends AppCompatActivity {
|
||||
RelativeLayout relativeLayout = remoteRenderersLayout.findViewWithTag(sessionId);
|
||||
if (relativeLayout != null) {
|
||||
ImageView imageView;
|
||||
ImageView avatarImageView = relativeLayout.findViewById(R.id.avatarImageView);
|
||||
SurfaceViewRenderer surfaceViewRenderer = relativeLayout.findViewById(R.id.surface_view);
|
||||
|
||||
if (video) {
|
||||
imageView = relativeLayout.findViewById(R.id.remote_video_off);
|
||||
|
||||
if (change) {
|
||||
avatarImageView.setVisibility(View.INVISIBLE);
|
||||
surfaceViewRenderer.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
avatarImageView.setVisibility(View.VISIBLE);
|
||||
surfaceViewRenderer.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
} else {
|
||||
imageView = relativeLayout.findViewById(R.id.remote_audio_off);
|
||||
}
|
||||
@ -1228,14 +1239,12 @@ public class CallActivity extends AppCompatActivity {
|
||||
}
|
||||
}
|
||||
|
||||
private void gotRemoteStream(MediaStream stream, String session) {
|
||||
removeMediaStream(session);
|
||||
|
||||
if (stream.videoTracks.size() == 1) {
|
||||
VideoTrack videoTrack = stream.videoTracks.get(0);
|
||||
try {
|
||||
private void setupNewPeerLayout(String session) {
|
||||
if (remoteRenderersLayout.findViewWithTag(session) == null) {
|
||||
basicUISetupList.add(session);
|
||||
runOnUiThread(() -> {
|
||||
RelativeLayout relativeLayout = (RelativeLayout)
|
||||
getLayoutInflater().inflate(R.layout.surface_renderer, remoteRenderersLayout,
|
||||
getLayoutInflater().inflate(R.layout.call_item, remoteRenderersLayout,
|
||||
false);
|
||||
relativeLayout.setTag(session);
|
||||
SurfaceViewRenderer surfaceViewRenderer = relativeLayout.findViewById(R.id
|
||||
@ -1247,12 +1256,40 @@ public class CallActivity extends AppCompatActivity {
|
||||
surfaceViewRenderer.setEnableHardwareScaler(false);
|
||||
surfaceViewRenderer.setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_FIT);
|
||||
surfaceViewRenderer.setOnClickListener(videoOnClickListener);
|
||||
VideoRenderer remoteRenderer = new VideoRenderer(surfaceViewRenderer);
|
||||
videoTrack.addRenderer(remoteRenderer);
|
||||
remoteRenderersLayout.addView(relativeLayout);
|
||||
gotNick(session, getPeerConnectionWrapperForSessionId(session).getNick());
|
||||
} catch (Exception e) {
|
||||
Log.d(TAG, "Failed to create a new video view");
|
||||
|
||||
basicUISetupList.remove(session);
|
||||
callControls.setZ(100.0f);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void setupVideoStreamForLayout(@Nullable MediaStream mediaStream, String session, boolean enable) {
|
||||
boolean isInitialLayoutSetupForPeer = false;
|
||||
if (remoteRenderersLayout.findViewWithTag(session) == null) {
|
||||
setupNewPeerLayout(session);
|
||||
isInitialLayoutSetupForPeer = true;
|
||||
}
|
||||
|
||||
RelativeLayout relativeLayout = remoteRenderersLayout.findViewWithTag(session);
|
||||
SurfaceViewRenderer surfaceViewRenderer = relativeLayout.findViewById(R.id.surface_view);
|
||||
ImageView imageView = relativeLayout.findViewById(R.id.avatarImageView);
|
||||
|
||||
if (mediaStream != null && mediaStream.videoTracks != null && mediaStream.videoTracks.size() > 0 && enable) {
|
||||
VideoTrack videoTrack = mediaStream.videoTracks.get(0);
|
||||
|
||||
VideoRenderer remoteRenderer = new VideoRenderer(surfaceViewRenderer);
|
||||
videoTrack.addRenderer(remoteRenderer);
|
||||
|
||||
imageView.setVisibility(View.INVISIBLE);
|
||||
surfaceViewRenderer.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
imageView.setVisibility(View.VISIBLE);
|
||||
surfaceViewRenderer.setVisibility(View.INVISIBLE);
|
||||
|
||||
if (isInitialLayoutSetupForPeer && isVoiceOnlyCall) {
|
||||
gotAudioOrVideoChange(true, session, false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1310,8 +1347,8 @@ public class CallActivity extends AppCompatActivity {
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.BACKGROUND)
|
||||
public void onMessageEvent(PeerConnectionEvent peerConnectionEvent) {
|
||||
if (peerConnectionEvent.getPeerConnectionEventType().equals(PeerConnectionEvent.PeerConnectionEventType
|
||||
.CLOSE_PEER)) {
|
||||
if (peerConnectionEvent.getPeerConnectionEventType().equals(PeerConnectionEvent.PeerConnectionEventType
|
||||
.PEER_CLOSED)) {
|
||||
endPeerConnection(peerConnectionEvent.getSessionId());
|
||||
} else if (peerConnectionEvent.getPeerConnectionEventType().equals(PeerConnectionEvent
|
||||
.PeerConnectionEventType.SENSOR_FAR) ||
|
||||
@ -1327,7 +1364,7 @@ public class CallActivity extends AppCompatActivity {
|
||||
.PeerConnectionEventType.NICK_CHANGE)) {
|
||||
runOnUiThread(() -> gotNick(peerConnectionEvent.getSessionId(), peerConnectionEvent.getNick()));
|
||||
} else if (peerConnectionEvent.getPeerConnectionEventType().equals(PeerConnectionEvent
|
||||
.PeerConnectionEventType.VIDEO_CHANGE)) {
|
||||
.PeerConnectionEventType.VIDEO_CHANGE) && !isVoiceOnlyCall) {
|
||||
runOnUiThread(() -> gotAudioOrVideoChange(true, peerConnectionEvent.getSessionId(),
|
||||
peerConnectionEvent.getChangeValue()));
|
||||
} else if (peerConnectionEvent.getPeerConnectionEventType().equals(PeerConnectionEvent
|
||||
@ -1362,9 +1399,11 @@ public class CallActivity extends AppCompatActivity {
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onMessageEvent(MediaStreamEvent mediaStreamEvent) {
|
||||
if (mediaStreamEvent.getMediaStream() != null) {
|
||||
gotRemoteStream(mediaStreamEvent.getMediaStream(), mediaStreamEvent.getSession());
|
||||
setupVideoStreamForLayout(mediaStreamEvent.getMediaStream(), mediaStreamEvent.getSession(),
|
||||
mediaStreamEvent.getMediaStream().videoTracks != null
|
||||
&& mediaStreamEvent.getMediaStream().videoTracks.size() > 0);
|
||||
} else {
|
||||
removeMediaStream(mediaStreamEvent.getSession());
|
||||
setupVideoStreamForLayout(null, mediaStreamEvent.getSession(), false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,6 +40,6 @@ public class PeerConnectionEvent {
|
||||
}
|
||||
|
||||
public enum PeerConnectionEventType {
|
||||
CLOSE_PEER, SENSOR_FAR, SENSOR_NEAR, NICK_CHANGE, AUDIO_CHANGE, VIDEO_CHANGE
|
||||
PEER_CONNECTED, PEER_CLOSED, SENSOR_FAR, SENSOR_NEAR, NICK_CHANGE, AUDIO_CHANGE, VIDEO_CHANGE
|
||||
}
|
||||
}
|
||||
|
@ -55,6 +55,7 @@ public class MagicPeerConnectionWrapper {
|
||||
private PeerConnection peerConnection;
|
||||
private String sessionId;
|
||||
private String nick;
|
||||
private String userId;
|
||||
private MediaConstraints mediaConstraints;
|
||||
private DataChannel magicDataChannel;
|
||||
private MagicSdpObserver magicSdpObserver;
|
||||
@ -248,11 +249,15 @@ public class MagicPeerConnectionWrapper {
|
||||
|
||||
@Override
|
||||
public void onIceConnectionChange(PeerConnection.IceConnectionState iceConnectionState) {
|
||||
if (iceConnectionState.equals(PeerConnection.IceConnectionState.CONNECTED) && hasInitiated) {
|
||||
sendInitialMediaStatus();
|
||||
if (iceConnectionState.equals(PeerConnection.IceConnectionState.CONNECTED)) {
|
||||
EventBus.getDefault().post(new PeerConnectionEvent(PeerConnectionEvent.PeerConnectionEventType
|
||||
.PEER_CONNECTED, sessionId, null, null));
|
||||
if (hasInitiated) {
|
||||
sendInitialMediaStatus();
|
||||
}
|
||||
} else if (iceConnectionState.equals(PeerConnection.IceConnectionState.CLOSED)) {
|
||||
EventBus.getDefault().post(new PeerConnectionEvent(PeerConnectionEvent.PeerConnectionEventType
|
||||
.CLOSE_PEER, sessionId, null, null));
|
||||
.PEER_CLOSED, sessionId, null, null));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -74,7 +74,6 @@
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="60dp"
|
||||
android:layout_marginEnd="20dp"
|
||||
android:alpha="0.7"
|
||||
android:visibility="gone"
|
||||
app:checked="false"
|
||||
app:enableInitialAnimation="false"
|
||||
|
@ -29,7 +29,15 @@
|
||||
<org.webrtc.SurfaceViewRenderer
|
||||
android:id="@+id/surface_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="invisible"/>
|
||||
|
||||
<ImageView
|
||||
android:layout_width="80dp"
|
||||
android:layout_height="80dp"
|
||||
android:id="@+id/avatarImageView"
|
||||
android:layout_centerInParent="true"
|
||||
android:src="@drawable/ic_baseline_arrow_downward_24px"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/remote_video_off"
|
@ -26,7 +26,6 @@
|
||||
android:id="@+id/conversation_voice_call"
|
||||
android:icon="@drawable/ic_call_white_24dp"
|
||||
android:title="@string/nc_conversation_menu_voice_call"
|
||||
android:visible="false"
|
||||
app:showAsAction="always"/>
|
||||
|
||||
<item
|
||||
|
Loading…
Reference in New Issue
Block a user