diff --git a/app/src/gplay/java/com/nextcloud/talk/services/firebase/MagicFirebaseMessagingService.kt b/app/src/gplay/java/com/nextcloud/talk/services/firebase/MagicFirebaseMessagingService.kt
index babda90c6..0c0ec6dff 100644
--- a/app/src/gplay/java/com/nextcloud/talk/services/firebase/MagicFirebaseMessagingService.kt
+++ b/app/src/gplay/java/com/nextcloud/talk/services/firebase/MagicFirebaseMessagingService.kt
@@ -41,7 +41,7 @@ import com.bluelinelabs.logansquare.LoganSquare
import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage
import com.nextcloud.talk.R
-import com.nextcloud.talk.activities.MagicCallActivity
+import com.nextcloud.talk.activities.CallNotificationActivity
import com.nextcloud.talk.api.NcApi
import com.nextcloud.talk.application.NextcloudTalkApplication
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
@@ -178,7 +178,7 @@ class MagicFirebaseMessagingService : FirebaseMessagingService() {
)
}
} else if (type == "call") {
- val fullScreenIntent = Intent(applicationContext, MagicCallActivity::class.java)
+ val fullScreenIntent = Intent(applicationContext, CallNotificationActivity::class.java)
val bundle = Bundle()
bundle.putString(BundleKeys.KEY_ROOM_ID, decryptedPushMessage!!.id)
bundle.putParcelable(KEY_USER_ENTITY, signatureVerification!!.userEntity)
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index e254e15ce..1d0260733 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -123,9 +123,24 @@
+ android:name=".activities.CallActivity"
+ android:theme="@style/AppTheme.CallLauncher"
+ android:supportsPictureInPicture="true"
+ android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"
+ android:launchMode="singleTask"
+ android:taskAffinity=".call"
+ android:excludeFromRecents="true"
+ android:showOnLockScreen="true"/>
+
+
.
*/
-package com.nextcloud.talk.controllers;
+package com.nextcloud.talk.activities;
import android.Manifest;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.annotation.SuppressLint;
+import android.app.PendingIntent;
+import android.app.RemoteAction;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
import android.content.res.Configuration;
import android.graphics.Color;
+import android.graphics.drawable.Icon;
import android.media.AudioAttributes;
import android.media.MediaPlayer;
import android.net.Uri;
@@ -36,28 +43,20 @@ import android.os.Looper;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.Log;
-import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.FrameLayout;
-import android.widget.GridView;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.ProgressBar;
import android.widget.RelativeLayout;
-import android.widget.TextView;
import com.bluelinelabs.logansquare.LoganSquare;
-import com.facebook.drawee.view.SimpleDraweeView;
import com.nextcloud.talk.R;
-import com.nextcloud.talk.activities.MagicCallActivity;
import com.nextcloud.talk.adapters.ParticipantDisplayItem;
import com.nextcloud.talk.adapters.ParticipantsAdapter;
import com.nextcloud.talk.api.NcApi;
import com.nextcloud.talk.application.NextcloudTalkApplication;
-import com.nextcloud.talk.controllers.base.BaseController;
+import com.nextcloud.talk.databinding.CallActivityBinding;
import com.nextcloud.talk.events.ConfigurationChangeEvent;
import com.nextcloud.talk.events.MediaStreamEvent;
import com.nextcloud.talk.events.NetworkEvent;
@@ -122,7 +121,6 @@ import org.webrtc.PeerConnectionFactory;
import org.webrtc.RendererCommon;
import org.webrtc.SessionDescription;
import org.webrtc.SurfaceTextureHelper;
-import org.webrtc.SurfaceViewRenderer;
import org.webrtc.VideoCapturer;
import org.webrtc.VideoSource;
import org.webrtc.VideoTrack;
@@ -139,14 +137,12 @@ import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
+import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import autodagger.AutoInjector;
-import butterknife.BindView;
-import butterknife.OnClick;
-import butterknife.OnItemClick;
-import butterknife.OnLongClick;
import io.reactivex.Observable;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
@@ -159,65 +155,7 @@ import okhttp3.Cache;
import pub.devrel.easypermissions.AfterPermissionGranted;
@AutoInjector(NextcloudTalkApplication.class)
-public class CallController extends BaseController {
-
- private static final String TAG = "CallController";
-
- private static final String[] PERMISSIONS_CALL = {
- android.Manifest.permission.CAMERA,
- android.Manifest.permission.RECORD_AUDIO,
- };
-
- private static final String[] PERMISSIONS_CAMERA = {
- Manifest.permission.CAMERA
- };
-
- private static final String[] PERMISSIONS_MICROPHONE = {
- Manifest.permission.RECORD_AUDIO
- };
-
- @BindView(R.id.callControlEnableSpeaker)
- SimpleDraweeView callControlEnableSpeaker;
-
- @BindView(R.id.pip_video_view)
- SurfaceViewRenderer pipVideoView;
- @BindView(R.id.controllerCallLayout)
- RelativeLayout controllerCallLayout;
- @BindView(R.id.gridview)
- GridView gridView;
-
- @BindView(R.id.callControlsLinearLayout)
- LinearLayout callControls;
- @BindView(R.id.call_control_microphone)
- SimpleDraweeView microphoneControlButton;
- @BindView(R.id.call_control_camera)
- SimpleDraweeView cameraControlButton;
- @BindView(R.id.call_control_switch_camera)
- SimpleDraweeView cameraSwitchButton;
- @BindView(R.id.callStateTextView)
- TextView callStateTextView;
-
- @BindView(R.id.callInfosLinearLayout)
- LinearLayout callInfosLinearLayout;
- @BindView(R.id.callVoiceOrVideoTextView)
- TextView callVoiceOrVideoTextView;
- @BindView(R.id.callConversationNameTextView)
- TextView callConversationNameTextView;
-
- @BindView(R.id.selfVideoView)
- FrameLayout selfVideoView;
-
- @BindView(R.id.callStateRelativeLayoutView)
- RelativeLayout callStateView;
-
- @BindView(R.id.conversationRelativeLayoutView)
- RelativeLayout conversationView;
-
- @BindView(R.id.errorImageView)
- ImageView errorImageView;
-
- @BindView(R.id.callStateProgressBar)
- ProgressBar progressBar;
+public class CallActivity extends CallBaseActivity {
@Inject
NcApi ncApi;
@@ -230,6 +168,28 @@ public class CallController extends BaseController {
@Inject
Cache cache;
+ public static final String TAG = "CallActivity";
+
+ private static final String[] PERMISSIONS_CALL = {
+ android.Manifest.permission.CAMERA,
+ android.Manifest.permission.RECORD_AUDIO,
+ };
+
+ private static final String[] PERMISSIONS_CAMERA = {
+ Manifest.permission.CAMERA
+ };
+
+ private static final String[] PERMISSIONS_MICROPHONE = {
+ Manifest.permission.RECORD_AUDIO
+ };
+
+ private static final String MICROPHONE_PIP_INTENT_NAME = "microphone_pip_intent";
+ private static final String MICROPHONE_PIP_INTENT_EXTRA_ACTION = "microphone_pip_action";
+ private static final int MICROPHONE_PIP_REQUEST_MUTE = 1;
+ private static final int MICROPHONE_PIP_REQUEST_UNMUTE = 2;
+
+ private BroadcastReceiver mReceiver;
+
private PeerConnectionFactory peerConnectionFactory;
private MediaConstraints audioConstraints;
private MediaConstraints videoConstraints;
@@ -255,7 +215,7 @@ public class CallController extends BaseController {
private Map participantMap = new HashMap<>();
private boolean videoOn = false;
- private boolean audioOn = false;
+ private boolean microphoneOn = false;
private boolean isVoiceOnlyCall;
private boolean isIncomingCallFromNotification;
@@ -290,89 +250,143 @@ public class CallController extends BaseController {
private Map participantDisplayItems;
private ParticipantsAdapter participantsAdapter;
+ private CallActivityBinding binding;
+
@Parcel
public enum CallStatus {
CONNECTING, CALLING_TIMEOUT, JOINED, IN_CONVERSATION, RECONNECTING, OFFLINE, LEAVING, PUBLISHER_FAILED
}
- public CallController(Bundle args) {
- super(args);
+ @SuppressLint("ClickableViewAccessibility")
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ Log.d(TAG, "onCreate");
+ super.onCreate(savedInstanceState);
+
NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
- roomId = args.getString(BundleKeys.INSTANCE.getKEY_ROOM_ID(), "");
- roomToken = args.getString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN(), "");
- conversationUser = args.getParcelable(BundleKeys.INSTANCE.getKEY_USER_ENTITY());
- conversationPassword = args.getString(BundleKeys.INSTANCE.getKEY_CONVERSATION_PASSWORD(), "");
- conversationName = args.getString(BundleKeys.INSTANCE.getKEY_CONVERSATION_NAME(), "");
- isVoiceOnlyCall = args.getBoolean(BundleKeys.INSTANCE.getKEY_CALL_VOICE_ONLY(), false);
+ binding = CallActivityBinding.inflate(getLayoutInflater());
+ setContentView(binding.getRoot());
- if (args.containsKey(BundleKeys.INSTANCE.getKEY_FROM_NOTIFICATION_START_CALL())) {
- isIncomingCallFromNotification = args.getBoolean(BundleKeys.INSTANCE.getKEY_FROM_NOTIFICATION_START_CALL());
+ hideNavigationIfNoPipAvailable();
+
+ Bundle extras = getIntent().getExtras();
+ roomId = extras.getString(BundleKeys.INSTANCE.getKEY_ROOM_ID(), "");
+ roomToken = extras.getString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN(), "");
+ conversationUser = extras.getParcelable(BundleKeys.INSTANCE.getKEY_USER_ENTITY());
+ conversationPassword = extras.getString(BundleKeys.INSTANCE.getKEY_CONVERSATION_PASSWORD(), "");
+ conversationName = extras.getString(BundleKeys.INSTANCE.getKEY_CONVERSATION_NAME(), "");
+ isVoiceOnlyCall = extras.getBoolean(BundleKeys.INSTANCE.getKEY_CALL_VOICE_ONLY(), false);
+
+ if (extras.containsKey(BundleKeys.INSTANCE.getKEY_FROM_NOTIFICATION_START_CALL())) {
+ isIncomingCallFromNotification = extras.getBoolean(BundleKeys.INSTANCE.getKEY_FROM_NOTIFICATION_START_CALL());
}
credentials = ApiUtils.getCredentials(conversationUser.getUsername(), conversationUser.getToken());
- baseUrl = args.getString(BundleKeys.INSTANCE.getKEY_MODIFIED_BASE_URL(), "");
-
+ baseUrl = extras.getString(BundleKeys.INSTANCE.getKEY_MODIFIED_BASE_URL(), "");
if (TextUtils.isEmpty(baseUrl)) {
baseUrl = conversationUser.getBaseUrl();
}
powerManagerUtils = new PowerManagerUtils();
- if (args.getString("state", "").equalsIgnoreCase("resume")) {
+ if (extras.getString("state", "").equalsIgnoreCase("resume")) {
setCallState(CallStatus.IN_CONVERSATION);
} else {
setCallState(CallStatus.CONNECTING);
}
- }
- @Override
- protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
- return inflater.inflate(R.layout.controller_call, container, false);
- }
+ initClickListeners();
+ binding.microphoneButton.setOnTouchListener(new MicrophoneButtonTouchListener());
- private void createCameraEnumerator() {
- if (getActivity() != null) {
- boolean camera2EnumeratorIsSupported = false;
- try {
- camera2EnumeratorIsSupported = Camera2Enumerator.isSupported(getActivity());
- } catch (final Throwable throwable) {
- Log.w(TAG, "Camera2Enumator threw an error");
- }
+ pulseAnimation = PulseAnimation.create().with(binding.microphoneButton)
+ .setDuration(310)
+ .setRepeatCount(PulseAnimation.INFINITE)
+ .setRepeatMode(PulseAnimation.REVERSE);
- if (camera2EnumeratorIsSupported) {
- cameraEnumerator = new Camera2Enumerator(getActivity());
- } else {
- cameraEnumerator = new Camera1Enumerator(MagicWebRTCUtils.shouldEnableVideoHardwareAcceleration());
- }
+ binding.callControls.setZ(100.0f);
+ basicInitialization();
+ participantDisplayItems = new HashMap<>();
+ initViews();
+ if (!isConnectionEstablished()) {
+ initiateCall();
}
+ updateSelfVideoViewPosition();
}
- @SuppressLint("ClickableViewAccessibility")
@Override
- protected void onViewBound(@NonNull View view) {
- super.onViewBound(view);
-
- microphoneControlButton.setOnTouchListener(new MicrophoneButtonTouchListener());
-
- pulseAnimation = PulseAnimation.create().with(microphoneControlButton)
- .setDuration(310)
- .setRepeatCount(PulseAnimation.INFINITE)
- .setRepeatMode(PulseAnimation.REVERSE);
-
-
+ public void onStart() {
+ super.onStart();
try {
cache.evictAll();
} catch (IOException e) {
Log.e(TAG, "Failed to evict cache");
}
+ }
- callControls.setZ(100.0f);
- basicInitialization();
- initViews();
- initPipView();
- initiateCall();
+ private void initClickListeners() {
+ binding.pictureInPictureButton.setOnClickListener(l -> enterPipMode());
+
+ binding.speakerButton.setOnClickListener(l -> {
+ if (audioManager != null) {
+ audioManager.toggleUseSpeakerphone();
+ if (audioManager.isSpeakerphoneAutoOn()) {
+ binding.speakerButton.getHierarchy().setPlaceholderImage(R.drawable.ic_volume_up_white_24dp);
+ } else {
+ binding.speakerButton.getHierarchy().setPlaceholderImage(R.drawable.ic_volume_mute_white_24dp);
+ }
+ }
+ });
+
+ binding.microphoneButton.setOnClickListener(l -> onMicrophoneClick());
+ binding.microphoneButton.setOnLongClickListener(l -> {
+ if (!microphoneOn) {
+ callControlHandler.removeCallbacksAndMessages(null);
+ callInfosHandler.removeCallbacksAndMessages(null);
+ cameraSwitchHandler.removeCallbacksAndMessages(null);
+ isPTTActive = true;
+ binding.callControls.setVisibility(View.VISIBLE);
+ if (!isVoiceOnlyCall) {
+ binding.switchSelfVideoButton.setVisibility(View.VISIBLE);
+ }
+ }
+ onMicrophoneClick();
+ return true;
+ });
+
+ binding.cameraButton.setOnClickListener(l -> onCameraClick());
+
+ binding.hangupButton.setOnClickListener(l -> {
+ setCallState(CallStatus.LEAVING);
+ hangup(true);
+ });
+
+ binding.switchSelfVideoButton.setOnClickListener(l -> switchCamera());
+
+ binding.gridview.setOnItemClickListener((parent, view, position, id) -> animateCallControls(true, 0));
+
+ binding.callStates.callStateRelativeLayout.setOnClickListener(l -> {
+ if (currentCallStatus.equals(CallStatus.CALLING_TIMEOUT)) {
+ setCallState(CallStatus.RECONNECTING);
+ hangupNetworkCalls(false);
+ }
+ });
+ }
+
+ private void createCameraEnumerator() {
+ boolean camera2EnumeratorIsSupported = false;
+ try {
+ camera2EnumeratorIsSupported = Camera2Enumerator.isSupported(this);
+ } catch (final Throwable throwable) {
+ Log.w(TAG, "Camera2Enumator threw an error");
+ }
+
+ if (camera2EnumeratorIsSupported) {
+ cameraEnumerator = new Camera2Enumerator(this);
+ } else {
+ cameraEnumerator = new Camera1Enumerator(MagicWebRTCUtils.shouldEnableVideoHardwareAcceleration());
+ }
}
private void basicInitialization() {
@@ -382,14 +396,14 @@ public class CallController extends BaseController {
//Create a new PeerConnectionFactory instance.
PeerConnectionFactory.Options options = new PeerConnectionFactory.Options();
DefaultVideoEncoderFactory defaultVideoEncoderFactory = new DefaultVideoEncoderFactory(
- rootEglBase.getEglBaseContext(), true, true);
+ rootEglBase.getEglBaseContext(), true, true);
DefaultVideoDecoderFactory defaultVideoDecoderFactory = new DefaultVideoDecoderFactory(rootEglBase.getEglBaseContext());
peerConnectionFactory = PeerConnectionFactory.builder()
- .setOptions(options)
- .setVideoEncoderFactory(defaultVideoEncoderFactory)
- .setVideoDecoderFactory(defaultVideoDecoderFactory)
- .createPeerConnectionFactory();
+ .setOptions(options)
+ .setVideoEncoderFactory(defaultVideoEncoderFactory)
+ .setVideoDecoderFactory(defaultVideoDecoderFactory)
+ .createPeerConnectionFactory();
//Create MediaConstraints - Will be useful for specifying video and audio constraints.
audioConstraints = new MediaConstraints();
@@ -436,138 +450,156 @@ public class CallController extends BaseController {
}
private void handleFromNotification() {
- int apiVersion = ApiUtils.getConversationApiVersion(conversationUser, new int[] {ApiUtils.APIv4, 1});
+ int apiVersion = ApiUtils.getConversationApiVersion(conversationUser, new int[]{ApiUtils.APIv4, 1});
ncApi.getRooms(credentials, ApiUtils.getUrlForRooms(apiVersion, baseUrl))
- .retry(3)
- .subscribeOn(Schedulers.io())
- .observeOn(AndroidSchedulers.mainThread())
- .subscribe(new Observer() {
- @Override
- public void onSubscribe(@io.reactivex.annotations.NonNull Disposable d) {
- // unused atm
- }
+ .retry(3)
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(new Observer() {
+ @Override
+ public void onSubscribe(@io.reactivex.annotations.NonNull Disposable d) {
+ // unused atm
+ }
- @Override
- public void onNext(@io.reactivex.annotations.NonNull RoomsOverall roomsOverall) {
- for (Conversation conversation : roomsOverall.getOcs().getData()) {
- if (roomId.equals(conversation.getRoomId())) {
- roomToken = conversation.getToken();
- break;
- }
+ @Override
+ public void onNext(@io.reactivex.annotations.NonNull RoomsOverall roomsOverall) {
+ for (Conversation conversation : roomsOverall.getOcs().getData()) {
+ if (roomId.equals(conversation.getRoomId())) {
+ roomToken = conversation.getToken();
+ break;
}
-
- checkPermissions();
}
- @Override
- public void onError(@io.reactivex.annotations.NonNull Throwable e) {
- // unused atm
- }
+ checkPermissions();
+ }
- @Override
- public void onComplete() {
- // unused atm
- }
- });
+ @Override
+ public void onError(@io.reactivex.annotations.NonNull Throwable e) {
+ // unused atm
+ }
+
+ @Override
+ public void onComplete() {
+ // unused atm
+ }
+ });
}
-
@SuppressLint("ClickableViewAccessibility")
private void initViews() {
- participantDisplayItems = new HashMap<>();
+ Log.d(TAG, "initViews");
+ binding.callInfosLinearLayout.setVisibility(View.VISIBLE);
+ binding.selfVideoViewWrapper.setVisibility(View.VISIBLE);
+
+ if (!isPipModePossible()) {
+ binding.pictureInPictureButton.setVisibility(View.GONE);
+ }
if (isVoiceOnlyCall) {
- callControlEnableSpeaker.setVisibility(View.VISIBLE);
- cameraSwitchButton.setVisibility(View.GONE);
- cameraControlButton.setVisibility(View.GONE);
- pipVideoView.setVisibility(View.GONE);
+ binding.speakerButton.setVisibility(View.VISIBLE);
+ binding.switchSelfVideoButton.setVisibility(View.GONE);
+ binding.cameraButton.setVisibility(View.GONE);
+ binding.selfVideoRenderer.setVisibility(View.GONE);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
params.addRule(RelativeLayout.BELOW, R.id.callInfosLinearLayout);
- int callControlsHeight =
- Math.round(getApplicationContext().getResources().getDimension(R.dimen.call_controls_height));
- params.setMargins(0,0,0, callControlsHeight);
- gridView.setLayoutParams(params);
+ int callControlsHeight = Math.round(getApplicationContext().getResources().getDimension(R.dimen.call_controls_height));
+ params.setMargins(0, 0, 0, callControlsHeight);
+ binding.gridview.setLayoutParams(params);
} else {
- callControlEnableSpeaker.setVisibility(View.GONE);
+ RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT);
+ params.setMargins(0, 0, 0, 0);
+ binding.gridview.setLayoutParams(params);
+
+ binding.speakerButton.setVisibility(View.GONE);
if (cameraEnumerator.getDeviceNames().length < 2) {
- cameraSwitchButton.setVisibility(View.GONE);
+ binding.switchSelfVideoButton.setVisibility(View.GONE);
}
-
- 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);
-
- pipVideoView.setOnTouchListener(new SelfVideoTouchListener());
+ initSelfVideoView();
}
- gridView.setOnTouchListener(new View.OnTouchListener() {
+ binding.gridview.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent me) {
int action = me.getActionMasked();
if (action == MotionEvent.ACTION_DOWN) {
- showCallControls();
+ animateCallControls(true, 0);
}
return false;
}
});
+ animateCallControls(true, 0);
+
initGridAdapter();
}
+ @SuppressLint("ClickableViewAccessibility")
+ private void initSelfVideoView() {
+ try {
+ binding.selfVideoRenderer.init(rootEglBase.getEglBaseContext(), null);
+ } catch (IllegalStateException e) {
+ Log.d(TAG, "selfVideoRenderer already initialized", e);
+ }
+
+ binding.selfVideoRenderer.setZOrderMediaOverlay(true);
+ // disabled because it causes some devices to crash
+ binding.selfVideoRenderer.setEnableHardwareScaler(false);
+ binding.selfVideoRenderer.setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_FIT);
+ binding.selfVideoRenderer.setOnTouchListener(new SelfVideoTouchListener());
+ }
+
private void initGridAdapter() {
- if (conversationView != null) {
- GridView gridView = conversationView.findViewById(R.id.gridview);
-
- int columns;
- int participantsInGrid = participantDisplayItems.size();
- if (getResources() != null && getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
- if (participantsInGrid > 2) {
- columns = 2;
- } else {
- columns = 1;
- }
+ Log.d(TAG, "initGridAdapter");
+ int columns;
+ int participantsInGrid = participantDisplayItems.size();
+ if (getResources() != null && getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
+ if (participantsInGrid > 2) {
+ columns = 2;
} else {
- if (participantsInGrid > 2) {
- columns = 3;
- } else if (participantsInGrid > 1) {
- columns = 2;
- } else {
- columns = 1;
- }
+ columns = 1;
}
+ } else {
+ if (participantsInGrid > 2) {
+ columns = 3;
+ } else if (participantsInGrid > 1) {
+ columns = 2;
+ } else {
+ columns = 1;
+ }
+ }
- gridView.setNumColumns(columns);
+ binding.gridview.setNumColumns(columns);
- RelativeLayout gridViewWrapper = conversationView.findViewById(R.id.conversationRelativeLayoutView);
- gridViewWrapper.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
- @Override
- public void onGlobalLayout() {
- gridViewWrapper.getViewTreeObserver().removeOnGlobalLayoutListener(this);
- int height = gridViewWrapper.getMeasuredHeight();
- gridView.setMinimumHeight(height);
- }
- });
+ binding.conversationRelativeLayout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
+ @Override
+ public void onGlobalLayout() {
+ binding.conversationRelativeLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
+ int height = binding.conversationRelativeLayout.getMeasuredHeight();
+ binding.gridview.setMinimumHeight(height);
+ }
+ });
- LinearLayout callInfosLinearLayout = conversationView.findViewById(R.id.callInfosLinearLayout);
- callInfosLinearLayout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
- @Override
- public void onGlobalLayout() {
- callInfosLinearLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
- }
- });
+ binding.callInfosLinearLayout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
+ @Override
+ public void onGlobalLayout() {
+ binding.callInfosLinearLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
+ }
+ });
- participantsAdapter = new ParticipantsAdapter(
- this.getActivity(),
- participantDisplayItems,
- gridViewWrapper,
- callInfosLinearLayout,
- columns,
- isVoiceOnlyCall);
- gridView.setAdapter(participantsAdapter);
+ participantsAdapter = new ParticipantsAdapter(
+ this,
+ participantDisplayItems,
+ binding.conversationRelativeLayout,
+ binding.callInfosLinearLayout,
+ columns,
+ isVoiceOnlyCall);
+ binding.gridview.setAdapter(participantsAdapter);
+
+ if (isInPipMode) {
+ updateUiForPipMode();
}
}
@@ -575,7 +607,7 @@ public class CallController extends BaseController {
private void checkPermissions() {
if (isVoiceOnlyCall) {
onMicrophoneClick();
- } else if (getActivity() != null) {
+ } else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(PERMISSIONS_CALL, 100);
} else {
@@ -591,30 +623,29 @@ public class CallController extends BaseController {
@AfterPermissionGranted(100)
private void onPermissionsGranted() {
- if (EffortlessPermissions.hasPermissions(getActivity(), PERMISSIONS_CALL)) {
+ if (EffortlessPermissions.hasPermissions(this, PERMISSIONS_CALL)) {
if (!videoOn && !isVoiceOnlyCall) {
onCameraClick();
}
- if (!audioOn) {
+ if (!microphoneOn) {
onMicrophoneClick();
}
if (!isVoiceOnlyCall) {
if (cameraEnumerator.getDeviceNames().length == 0) {
- cameraControlButton.setVisibility(View.GONE);
+ binding.cameraButton.setVisibility(View.GONE);
}
if (cameraEnumerator.getDeviceNames().length > 1) {
- cameraSwitchButton.setVisibility(View.VISIBLE);
+ binding.switchSelfVideoButton.setVisibility(View.VISIBLE);
}
}
if (!isConnectionEstablished()) {
fetchSignalingSettings();
}
- } else if (getActivity() != null && EffortlessPermissions.somePermissionPermanentlyDenied(getActivity(),
- PERMISSIONS_CALL)) {
+ } else if (EffortlessPermissions.somePermissionPermanentlyDenied(this, PERMISSIONS_CALL)) {
checkIfSomeAreApproved();
}
@@ -623,30 +654,30 @@ public class CallController extends BaseController {
private void checkIfSomeAreApproved() {
if (!isVoiceOnlyCall) {
if (cameraEnumerator.getDeviceNames().length == 0) {
- cameraControlButton.setVisibility(View.GONE);
+ binding.cameraButton.setVisibility(View.GONE);
}
if (cameraEnumerator.getDeviceNames().length > 1) {
- cameraSwitchButton.setVisibility(View.VISIBLE);
+ binding.switchSelfVideoButton.setVisibility(View.VISIBLE);
}
- if (getActivity() != null && EffortlessPermissions.hasPermissions(getActivity(), PERMISSIONS_CAMERA)) {
+ if (EffortlessPermissions.hasPermissions(this, PERMISSIONS_CAMERA)) {
if (!videoOn) {
onCameraClick();
}
} else {
- cameraControlButton.getHierarchy().setPlaceholderImage(R.drawable.ic_videocam_off_white_24px);
- cameraControlButton.setAlpha(0.7f);
- cameraSwitchButton.setVisibility(View.GONE);
+ binding.cameraButton.getHierarchy().setPlaceholderImage(R.drawable.ic_videocam_off_white_24px);
+ binding.cameraButton.setAlpha(0.7f);
+ binding.switchSelfVideoButton.setVisibility(View.GONE);
}
}
- if (EffortlessPermissions.hasPermissions(getActivity(), PERMISSIONS_MICROPHONE)) {
- if (!audioOn) {
+ if (EffortlessPermissions.hasPermissions(this, PERMISSIONS_MICROPHONE)) {
+ if (!microphoneOn) {
onMicrophoneClick();
}
} else {
- microphoneControlButton.getHierarchy().setPlaceholderImage(R.drawable.ic_mic_off_white_24px);
+ binding.microphoneButton.getHierarchy().setPlaceholderImage(R.drawable.ic_mic_off_white_24px);
}
if (!isConnectionEstablished()) {
@@ -658,14 +689,14 @@ public class CallController extends BaseController {
private void onPermissionsDenied() {
if (!isVoiceOnlyCall) {
if (cameraEnumerator.getDeviceNames().length == 0) {
- cameraControlButton.setVisibility(View.GONE);
+ binding.cameraButton.setVisibility(View.GONE);
} else if (cameraEnumerator.getDeviceNames().length == 1) {
- cameraSwitchButton.setVisibility(View.GONE);
+ binding.switchSelfVideoButton.setVisibility(View.GONE);
}
}
- if (getActivity() != null && (EffortlessPermissions.hasPermissions(getActivity(), PERMISSIONS_CAMERA) ||
- EffortlessPermissions.hasPermissions(getActivity(), PERMISSIONS_MICROPHONE))) {
+ if ((EffortlessPermissions.hasPermissions(this, PERMISSIONS_CAMERA) ||
+ EffortlessPermissions.hasPermissions(this, PERMISSIONS_MICROPHONE))) {
checkIfSomeAreApproved();
} else if (!isConnectionEstablished()) {
fetchSignalingSettings();
@@ -673,13 +704,13 @@ public class CallController extends BaseController {
}
private void onAudioManagerDevicesChanged(
- final MagicAudioManager.AudioDevice device, final Set availableDevices) {
+ final MagicAudioManager.AudioDevice device, final Set availableDevices) {
Log.d(TAG, "onAudioManagerDevicesChanged: " + availableDevices + ", "
- + "selected: " + device);
+ + "selected: " + device);
final boolean shouldDisableProximityLock = (device.equals(MagicAudioManager.AudioDevice.WIRED_HEADSET)
- || device.equals(MagicAudioManager.AudioDevice.SPEAKER_PHONE)
- || device.equals(MagicAudioManager.AudioDevice.BLUETOOTH));
+ || device.equals(MagicAudioManager.AudioDevice.SPEAKER_PHONE)
+ || device.equals(MagicAudioManager.AudioDevice.BLUETOOTH));
if (shouldDisableProximityLock) {
powerManagerUtils.updatePhoneState(PowerManagerUtils.PhoneState.WITHOUT_PROXIMITY_SENSOR_LOCK);
@@ -701,7 +732,7 @@ public class CallController extends BaseController {
localVideoTrack = peerConnectionFactory.createVideoTrack("NCv0", videoSource);
localMediaStream.addTrack(localVideoTrack);
localVideoTrack.setEnabled(false);
- localVideoTrack.addSink(pipVideoView);
+ localVideoTrack.addSink(binding.selfVideoRenderer);
}
private void microphoneInitialization() {
@@ -722,7 +753,7 @@ public class CallController extends BaseController {
Logging.d(TAG, "Creating front facing camera capturer.");
VideoCapturer videoCapturer = enumerator.createCapturer(deviceName, null);
if (videoCapturer != null) {
- pipVideoView.setMirror(true);
+ binding.selfVideoRenderer.setMirror(true);
return videoCapturer;
}
}
@@ -737,7 +768,7 @@ public class CallController extends BaseController {
VideoCapturer videoCapturer = enumerator.createCapturer(deviceName, null);
if (videoCapturer != null) {
- pipVideoView.setMirror(false);
+ binding.selfVideoRenderer.setMirror(false);
return videoCapturer;
}
}
@@ -746,75 +777,51 @@ public class CallController extends BaseController {
return null;
}
- @OnLongClick(R.id.call_control_microphone)
- boolean onMicrophoneLongClick() {
- if (!audioOn) {
- callControlHandler.removeCallbacksAndMessages(null);
- callInfosHandler.removeCallbacksAndMessages(null);
- cameraSwitchHandler.removeCallbacksAndMessages(null);
- isPTTActive = true;
- callControls.setVisibility(View.VISIBLE);
- if (!isVoiceOnlyCall) {
- cameraSwitchButton.setVisibility(View.VISIBLE);
- }
- }
-
- onMicrophoneClick();
- return true;
- }
-
- @OnClick(R.id.callControlEnableSpeaker)
- public void onEnableSpeakerphoneClick() {
- if (audioManager != null) {
- audioManager.toggleUseSpeakerphone();
- if (audioManager.isSpeakerphoneAutoOn()) {
- callControlEnableSpeaker.getHierarchy().setPlaceholderImage(R.drawable.ic_volume_up_white_24dp);
- } else {
- callControlEnableSpeaker.getHierarchy().setPlaceholderImage(R.drawable.ic_volume_mute_white_24dp);
- }
- }
- }
-
- @OnClick(R.id.call_control_microphone)
public void onMicrophoneClick() {
- if (getActivity() != null && EffortlessPermissions.hasPermissions(getActivity(), PERMISSIONS_MICROPHONE)) {
+ if (EffortlessPermissions.hasPermissions(this, PERMISSIONS_MICROPHONE)) {
- if (getActivity() != null && !appPreferences.getPushToTalkIntroShown()) {
- spotlightView = new SpotlightView.Builder(getActivity())
- .introAnimationDuration(300)
- .enableRevealAnimation(true)
- .performClick(false)
- .fadeinTextDuration(400)
- .headingTvColor(getResources().getColor(R.color.colorPrimary))
- .headingTvSize(20)
- .headingTvText(getResources().getString(R.string.nc_push_to_talk))
- .subHeadingTvColor(getResources().getColor(R.color.bg_default))
- .subHeadingTvSize(16)
- .subHeadingTvText(getResources().getString(R.string.nc_push_to_talk_desc))
- .maskColor(Color.parseColor("#dc000000"))
- .target(microphoneControlButton)
- .lineAnimDuration(400)
- .lineAndArcColor(getResources().getColor(R.color.colorPrimary))
- .enableDismissAfterShown(true)
- .dismissOnBackPress(true)
- .usageId("pushToTalk")
- .show();
+ if (!appPreferences.getPushToTalkIntroShown()) {
+ spotlightView = new SpotlightView.Builder(this)
+ .introAnimationDuration(300)
+ .enableRevealAnimation(true)
+ .performClick(false)
+ .fadeinTextDuration(400)
+ .headingTvColor(getResources().getColor(R.color.colorPrimary))
+ .headingTvSize(20)
+ .headingTvText(getResources().getString(R.string.nc_push_to_talk))
+ .subHeadingTvColor(getResources().getColor(R.color.bg_default))
+ .subHeadingTvSize(16)
+ .subHeadingTvText(getResources().getString(R.string.nc_push_to_talk_desc))
+ .maskColor(Color.parseColor("#dc000000"))
+ .target(binding.microphoneButton)
+ .lineAnimDuration(400)
+ .lineAndArcColor(getResources().getColor(R.color.colorPrimary))
+ .enableDismissAfterShown(true)
+ .dismissOnBackPress(true)
+ .usageId("pushToTalk")
+ .show();
appPreferences.setPushToTalkIntroShown(true);
}
if (!isPTTActive) {
- audioOn = !audioOn;
+ microphoneOn = !microphoneOn;
- if (audioOn) {
- microphoneControlButton.getHierarchy().setPlaceholderImage(R.drawable.ic_mic_white_24px);
+ if (microphoneOn) {
+ binding.microphoneButton.getHierarchy().setPlaceholderImage(R.drawable.ic_mic_white_24px);
+ updatePictureInPictureActions(R.drawable.ic_mic_white_24px,
+ getResources().getString(R.string.nc_pip_microphone_mute),
+ MICROPHONE_PIP_REQUEST_MUTE);
} else {
- microphoneControlButton.getHierarchy().setPlaceholderImage(R.drawable.ic_mic_off_white_24px);
+ binding.microphoneButton.getHierarchy().setPlaceholderImage(R.drawable.ic_mic_off_white_24px);
+ updatePictureInPictureActions(R.drawable.ic_mic_off_white_24px,
+ getResources().getString(R.string.nc_pip_microphone_unmute),
+ MICROPHONE_PIP_REQUEST_UNMUTE);
}
- toggleMedia(audioOn, false);
+ toggleMedia(microphoneOn, false);
} else {
- microphoneControlButton.getHierarchy().setPlaceholderImage(R.drawable.ic_mic_white_24px);
+ binding.microphoneButton.getHierarchy().setPlaceholderImage(R.drawable.ic_mic_white_24px);
pulseAnimation.start();
toggleMedia(true, false);
}
@@ -823,13 +830,12 @@ public class CallController extends BaseController {
fetchSignalingSettings();
}
- } else if (getActivity() != null && EffortlessPermissions.somePermissionPermanentlyDenied(getActivity(),
- PERMISSIONS_MICROPHONE)) {
+ } else if (EffortlessPermissions.somePermissionPermanentlyDenied(this, PERMISSIONS_MICROPHONE)) {
// Microphone permission is permanently denied so we cannot request it normally.
OpenAppDetailsDialogFragment.show(
- R.string.nc_microphone_permission_permanently_denied,
- R.string.nc_permissions_settings, (AppCompatActivity) getActivity());
+ R.string.nc_microphone_permission_permanently_denied,
+ R.string.nc_permissions_settings, (AppCompatActivity) this);
} else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(PERMISSIONS_MICROPHONE, 100);
@@ -839,39 +845,26 @@ public class CallController extends BaseController {
}
}
- @OnClick(R.id.callControlToggleChat)
- void onToggleChatClick() {
- ((MagicCallActivity) getActivity()).showChat();
- }
-
- @OnClick(R.id.callControlHangupView)
- void onHangupClick() {
- setCallState(CallStatus.LEAVING);
- hangup(true);
- }
-
- @OnClick(R.id.call_control_camera)
public void onCameraClick() {
- if (getActivity() != null && EffortlessPermissions.hasPermissions(getActivity(), PERMISSIONS_CAMERA)) {
+ if (EffortlessPermissions.hasPermissions(this, PERMISSIONS_CAMERA)) {
videoOn = !videoOn;
if (videoOn) {
- cameraControlButton.getHierarchy().setPlaceholderImage(R.drawable.ic_videocam_white_24px);
+ binding.cameraButton.getHierarchy().setPlaceholderImage(R.drawable.ic_videocam_white_24px);
if (cameraEnumerator.getDeviceNames().length > 1) {
- cameraSwitchButton.setVisibility(View.VISIBLE);
+ binding.switchSelfVideoButton.setVisibility(View.VISIBLE);
}
} else {
- cameraControlButton.getHierarchy().setPlaceholderImage(R.drawable.ic_videocam_off_white_24px);
- cameraSwitchButton.setVisibility(View.GONE);
+ binding.cameraButton.getHierarchy().setPlaceholderImage(R.drawable.ic_videocam_off_white_24px);
+ binding.switchSelfVideoButton.setVisibility(View.GONE);
}
toggleMedia(videoOn, true);
- } else if (getActivity() != null && EffortlessPermissions.somePermissionPermanentlyDenied(getActivity(),
- PERMISSIONS_CAMERA)) {
+ } else if (EffortlessPermissions.somePermissionPermanentlyDenied(this, PERMISSIONS_CAMERA)) {
// Camera permission is permanently denied so we cannot request it normally.
OpenAppDetailsDialogFragment.show(
- R.string.nc_camera_permission_permanently_denied,
- R.string.nc_permissions_settings, (AppCompatActivity) getActivity());
+ R.string.nc_camera_permission_permanently_denied,
+ R.string.nc_permissions_settings, (AppCompatActivity) this);
} else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
@@ -883,14 +876,13 @@ public class CallController extends BaseController {
}
- @OnClick({R.id.call_control_switch_camera})
public void switchCamera() {
CameraVideoCapturer cameraVideoCapturer = (CameraVideoCapturer) videoCapturer;
if (cameraVideoCapturer != null) {
cameraVideoCapturer.switchCamera(new CameraVideoCapturer.CameraSwitchHandler() {
@Override
public void onCameraSwitchDone(boolean currentCameraIsFront) {
- pipVideoView.setMirror(currentCameraIsFront);
+ binding.selfVideoRenderer.setMirror(currentCameraIsFront);
}
@Override
@@ -906,11 +898,11 @@ public class CallController extends BaseController {
if (video) {
message = "videoOff";
if (enable) {
- cameraControlButton.setAlpha(1.0f);
+ binding.cameraButton.setAlpha(1.0f);
message = "videoOn";
startVideoCapture();
} else {
- cameraControlButton.setAlpha(0.7f);
+ binding.cameraButton.setAlpha(0.7f);
if (videoCapturer != null) {
try {
videoCapturer.stopCapture();
@@ -924,17 +916,17 @@ public class CallController extends BaseController {
localMediaStream.videoTracks.get(0).setEnabled(enable);
}
if (enable) {
- pipVideoView.setVisibility(View.VISIBLE);
+ binding.selfVideoRenderer.setVisibility(View.VISIBLE);
} else {
- pipVideoView.setVisibility(View.INVISIBLE);
+ binding.selfVideoRenderer.setVisibility(View.INVISIBLE);
}
} else {
message = "audioOff";
if (enable) {
message = "audioOn";
- microphoneControlButton.setAlpha(1.0f);
+ binding.microphoneButton.setAlpha(1.0f);
} else {
- microphoneControlButton.setAlpha(0.7f);
+ binding.microphoneButton.setAlpha(0.7f);
}
if (localMediaStream != null && localMediaStream.audioTracks.size() > 0) {
@@ -974,16 +966,16 @@ public class CallController extends BaseController {
cameraSwitchHandler.removeCallbacksAndMessages(null);
alpha = 1.0f;
duration = 1000;
- if (callControls.getVisibility() != View.VISIBLE) {
- callControls.setAlpha(0.0f);
- callControls.setVisibility(View.VISIBLE);
+ if (binding.callControls.getVisibility() != View.VISIBLE) {
+ binding.callControls.setAlpha(0.0f);
+ binding.callControls.setVisibility(View.VISIBLE);
- callInfosLinearLayout.setAlpha(0.0f);
- callInfosLinearLayout.setVisibility(View.VISIBLE);
+ binding.callInfosLinearLayout.setAlpha(0.0f);
+ binding.callInfosLinearLayout.setVisibility(View.VISIBLE);
- cameraSwitchButton.setAlpha(0.0f);
+ binding.switchSelfVideoButton.setAlpha(0.0f);
if (videoOn) {
- cameraSwitchButton.setVisibility(View.VISIBLE);
+ binding.switchSelfVideoButton.setVisibility(View.VISIBLE);
}
} else {
callControlHandler.postDelayed(() -> animateCallControls(false, 0), 5000);
@@ -994,91 +986,91 @@ public class CallController extends BaseController {
duration = 1000;
}
- if (callControls != null) {
- callControls.setEnabled(false);
- callControls.animate()
- .translationY(0)
- .alpha(alpha)
- .setDuration(duration)
- .setStartDelay(startDelay)
- .setListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- super.onAnimationEnd(animation);
- if (callControls != null) {
- if (!show) {
- callControls.setVisibility(View.GONE);
- if (spotlightView != null && spotlightView.getVisibility() != View.GONE) {
- spotlightView.setVisibility(View.GONE);
+ if (binding.callControls != null) {
+ binding.callControls.setEnabled(false);
+ binding.callControls.animate()
+ .translationY(0)
+ .alpha(alpha)
+ .setDuration(duration)
+ .setStartDelay(startDelay)
+ .setListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ if (binding.callControls != null) {
+ if (!show) {
+ binding.callControls.setVisibility(View.GONE);
+ if (spotlightView != null && spotlightView.getVisibility() != View.GONE) {
+ spotlightView.setVisibility(View.GONE);
+ }
+ } else {
+ callControlHandler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ if (!isPTTActive) {
+ animateCallControls(false, 0);
+ }
}
- } else {
- callControlHandler.postDelayed(new Runnable() {
- @Override
- public void run() {
- if (!isPTTActive) {
- animateCallControls(false, 0);
- }
- }
- }, 7500);
- }
-
- callControls.setEnabled(true);
+ }, 7500);
}
+
+ binding.callControls.setEnabled(true);
}
- });
+ }
+ });
}
- if (callInfosLinearLayout != null) {
- callInfosLinearLayout.setEnabled(false);
- callInfosLinearLayout.animate()
- .translationY(0)
- .alpha(alpha)
- .setDuration(duration)
- .setStartDelay(startDelay)
- .setListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- super.onAnimationEnd(animation);
- if (callInfosLinearLayout != null) {
- if (!show) {
- callInfosLinearLayout.setVisibility(View.GONE);
- } else {
- callInfosHandler.postDelayed(new Runnable() {
- @Override
- public void run() {
- if (!isPTTActive) {
- animateCallControls(false, 0);
- }
+ if (binding.callInfosLinearLayout != null) {
+ binding.callInfosLinearLayout.setEnabled(false);
+ binding.callInfosLinearLayout.animate()
+ .translationY(0)
+ .alpha(alpha)
+ .setDuration(duration)
+ .setStartDelay(startDelay)
+ .setListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ if (binding.callInfosLinearLayout != null) {
+ if (!show) {
+ binding.callInfosLinearLayout.setVisibility(View.GONE);
+ } else {
+ callInfosHandler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ if (!isPTTActive) {
+ animateCallControls(false, 0);
}
- }, 7500);
- }
-
- callInfosLinearLayout.setEnabled(true);
+ }
+ }, 7500);
}
+
+ binding.callInfosLinearLayout.setEnabled(true);
}
- });
+ }
+ });
}
- if (cameraSwitchButton != null) {
- cameraSwitchButton.setEnabled(false);
- cameraSwitchButton.animate()
- .translationY(0)
- .alpha(alpha)
- .setDuration(duration)
- .setStartDelay(startDelay)
- .setListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- super.onAnimationEnd(animation);
- if (cameraSwitchButton != null) {
- if (!show) {
- cameraSwitchButton.setVisibility(View.GONE);
- }
-
- cameraSwitchButton.setEnabled(true);
+ if (binding.switchSelfVideoButton != null) {
+ binding.switchSelfVideoButton.setEnabled(false);
+ binding.switchSelfVideoButton.animate()
+ .translationY(0)
+ .alpha(alpha)
+ .setDuration(duration)
+ .setStartDelay(startDelay)
+ .setListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ if (binding.switchSelfVideoButton != null) {
+ if (!show) {
+ binding.switchSelfVideoButton.setVisibility(View.GONE);
}
+
+ binding.switchSelfVideoButton.setEnabled(true);
}
- });
+ }
+ });
}
}
@@ -1087,179 +1079,189 @@ public class CallController extends BaseController {
@Override
public void onDestroy() {
if (!currentCallStatus.equals(CallStatus.LEAVING)) {
- onHangupClick();
+ setCallState(CallStatus.LEAVING);
+ hangup(true);
}
powerManagerUtils.updatePhoneState(PowerManagerUtils.PhoneState.IDLE);
super.onDestroy();
}
private void fetchSignalingSettings() {
- int apiVersion = ApiUtils.getSignalingApiVersion(conversationUser, new int[] {ApiUtils.APIv3, 2, 1});
+ int apiVersion = ApiUtils.getSignalingApiVersion(conversationUser, new int[]{ApiUtils.APIv3, 2, 1});
ncApi.getSignalingSettings(credentials, ApiUtils.getUrlForSignalingSettings(apiVersion, baseUrl))
- .subscribeOn(Schedulers.io())
- .retry(3)
- .observeOn(AndroidSchedulers.mainThread())
- .subscribe(new Observer() {
- @Override
- public void onSubscribe(@io.reactivex.annotations.NonNull Disposable d) {
- // unused atm
- }
+ .subscribeOn(Schedulers.io())
+ .retry(3)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(new Observer() {
+ @Override
+ public void onSubscribe(@io.reactivex.annotations.NonNull Disposable d) {
+ // unused atm
+ }
- @Override
- public void onNext(@io.reactivex.annotations.NonNull SignalingSettingsOverall signalingSettingsOverall) {
- if (signalingSettingsOverall != null && signalingSettingsOverall.getOcs() != null &&
- signalingSettingsOverall.getOcs().getSettings() != null) {
+ @Override
+ public void onNext(@io.reactivex.annotations.NonNull SignalingSettingsOverall signalingSettingsOverall) {
+ if (signalingSettingsOverall != null && signalingSettingsOverall.getOcs() != null &&
+ signalingSettingsOverall.getOcs().getSettings() != null) {
+ externalSignalingServer = new ExternalSignalingServer();
+
+ if (!TextUtils.isEmpty(signalingSettingsOverall.getOcs().getSettings().getExternalSignalingServer()) &&
+ !TextUtils.isEmpty(signalingSettingsOverall.getOcs().getSettings().getExternalSignalingTicket())) {
externalSignalingServer = new ExternalSignalingServer();
+ externalSignalingServer.setExternalSignalingServer(signalingSettingsOverall.getOcs().getSettings().getExternalSignalingServer());
+ externalSignalingServer.setExternalSignalingTicket(signalingSettingsOverall.getOcs().getSettings().getExternalSignalingTicket());
+ hasExternalSignalingServer = true;
+ } else {
+ hasExternalSignalingServer = false;
+ }
- if (!TextUtils.isEmpty(signalingSettingsOverall.getOcs().getSettings().getExternalSignalingServer()) &&
- !TextUtils.isEmpty(signalingSettingsOverall.getOcs().getSettings().getExternalSignalingTicket())) {
- externalSignalingServer = new ExternalSignalingServer();
- externalSignalingServer.setExternalSignalingServer(signalingSettingsOverall.getOcs().getSettings().getExternalSignalingServer());
- externalSignalingServer.setExternalSignalingTicket(signalingSettingsOverall.getOcs().getSettings().getExternalSignalingTicket());
- hasExternalSignalingServer = true;
- } else {
- hasExternalSignalingServer = false;
+ if (!conversationUser.getUserId().equals("?")) {
+ try {
+ userUtils.createOrUpdateUser(null, null, null, null, null, null, null,
+ conversationUser.getId(), null, null, LoganSquare.serialize(externalSignalingServer))
+ .subscribeOn(Schedulers.io())
+ .subscribe();
+ } catch (IOException exception) {
+ Log.e(TAG, "Failed to serialize external signaling server", exception);
}
+ } else {
+ try {
+ conversationUser.setExternalSignalingServer(LoganSquare.serialize(externalSignalingServer));
+ } catch (IOException exception) {
+ Log.e(TAG, "Failed to serialize external signaling server", exception);
+ }
+ }
- if (!conversationUser.getUserId().equals("?")) {
- try {
- userUtils.createOrUpdateUser(null, null, null, null, null, null, null,
- conversationUser.getId(), null, null, LoganSquare.serialize(externalSignalingServer))
- .subscribeOn(Schedulers.io())
- .subscribe();
- } catch (IOException exception) {
- Log.e(TAG, "Failed to serialize external signaling server", exception);
+ if (signalingSettingsOverall.getOcs().getSettings().getStunServers() != null) {
+ List stunServers =
+ signalingSettingsOverall.getOcs().getSettings().getStunServers();
+ if (apiVersion == ApiUtils.APIv3) {
+ for (IceServer stunServer : stunServers) {
+ if (stunServer.getUrls() != null) {
+ for (String url : stunServer.getUrls()) {
+ iceServers.add(new PeerConnection.IceServer(url));
+ }
+ }
}
} else {
- try {
- conversationUser.setExternalSignalingServer(LoganSquare.serialize(externalSignalingServer));
- } catch (IOException exception) {
- Log.e(TAG, "Failed to serialize external signaling server", exception);
- }
- }
-
- if (signalingSettingsOverall.getOcs().getSettings().getStunServers() != null) {
- List stunServers =
- signalingSettingsOverall.getOcs().getSettings().getStunServers();
- if (apiVersion == ApiUtils.APIv3) {
+ if (signalingSettingsOverall.getOcs().getSettings().getStunServers() != null) {
for (IceServer stunServer : stunServers) {
- if (stunServer.getUrls() != null) {
- for (String url : stunServer.getUrls()) {
- iceServers.add(new PeerConnection.IceServer(url));
- }
- }
- }
- } else {
- if (signalingSettingsOverall.getOcs().getSettings().getStunServers() != null) {
- for (IceServer stunServer : stunServers) {
- iceServers.add(new PeerConnection.IceServer(stunServer.getUrl()));
- }
- }
- }
- }
-
- if (signalingSettingsOverall.getOcs().getSettings().getTurnServers() != null) {
- List turnServers =
- signalingSettingsOverall.getOcs().getSettings().getTurnServers();
- for (IceServer turnServer : turnServers) {
- if (turnServer.getUrls() != null) {
- for (String url : turnServer.getUrls()) {
- iceServers.add(new PeerConnection.IceServer(
- url, turnServer.getUsername(), turnServer.getCredential()
- ));
- }
+ iceServers.add(new PeerConnection.IceServer(stunServer.getUrl()));
}
}
}
}
- checkCapabilities();
+ if (signalingSettingsOverall.getOcs().getSettings().getTurnServers() != null) {
+ List turnServers =
+ signalingSettingsOverall.getOcs().getSettings().getTurnServers();
+ for (IceServer turnServer : turnServers) {
+ if (turnServer.getUrls() != null) {
+ for (String url : turnServer.getUrls()) {
+ iceServers.add(new PeerConnection.IceServer(
+ url, turnServer.getUsername(), turnServer.getCredential()
+ ));
+ }
+ }
+ }
+ }
}
- @Override
- public void onError(@io.reactivex.annotations.NonNull Throwable e) {
- Log.e(TAG, e.getMessage(), e);
- }
+ checkCapabilities();
+ }
- @Override
- public void onComplete() {
- // unused atm
- }
- });
+ @Override
+ public void onError(@io.reactivex.annotations.NonNull Throwable e) {
+ Log.e(TAG, e.getMessage(), e);
+ }
+
+ @Override
+ public void onComplete() {
+ // unused atm
+ }
+ });
}
private void checkCapabilities() {
ncApi.getCapabilities(credentials, ApiUtils.getUrlForCapabilities(baseUrl))
- .retry(3)
- .subscribeOn(Schedulers.io())
- .observeOn(AndroidSchedulers.mainThread())
- .subscribe(new Observer() {
- @Override
- public void onSubscribe(@io.reactivex.annotations.NonNull Disposable d) {
- // unused atm
- }
+ .retry(3)
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(new Observer() {
+ @Override
+ public void onSubscribe(@io.reactivex.annotations.NonNull Disposable d) {
+ // unused atm
+ }
- @Override
- public void onNext(@io.reactivex.annotations.NonNull CapabilitiesOverall capabilitiesOverall) {
- // FIXME check for compatible Call API version
- if (hasExternalSignalingServer) {
- setupAndInitiateWebSocketsConnection();
- } else {
- joinRoomAndCall();
- }
+ @Override
+ public void onNext(@io.reactivex.annotations.NonNull CapabilitiesOverall capabilitiesOverall) {
+ // FIXME check for compatible Call API version
+ if (hasExternalSignalingServer) {
+ setupAndInitiateWebSocketsConnection();
+ } else {
+ joinRoomAndCall();
}
+ }
- @Override
- public void onError(@io.reactivex.annotations.NonNull Throwable e) {
- // unused atm
- }
+ @Override
+ public void onError(@io.reactivex.annotations.NonNull Throwable e) {
+ // unused atm
+ }
- @Override
- public void onComplete() {
- // unused atm
- }
- });
+ @Override
+ public void onComplete() {
+ // unused atm
+ }
+ });
}
private void joinRoomAndCall() {
callSession = ApplicationWideCurrentRoomHolder.getInstance().getSession();
- int apiVersion = ApiUtils.getConversationApiVersion(conversationUser, new int[] {ApiUtils.APIv4, 1});
+ int apiVersion = ApiUtils.getConversationApiVersion(conversationUser, new int[]{ApiUtils.APIv4, 1});
+
+ Log.d(TAG, "joinRoomAndCall");
+ Log.d(TAG, " baseUrl= " + baseUrl);
+ Log.d(TAG, " roomToken= " + roomToken);
+ Log.d(TAG, " callSession= " + callSession);
+
+ String url = ApiUtils.getUrlForParticipantsActive(apiVersion, baseUrl, roomToken);
+ Log.d(TAG, " url= " + url);
if (TextUtils.isEmpty(callSession)) {
- ncApi.joinRoom(credentials, ApiUtils.getUrlForParticipantsActive(apiVersion, baseUrl, roomToken),
- conversationPassword)
- .subscribeOn(Schedulers.io())
- .observeOn(AndroidSchedulers.mainThread())
- .retry(3)
- .subscribe(new Observer() {
- @Override
- public void onSubscribe(@io.reactivex.annotations.NonNull Disposable d) {
- // unused atm
- }
+ ncApi.joinRoom(credentials, url, conversationPassword)
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .retry(3)
+ .subscribe(new Observer() {
+ @Override
+ public void onSubscribe(@io.reactivex.annotations.NonNull Disposable d) {
+ // unused atm
+ }
- @Override
- public void onNext(@io.reactivex.annotations.NonNull RoomOverall roomOverall) {
- callSession = roomOverall.getOcs().getData().getSessionId();
- ApplicationWideCurrentRoomHolder.getInstance().setSession(callSession);
- ApplicationWideCurrentRoomHolder.getInstance().setCurrentRoomId(roomId);
- ApplicationWideCurrentRoomHolder.getInstance().setCurrentRoomToken(roomToken);
- ApplicationWideCurrentRoomHolder.getInstance().setUserInRoom(conversationUser);
- callOrJoinRoomViaWebSocket();
- }
+ @Override
+ public void onNext(@io.reactivex.annotations.NonNull RoomOverall roomOverall) {
+ callSession = roomOverall.getOcs().getData().getSessionId();
+ Log.d(TAG, " new callSession by joinRoom= " + callSession);
- @Override
- public void onError(@io.reactivex.annotations.NonNull Throwable e) {
- // unused atm
- }
+ ApplicationWideCurrentRoomHolder.getInstance().setSession(callSession);
+ ApplicationWideCurrentRoomHolder.getInstance().setCurrentRoomId(roomId);
+ ApplicationWideCurrentRoomHolder.getInstance().setCurrentRoomToken(roomToken);
+ ApplicationWideCurrentRoomHolder.getInstance().setUserInRoom(conversationUser);
+ callOrJoinRoomViaWebSocket();
+ }
- @Override
- public void onComplete() {
- // unused atm
- }
- });
+ @Override
+ public void onError(@io.reactivex.annotations.NonNull Throwable e) {
+ Log.e(TAG, "joinRoom onError", e);
+ }
+
+ @Override
+ public void onComplete() {
+ Log.d(TAG, "joinRoom onComplete");
+ }
+ });
} else {
// we are in a room and start a call -> same session needs to be used
callOrJoinRoomViaWebSocket();
@@ -1282,81 +1284,82 @@ public class CallController extends BaseController {
inCallFlag = (int) Participant.ParticipantFlags.IN_CALL_WITH_AUDIO_AND_VIDEO.getValue();
}
- int apiVersion = ApiUtils.getCallApiVersion(conversationUser, new int[] {ApiUtils.APIv4, 1});
+ int apiVersion = ApiUtils.getCallApiVersion(conversationUser, new int[]{ApiUtils.APIv4, 1});
ncApi.joinCall(credentials, ApiUtils.getUrlForCall(apiVersion, baseUrl, roomToken), inCallFlag)
- .subscribeOn(Schedulers.io())
- .retry(3)
- .observeOn(AndroidSchedulers.mainThread())
- .subscribe(new Observer() {
- @Override
- public void onSubscribe(@io.reactivex.annotations.NonNull Disposable d) {
- // unused atm
- }
+ .subscribeOn(Schedulers.io())
+ .retry(3)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(new Observer() {
+ @Override
+ public void onSubscribe(@io.reactivex.annotations.NonNull Disposable d) {
+ // unused atm
+ }
- @Override
- public void onNext(@io.reactivex.annotations.NonNull GenericOverall genericOverall) {
- if (!currentCallStatus.equals(CallStatus.LEAVING)) {
- setCallState(CallStatus.JOINED);
+ @Override
+ public void onNext(@io.reactivex.annotations.NonNull GenericOverall genericOverall) {
+ if (!currentCallStatus.equals(CallStatus.LEAVING)) {
+ setCallState(CallStatus.JOINED);
- ApplicationWideCurrentRoomHolder.getInstance().setInCall(true);
+ ApplicationWideCurrentRoomHolder.getInstance().setInCall(true);
+ ApplicationWideCurrentRoomHolder.getInstance().setDialing(false);
- if (!TextUtils.isEmpty(roomToken)) {
- NotificationUtils.INSTANCE.cancelExistingNotificationsForRoom(getApplicationContext(),
- conversationUser,
- roomToken);
- }
+ if (!TextUtils.isEmpty(roomToken)) {
+ NotificationUtils.INSTANCE.cancelExistingNotificationsForRoom(getApplicationContext(),
+ conversationUser,
+ roomToken);
+ }
- if (!hasExternalSignalingServer) {
- int apiVersion = ApiUtils.getSignalingApiVersion(conversationUser,
- new int[] {ApiUtils.APIv3, 2, 1});
+ if (!hasExternalSignalingServer) {
+ int apiVersion = ApiUtils.getSignalingApiVersion(conversationUser,
+ new int[]{ApiUtils.APIv3, 2, 1});
- ncApi.pullSignalingMessages(credentials,
- ApiUtils.getUrlForSignaling(apiVersion,
- baseUrl,
- roomToken))
- .subscribeOn(Schedulers.io())
- .observeOn(AndroidSchedulers.mainThread())
- .repeatWhen(observable -> observable)
- .takeWhile(observable -> isConnectionEstablished())
- .retry(3, observable -> isConnectionEstablished())
- .subscribe(new Observer() {
- @Override
- public void onSubscribe(@io.reactivex.annotations.NonNull Disposable d) {
- signalingDisposable = d;
- }
+ ncApi.pullSignalingMessages(credentials,
+ ApiUtils.getUrlForSignaling(apiVersion,
+ baseUrl,
+ roomToken))
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .repeatWhen(observable -> observable)
+ .takeWhile(observable -> isConnectionEstablished())
+ .retry(3, observable -> isConnectionEstablished())
+ .subscribe(new Observer() {
+ @Override
+ public void onSubscribe(@io.reactivex.annotations.NonNull Disposable d) {
+ signalingDisposable = d;
+ }
- @Override
- public void onNext(
- @io.reactivex.annotations.NonNull
- SignalingOverall signalingOverall) {
- receivedSignalingMessages(signalingOverall.getOcs().getSignalings());
- }
+ @Override
+ public void onNext(
+ @io.reactivex.annotations.NonNull
+ SignalingOverall signalingOverall) {
+ receivedSignalingMessages(signalingOverall.getOcs().getSignalings());
+ }
- @Override
- public void onError(@io.reactivex.annotations.NonNull Throwable e) {
- dispose(signalingDisposable);
- }
+ @Override
+ public void onError(@io.reactivex.annotations.NonNull Throwable e) {
+ dispose(signalingDisposable);
+ }
- @Override
- public void onComplete() {
- dispose(signalingDisposable);
- }
- });
- }
+ @Override
+ public void onComplete() {
+ dispose(signalingDisposable);
+ }
+ });
}
}
+ }
- @Override
- public void onError(@io.reactivex.annotations.NonNull Throwable e) {
- // unused atm
- }
+ @Override
+ public void onError(@io.reactivex.annotations.NonNull Throwable e) {
+ // unused atm
+ }
- @Override
- public void onComplete() {
- // unused atm
- }
- });
+ @Override
+ public void onComplete() {
+ // unused atm
+ }
+ });
}
private void setupAndInitiateWebSocketsConnection() {
@@ -1366,9 +1369,9 @@ public class CallController extends BaseController {
if (webSocketClient == null) {
webSocketClient = WebSocketConnectionHelper.getExternalSignalingInstanceForServer(
- externalSignalingServer.getExternalSignalingServer(),
- conversationUser, externalSignalingServer.getExternalSignalingTicket(),
- TextUtils.isEmpty(credentials));
+ externalSignalingServer.getExternalSignalingServer(),
+ conversationUser, externalSignalingServer.getExternalSignalingTicket(),
+ TextUtils.isEmpty(credentials));
} else {
if (webSocketClient.isConnected() && currentCallStatus.equals(CallStatus.PUBLISHER_FAILED)) {
webSocketClient.restartWebSocket();
@@ -1408,27 +1411,22 @@ public class CallController extends BaseController {
case "participantsUpdate":
if (webSocketCommunicationEvent.getHashMap().get("roomToken").equals(roomToken)) {
processUsersInRoom(
- (List>) webSocketClient
- .getJobWithId(
- Integer.valueOf(webSocketCommunicationEvent.getHashMap().get("jobId"))));
+ (List>) webSocketClient
+ .getJobWithId(
+ Integer.valueOf(webSocketCommunicationEvent.getHashMap().get("jobId"))));
}
break;
case "signalingMessage":
processMessage((NCSignalingMessage) webSocketClient.getJobWithId(
- Integer.valueOf(webSocketCommunicationEvent.getHashMap().get("jobId"))));
+ Integer.valueOf(webSocketCommunicationEvent.getHashMap().get("jobId"))));
break;
case "peerReadyForRequestingOffer":
webSocketClient.requestOfferForSessionIdWithType(
- webSocketCommunicationEvent.getHashMap().get("sessionId"), "video");
+ webSocketCommunicationEvent.getHashMap().get("sessionId"), "video");
break;
}
}
- @OnItemClick({R.id.gridview})
- public void showCallControls() {
- animateCallControls(true, 0);
- }
-
private void dispose(@Nullable Disposable disposable) {
if (disposable != null && !disposable.isDisposed()) {
disposable.dispose();
@@ -1473,8 +1471,8 @@ public class CallController extends BaseController {
private void processMessage(NCSignalingMessage ncSignalingMessage) {
if (ncSignalingMessage.getRoomType().equals("video") || ncSignalingMessage.getRoomType().equals("screen")) {
MagicPeerConnectionWrapper magicPeerConnectionWrapper =
- getPeerConnectionWrapperForSessionIdAndType(ncSignalingMessage.getFrom(),
- ncSignalingMessage.getRoomType(), false);
+ getPeerConnectionWrapperForSessionIdAndType(ncSignalingMessage.getFrom(),
+ ncSignalingMessage.getRoomType(), false);
String type = null;
if (ncSignalingMessage.getPayload() != null && ncSignalingMessage.getPayload().getType() != null) {
@@ -1494,16 +1492,16 @@ public class CallController extends BaseController {
SessionDescription sessionDescriptionWithPreferredCodec;
String sessionDescriptionStringWithPreferredCodec = MagicWebRTCUtils.preferCodec
- (ncSignalingMessage.getPayload().getSdp(),
- "H264", false);
+ (ncSignalingMessage.getPayload().getSdp(),
+ "H264", false);
sessionDescriptionWithPreferredCodec = new SessionDescription(
- SessionDescription.Type.fromCanonicalForm(type),
- sessionDescriptionStringWithPreferredCodec);
+ SessionDescription.Type.fromCanonicalForm(type),
+ sessionDescriptionStringWithPreferredCodec);
if (magicPeerConnectionWrapper.getPeerConnection() != null) {
magicPeerConnectionWrapper.getPeerConnection().setRemoteDescription(magicPeerConnectionWrapper
- .getMagicSdpObserver(), sessionDescriptionWithPreferredCodec);
+ .getMagicSdpObserver(), sessionDescriptionWithPreferredCodec);
}
break;
case "candidate":
@@ -1540,8 +1538,8 @@ public class CallController extends BaseController {
videoCapturer = null;
}
- if (pipVideoView != null) {
- pipVideoView.release();
+ if (binding.selfVideoRenderer != null) {
+ binding.selfVideoRenderer.release();
}
if (audioSource != null) {
@@ -1577,72 +1575,74 @@ public class CallController extends BaseController {
}
hangupNetworkCalls(shutDownView);
+ ApplicationWideCurrentRoomHolder.getInstance().setInCall(false);
}
private void hangupNetworkCalls(boolean shutDownView) {
- int apiVersion = ApiUtils.getCallApiVersion(conversationUser, new int[] {ApiUtils.APIv4, 1});
+ int apiVersion = ApiUtils.getCallApiVersion(conversationUser, new int[]{ApiUtils.APIv4, 1});
ncApi.leaveCall(credentials, ApiUtils.getUrlForCall(apiVersion, baseUrl, roomToken))
- .subscribeOn(Schedulers.io())
- .observeOn(AndroidSchedulers.mainThread())
- .subscribe(new Observer() {
- @Override
- public void onSubscribe(@io.reactivex.annotations.NonNull Disposable d) {
- // unused atm
- }
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(new Observer() {
+ @Override
+ public void onSubscribe(@io.reactivex.annotations.NonNull Disposable d) {
+ // unused atm
+ }
- @Override
- public void onNext(@io.reactivex.annotations.NonNull GenericOverall genericOverall) {
- if (shutDownView && getActivity() != null) {
- getActivity().finish();
- } else if (!shutDownView &&
- (currentCallStatus == CallStatus.RECONNECTING ||
- currentCallStatus == CallStatus.PUBLISHER_FAILED)) {
- initiateCall();
- }
+ @Override
+ public void onNext(@io.reactivex.annotations.NonNull GenericOverall genericOverall) {
+ if (shutDownView) {
+ finish();
+ } else if (!shutDownView &&
+ (currentCallStatus == CallStatus.RECONNECTING ||
+ currentCallStatus == CallStatus.PUBLISHER_FAILED)) {
+ initiateCall();
}
+ }
- @Override
- public void onError(@io.reactivex.annotations.NonNull Throwable e) {
- // unused atm
- }
+ @Override
+ public void onError(@io.reactivex.annotations.NonNull Throwable e) {
+ // unused atm
+ }
- @Override
- public void onComplete() {
- // unused atm
- }
- });
+ @Override
+ public void onComplete() {
+ // unused atm
+ }
+ });
}
+ // TODO: why is this never called?!
private void leaveRoom(boolean shutDownView) {
- int apiVersion = ApiUtils.getConversationApiVersion(conversationUser, new int[] {ApiUtils.APIv4, 1});
+ int apiVersion = ApiUtils.getConversationApiVersion(conversationUser, new int[]{ApiUtils.APIv4, 1});
ncApi.leaveRoom(credentials, ApiUtils.getUrlForParticipantsActive(apiVersion, baseUrl, roomToken))
- .subscribeOn(Schedulers.io())
- .observeOn(AndroidSchedulers.mainThread())
- .subscribe(new Observer() {
- @Override
- public void onSubscribe(@io.reactivex.annotations.NonNull Disposable d) {
- // unused atm
- }
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(new Observer() {
+ @Override
+ public void onSubscribe(@io.reactivex.annotations.NonNull Disposable d) {
+ // unused atm
+ }
- @Override
- public void onNext(@io.reactivex.annotations.NonNull GenericOverall genericOverall) {
- if (shutDownView && getActivity() != null) {
- getActivity().finish();
- }
+ @Override
+ public void onNext(@io.reactivex.annotations.NonNull GenericOverall genericOverall) {
+ if (shutDownView) {
+ finish();
}
+ }
- @Override
- public void onError(@io.reactivex.annotations.NonNull Throwable e) {
- // unused atm
- }
+ @Override
+ public void onError(@io.reactivex.annotations.NonNull Throwable e) {
+ // unused atm
+ }
- @Override
- public void onComplete() {
- // unused atm
- }
- });
+ @Override
+ public void onComplete() {
+ // unused atm
+ }
+ });
}
private void startVideoCapture() {
@@ -1721,34 +1721,34 @@ public class CallController extends BaseController {
private void getPeersForCall() {
Log.d(TAG, "getPeersForCall");
- int apiVersion = ApiUtils.getCallApiVersion(conversationUser, new int[] {ApiUtils.APIv4, 1});
+ int apiVersion = ApiUtils.getCallApiVersion(conversationUser, new int[]{ApiUtils.APIv4, 1});
ncApi.getPeersForCall(credentials, ApiUtils.getUrlForCall(apiVersion, baseUrl, roomToken))
- .subscribeOn(Schedulers.io())
- .subscribe(new Observer() {
- @Override
- public void onSubscribe(@io.reactivex.annotations.NonNull Disposable d) {
- // unused atm
- }
+ .subscribeOn(Schedulers.io())
+ .subscribe(new Observer() {
+ @Override
+ public void onSubscribe(@io.reactivex.annotations.NonNull Disposable d) {
+ // unused atm
+ }
- @Override
- public void onNext(@io.reactivex.annotations.NonNull ParticipantsOverall participantsOverall) {
- participantMap = new HashMap<>();
- for (Participant participant : participantsOverall.getOcs().getData()) {
- participantMap.put(participant.getSessionId(), participant);
- }
+ @Override
+ public void onNext(@io.reactivex.annotations.NonNull ParticipantsOverall participantsOverall) {
+ participantMap = new HashMap<>();
+ for (Participant participant : participantsOverall.getOcs().getData()) {
+ participantMap.put(participant.getSessionId(), participant);
}
+ }
- @Override
- public void onError(@io.reactivex.annotations.NonNull Throwable e) {
- Log.e(TAG, "error while executing getPeersForCall", e);
- }
+ @Override
+ public void onError(@io.reactivex.annotations.NonNull Throwable e) {
+ Log.e(TAG, "error while executing getPeersForCall", e);
+ }
- @Override
- public void onComplete() {
- // unused atm
- }
- });
+ @Override
+ public void onComplete() {
+ // unused atm
+ }
+ });
}
private void deleteMagicPeerConnection(MagicPeerConnectionWrapper magicPeerConnectionWrapper) {
@@ -1839,16 +1839,12 @@ public class CallController extends BaseController {
private void endPeerConnection(String sessionId, boolean justScreen) {
List magicPeerConnectionWrappers;
MagicPeerConnectionWrapper magicPeerConnectionWrapper;
- if (!(magicPeerConnectionWrappers = getPeerConnectionWrapperListForSessionId(sessionId)).isEmpty()
- && getActivity() != null) {
+ if (!(magicPeerConnectionWrappers = getPeerConnectionWrapperListForSessionId(sessionId)).isEmpty()) {
for (int i = 0; i < magicPeerConnectionWrappers.size(); i++) {
magicPeerConnectionWrapper = magicPeerConnectionWrappers.get(i);
if (magicPeerConnectionWrapper.getSessionId().equals(sessionId)) {
if (magicPeerConnectionWrapper.getVideoStreamType().equals("screen") || !justScreen) {
-
-
- // TODO runOnUiThread not necessary???
- getActivity().runOnUiThread(() -> removeMediaStream(sessionId));
+ runOnUiThread(() -> removeMediaStream(sessionId));
deleteMagicPeerConnection(magicPeerConnectionWrapper);
}
}
@@ -1860,11 +1856,11 @@ public class CallController extends BaseController {
Log.d(TAG, "removeMediaStream");
participantDisplayItems.remove(sessionId);
- if (!isBeingDestroyed() && !isDestroyed()) {
+ if (!isDestroyed()) {
initGridAdapter();
- if (callControls != null) {
- callControls.setZ(100.0f);
+ if (binding.callControls != null) {
+ binding.callControls.setZ(100.0f);
}
}
}
@@ -1873,40 +1869,43 @@ public class CallController extends BaseController {
public void onMessageEvent(ConfigurationChangeEvent configurationChangeEvent) {
powerManagerUtils.setOrientation(Objects.requireNonNull(getResources()).getConfiguration().orientation);
initGridAdapter();
- initPipView();
+ updateSelfVideoViewPosition();
}
- private void initPipView() {
- FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) pipVideoView.getLayoutParams();
+ private void updateSelfVideoViewPosition() {
+ Log.d(TAG, "updateSelfVideoViewPosition");
+ if (!isInPipMode) {
+ FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) binding.selfVideoRenderer.getLayoutParams();
- DisplayMetrics displayMetrics = getApplicationContext().getResources().getDisplayMetrics();
- int screenWidthPx = displayMetrics.widthPixels;
+ DisplayMetrics displayMetrics = getApplicationContext().getResources().getDisplayMetrics();
+ int screenWidthPx = displayMetrics.widthPixels;
- int screenWidthDp = (int) DisplayUtils.convertPixelToDp(screenWidthPx, getApplicationContext());
+ int screenWidthDp = (int) DisplayUtils.convertPixelToDp(screenWidthPx, getApplicationContext());
- float newXafterRotate = 0;
- float newYafterRotate;
- if (callInfosLinearLayout.getVisibility() == View.VISIBLE) {
- newYafterRotate = 250;
- } else {
- newYafterRotate = 20;
+ float newXafterRotate = 0;
+ float newYafterRotate;
+ if (binding.callInfosLinearLayout.getVisibility() == View.VISIBLE) {
+ newYafterRotate = 250;
+ } else {
+ newYafterRotate = 20;
+ }
+
+ if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
+ layoutParams.height = (int) getResources().getDimension(R.dimen.large_preview_dimension);
+ layoutParams.width = FrameLayout.LayoutParams.WRAP_CONTENT;
+ newXafterRotate = (float) (screenWidthDp - getResources().getDimension(R.dimen.large_preview_dimension) * 0.8);
+
+ } else if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
+ layoutParams.height = FrameLayout.LayoutParams.WRAP_CONTENT;
+ layoutParams.width = (int) getResources().getDimension(R.dimen.large_preview_dimension);
+ newXafterRotate = (float) (screenWidthDp - getResources().getDimension(R.dimen.large_preview_dimension) * 0.5);
+ }
+ binding.selfVideoRenderer.setLayoutParams(layoutParams);
+
+ int newXafterRotatePx = (int) DisplayUtils.convertDpToPixel(newXafterRotate, getApplicationContext());
+ binding.selfVideoViewWrapper.setY(newYafterRotate);
+ binding.selfVideoViewWrapper.setX(newXafterRotatePx);
}
-
- if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
- layoutParams.height = (int) getResources().getDimension(R.dimen.large_preview_dimension);
- layoutParams.width = FrameLayout.LayoutParams.WRAP_CONTENT;
- newXafterRotate = (float) (screenWidthDp - getResources().getDimension(R.dimen.large_preview_dimension) * 0.8);
-
- } else if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
- layoutParams.height = FrameLayout.LayoutParams.WRAP_CONTENT;
- layoutParams.width = (int) getResources().getDimension(R.dimen.large_preview_dimension);
- newXafterRotate = (float) (screenWidthDp - getResources().getDimension(R.dimen.large_preview_dimension) * 0.5);
- }
- pipVideoView.setLayoutParams(layoutParams);
-
- int newXafterRotatePx = (int) DisplayUtils.convertDpToPixel(newXafterRotate, getApplicationContext());
- selfVideoView.setY(newYafterRotate);
- selfVideoView.setX(newXafterRotatePx);
}
@Subscribe(threadMode = ThreadMode.MAIN)
@@ -1914,19 +1913,19 @@ public class CallController extends BaseController {
String sessionId = peerConnectionEvent.getSessionId();
if (peerConnectionEvent.getPeerConnectionEventType().equals(PeerConnectionEvent.PeerConnectionEventType
- .PEER_CLOSED)) {
+ .PEER_CLOSED)) {
endPeerConnection(sessionId, peerConnectionEvent.getVideoStreamType().equals("screen"));
} else if (peerConnectionEvent.getPeerConnectionEventType().equals(PeerConnectionEvent
- .PeerConnectionEventType.SENSOR_FAR) ||
- peerConnectionEvent.getPeerConnectionEventType().equals(PeerConnectionEvent
- .PeerConnectionEventType.SENSOR_NEAR)) {
+ .PeerConnectionEventType.SENSOR_FAR) ||
+ peerConnectionEvent.getPeerConnectionEventType().equals(PeerConnectionEvent
+ .PeerConnectionEventType.SENSOR_NEAR)) {
if (!isVoiceOnlyCall) {
boolean enableVideo = peerConnectionEvent.getPeerConnectionEventType().equals(PeerConnectionEvent
- .PeerConnectionEventType.SENSOR_FAR) && videoOn;
- if (getActivity() != null && EffortlessPermissions.hasPermissions(getActivity(), PERMISSIONS_CAMERA) &&
- (currentCallStatus.equals(CallStatus.CONNECTING) || isConnectionEstablished()) && videoOn
- && enableVideo != localVideoTrack.enabled()) {
+ .PeerConnectionEventType.SENSOR_FAR) && videoOn;
+ if (EffortlessPermissions.hasPermissions(this, PERMISSIONS_CAMERA) &&
+ (currentCallStatus.equals(CallStatus.CONNECTING) || isConnectionEstablished()) && videoOn
+ && enableVideo != localVideoTrack.enabled()) {
toggleMedia(enableVideo, true);
}
}
@@ -1967,30 +1966,30 @@ public class CallController extends BaseController {
if (magicPeerConnectionWrapperList.get(i).isMCUPublisher()) {
magicPeerConnectionWrapper = magicPeerConnectionWrapperList.get(i);
Observable
- .interval(1, TimeUnit.SECONDS)
- .repeatUntil(() -> (!isConnectionEstablished() || isBeingDestroyed() || isDestroyed()))
- .observeOn(Schedulers.io())
- .subscribe(new Observer() {
- @Override
- public void onSubscribe(@io.reactivex.annotations.NonNull Disposable d) {
- // unused atm
- }
+ .interval(1, TimeUnit.SECONDS)
+ .repeatUntil(() -> (!isConnectionEstablished() || isDestroyed()))
+ .observeOn(Schedulers.io())
+ .subscribe(new Observer() {
+ @Override
+ public void onSubscribe(@io.reactivex.annotations.NonNull Disposable d) {
+ // unused atm
+ }
- @Override
- public void onNext(@io.reactivex.annotations.NonNull Long aLong) {
- magicPeerConnectionWrapper.sendNickChannelData(dataChannelMessage);
- }
+ @Override
+ public void onNext(@io.reactivex.annotations.NonNull Long aLong) {
+ magicPeerConnectionWrapper.sendNickChannelData(dataChannelMessage);
+ }
- @Override
- public void onError(@io.reactivex.annotations.NonNull Throwable e) {
- // unused atm
- }
+ @Override
+ public void onError(@io.reactivex.annotations.NonNull Throwable e) {
+ // unused atm
+ }
- @Override
- public void onComplete() {
- // unused atm
- }
- });
+ @Override
+ public void onComplete() {
+ // unused atm
+ }
+ });
break;
}
@@ -2001,19 +2000,19 @@ public class CallController extends BaseController {
public void onMessageEvent(MediaStreamEvent mediaStreamEvent) {
if (mediaStreamEvent.getMediaStream() != null) {
boolean hasAtLeastOneVideoStream = mediaStreamEvent.getMediaStream().videoTracks != null
- && mediaStreamEvent.getMediaStream().videoTracks.size() > 0;
+ && mediaStreamEvent.getMediaStream().videoTracks.size() > 0;
setupVideoStreamForLayout(
- mediaStreamEvent.getMediaStream(),
- mediaStreamEvent.getSession(),
- hasAtLeastOneVideoStream,
- mediaStreamEvent.getVideoStreamType());
+ mediaStreamEvent.getMediaStream(),
+ mediaStreamEvent.getSession(),
+ hasAtLeastOneVideoStream,
+ mediaStreamEvent.getVideoStreamType());
} else {
setupVideoStreamForLayout(
- null,
- mediaStreamEvent.getSession(),
- false,
- mediaStreamEvent.getVideoStreamType());
+ null,
+ mediaStreamEvent.getSession(),
+ false,
+ mediaStreamEvent.getVideoStreamType());
}
}
@@ -2045,46 +2044,46 @@ public class CallController extends BaseController {
if (!hasExternalSignalingServer) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("{")
- .append("\"fn\":\"")
- .append(StringEscapeUtils.escapeJson(LoganSquare.serialize(ncMessageWrapper.getSignalingMessage()))).append("\"")
- .append(",")
- .append("\"sessionId\":")
- .append("\"").append(StringEscapeUtils.escapeJson(callSession)).append("\"")
- .append(",")
- .append("\"ev\":\"message\"")
- .append("}");
+ .append("\"fn\":\"")
+ .append(StringEscapeUtils.escapeJson(LoganSquare.serialize(ncMessageWrapper.getSignalingMessage()))).append("\"")
+ .append(",")
+ .append("\"sessionId\":")
+ .append("\"").append(StringEscapeUtils.escapeJson(callSession)).append("\"")
+ .append(",")
+ .append("\"ev\":\"message\"")
+ .append("}");
List strings = new ArrayList<>();
String stringToSend = stringBuilder.toString();
strings.add(stringToSend);
- int apiVersion = ApiUtils.getSignalingApiVersion(conversationUser, new int[] {ApiUtils.APIv3, 2, 1});
+ int apiVersion = ApiUtils.getSignalingApiVersion(conversationUser, new int[]{ApiUtils.APIv3, 2, 1});
ncApi.sendSignalingMessages(credentials, ApiUtils.getUrlForSignaling(apiVersion, baseUrl, roomToken),
strings.toString())
- .retry(3)
- .subscribeOn(Schedulers.io())
- .subscribe(new Observer() {
- @Override
- public void onSubscribe(@io.reactivex.annotations.NonNull Disposable d) {
- // unused atm
- }
+ .retry(3)
+ .subscribeOn(Schedulers.io())
+ .subscribe(new Observer() {
+ @Override
+ public void onSubscribe(@io.reactivex.annotations.NonNull Disposable d) {
+ // unused atm
+ }
- @Override
- public void onNext(@io.reactivex.annotations.NonNull SignalingOverall signalingOverall) {
- receivedSignalingMessages(signalingOverall.getOcs().getSignalings());
- }
+ @Override
+ public void onNext(@io.reactivex.annotations.NonNull SignalingOverall signalingOverall) {
+ receivedSignalingMessages(signalingOverall.getOcs().getSignalings());
+ }
- @Override
- public void onError(@io.reactivex.annotations.NonNull Throwable e) {
- Log.e(TAG, "", e);
- }
+ @Override
+ public void onError(@io.reactivex.annotations.NonNull Throwable e) {
+ Log.e(TAG, "", e);
+ }
- @Override
- public void onComplete() {
- // unused atm
- }
- });
+ @Override
+ public void onComplete() {
+ // unused atm
+ }
+ });
} else {
webSocketClient.sendCallMessage(ncMessageWrapper);
}
@@ -2136,15 +2135,7 @@ public class CallController extends BaseController {
participantDisplayItems.put(session, participantDisplayItem);
initGridAdapter();
- callControls.setZ(100.0f);
- }
-
- @OnClick(R.id.callStateRelativeLayoutView)
- public void onConnectingViewClick() {
- if (currentCallStatus.equals(CallStatus.CALLING_TIMEOUT)) {
- setCallState(CallStatus.RECONNECTING);
- hangupNetworkCalls(false);
- }
+ binding.callControls.setZ(100.0f);
}
private void setCallState(CallStatus callState) {
@@ -2161,105 +2152,105 @@ public class CallController extends BaseController {
handler.post(() -> {
playCallingSound();
if (isIncomingCallFromNotification) {
- callStateTextView.setText(R.string.nc_call_incoming);
+ binding.callStates.callStateTextView.setText(R.string.nc_call_incoming);
} else {
- callStateTextView.setText(R.string.nc_call_ringing);
+ binding.callStates.callStateTextView.setText(R.string.nc_call_ringing);
}
- callConversationNameTextView.setText(conversationName);
+ binding.callConversationNameTextView.setText(conversationName);
- callVoiceOrVideoTextView.setText(getDescriptionForCallType());
+ binding.callModeTextView.setText(getDescriptionForCallType());
- if (callStateView.getVisibility() != View.VISIBLE) {
- callStateView.setVisibility(View.VISIBLE);
+ if (binding.callStates.callStateRelativeLayout.getVisibility() != View.VISIBLE) {
+ binding.callStates.callStateRelativeLayout.setVisibility(View.VISIBLE);
}
- if (gridView.getVisibility() != View.INVISIBLE) {
- gridView.setVisibility(View.INVISIBLE);
+ if (binding.gridview.getVisibility() != View.INVISIBLE) {
+ binding.gridview.setVisibility(View.INVISIBLE);
}
- if (progressBar.getVisibility() != View.VISIBLE) {
- progressBar.setVisibility(View.VISIBLE);
+ if (binding.callStates.callStateProgressBar.getVisibility() != View.VISIBLE) {
+ binding.callStates.callStateProgressBar.setVisibility(View.VISIBLE);
}
- if (errorImageView.getVisibility() != View.GONE) {
- errorImageView.setVisibility(View.GONE);
+ if (binding.callStates.errorImageView.getVisibility() != View.GONE) {
+ binding.callStates.errorImageView.setVisibility(View.GONE);
}
});
break;
case CALLING_TIMEOUT:
handler.post(() -> {
hangup(false);
- callStateTextView.setText(R.string.nc_call_timeout);
- callVoiceOrVideoTextView.setText(getDescriptionForCallType());
- if (callStateView.getVisibility() != View.VISIBLE) {
- callStateView.setVisibility(View.VISIBLE);
+ binding.callStates.callStateTextView.setText(R.string.nc_call_timeout);
+ binding.callModeTextView.setText(getDescriptionForCallType());
+ if (binding.callStates.callStateRelativeLayout.getVisibility() != View.VISIBLE) {
+ binding.callStates.callStateRelativeLayout.setVisibility(View.VISIBLE);
}
- if (progressBar.getVisibility() != View.GONE) {
- progressBar.setVisibility(View.GONE);
+ if (binding.callStates.callStateProgressBar.getVisibility() != View.GONE) {
+ binding.callStates.callStateProgressBar.setVisibility(View.GONE);
}
- if (gridView.getVisibility() != View.INVISIBLE) {
- gridView.setVisibility(View.INVISIBLE);
+ if (binding.gridview.getVisibility() != View.INVISIBLE) {
+ binding.gridview.setVisibility(View.INVISIBLE);
}
- errorImageView.setImageResource(R.drawable.ic_av_timer_timer_24dp);
+ binding.callStates.errorImageView.setImageResource(R.drawable.ic_av_timer_timer_24dp);
- if (errorImageView.getVisibility() != View.VISIBLE) {
- errorImageView.setVisibility(View.VISIBLE);
+ if (binding.callStates.errorImageView.getVisibility() != View.VISIBLE) {
+ binding.callStates.errorImageView.setVisibility(View.VISIBLE);
}
});
break;
case RECONNECTING:
handler.post(() -> {
playCallingSound();
- callStateTextView.setText(R.string.nc_call_reconnecting);
- callVoiceOrVideoTextView.setText(getDescriptionForCallType());
- if (callStateView.getVisibility() != View.VISIBLE) {
- callStateView.setVisibility(View.VISIBLE);
+ binding.callStates.callStateTextView.setText(R.string.nc_call_reconnecting);
+ binding.callModeTextView.setText(getDescriptionForCallType());
+ if (binding.callStates.callStateRelativeLayout.getVisibility() != View.VISIBLE) {
+ binding.callStates.callStateRelativeLayout.setVisibility(View.VISIBLE);
}
- if (gridView.getVisibility() != View.INVISIBLE) {
- gridView.setVisibility(View.INVISIBLE);
+ if (binding.gridview.getVisibility() != View.INVISIBLE) {
+ binding.gridview.setVisibility(View.INVISIBLE);
}
- if (progressBar.getVisibility() != View.VISIBLE) {
- progressBar.setVisibility(View.VISIBLE);
+ if (binding.callStates.callStateProgressBar.getVisibility() != View.VISIBLE) {
+ binding.callStates.callStateProgressBar.setVisibility(View.VISIBLE);
}
- if (errorImageView.getVisibility() != View.GONE) {
- errorImageView.setVisibility(View.GONE);
+ if (binding.callStates.errorImageView.getVisibility() != View.GONE) {
+ binding.callStates.errorImageView.setVisibility(View.GONE);
}
});
break;
case JOINED:
handler.postDelayed(() -> setCallState(CallStatus.CALLING_TIMEOUT), 45000);
handler.post(() -> {
- callVoiceOrVideoTextView.setText(getDescriptionForCallType());
- if (callStateView != null) {
+ binding.callModeTextView.setText(getDescriptionForCallType());
+ if (binding.callStates.callStateRelativeLayout != null) {
if (isIncomingCallFromNotification) {
- callStateTextView.setText(R.string.nc_call_incoming);
+ binding.callStates.callStateTextView.setText(R.string.nc_call_incoming);
} else {
- callStateTextView.setText(R.string.nc_call_ringing);
+ binding.callStates.callStateTextView.setText(R.string.nc_call_ringing);
}
- if (callStateView.getVisibility() != View.VISIBLE) {
- callStateView.setVisibility(View.VISIBLE);
+ if (binding.callStates.callStateRelativeLayout.getVisibility() != View.VISIBLE) {
+ binding.callStates.callStateRelativeLayout.setVisibility(View.VISIBLE);
}
}
- if (progressBar != null) {
- if (progressBar.getVisibility() != View.VISIBLE) {
- progressBar.setVisibility(View.VISIBLE);
+ if (binding.callStates.callStateProgressBar != null) {
+ if (binding.callStates.callStateProgressBar.getVisibility() != View.VISIBLE) {
+ binding.callStates.callStateProgressBar.setVisibility(View.VISIBLE);
}
}
- if (gridView != null) {
- if (gridView.getVisibility() != View.INVISIBLE) {
- gridView.setVisibility(View.INVISIBLE);
+ if (binding.gridview != null) {
+ if (binding.gridview.getVisibility() != View.INVISIBLE) {
+ binding.gridview.setVisibility(View.INVISIBLE);
}
}
- if (errorImageView != null) {
- if (errorImageView.getVisibility() != View.GONE) {
- errorImageView.setVisibility(View.GONE);
+ if (binding.callStates.errorImageView != null) {
+ if (binding.callStates.errorImageView.getVisibility() != View.GONE) {
+ binding.callStates.errorImageView.setVisibility(View.GONE);
}
}
});
@@ -2267,37 +2258,37 @@ public class CallController extends BaseController {
case IN_CONVERSATION:
handler.post(() -> {
stopCallingSound();
- callVoiceOrVideoTextView.setText(getDescriptionForCallType());
+ binding.callModeTextView.setText(getDescriptionForCallType());
if (!isVoiceOnlyCall) {
- callInfosLinearLayout.setVisibility(View.GONE);
+ binding.callInfosLinearLayout.setVisibility(View.GONE);
}
if (!isPTTActive) {
animateCallControls(false, 5000);
}
- if (callStateView != null) {
- if (callStateView.getVisibility() != View.INVISIBLE) {
- callStateView.setVisibility(View.INVISIBLE);
+ if (binding.callStates.callStateRelativeLayout != null) {
+ if (binding.callStates.callStateRelativeLayout.getVisibility() != View.INVISIBLE) {
+ binding.callStates.callStateRelativeLayout.setVisibility(View.INVISIBLE);
}
}
- if (progressBar != null) {
- if (progressBar.getVisibility() != View.GONE) {
- progressBar.setVisibility(View.GONE);
+ if (binding.callStates.callStateProgressBar != null) {
+ if (binding.callStates.callStateProgressBar.getVisibility() != View.GONE) {
+ binding.callStates.callStateProgressBar.setVisibility(View.GONE);
}
}
- if (gridView != null) {
- if (gridView.getVisibility() != View.VISIBLE) {
- gridView.setVisibility(View.VISIBLE);
+ if (binding.gridview != null) {
+ if (binding.gridview.getVisibility() != View.VISIBLE) {
+ binding.gridview.setVisibility(View.VISIBLE);
}
}
- if (errorImageView != null) {
- if (errorImageView.getVisibility() != View.GONE) {
- errorImageView.setVisibility(View.GONE);
+ if (binding.callStates.errorImageView != null) {
+ if (binding.callStates.errorImageView.getVisibility() != View.GONE) {
+ binding.callStates.errorImageView.setVisibility(View.GONE);
}
}
});
@@ -2306,45 +2297,45 @@ public class CallController extends BaseController {
handler.post(() -> {
stopCallingSound();
- if (callStateTextView != null) {
- callStateTextView.setText(R.string.nc_offline);
+ if (binding.callStates.callStateTextView != null) {
+ binding.callStates.callStateTextView.setText(R.string.nc_offline);
- if (callStateView.getVisibility() != View.VISIBLE) {
- callStateView.setVisibility(View.VISIBLE);
+ if (binding.callStates.callStateRelativeLayout.getVisibility() != View.VISIBLE) {
+ binding.callStates.callStateRelativeLayout.setVisibility(View.VISIBLE);
}
}
- if (gridView != null) {
- if (gridView.getVisibility() != View.INVISIBLE) {
- gridView.setVisibility(View.INVISIBLE);
+ if (binding.gridview != null) {
+ if (binding.gridview.getVisibility() != View.INVISIBLE) {
+ binding.gridview.setVisibility(View.INVISIBLE);
}
}
- if (progressBar != null) {
- if (progressBar.getVisibility() != View.GONE) {
- progressBar.setVisibility(View.GONE);
+ if (binding.callStates.callStateProgressBar != null) {
+ if (binding.callStates.callStateProgressBar.getVisibility() != View.GONE) {
+ binding.callStates.callStateProgressBar.setVisibility(View.GONE);
}
}
- if (errorImageView != null) {
- errorImageView.setImageResource(R.drawable.ic_signal_wifi_off_white_24dp);
- if (errorImageView.getVisibility() != View.VISIBLE) {
- errorImageView.setVisibility(View.VISIBLE);
+ if (binding.callStates.errorImageView != null) {
+ binding.callStates.errorImageView.setImageResource(R.drawable.ic_signal_wifi_off_white_24dp);
+ if (binding.callStates.errorImageView.getVisibility() != View.VISIBLE) {
+ binding.callStates.errorImageView.setVisibility(View.VISIBLE);
}
}
});
break;
case LEAVING:
handler.post(() -> {
- if (!isDestroyed() && !isBeingDestroyed()) {
+ if (!isDestroyed()) {
stopCallingSound();
- callVoiceOrVideoTextView.setText(getDescriptionForCallType());
- callStateTextView.setText(R.string.nc_leaving_call);
- callStateView.setVisibility(View.VISIBLE);
- gridView.setVisibility(View.INVISIBLE);
- progressBar.setVisibility(View.VISIBLE);
- errorImageView.setVisibility(View.GONE);
+ binding.callModeTextView.setText(getDescriptionForCallType());
+ binding.callStates.callStateTextView.setText(R.string.nc_leaving_call);
+ binding.callStates.callStateRelativeLayout.setVisibility(View.VISIBLE);
+ binding.gridview.setVisibility(View.INVISIBLE);
+ binding.callStates.callStateProgressBar.setVisibility(View.VISIBLE);
+ binding.callStates.errorImageView.setVisibility(View.GONE);
}
});
break;
@@ -2367,29 +2358,28 @@ public class CallController extends BaseController {
Uri ringtoneUri;
if (isIncomingCallFromNotification) {
ringtoneUri = Uri.parse("android.resource://" + getApplicationContext().getPackageName() +
- "/raw/librem_by_feandesign_call");
+ "/raw/librem_by_feandesign_call");
} else {
ringtoneUri = Uri.parse("android.resource://" + getApplicationContext().getPackageName() + "/raw" +
- "/tr110_1_kap8_3_freiton1");
+ "/tr110_1_kap8_3_freiton1");
}
- if (getActivity() != null) {
- mediaPlayer = new MediaPlayer();
- try {
- mediaPlayer.setDataSource(Objects.requireNonNull(getActivity()), ringtoneUri);
- mediaPlayer.setLooping(true);
- AudioAttributes audioAttributes = new AudioAttributes.Builder().setContentType(
- AudioAttributes.CONTENT_TYPE_SONIFICATION)
- .setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION)
- .build();
- mediaPlayer.setAudioAttributes(audioAttributes);
- mediaPlayer.setOnPreparedListener(mp -> mediaPlayer.start());
+ mediaPlayer = new MediaPlayer();
+ try {
+ mediaPlayer.setDataSource(this, ringtoneUri);
+ mediaPlayer.setLooping(true);
+ AudioAttributes audioAttributes = new AudioAttributes.Builder().setContentType(
+ AudioAttributes.CONTENT_TYPE_SONIFICATION)
+ .setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION)
+ .build();
+ mediaPlayer.setAudioAttributes(audioAttributes);
- mediaPlayer.prepareAsync();
+ mediaPlayer.setOnPreparedListener(mp -> mediaPlayer.start());
- } catch (IOException e) {
- Log.e(TAG, "Failed to play sound");
- }
+ mediaPlayer.prepareAsync();
+
+ } catch (IOException e) {
+ Log.e(TAG, "Failed to play sound");
}
}
@@ -2404,18 +2394,6 @@ public class CallController extends BaseController {
}
}
- @Override
- protected void onAttach(@NonNull View view) {
- super.onAttach(view);
- eventBus.register(this);
- }
-
- @Override
- protected void onDetach(@NonNull View view) {
- super.onDetach(view);
- eventBus.unregister(this);
- }
-
private class MicrophoneButtonTouchListener implements View.OnTouchListener {
@SuppressLint("ClickableViewAccessibility")
@@ -2424,7 +2402,7 @@ public class CallController extends BaseController {
v.onTouchEvent(event);
if (event.getAction() == MotionEvent.ACTION_UP && isPTTActive) {
isPTTActive = false;
- microphoneControlButton.getHierarchy().setPlaceholderImage(R.drawable.ic_mic_off_white_24px);
+ binding.microphoneButton.getHierarchy().setPlaceholderImage(R.drawable.ic_mic_off_white_24px);
pulseAnimation.stop();
toggleMedia(false, false);
animateCallControls(false, 5000);
@@ -2436,18 +2414,125 @@ public class CallController extends BaseController {
@Subscribe(threadMode = ThreadMode.BACKGROUND)
public void onMessageEvent(NetworkEvent networkEvent) {
if (networkEvent.getNetworkConnectionEvent()
- .equals(NetworkEvent.NetworkConnectionEvent.NETWORK_CONNECTED)) {
+ .equals(NetworkEvent.NetworkConnectionEvent.NETWORK_CONNECTED)) {
if (handler != null) {
handler.removeCallbacksAndMessages(null);
}
} else if (networkEvent.getNetworkConnectionEvent()
- .equals(NetworkEvent.NetworkConnectionEvent.NETWORK_DISCONNECTED)) {
+ .equals(NetworkEvent.NetworkConnectionEvent.NETWORK_DISCONNECTED)) {
if (handler != null) {
handler.removeCallbacksAndMessages(null);
}
}
}
+ @RequiresApi(api = Build.VERSION_CODES.O)
+ @Override
+ public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode, Configuration newConfig) {
+ super.onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig);
+ Log.d(TAG, "onPictureInPictureModeChanged");
+ Log.d(TAG, "isInPictureInPictureMode= " + isInPictureInPictureMode);
+ isInPipMode = isInPictureInPictureMode;
+ if (isInPictureInPictureMode) {
+ mReceiver =
+ new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (intent == null || !MICROPHONE_PIP_INTENT_NAME.equals(intent.getAction())) {
+ return;
+ }
+
+ final int action = intent.getIntExtra(MICROPHONE_PIP_INTENT_EXTRA_ACTION, 0);
+ switch (action) {
+ case MICROPHONE_PIP_REQUEST_MUTE:
+ case MICROPHONE_PIP_REQUEST_UNMUTE:
+ onMicrophoneClick();
+ break;
+ }
+ }
+ };
+ registerReceiver(mReceiver, new IntentFilter(MICROPHONE_PIP_INTENT_NAME));
+
+ updateUiForPipMode();
+ } else {
+ unregisterReceiver(mReceiver);
+ mReceiver = null;
+
+ updateUiForNormalMode();
+ }
+ }
+
+ void updatePictureInPictureActions(
+ @DrawableRes int iconId,
+ String title,
+ int requestCode) {
+
+ if (isGreaterEqualOreo() && isPipModePossible()) {
+ final ArrayList actions = new ArrayList<>();
+
+ final Icon icon = Icon.createWithResource(this, iconId);
+ final PendingIntent intent =
+ PendingIntent.getBroadcast(
+ this,
+ requestCode,
+ new Intent(MICROPHONE_PIP_INTENT_NAME).putExtra(MICROPHONE_PIP_INTENT_EXTRA_ACTION, requestCode),
+ 0);
+
+ actions.add(new RemoteAction(icon, title, title, intent));
+
+ mPictureInPictureParamsBuilder.setActions(actions);
+ setPictureInPictureParams(mPictureInPictureParamsBuilder.build());
+ }
+ }
+
+ public void updateUiForPipMode() {
+ Log.d(TAG, "updateUiForPipMode");
+ RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT);
+ params.setMargins(0, 0, 0, 0);
+ binding.gridview.setLayoutParams(params);
+
+
+ binding.callControls.setVisibility(View.GONE);
+ binding.callInfosLinearLayout.setVisibility(View.GONE);
+ binding.selfVideoViewWrapper.setVisibility(View.GONE);
+ binding.callStates.callStateRelativeLayout.setVisibility(View.GONE);
+
+ if (participantDisplayItems.size() > 1) {
+ binding.pipCallConversationNameTextView.setText(conversationName);
+ binding.pipGroupCallOverlay.setVisibility(View.VISIBLE);
+ } else {
+ binding.pipGroupCallOverlay.setVisibility(View.INVISIBLE);
+ }
+
+ binding.selfVideoRenderer.release();
+ }
+
+ public void updateUiForNormalMode() {
+ Log.d(TAG, "updateUiForNormalMode");
+ if (isVoiceOnlyCall) {
+ binding.callControls.setVisibility(View.VISIBLE);
+ } else {
+ binding.callControls.setVisibility(View.INVISIBLE); // animateCallControls needs this to be invisible for a check.
+ }
+ initViews();
+
+ binding.callInfosLinearLayout.setVisibility(View.VISIBLE);
+ binding.selfVideoViewWrapper.setVisibility(View.VISIBLE);
+
+ binding.pipGroupCallOverlay.setVisibility(View.INVISIBLE);
+ }
+
+ @Override
+ void suppressFitsSystemWindows() {
+ binding.controllerCallLayout.setFitsSystemWindows(false);
+ }
+
+ public void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ eventBus.post(new ConfigurationChangeEvent());
+ }
+
private class SelfVideoTouchListener implements View.OnTouchListener {
@SuppressLint("ClickableViewAccessibility")
@@ -2456,10 +2541,10 @@ public class CallController extends BaseController {
long duration = event.getEventTime() - event.getDownTime();
if (event.getActionMasked() == MotionEvent.ACTION_MOVE) {
- float newY = event.getRawY() - selfVideoView.getHeight() / (float) 2;
- float newX = event.getRawX() - selfVideoView.getWidth() / (float) 2;
- selfVideoView.setY(newY);
- selfVideoView.setX(newX);
+ float newY = event.getRawY() - binding.selfVideoViewWrapper.getHeight() / (float) 2;
+ float newX = event.getRawX() - binding.selfVideoViewWrapper.getWidth() / (float) 2;
+ binding.selfVideoViewWrapper.setY(newY);
+ binding.selfVideoViewWrapper.setX(newX);
} else if (event.getActionMasked() == MotionEvent.ACTION_UP && duration < 100) {
switchCamera();
}
diff --git a/app/src/main/java/com/nextcloud/talk/activities/CallBaseActivity.java b/app/src/main/java/com/nextcloud/talk/activities/CallBaseActivity.java
new file mode 100644
index 000000000..66da91360
--- /dev/null
+++ b/app/src/main/java/com/nextcloud/talk/activities/CallBaseActivity.java
@@ -0,0 +1,131 @@
+package com.nextcloud.talk.activities;
+
+import android.annotation.SuppressLint;
+import android.app.AppOpsManager;
+import android.app.KeyguardManager;
+import android.app.PictureInPictureParams;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.Build;
+import android.os.Bundle;
+import android.util.Log;
+import android.util.Rational;
+import android.view.View;
+import android.view.Window;
+import android.view.WindowManager;
+
+import com.nextcloud.talk.BuildConfig;
+
+public abstract class CallBaseActivity extends BaseActivity {
+
+ public static final String TAG = "CallBaseActivity";
+
+ public PictureInPictureParams.Builder mPictureInPictureParamsBuilder;
+ public Boolean isInPipMode = false;
+
+ @SuppressLint("ClickableViewAccessibility")
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ requestWindowFeature(Window.FEATURE_NO_TITLE);
+ dismissKeyguard();
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+
+ if (isGreaterEqualOreo() && isPipModePossible()) {
+ mPictureInPictureParamsBuilder = new PictureInPictureParams.Builder();
+ }
+ }
+
+ void hideNavigationIfNoPipAvailable(){
+ if (!isPipModePossible()) {
+ getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
+ View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
+ View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
+ View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
+ suppressFitsSystemWindows();
+ }
+ }
+
+ void dismissKeyguard() {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
+ setShowWhenLocked(true);
+ setTurnScreenOn(true);
+ KeyguardManager keyguardManager = (KeyguardManager) getSystemService(KEYGUARD_SERVICE);
+ keyguardManager.requestDismissKeyguard(this, null);
+ } else {
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
+ }
+ }
+
+ void enableKeyguard() {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
+ setShowWhenLocked(false);
+ } else {
+ getWindow().clearFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
+ getWindow().clearFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
+ getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
+ }
+ }
+
+ @Override
+ public void onStop() {
+ super.onStop();
+ if (isInPipMode) {
+ finish();
+ }
+ }
+
+ @Override
+ public void onBackPressed() {
+ if (isPipModePossible()) {
+ enterPipMode();
+ }
+ }
+
+ @Override
+ protected void onUserLeaveHint() {
+ enterPipMode();
+ }
+
+ void enterPipMode() {
+ enableKeyguard();
+ if (isGreaterEqualOreo() && isPipModePossible()) {
+ Rational pipRatio = new Rational(300, 500);
+ mPictureInPictureParamsBuilder.setAspectRatio(pipRatio);
+ enterPictureInPictureMode(mPictureInPictureParamsBuilder.build());
+ } else {
+ // we don't support other solutions than PIP to have a call in the background.
+ // If PIP is not available the call is ended when user presses the home button.
+ Log.d(TAG, "Activity was finished because PIP is not available.");
+ finish();
+ }
+ }
+
+ boolean isPipModePossible() {
+ if (isGreaterEqualOreo()) {
+ boolean deviceHasPipFeature = getPackageManager().hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE);
+
+ AppOpsManager appOpsManager = (AppOpsManager) getSystemService(Context.APP_OPS_SERVICE);
+ boolean isPipFeatureGranted = appOpsManager.checkOpNoThrow(
+ AppOpsManager.OPSTR_PICTURE_IN_PICTURE,
+ android.os.Process.myUid(),
+ BuildConfig.APPLICATION_ID) == AppOpsManager.MODE_ALLOWED;
+ return deviceHasPipFeature && isPipFeatureGranted;
+ }
+ return false;
+ }
+
+ boolean isGreaterEqualOreo(){
+ return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;
+ }
+
+ abstract void updateUiForPipMode();
+
+ abstract void updateUiForNormalMode();
+
+ abstract void suppressFitsSystemWindows();
+}
diff --git a/app/src/main/java/com/nextcloud/talk/activities/CallNotificationActivity.java b/app/src/main/java/com/nextcloud/talk/activities/CallNotificationActivity.java
new file mode 100644
index 000000000..7c126e4d6
--- /dev/null
+++ b/app/src/main/java/com/nextcloud/talk/activities/CallNotificationActivity.java
@@ -0,0 +1,458 @@
+/*
+ * Nextcloud Talk application
+ *
+ * @author Mario Danic
+ * Copyright (C) 2017-2018 Mario Danic
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package com.nextcloud.talk.activities;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Configuration;
+import android.graphics.Bitmap;
+import android.graphics.drawable.BitmapDrawable;
+import android.media.AudioAttributes;
+import android.media.MediaPlayer;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Handler;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.View;
+
+import com.bluelinelabs.logansquare.LoganSquare;
+import com.facebook.common.executors.UiThreadImmediateExecutorService;
+import com.facebook.common.references.CloseableReference;
+import com.facebook.datasource.DataSource;
+import com.facebook.drawee.backends.pipeline.Fresco;
+import com.facebook.imagepipeline.core.ImagePipeline;
+import com.facebook.imagepipeline.datasource.BaseBitmapDataSubscriber;
+import com.facebook.imagepipeline.image.CloseableImage;
+import com.facebook.imagepipeline.request.ImageRequest;
+import com.nextcloud.talk.R;
+import com.nextcloud.talk.api.NcApi;
+import com.nextcloud.talk.application.NextcloudTalkApplication;
+import com.nextcloud.talk.databinding.CallNotificationActivityBinding;
+import com.nextcloud.talk.events.CallNotificationClick;
+import com.nextcloud.talk.models.RingtoneSettings;
+import com.nextcloud.talk.models.database.CapabilitiesUtil;
+import com.nextcloud.talk.models.database.UserEntity;
+import com.nextcloud.talk.models.json.conversations.Conversation;
+import com.nextcloud.talk.models.json.conversations.RoomOverall;
+import com.nextcloud.talk.models.json.participants.Participant;
+import com.nextcloud.talk.models.json.participants.ParticipantsOverall;
+import com.nextcloud.talk.utils.ApiUtils;
+import com.nextcloud.talk.utils.DisplayUtils;
+import com.nextcloud.talk.utils.DoNotDisturbUtils;
+import com.nextcloud.talk.utils.bundle.BundleKeys;
+import com.nextcloud.talk.utils.preferences.AppPreferences;
+
+import org.greenrobot.eventbus.EventBus;
+import org.parceler.Parcels;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.inject.Inject;
+
+import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
+import autodagger.AutoInjector;
+import butterknife.OnClick;
+import io.reactivex.Observer;
+import io.reactivex.android.schedulers.AndroidSchedulers;
+import io.reactivex.disposables.Disposable;
+import io.reactivex.schedulers.Schedulers;
+import okhttp3.Cache;
+
+@SuppressLint("LongLogTag")
+@AutoInjector(NextcloudTalkApplication.class)
+public class CallNotificationActivity extends CallBaseActivity {
+
+ public static final String TAG = "CallNotificationActivity";
+
+ @Inject
+ NcApi ncApi;
+
+ @Inject
+ AppPreferences appPreferences;
+
+ @Inject
+ Cache cache;
+
+ @Inject
+ EventBus eventBus;
+
+ @Inject
+ Context context;
+
+ private List disposablesList = new ArrayList<>();
+ private Bundle originalBundle;
+ private String roomId;
+ private UserEntity userBeingCalled;
+ private String credentials;
+ private Conversation currentConversation;
+ private MediaPlayer mediaPlayer;
+ private boolean leavingScreen = false;
+ private Handler handler;
+ private CallNotificationActivityBinding binding;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ Log.d(TAG, "onCreate");
+ super.onCreate(savedInstanceState);
+
+ NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
+
+ binding = CallNotificationActivityBinding.inflate(getLayoutInflater());
+ setContentView(binding.getRoot());
+
+ hideNavigationIfNoPipAvailable();
+
+ eventBus.post(new CallNotificationClick());
+
+ Bundle extras = getIntent().getExtras();
+ this.roomId = extras.getString(BundleKeys.INSTANCE.getKEY_ROOM_ID(), "");
+ this.currentConversation = Parcels.unwrap(extras.getParcelable(BundleKeys.INSTANCE.getKEY_ROOM()));
+ this.userBeingCalled = extras.getParcelable(BundleKeys.INSTANCE.getKEY_USER_ENTITY());
+
+ this.originalBundle = extras;
+ credentials = ApiUtils.getCredentials(userBeingCalled.getUsername(), userBeingCalled.getToken());
+
+ setCallDescriptionText();
+
+ if (currentConversation == null) {
+ handleFromNotification();
+ } else {
+ setUpAfterConversationIsKnown();
+ }
+
+ if (DoNotDisturbUtils.INSTANCE.shouldPlaySound()) {
+ playRingtoneSound();
+ }
+
+ initClickListeners();
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+
+ if (handler == null) {
+ handler = new Handler();
+
+ try {
+ cache.evictAll();
+ } catch (IOException e) {
+ Log.e(TAG, "Failed to evict cache");
+ }
+ }
+ }
+
+ private void initClickListeners() {
+ binding.callAnswerVoiceOnlyView.setOnClickListener(l -> {
+ Log.d(TAG, "accept call (voice only)");
+ originalBundle.putBoolean(BundleKeys.INSTANCE.getKEY_CALL_VOICE_ONLY(), true);
+ proceedToCall();
+ });
+
+ binding.callAnswerCameraView.setOnClickListener(l -> {
+ Log.d(TAG, "accept call (with video)");
+ originalBundle.putBoolean(BundleKeys.INSTANCE.getKEY_CALL_VOICE_ONLY(), false);
+ proceedToCall();
+ });
+
+ binding.hangupButton.setOnClickListener(l -> hangup());
+ }
+
+ private void setCallDescriptionText() {
+ String callDescriptionWithoutTypeInfo =
+ String.format(
+ getResources().getString(R.string.nc_call_unknown),
+ getResources().getString(R.string.nc_app_product_name));
+
+ binding.incomingCallVoiceOrVideoTextView.setText(callDescriptionWithoutTypeInfo);
+ }
+
+ private void showAnswerControls() {
+ binding.callAnswerCameraView.setVisibility(View.VISIBLE);
+ binding.callAnswerVoiceOnlyView.setVisibility(View.VISIBLE);
+ }
+
+ @OnClick(R.id.hangupButton)
+ void hangup() {
+ leavingScreen = true;
+ finish();
+ }
+
+ private void proceedToCall() {
+ originalBundle.putString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN(), currentConversation.getToken());
+ originalBundle.putString(BundleKeys.INSTANCE.getKEY_CONVERSATION_NAME(), currentConversation.getDisplayName());
+
+ Intent intent = new Intent(this, CallActivity.class);
+ intent.putExtras(originalBundle);
+ startActivity(intent);
+ }
+
+ private void checkIfAnyParticipantsRemainInRoom() {
+ int apiVersion = ApiUtils.getCallApiVersion(userBeingCalled, new int[]{ApiUtils.APIv4, 1});
+
+ ncApi.getPeersForCall(credentials, ApiUtils.getUrlForCall(apiVersion, userBeingCalled.getBaseUrl(),
+ currentConversation.getToken()))
+ .subscribeOn(Schedulers.io())
+ .takeWhile(observable -> !leavingScreen)
+ .subscribe(new Observer() {
+ @Override
+ public void onSubscribe(Disposable d) {
+ disposablesList.add(d);
+ }
+
+ @Override
+ public void onNext(ParticipantsOverall participantsOverall) {
+ boolean hasParticipantsInCall = false;
+ boolean inCallOnDifferentDevice = false;
+ List participantList = participantsOverall.getOcs().getData();
+ hasParticipantsInCall = participantList.size() > 0;
+
+ if (hasParticipantsInCall) {
+ for (Participant participant : participantList) {
+ if (participant.getActorType() == Participant.ActorType.USERS &&
+ participant.getActorId().equals(userBeingCalled.getUserId())) {
+ inCallOnDifferentDevice = true;
+ break;
+ }
+ }
+ }
+
+ if (!hasParticipantsInCall || inCallOnDifferentDevice) {
+ runOnUiThread(() -> hangup());
+ }
+ }
+
+ @Override
+ public void onError(Throwable e) {
+
+ }
+
+ @Override
+ public void onComplete() {
+ if (!leavingScreen) {
+ handler.postDelayed(() -> checkIfAnyParticipantsRemainInRoom(), 5000);
+ }
+ }
+ });
+
+ }
+
+ private void handleFromNotification() {
+ int apiVersion = ApiUtils.getConversationApiVersion(userBeingCalled, new int[]{ApiUtils.APIv4,
+ ApiUtils.APIv3, 1});
+
+ ncApi.getRoom(credentials, ApiUtils.getUrlForRoom(apiVersion, userBeingCalled.getBaseUrl(), roomId))
+ .subscribeOn(Schedulers.io())
+ .retry(3)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(new Observer() {
+ @Override
+ public void onSubscribe(@io.reactivex.annotations.NonNull Disposable d) {
+ disposablesList.add(d);
+ }
+
+ @Override
+ public void onNext(@io.reactivex.annotations.NonNull RoomOverall roomOverall) {
+ currentConversation = roomOverall.getOcs().data;
+ setUpAfterConversationIsKnown();
+
+ if (apiVersion >= 3) {
+ boolean hasCallFlags =
+ CapabilitiesUtil.hasSpreedFeatureCapability(userBeingCalled,
+ "conversation-call-flags");
+ if (hasCallFlags) {
+ if (isInCallWithVideo(currentConversation.callFlag)) {
+ binding.incomingCallVoiceOrVideoTextView.setText(
+ String.format(getResources().getString(R.string.nc_call_video),
+ getResources().getString(R.string.nc_app_product_name)));
+ } else {
+ binding.incomingCallVoiceOrVideoTextView.setText(
+ String.format(getResources().getString(R.string.nc_call_voice),
+ getResources().getString(R.string.nc_app_product_name)));
+ }
+ }
+ }
+ }
+
+ @Override
+ public void onError(@io.reactivex.annotations.NonNull Throwable e) {
+ Log.e(TAG, e.getMessage(), e);
+ }
+
+ @Override
+ public void onComplete() {
+
+ }
+ });
+ }
+
+ private boolean isInCallWithVideo(int callFlag) {
+ return (Participant.ParticipantFlags.IN_CALL_WITH_VIDEO.getValue() == callFlag
+ || Participant.ParticipantFlags.IN_CALL_WITH_AUDIO_AND_VIDEO.getValue() == callFlag);
+ }
+
+ private void setUpAfterConversationIsKnown() {
+ binding.conversationNameTextView.setText(currentConversation.getDisplayName());
+
+ if(currentConversation.getType() == Conversation.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL){
+ setAvatarForOneToOneCall();
+ } else {
+ binding.avatarImageView.setImageResource(R.drawable.ic_circular_group);
+ }
+
+ checkIfAnyParticipantsRemainInRoom();
+ showAnswerControls();
+ }
+
+ private void setAvatarForOneToOneCall() {
+ ImageRequest imageRequest =
+ DisplayUtils.getImageRequestForUrl(
+ ApiUtils.getUrlForAvatarWithName(userBeingCalled.getBaseUrl(),
+ currentConversation.getName(),
+ R.dimen.avatar_size_big), null);
+
+ ImagePipeline imagePipeline = Fresco.getImagePipeline();
+ DataSource> dataSource = imagePipeline.fetchDecodedImage(imageRequest, null);
+
+ dataSource.subscribe(new BaseBitmapDataSubscriber() {
+ @Override
+ protected void onNewResultImpl(@Nullable Bitmap bitmap) {
+ binding.avatarImageView.getHierarchy().setImage(
+ new BitmapDrawable(getResources(), bitmap),
+ 100,
+ true);
+ }
+
+ @Override
+ protected void onFailureImpl(DataSource> dataSource) {
+ Log.e(TAG, "failed to load avatar");
+ }
+ }, UiThreadImmediateExecutorService.getInstance());
+ }
+
+ private void endMediaNotifications() {
+ if (mediaPlayer != null) {
+ if (mediaPlayer.isPlaying()) {
+ mediaPlayer.stop();
+ }
+
+ mediaPlayer.release();
+ mediaPlayer = null;
+ }
+ }
+
+ @Override
+ public void onDestroy() {
+ leavingScreen = true;
+ if (handler != null) {
+ handler.removeCallbacksAndMessages(null);
+ handler = null;
+ }
+ dispose();
+ endMediaNotifications();
+ super.onDestroy();
+ }
+
+ private void dispose() {
+ if (disposablesList != null) {
+ for (Disposable disposable : disposablesList) {
+ if (!disposable.isDisposed()) {
+ disposable.dispose();
+ }
+ }
+ }
+ }
+
+ private void playRingtoneSound() {
+ String callRingtonePreferenceString = appPreferences.getCallRingtoneUri();
+ Uri ringtoneUri;
+
+ if (TextUtils.isEmpty(callRingtonePreferenceString)) {
+ // play default sound
+ ringtoneUri = Uri.parse("android.resource://" + getApplicationContext().getPackageName() +
+ "/raw/librem_by_feandesign_call");
+ } else {
+ try {
+ RingtoneSettings ringtoneSettings = LoganSquare.parse(
+ callRingtonePreferenceString, RingtoneSettings.class);
+ ringtoneUri = ringtoneSettings.getRingtoneUri();
+ } catch (IOException e) {
+ Log.e(TAG, "Failed to parse ringtone settings");
+ ringtoneUri = Uri.parse("android.resource://" + getApplicationContext().getPackageName() +
+ "/raw/librem_by_feandesign_call");
+ }
+ }
+
+ if (ringtoneUri != null) {
+ mediaPlayer = new MediaPlayer();
+ try {
+ mediaPlayer.setDataSource(this, ringtoneUri);
+
+ mediaPlayer.setLooping(true);
+ AudioAttributes audioAttributes = new AudioAttributes
+ .Builder()
+ .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
+ .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
+ .build();
+ mediaPlayer.setAudioAttributes(audioAttributes);
+
+ mediaPlayer.setOnPreparedListener(mp -> mediaPlayer.start());
+
+ mediaPlayer.prepareAsync();
+ } catch (IOException e) {
+ Log.e(TAG, "Failed to set data source");
+ }
+ }
+ }
+
+ @RequiresApi(api = Build.VERSION_CODES.O)
+ @Override
+ public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode, Configuration newConfig) {
+ super.onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig);
+ isInPipMode = isInPictureInPictureMode;
+ if (isInPictureInPictureMode) {
+ updateUiForPipMode();
+ } else {
+ updateUiForNormalMode();
+ }
+ }
+
+ public void updateUiForPipMode() {
+ binding.callAnswerButtons.setVisibility(View.INVISIBLE);
+ binding.incomingCallRelativeLayout.setVisibility(View.INVISIBLE);
+ }
+
+ public void updateUiForNormalMode() {
+ binding.callAnswerButtons.setVisibility(View.VISIBLE);
+ binding.incomingCallRelativeLayout.setVisibility(View.VISIBLE);
+ }
+
+ @Override
+ void suppressFitsSystemWindows() {
+ binding.controllerCallNotificationLayout.setFitsSystemWindows(false);
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/nextcloud/talk/activities/MagicCallActivity.kt b/app/src/main/java/com/nextcloud/talk/activities/MagicCallActivity.kt
deleted file mode 100644
index 496756524..000000000
--- a/app/src/main/java/com/nextcloud/talk/activities/MagicCallActivity.kt
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Nextcloud Talk application
- *
- * @author Mario Danic
- * @author Andy Scherzinger
- * Copyright (C) 2021 Andy Scherzinger (infoi@andy-scherzinger.de)
- * Copyright (C) 2017-2018 Mario Danic
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-package com.nextcloud.talk.activities
-
-import android.app.KeyguardManager
-import android.content.res.Configuration
-import android.os.Build
-import android.os.Bundle
-import android.view.View
-import android.view.Window
-import android.view.WindowManager
-import autodagger.AutoInjector
-import com.bluelinelabs.conductor.Conductor
-import com.bluelinelabs.conductor.Router
-import com.bluelinelabs.conductor.RouterTransaction
-import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler
-import com.nextcloud.talk.R
-import com.nextcloud.talk.application.NextcloudTalkApplication
-import com.nextcloud.talk.controllers.CallController
-import com.nextcloud.talk.controllers.CallNotificationController
-import com.nextcloud.talk.controllers.ChatController
-import com.nextcloud.talk.databinding.ActivityMagicCallBinding
-import com.nextcloud.talk.events.ConfigurationChangeEvent
-import com.nextcloud.talk.utils.bundle.BundleKeys
-
-@AutoInjector(NextcloudTalkApplication::class)
-class MagicCallActivity : BaseActivity() {
- lateinit var binding: ActivityMagicCallBinding
-
- private lateinit var chatController: ChatController
-
- private var router: Router? = null
- private var chatRouter: Router? = null
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this)
- setTheme(R.style.CallTheme)
-
- requestWindowFeature(Window.FEATURE_NO_TITLE)
- dismissKeyguard()
- window.addFlags(
- WindowManager.LayoutParams.FLAG_FULLSCREEN or
- WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
- )
- window.decorView.systemUiVisibility = systemUiVisibility
-
- binding = ActivityMagicCallBinding.inflate(layoutInflater)
- setContentView(binding.root)
-
- router = Conductor.attachRouter(this, binding.controllerContainer, savedInstanceState)
- router!!.setPopsLastView(false)
-
- if (!router!!.hasRootController()) {
- if (intent.getBooleanExtra(BundleKeys.KEY_FROM_NOTIFICATION_START_CALL, false)) {
- router!!.setRoot(
- RouterTransaction.with(CallNotificationController(intent.extras))
- .pushChangeHandler(HorizontalChangeHandler())
- .popChangeHandler(HorizontalChangeHandler())
- )
- } else {
- router!!.setRoot(
- RouterTransaction.with(CallController(intent.extras))
- .pushChangeHandler(HorizontalChangeHandler())
- .popChangeHandler(HorizontalChangeHandler())
- )
- }
- }
-
- val extras = intent.extras ?: Bundle()
- extras.putBoolean("showToggleChat", true)
-
- chatController = ChatController(extras)
- chatRouter = Conductor.attachRouter(this, binding.chatControllerView, savedInstanceState)
- chatRouter!!.setRoot(
- RouterTransaction.with(chatController)
- .pushChangeHandler(HorizontalChangeHandler())
- .popChangeHandler(HorizontalChangeHandler())
- )
- }
-
- fun showChat() {
- enableKeyguard()
- binding.chatControllerView.visibility = View.VISIBLE
- binding.controllerContainer.visibility = View.GONE
- chatController.wasDetached = false
- chatController.pullChatMessages(1)
- }
-
- fun showCall() {
- binding.controllerContainer.visibility = View.VISIBLE
- binding.chatControllerView.visibility = View.GONE
- chatController.wasDetached = true
- }
-
- override fun onConfigurationChanged(newConfig: Configuration) {
- super.onConfigurationChanged(newConfig)
- eventBus.post(ConfigurationChangeEvent())
- }
-
- private fun dismissKeyguard() {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
- setShowWhenLocked(true)
- setTurnScreenOn(true)
- val keyguardManager = getSystemService(KEYGUARD_SERVICE) as KeyguardManager
- keyguardManager.requestDismissKeyguard(this, null)
- } else {
- window.addFlags(
- WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD or
- WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or
- WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
- )
- }
- }
-
- private fun enableKeyguard() {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
- setShowWhenLocked(false)
- } else {
- window.clearFlags(
- WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD or
- WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or
- WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
- )
- }
- }
-
- companion object {
- private val TAG = "MagicCallActivity"
-
- private val systemUiVisibility: Int
- get() {
- var flags = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_FULLSCREEN
- flags = flags or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
- return flags
- }
- }
-}
diff --git a/app/src/main/java/com/nextcloud/talk/activities/MainActivity.kt b/app/src/main/java/com/nextcloud/talk/activities/MainActivity.kt
index 7e803a7a7..de8dbf73b 100644
--- a/app/src/main/java/com/nextcloud/talk/activities/MainActivity.kt
+++ b/app/src/main/java/com/nextcloud/talk/activities/MainActivity.kt
@@ -40,7 +40,6 @@ import com.google.android.material.snackbar.Snackbar
import com.nextcloud.talk.R
import com.nextcloud.talk.api.NcApi
import com.nextcloud.talk.application.NextcloudTalkApplication
-import com.nextcloud.talk.controllers.CallNotificationController
import com.nextcloud.talk.controllers.ConversationsListController
import com.nextcloud.talk.controllers.LockedController
import com.nextcloud.talk.controllers.ServerSelectionController
@@ -310,11 +309,9 @@ class MainActivity : BaseActivity(), ActionBarProvider {
handleActionFromContact(intent)
if (intent.hasExtra(BundleKeys.KEY_FROM_NOTIFICATION_START_CALL)) {
if (intent.getBooleanExtra(BundleKeys.KEY_FROM_NOTIFICATION_START_CALL, false)) {
- router!!.pushController(
- RouterTransaction.with(CallNotificationController(intent.extras))
- .pushChangeHandler(HorizontalChangeHandler())
- .popChangeHandler(HorizontalChangeHandler())
- )
+ val callNotificationIntent = Intent(this, CallNotificationActivity::class.java)
+ intent.extras?.let { callNotificationIntent.putExtras(it) }
+ startActivity(callNotificationIntent)
} else {
ConductorRemapping.remapChatController(
router!!, intent.getLongExtra(BundleKeys.KEY_INTERNAL_USER_ID, -1),
diff --git a/app/src/main/java/com/nextcloud/talk/adapters/ParticipantsAdapter.java b/app/src/main/java/com/nextcloud/talk/adapters/ParticipantsAdapter.java
index d0b4b43fc..9a383552a 100644
--- a/app/src/main/java/com/nextcloud/talk/adapters/ParticipantsAdapter.java
+++ b/app/src/main/java/com/nextcloud/talk/adapters/ParticipantsAdapter.java
@@ -15,6 +15,7 @@ import com.facebook.drawee.backends.pipeline.Fresco;
import com.facebook.drawee.interfaces.DraweeController;
import com.facebook.drawee.view.SimpleDraweeView;
import com.nextcloud.talk.R;
+import com.nextcloud.talk.activities.CallActivity;
import com.nextcloud.talk.utils.DisplayUtils;
import org.webrtc.MediaStream;
@@ -79,6 +80,8 @@ public class ParticipantsAdapter extends BaseAdapter {
surfaceViewRenderer = convertView.findViewById(R.id.surface_view);
try {
+ Log.d(TAG, "hasSurface: " + participantDisplayItem.getRootEglBase().hasSurface());
+
surfaceViewRenderer.setMirror(false);
surfaceViewRenderer.init(participantDisplayItem.getRootEglBase().getEglBaseContext(), null);
surfaceViewRenderer.setZOrderMediaOverlay(false);
@@ -96,7 +99,6 @@ public class ParticipantsAdapter extends BaseAdapter {
layoutParams.height = scaleGridViewItemHeight();
convertView.setLayoutParams(layoutParams);
-
TextView nickTextView = convertView.findViewById(R.id.peer_nick_text_view);
SimpleDraweeView imageView = convertView.findViewById(R.id.avatarImageView);
@@ -110,8 +112,13 @@ public class ParticipantsAdapter extends BaseAdapter {
} else {
imageView.setVisibility(View.VISIBLE);
surfaceViewRenderer.setVisibility(View.INVISIBLE);
- nickTextView.setVisibility(View.VISIBLE);
- nickTextView.setText(participantDisplayItem.getNick());
+
+ if (((CallActivity) mContext).isInPipMode) {
+ nickTextView.setVisibility(View.GONE);
+ } else {
+ nickTextView.setVisibility(View.VISIBLE);
+ nickTextView.setText(participantDisplayItem.getNick());
+ }
imageView.setController(null);
DraweeController draweeController = Fresco.newDraweeControllerBuilder()
@@ -127,7 +134,9 @@ public class ParticipantsAdapter extends BaseAdapter {
} else {
audioOffView.setVisibility(View.INVISIBLE);
}
+
return convertView;
+
}
private boolean hasVideoStream(ParticipantDisplayItem participantDisplayItem, MediaStream mediaStream) {
diff --git a/app/src/main/java/com/nextcloud/talk/controllers/CallNotificationController.java b/app/src/main/java/com/nextcloud/talk/controllers/CallNotificationController.java
deleted file mode 100644
index 66e6dcdf7..000000000
--- a/app/src/main/java/com/nextcloud/talk/controllers/CallNotificationController.java
+++ /dev/null
@@ -1,520 +0,0 @@
-/*
- * Nextcloud Talk application
- *
- * @author Mario Danic
- * Copyright (C) 2017-2018 Mario Danic
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-package com.nextcloud.talk.controllers;
-
-import android.annotation.SuppressLint;
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.Color;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.ColorDrawable;
-import android.media.AudioAttributes;
-import android.media.MediaPlayer;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Handler;
-import android.renderscript.RenderScript;
-import android.text.TextUtils;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ImageView;
-import android.widget.RelativeLayout;
-import android.widget.TextView;
-
-import com.bluelinelabs.conductor.RouterTransaction;
-import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler;
-import com.bluelinelabs.logansquare.LoganSquare;
-import com.facebook.common.executors.UiThreadImmediateExecutorService;
-import com.facebook.common.references.CloseableReference;
-import com.facebook.datasource.DataSource;
-import com.facebook.drawee.backends.pipeline.Fresco;
-import com.facebook.drawee.view.SimpleDraweeView;
-import com.facebook.imagepipeline.core.ImagePipeline;
-import com.facebook.imagepipeline.datasource.BaseBitmapDataSubscriber;
-import com.facebook.imagepipeline.image.CloseableImage;
-import com.facebook.imagepipeline.postprocessors.BlurPostProcessor;
-import com.facebook.imagepipeline.request.ImageRequest;
-import com.nextcloud.talk.R;
-import com.nextcloud.talk.api.NcApi;
-import com.nextcloud.talk.application.NextcloudTalkApplication;
-import com.nextcloud.talk.controllers.base.BaseController;
-import com.nextcloud.talk.events.CallNotificationClick;
-import com.nextcloud.talk.events.ConfigurationChangeEvent;
-import com.nextcloud.talk.models.RingtoneSettings;
-import com.nextcloud.talk.models.database.CapabilitiesUtil;
-import com.nextcloud.talk.models.database.UserEntity;
-import com.nextcloud.talk.models.json.conversations.Conversation;
-import com.nextcloud.talk.models.json.conversations.RoomOverall;
-import com.nextcloud.talk.models.json.participants.Participant;
-import com.nextcloud.talk.models.json.participants.ParticipantsOverall;
-import com.nextcloud.talk.utils.ApiUtils;
-import com.nextcloud.talk.utils.DisplayUtils;
-import com.nextcloud.talk.utils.DoNotDisturbUtils;
-import com.nextcloud.talk.utils.bundle.BundleKeys;
-import com.nextcloud.talk.utils.preferences.AppPreferences;
-import com.nextcloud.talk.utils.singletons.AvatarStatusCodeHolder;
-
-import org.greenrobot.eventbus.EventBus;
-import org.greenrobot.eventbus.Subscribe;
-import org.greenrobot.eventbus.ThreadMode;
-import org.michaelevans.colorart.library.ColorArt;
-import org.parceler.Parcels;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.inject.Inject;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.constraintlayout.widget.ConstraintLayout;
-import autodagger.AutoInjector;
-import butterknife.BindView;
-import butterknife.OnClick;
-import io.reactivex.Observer;
-import io.reactivex.android.schedulers.AndroidSchedulers;
-import io.reactivex.disposables.Disposable;
-import io.reactivex.schedulers.Schedulers;
-import okhttp3.Cache;
-
-@AutoInjector(NextcloudTalkApplication.class)
-public class CallNotificationController extends BaseController {
-
- private static final String TAG = "CallNotificationController";
-
- @Inject
- NcApi ncApi;
-
- @Inject
- AppPreferences appPreferences;
-
- @Inject
- Cache cache;
-
- @Inject
- EventBus eventBus;
-
- @Inject
- Context context;
-
- @BindView(R.id.incomingCallVoiceOrVideoTextView)
- TextView incomingCallVoiceOrVideoTextView;
-
- @BindView(R.id.conversationNameTextView)
- TextView conversationNameTextView;
-
- @BindView(R.id.avatarImageView)
- SimpleDraweeView avatarImageView;
-
- @BindView(R.id.callAnswerVoiceOnlyView)
- SimpleDraweeView callAnswerVoiceOnlyView;
-
- @BindView(R.id.callAnswerCameraView)
- SimpleDraweeView callAnswerCameraView;
-
- @BindView(R.id.backgroundImageView)
- ImageView backgroundImageView;
-
- @BindView(R.id.incomingTextRelativeLayout)
- RelativeLayout incomingTextRelativeLayout;
-
- private List disposablesList = new ArrayList<>();
- private Bundle originalBundle;
- private String roomId;
- private UserEntity userBeingCalled;
- private String credentials;
- private Conversation currentConversation;
- private MediaPlayer mediaPlayer;
- private boolean leavingScreen = false;
- private RenderScript renderScript;
- private Handler handler;
-
- public CallNotificationController(Bundle args) {
- super(args);
- NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
-
- eventBus.post(new CallNotificationClick());
- this.roomId = args.getString(BundleKeys.INSTANCE.getKEY_ROOM_ID(), "");
- this.currentConversation = Parcels.unwrap(args.getParcelable(BundleKeys.INSTANCE.getKEY_ROOM()));
- this.userBeingCalled = args.getParcelable(BundleKeys.INSTANCE.getKEY_USER_ENTITY());
-
- this.originalBundle = args;
- credentials = ApiUtils.getCredentials(userBeingCalled.getUsername(), userBeingCalled.getToken());
- }
-
- @Override
- protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
- return inflater.inflate(R.layout.controller_call_notification, container, false);
- }
-
- private void showAnswerControls() {
- callAnswerCameraView.setVisibility(View.VISIBLE);
- callAnswerVoiceOnlyView.setVisibility(View.VISIBLE);
- }
-
- @OnClick(R.id.callControlHangupView)
- void hangup() {
- leavingScreen = true;
-
- if (getActivity() != null) {
- getActivity().finish();
- }
- }
-
- @OnClick(R.id.callAnswerCameraView)
- void answerWithCamera() {
- originalBundle.putBoolean(BundleKeys.INSTANCE.getKEY_CALL_VOICE_ONLY(), false);
- proceedToCall();
- }
-
- @OnClick(R.id.callAnswerVoiceOnlyView)
- void answerVoiceOnly() {
- originalBundle.putBoolean(BundleKeys.INSTANCE.getKEY_CALL_VOICE_ONLY(), true);
- proceedToCall();
- }
-
- private void proceedToCall() {
- originalBundle.putString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN(), currentConversation.getToken());
- originalBundle.putString(BundleKeys.INSTANCE.getKEY_CONVERSATION_NAME(), currentConversation.getDisplayName());
-
- getRouter().replaceTopController(RouterTransaction.with(new CallController(originalBundle))
- .popChangeHandler(new HorizontalChangeHandler())
- .pushChangeHandler(new HorizontalChangeHandler()));
- }
-
- private void checkIfAnyParticipantsRemainInRoom() {
- int apiVersion = ApiUtils.getCallApiVersion(userBeingCalled, new int[] {ApiUtils.APIv4, 1});
-
- ncApi.getPeersForCall(credentials, ApiUtils.getUrlForCall(apiVersion, userBeingCalled.getBaseUrl(),
- currentConversation.getToken()))
- .subscribeOn(Schedulers.io())
- .takeWhile(observable -> !leavingScreen)
- .subscribe(new Observer() {
- @Override
- public void onSubscribe(Disposable d) {
- disposablesList.add(d);
- }
-
- @Override
- public void onNext(ParticipantsOverall participantsOverall) {
- boolean hasParticipantsInCall = false;
- boolean inCallOnDifferentDevice = false;
- List participantList = participantsOverall.getOcs().getData();
- hasParticipantsInCall = participantList.size() > 0;
-
- if (hasParticipantsInCall) {
- for (Participant participant : participantList) {
- if (participant.getActorType() == Participant.ActorType.USERS &&
- participant.getActorId().equals(userBeingCalled.getUserId())) {
- inCallOnDifferentDevice = true;
- break;
- }
- }
- }
-
- if (!hasParticipantsInCall || inCallOnDifferentDevice) {
- if (getActivity() != null) {
- getActivity().runOnUiThread(() -> hangup());
- }
- }
- }
-
- @Override
- public void onError(Throwable e) {
-
- }
-
- @Override
- public void onComplete() {
- if (!leavingScreen) {
- handler.postDelayed(() -> checkIfAnyParticipantsRemainInRoom(), 5000);
- }
- }
- });
-
- }
-
- private void handleFromNotification() {
- int apiVersion = ApiUtils.getConversationApiVersion(userBeingCalled, new int[] {ApiUtils.APIv4,
- ApiUtils.APIv3, 1});
-
- ncApi.getRoom(credentials, ApiUtils.getUrlForRoom(apiVersion, userBeingCalled.getBaseUrl(), roomId))
- .subscribeOn(Schedulers.io())
- .retry(3)
- .observeOn(AndroidSchedulers.mainThread())
- .subscribe(new Observer() {
- @Override
- public void onSubscribe(@io.reactivex.annotations.NonNull Disposable d) {
- disposablesList.add(d);
- }
-
- @Override
- public void onNext(@io.reactivex.annotations.NonNull RoomOverall roomOverall) {
- currentConversation = roomOverall.getOcs().data;
- runAllThings();
-
- if (apiVersion >= 3) {
- boolean hasCallFlags =
- CapabilitiesUtil.hasSpreedFeatureCapability(userBeingCalled,
- "conversation-call-flags");
- if (hasCallFlags) {
- if (isInCallWithVideo(currentConversation.callFlag)) {
- incomingCallVoiceOrVideoTextView.setText(
- String.format(getResources().getString(R.string.nc_call_video),
- getResources().getString(R.string.nc_app_product_name)));
- } else {
- incomingCallVoiceOrVideoTextView.setText(
- String.format(getResources().getString(R.string.nc_call_voice),
- getResources().getString(R.string.nc_app_product_name)));
- }
- }
- }
- }
-
- @SuppressLint("LongLogTag")
- @Override
- public void onError(@io.reactivex.annotations.NonNull Throwable e) {
- Log.e(TAG, e.getMessage(), e);
- }
-
- @Override
- public void onComplete() {
-
- }
- });
- }
-
- private boolean isInCallWithVideo(int callFlag) {
- return (Participant.ParticipantFlags.IN_CALL_WITH_VIDEO.getValue() == callFlag
- || Participant.ParticipantFlags.IN_CALL_WITH_AUDIO_AND_VIDEO.getValue() == callFlag);
- }
-
- private void runAllThings() {
- if (conversationNameTextView != null) {
- conversationNameTextView.setText(currentConversation.getDisplayName());
- }
-
- loadAvatar();
- checkIfAnyParticipantsRemainInRoom();
- showAnswerControls();
- }
-
- @SuppressLint({"LongLogTag"})
- @Override
- protected void onViewBound(@NonNull View view) {
- super.onViewBound(view);
-
- String callDescriptionWithoutTypeInfo =
- String.format(
- getResources().getString(R.string.nc_call_unknown),
- getResources().getString(R.string.nc_app_product_name));
-
- incomingCallVoiceOrVideoTextView.setText(callDescriptionWithoutTypeInfo);
-
- renderScript = RenderScript.create(getActivity());
-
- if (handler == null) {
- handler = new Handler();
-
- try {
- cache.evictAll();
- } catch (IOException e) {
- Log.e(TAG, "Failed to evict cache");
- }
- }
-
- if (currentConversation == null) {
- handleFromNotification();
- } else {
- runAllThings();
- }
-
- if (DoNotDisturbUtils.INSTANCE.shouldPlaySound()) {
- playRingtoneSound();
- }
- }
-
- @Subscribe(threadMode = ThreadMode.MAIN)
- public void onMessageEvent(ConfigurationChangeEvent configurationChangeEvent) {
- ConstraintLayout.LayoutParams layoutParams = (ConstraintLayout.LayoutParams) avatarImageView.getLayoutParams();
- int dimen = (int) getResources().getDimension(R.dimen.avatar_size_very_big);
-
- layoutParams.width = dimen;
- layoutParams.height = dimen;
- avatarImageView.setLayoutParams(layoutParams);
- }
-
- @Override
- protected void onDetach(@NonNull View view) {
- super.onDetach(view);
- eventBus.unregister(this);
- }
-
- @Override
- protected void onAttach(@NonNull View view) {
- super.onAttach(view);
- eventBus.register(this);
- }
-
- private void loadAvatar() {
- switch (currentConversation.getType()) {
- case ROOM_TYPE_ONE_TO_ONE_CALL:
- avatarImageView.setVisibility(View.VISIBLE);
-
- ImageRequest imageRequest =
- DisplayUtils.getImageRequestForUrl(
- ApiUtils.getUrlForAvatarWithName(userBeingCalled.getBaseUrl(),
- currentConversation.getName(),
- R.dimen.avatar_size_very_big),
- null);
-
- ImagePipeline imagePipeline = Fresco.getImagePipeline();
- DataSource> dataSource = imagePipeline.fetchDecodedImage(imageRequest, null);
-
- dataSource.subscribe(new BaseBitmapDataSubscriber() {
- @Override
- protected void onNewResultImpl(@Nullable Bitmap bitmap) {
- if (avatarImageView != null) {
- avatarImageView.getHierarchy().setImage(new BitmapDrawable(bitmap), 100,
- true);
-
- if (getResources() != null) {
- incomingTextRelativeLayout.setBackground(
- getResources().getDrawable(R.drawable.incoming_gradient));
- }
-
- if (AvatarStatusCodeHolder.getInstance().getStatusCode() == 200 ||
- AvatarStatusCodeHolder.getInstance().getStatusCode() == 0) {
- if (getActivity() != null) {
- Bitmap backgroundBitmap = bitmap.copy(bitmap.getConfig(), true);
- new BlurPostProcessor(5, getActivity()).process(backgroundBitmap);
- backgroundImageView.setImageDrawable(new BitmapDrawable(backgroundBitmap));
- }
- } else if (AvatarStatusCodeHolder.getInstance().getStatusCode() == 201) {
- ColorArt colorArt = new ColorArt(bitmap);
- int color = colorArt.getBackgroundColor();
-
- float[] hsv = new float[3];
- Color.colorToHSV(color, hsv);
- hsv[2] *= 0.75f;
- color = Color.HSVToColor(hsv);
-
- backgroundImageView.setImageDrawable(new ColorDrawable(color));
- }
- }
- }
-
- @Override
- protected void onFailureImpl(DataSource> dataSource) {
- // unused atm
- }
- }, UiThreadImmediateExecutorService.getInstance());
-
- break;
- case ROOM_GROUP_CALL:
- avatarImageView.setImageResource(R.drawable.ic_circular_group);
- case ROOM_PUBLIC_CALL:
- avatarImageView.setImageResource(R.drawable.ic_circular_group);
- break;
- default:
- }
- }
-
- private void endMediaNotifications() {
- if (mediaPlayer != null) {
- if (mediaPlayer.isPlaying()) {
- mediaPlayer.stop();
- }
-
- mediaPlayer.release();
- mediaPlayer = null;
- }
- }
-
- @Override
- public void onDestroy() {
- AvatarStatusCodeHolder.getInstance().setStatusCode(0);
- leavingScreen = true;
- if (handler != null) {
- handler.removeCallbacksAndMessages(null);
- handler = null;
- }
- dispose();
- endMediaNotifications();
- super.onDestroy();
- }
-
- private void dispose() {
- if (disposablesList != null) {
- for (Disposable disposable : disposablesList) {
- if (!disposable.isDisposed()) {
- disposable.dispose();
- }
- }
- }
- }
-
- @SuppressLint("LongLogTag")
- private void playRingtoneSound() {
- String callRingtonePreferenceString = appPreferences.getCallRingtoneUri();
- Uri ringtoneUri;
-
- if (TextUtils.isEmpty(callRingtonePreferenceString)) {
- // play default sound
- ringtoneUri = Uri.parse("android.resource://" + getApplicationContext().getPackageName() +
- "/raw/librem_by_feandesign_call");
- } else {
- try {
- RingtoneSettings ringtoneSettings = LoganSquare.parse(
- callRingtonePreferenceString, RingtoneSettings.class);
- ringtoneUri = ringtoneSettings.getRingtoneUri();
- } catch (IOException e) {
- Log.e(TAG, "Failed to parse ringtone settings");
- ringtoneUri = Uri.parse("android.resource://" + getApplicationContext().getPackageName() +
- "/raw/librem_by_feandesign_call");
- }
- }
-
- if (ringtoneUri != null && getActivity() != null) {
- mediaPlayer = new MediaPlayer();
- try {
- mediaPlayer.setDataSource(getActivity(), ringtoneUri);
-
- mediaPlayer.setLooping(true);
- AudioAttributes audioAttributes = new AudioAttributes
- .Builder()
- .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
- .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
- .build();
- mediaPlayer.setAudioAttributes(audioAttributes);
-
- mediaPlayer.setOnPreparedListener(mp -> mediaPlayer.start());
-
- mediaPlayer.prepareAsync();
- } catch (IOException e) {
- Log.e(TAG, "Failed to set data source");
- }
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/nextcloud/talk/controllers/ChatController.kt b/app/src/main/java/com/nextcloud/talk/controllers/ChatController.kt
index cd18dc807..703c21ee0 100644
--- a/app/src/main/java/com/nextcloud/talk/controllers/ChatController.kt
+++ b/app/src/main/java/com/nextcloud/talk/controllers/ChatController.kt
@@ -94,7 +94,7 @@ import com.facebook.imagepipeline.datasource.BaseBitmapDataSubscriber
import com.facebook.imagepipeline.image.CloseableImage
import com.google.android.flexbox.FlexboxLayout
import com.nextcloud.talk.R
-import com.nextcloud.talk.activities.MagicCallActivity
+import com.nextcloud.talk.activities.CallActivity
import com.nextcloud.talk.activities.MainActivity
import com.nextcloud.talk.adapters.messages.IncomingLocationMessageViewHolder
import com.nextcloud.talk.adapters.messages.IncomingPreviewMessageViewHolder
@@ -232,7 +232,6 @@ class ChatController(args: Bundle) :
val roomId: String
val voiceOnly: Boolean
var isFirstMessagesProcessing = true
- var isLeavingForConversation: Boolean = false
var wasDetached: Boolean = false
var emojiPopup: EmojiPopup? = null
@@ -270,6 +269,8 @@ class ChatController(args: Bundle) :
this.roomToken = args.getString(KEY_ROOM_TOKEN, "")
this.sharedText = args.getString(BundleKeys.KEY_SHARED_TEXT, "")
+ Log.d(TAG, "roomToken = " + roomToken)
+
if (args.containsKey(KEY_ACTIVE_CONVERSATION)) {
this.currentConversation = Parcels.unwrap(args.getParcelable(KEY_ACTIVE_CONVERSATION))
}
@@ -290,6 +291,7 @@ class ChatController(args: Bundle) :
}
private fun getRoomInfo() {
+ Log.d(TAG, "getRoomInfo")
val shouldRepeat = CapabilitiesUtil.hasSpreedFeatureCapability(conversationUser, "webinary-lobby")
if (shouldRepeat) {
checkingLobbyStatus = true
@@ -309,6 +311,8 @@ class ChatController(args: Bundle) :
@Suppress("Detekt.TooGenericExceptionCaught")
override fun onNext(roomOverall: RoomOverall) {
currentConversation = roomOverall.ocs.data
+ Log.d(TAG, "currentConversation.toString : " + currentConversation.toString())
+ Log.d(TAG, "currentConversation.sessionId : " + currentConversation?.sessionId)
loadAvatarForStatusBar()
setTitle()
@@ -420,6 +424,7 @@ class ChatController(args: Bundle) :
override fun onViewBound(view: View) {
actionBar?.show()
+ Log.d(TAG, "onViewBound")
var adapterWasNull = false
if (adapter == null) {
@@ -577,15 +582,6 @@ class ChatController(args: Bundle) :
binding.messageInputView.setPadding(0, 0, 0, 0)
- if (args.containsKey("showToggleChat") && args.getBoolean("showToggleChat")) {
- binding.callControlToggleChat.visibility = View.VISIBLE
- wasDetached = true
- }
-
- binding.callControlToggleChat.setOnClickListener {
- (activity as MagicCallActivity).showCall()
- }
-
binding.messagesListView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
super.onScrollStateChanged(recyclerView, newState)
@@ -1376,10 +1372,8 @@ class ChatController(args: Bundle) :
activity?.findViewById(R.id.toolbar)?.setOnClickListener { v -> showConversationInfoScreen() }
}
- isLeavingForConversation = false
ApplicationWideCurrentRoomHolder.getInstance().currentRoomId = roomId
- ApplicationWideCurrentRoomHolder.getInstance().currentRoomToken = roomId
- ApplicationWideCurrentRoomHolder.getInstance().isInCall = false
+ ApplicationWideCurrentRoomHolder.getInstance().currentRoomToken = roomToken
ApplicationWideCurrentRoomHolder.getInstance().userInRoom = conversationUser
val smileyButton = binding.messageInputView.findViewById(R.id.smileyButton)
@@ -1443,11 +1437,6 @@ class ChatController(args: Bundle) :
override fun onDetach(view: View) {
super.onDetach(view)
-
- if (!isLeavingForConversation) {
- // current room is still "active", we need the info
- ApplicationWideCurrentRoomHolder.getInstance().clear()
- }
eventBus?.unregister(this)
if (activity != null) {
@@ -1457,8 +1446,10 @@ class ChatController(args: Bundle) :
if (conversationUser != null &&
activity != null &&
!activity?.isChangingConfigurations!! &&
- !isLeavingForConversation
+ !ApplicationWideCurrentRoomHolder.getInstance().isInCall &&
+ !ApplicationWideCurrentRoomHolder.getInstance().isDialing
) {
+ ApplicationWideCurrentRoomHolder.getInstance().clear()
wasDetached = true
leaveRoom()
}
@@ -2129,7 +2120,7 @@ class ChatController(args: Bundle) :
}
private fun startACall(isVoiceOnlyCall: Boolean) {
- isLeavingForConversation = true
+ ApplicationWideCurrentRoomHolder.getInstance().isDialing = true
val callIntent = getIntentForCall(isVoiceOnlyCall)
if (callIntent != null) {
startActivity(callIntent)
@@ -2151,7 +2142,7 @@ class ChatController(args: Bundle) :
}
return if (activity != null) {
- val callIntent = Intent(activity, MagicCallActivity::class.java)
+ val callIntent = Intent(activity, CallActivity::class.java)
callIntent.putExtras(bundle)
callIntent
} else {
@@ -2336,7 +2327,7 @@ class ChatController(args: Bundle) :
menu.findItem(R.id.action_forward_message).isVisible =
ChatMessage.MessageType.REGULAR_TEXT_MESSAGE == message.getMessageType()
if (menu.hasVisibleItems()) {
- if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) {
+ if (Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) {
setForceShowIcon(true)
}
show()
@@ -2509,7 +2500,7 @@ class ChatController(args: Bundle) :
}
override fun onNext(roomOverall: RoomOverall) {
- val conversationIntent = Intent(activity, MagicCallActivity::class.java)
+ val conversationIntent = Intent(activity, CallActivity::class.java)
val bundle = Bundle()
bundle.putParcelable(KEY_USER_ENTITY, conversationUser)
bundle.putString(KEY_ROOM_TOKEN, roomOverall.ocs.data.token)
diff --git a/app/src/main/java/com/nextcloud/talk/controllers/ContactsController.java b/app/src/main/java/com/nextcloud/talk/controllers/ContactsController.java
index 59115a39e..3d202cfd4 100644
--- a/app/src/main/java/com/nextcloud/talk/controllers/ContactsController.java
+++ b/app/src/main/java/com/nextcloud/talk/controllers/ContactsController.java
@@ -22,7 +22,6 @@ package com.nextcloud.talk.controllers;
import android.app.SearchManager;
import android.content.Context;
-import android.content.Intent;
import android.graphics.PorterDuff;
import android.os.Build;
import android.os.Bundle;
@@ -45,7 +44,6 @@ import com.bluelinelabs.conductor.changehandler.VerticalChangeHandler;
import com.bluelinelabs.logansquare.LoganSquare;
import com.kennyc.bottomsheet.BottomSheet;
import com.nextcloud.talk.R;
-import com.nextcloud.talk.activities.MagicCallActivity;
import com.nextcloud.talk.adapters.items.GenericTextHeaderItem;
import com.nextcloud.talk.adapters.items.UserItem;
import com.nextcloud.talk.api.NcApi;
@@ -106,7 +104,6 @@ import eu.davidea.flexibleadapter.FlexibleAdapter;
import eu.davidea.flexibleadapter.SelectableAdapter;
import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager;
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem;
-import eu.davidea.flexibleadapter.items.IFlexible;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
@@ -897,13 +894,10 @@ public class ContactsController extends BaseController implements SearchView.OnQ
@Override
public void onNext(RoomOverall roomOverall) {
if (getActivity() != null) {
- Intent conversationIntent = new Intent(getActivity(), MagicCallActivity.class);
Bundle bundle = new Bundle();
bundle.putParcelable(BundleKeys.INSTANCE.getKEY_USER_ENTITY(), currentUser);
bundle.putString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN(), roomOverall.getOcs().getData().getToken());
bundle.putString(BundleKeys.INSTANCE.getKEY_ROOM_ID(), roomOverall.getOcs().getData().getRoomId());
- conversationIntent.putExtras(bundle);
-
bundle.putParcelable(BundleKeys.INSTANCE.getKEY_ACTIVE_CONVERSATION(),
Parcels.wrap(roomOverall.getOcs().getData()));
diff --git a/app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/OperationsMenuController.java b/app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/OperationsMenuController.java
index d1226ba3a..d084ee654 100644
--- a/app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/OperationsMenuController.java
+++ b/app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/OperationsMenuController.java
@@ -38,7 +38,6 @@ import com.bluelinelabs.conductor.RouterTransaction;
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler;
import com.bluelinelabs.logansquare.LoganSquare;
import com.nextcloud.talk.R;
-import com.nextcloud.talk.activities.MagicCallActivity;
import com.nextcloud.talk.api.NcApi;
import com.nextcloud.talk.application.NextcloudTalkApplication;
import com.nextcloud.talk.controllers.base.BaseController;
@@ -714,7 +713,6 @@ public class OperationsMenuController extends BaseController {
eventBus.post(new BottomSheetLockEvent(true, 0,
true, true, dismissView));
- Intent conversationIntent = new Intent(getActivity(), MagicCallActivity.class);
Bundle bundle = new Bundle();
bundle.putString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN(), conversation.getToken());
bundle.putString(BundleKeys.INSTANCE.getKEY_ROOM_ID(), conversation.getRoomId());
@@ -723,8 +721,6 @@ public class OperationsMenuController extends BaseController {
bundle.putParcelable(BundleKeys.INSTANCE.getKEY_ACTIVE_CONVERSATION(), Parcels.wrap(conversation));
bundle.putString(BundleKeys.INSTANCE.getKEY_CONVERSATION_PASSWORD(), callPassword);
- conversationIntent.putExtras(bundle);
-
if (getParentController() != null) {
ConductorRemapping.INSTANCE.remapChatController(getParentController().getRouter(), currentUser.getId(),
conversation.getToken(), bundle, true);
diff --git a/app/src/main/java/com/nextcloud/talk/dagger/modules/RestModule.java b/app/src/main/java/com/nextcloud/talk/dagger/modules/RestModule.java
index 49dc31ec9..467ff1876 100644
--- a/app/src/main/java/com/nextcloud/talk/dagger/modules/RestModule.java
+++ b/app/src/main/java/com/nextcloud/talk/dagger/modules/RestModule.java
@@ -33,7 +33,6 @@ import com.nextcloud.talk.utils.ApiUtils;
import com.nextcloud.talk.utils.LoggingUtils;
import com.nextcloud.talk.utils.database.user.UserUtils;
import com.nextcloud.talk.utils.preferences.AppPreferences;
-import com.nextcloud.talk.utils.singletons.AvatarStatusCodeHolder;
import com.nextcloud.talk.utils.ssl.MagicKeyManager;
import com.nextcloud.talk.utils.ssl.MagicTrustManager;
import com.nextcloud.talk.utils.ssl.SSLSocketFactoryCompat;
@@ -253,10 +252,6 @@ public class RestModule {
Response response = chain.proceed(request);
- if (request.url().encodedPath().contains("/avatar/")) {
- AvatarStatusCodeHolder.getInstance().setStatusCode(response.code());
- }
-
return response;
}
}
diff --git a/app/src/main/java/com/nextcloud/talk/jobs/NotificationWorker.java b/app/src/main/java/com/nextcloud/talk/jobs/NotificationWorker.java
index d11134a45..9f2a2e09e 100644
--- a/app/src/main/java/com/nextcloud/talk/jobs/NotificationWorker.java
+++ b/app/src/main/java/com/nextcloud/talk/jobs/NotificationWorker.java
@@ -48,7 +48,7 @@ import com.facebook.imagepipeline.image.CloseableImage;
import com.facebook.imagepipeline.postprocessors.RoundAsCirclePostprocessor;
import com.facebook.imagepipeline.request.ImageRequest;
import com.nextcloud.talk.R;
-import com.nextcloud.talk.activities.MagicCallActivity;
+import com.nextcloud.talk.activities.CallActivity;
import com.nextcloud.talk.activities.MainActivity;
import com.nextcloud.talk.api.NcApi;
import com.nextcloud.talk.application.NextcloudTalkApplication;
@@ -590,7 +590,7 @@ public class NotificationWorker extends Worker {
boolean startACall = decryptedPushMessage.getType().equals("call");
if (startACall) {
- intent = new Intent(context, MagicCallActivity.class);
+ intent = new Intent(context, CallActivity.class);
} else {
intent = new Intent(context, MainActivity.class);
}
diff --git a/app/src/main/java/com/nextcloud/talk/utils/singletons/ApplicationWideCurrentRoomHolder.java b/app/src/main/java/com/nextcloud/talk/utils/singletons/ApplicationWideCurrentRoomHolder.java
index 6ce60d386..1ab12a531 100644
--- a/app/src/main/java/com/nextcloud/talk/utils/singletons/ApplicationWideCurrentRoomHolder.java
+++ b/app/src/main/java/com/nextcloud/talk/utils/singletons/ApplicationWideCurrentRoomHolder.java
@@ -28,6 +28,7 @@ public class ApplicationWideCurrentRoomHolder {
private String currentRoomToken = "";
private UserEntity userInRoom = new UserEntity();
private boolean inCall = false;
+ private boolean isDialing = false;
private String session = "";
public static ApplicationWideCurrentRoomHolder getInstance() {
@@ -38,6 +39,7 @@ public class ApplicationWideCurrentRoomHolder {
currentRoomId = "";
userInRoom = new UserEntity();
inCall = false;
+ isDialing = false;
currentRoomToken = "";
session = "";
}
@@ -74,6 +76,14 @@ public class ApplicationWideCurrentRoomHolder {
this.inCall = inCall;
}
+ public boolean isDialing() {
+ return isDialing;
+ }
+
+ public void setDialing(boolean dialing) {
+ isDialing = dialing;
+ }
+
public String getSession() {
return session;
}
diff --git a/app/src/main/res/drawable/ic_baseline_picture_in_picture_alt_24.xml b/app/src/main/res/drawable/ic_baseline_picture_in_picture_alt_24.xml
new file mode 100644
index 000000000..7837510dd
--- /dev/null
+++ b/app/src/main/res/drawable/ic_baseline_picture_in_picture_alt_24.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/app/src/main/res/layout/activity_magic_call.xml b/app/src/main/res/layout/activity_magic_call.xml
deleted file mode 100644
index 7ea065fa5..000000000
--- a/app/src/main/res/layout/activity_magic_call.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-
-
-
-
-
-
-
-
-
diff --git a/app/src/main/res/layout/controller_call.xml b/app/src/main/res/layout/call_activity.xml
similarity index 79%
rename from app/src/main/res/layout/controller_call.xml
rename to app/src/main/res/layout/call_activity.xml
index a02000cfc..42d739733 100644
--- a/app/src/main/res/layout/controller_call.xml
+++ b/app/src/main/res/layout/call_activity.xml
@@ -28,7 +28,7 @@
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:orientation="vertical"
- tools:context=".activities.MagicCallActivity">
+ tools:context=".activities.CallActivity">
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/controller_call_notification.xml b/app/src/main/res/layout/call_notification_activity.xml
similarity index 87%
rename from app/src/main/res/layout/controller_call_notification.xml
rename to app/src/main/res/layout/call_notification_activity.xml
index 76b47fa45..76c3f710c 100644
--- a/app/src/main/res/layout/controller_call_notification.xml
+++ b/app/src/main/res/layout/call_notification_activity.xml
@@ -22,19 +22,13 @@
-
-
+ android:layout_height="match_parent"
+ android:background="@color/grey950">
@@ -119,10 +113,9 @@
+ app:roundAsCircle="true" />
diff --git a/app/src/main/res/layout/call_states.xml b/app/src/main/res/layout/call_states.xml
index 136805f57..1e2a354d6 100644
--- a/app/src/main/res/layout/call_states.xml
+++ b/app/src/main/res/layout/call_states.xml
@@ -21,7 +21,7 @@
-->
diff --git a/app/src/main/res/layout/controller_chat.xml b/app/src/main/res/layout/controller_chat.xml
index b65baa4a8..413e56ffb 100644
--- a/app/src/main/res/layout/controller_chat.xml
+++ b/app/src/main/res/layout/controller_chat.xml
@@ -40,19 +40,6 @@
android:visibility="gone"
tools:visibility="visible" />
-
-
24dp
-
- 120dp
diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml
index 61a76806e..e52c554ed 100644
--- a/app/src/main/res/values/dimens.xml
+++ b/app/src/main/res/values/dimens.xml
@@ -33,8 +33,6 @@
40dp
30dp
96dp
- @dimen/avatar_fetching_size_very_big
- 180dp
14sp
6dp
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 501acb52c..ff1ce3b6b 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -221,6 +221,10 @@
%1$s with phone
%1$s with video
+
+ Mute microphone
+ Enable microphone
+
%1$s on %2$s notification channel
Calls notification channel
@@ -468,4 +472,5 @@
%1$s (%2$d)
Invalid password
Do you want to reauthorize or delete this account?
+
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index c266cc46d..ebd6e739b 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -51,10 +51,6 @@
- @color/fontAppbar
-
-
@@ -187,6 +183,13 @@
- @color/colorPrimary
+
+
+