diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index f1060a870..4f95aa544 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -46,7 +46,9 @@
tools:replace="label, icon, roundIcon, theme, name, allowBackup">
-
+
diff --git a/app/src/main/java/com/nextcloud/talk/activities/MagicCallActivity.java b/app/src/main/java/com/nextcloud/talk/activities/MagicCallActivity.java
new file mode 100644
index 000000000..c00fadf11
--- /dev/null
+++ b/app/src/main/java/com/nextcloud/talk/activities/MagicCallActivity.java
@@ -0,0 +1,96 @@
+/*
+ * 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.os.Bundle;
+import android.support.v7.app.AppCompatActivity;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.Window;
+import android.view.WindowManager;
+
+import com.bluelinelabs.conductor.Conductor;
+import com.bluelinelabs.conductor.Router;
+import com.bluelinelabs.conductor.RouterTransaction;
+import com.bluelinelabs.conductor.changehandler.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.utils.bundle.BundleKeys;
+
+import autodagger.AutoInjector;
+import butterknife.BindView;
+import butterknife.ButterKnife;
+
+@AutoInjector(NextcloudTalkApplication.class)
+public class MagicCallActivity extends AppCompatActivity {
+ private static final String TAG = "MagicCallActivity";
+
+ @BindView(R.id.controller_container)
+ ViewGroup container;
+
+ private Router router;
+
+ private static int getSystemUiVisibility() {
+ int flags = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN;
+ flags |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
+ return flags;
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject (this);
+
+ requestWindowFeature(Window.FEATURE_NO_TITLE);
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN |
+ WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON |
+ WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
+ WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
+ getWindow().getDecorView().setSystemUiVisibility(getSystemUiVisibility());
+
+ setContentView(R.layout.activity_magic_call);
+ ButterKnife.bind(this);
+ router = Conductor.attachRouter(this, container, savedInstanceState);
+ router.setPopsLastView(true);
+
+ if (!router.hasRootController()) {
+ if (getIntent().getBooleanExtra(BundleKeys.KEY_FROM_NOTIFICATION_START_CALL, false)) {
+ router.setRoot(RouterTransaction.with(new CallNotificationController(getIntent().getExtras()))
+ .pushChangeHandler(new HorizontalChangeHandler())
+ .popChangeHandler(new HorizontalChangeHandler()));
+ } else {
+ router.setRoot(RouterTransaction.with(new CallController(getIntent().getExtras()))
+ .pushChangeHandler(new HorizontalChangeHandler())
+ .popChangeHandler(new HorizontalChangeHandler()));
+ }
+ }
+ }
+
+ @Override
+ public void onBackPressed() {
+ if (!router.handleBack()) {
+ super.onBackPressed();
+ }
+ }
+
+}
diff --git a/app/src/main/java/com/nextcloud/talk/activities/CallActivity.java b/app/src/main/java/com/nextcloud/talk/controllers/CallController.java
similarity index 84%
rename from app/src/main/java/com/nextcloud/talk/activities/CallActivity.java
rename to app/src/main/java/com/nextcloud/talk/controllers/CallController.java
index b28eeb597..a78d7356f 100644
--- a/app/src/main/java/com/nextcloud/talk/activities/CallActivity.java
+++ b/app/src/main/java/com/nextcloud/talk/controllers/CallController.java
@@ -2,7 +2,7 @@
* Nextcloud Talk application
*
* @author Mario Danic
- * Copyright (C) 2017 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
@@ -16,19 +16,14 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
- *
- * Inspired by:
- * - Google samples
- * - https://github.com/vivek1794/webrtc-android-codelab (MIT licence)
*/
-package com.nextcloud.talk.activities;
+package com.nextcloud.talk.controllers;
import android.Manifest;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.annotation.SuppressLint;
-import android.content.res.Configuration;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
@@ -37,10 +32,10 @@ import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.util.Log;
+import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
-import android.view.Window;
-import android.view.WindowManager;
+import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
@@ -53,8 +48,8 @@ import com.bumptech.glide.request.RequestOptions;
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.MediaStreamEvent;
-import com.nextcloud.talk.events.PeerConnectionEvent;
import com.nextcloud.talk.events.SessionDescriptionSendEvent;
import com.nextcloud.talk.models.database.UserEntity;
import com.nextcloud.talk.models.json.call.CallOverall;
@@ -112,7 +107,6 @@ import org.webrtc.VideoSource;
import org.webrtc.VideoTrack;
import java.io.IOException;
-import java.net.CookieManager;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
@@ -125,7 +119,6 @@ import javax.inject.Inject;
import autodagger.AutoInjector;
import butterknife.BindView;
-import butterknife.ButterKnife;
import butterknife.OnClick;
import butterknife.OnLongClick;
import eu.davidea.flipview.FlipView;
@@ -140,8 +133,10 @@ import okhttp3.Cache;
import pub.devrel.easypermissions.AfterPermissionGranted;
@AutoInjector(NextcloudTalkApplication.class)
-public class CallActivity extends AppCompatActivity {
- private static final String TAG = "CallActivity";
+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,
@@ -162,7 +157,7 @@ public class CallActivity extends AppCompatActivity {
@BindView(R.id.remote_renderers_layout)
LinearLayout remoteRenderersLayout;
- @BindView(R.id.call_controls)
+ @BindView(R.id.callControlsLinearLayoutView)
LinearLayout callControls;
@BindView(R.id.call_control_microphone)
FlipView microphoneControlButton;
@@ -170,6 +165,11 @@ public class CallActivity extends AppCompatActivity {
FlipView cameraControlButton;
@BindView(R.id.call_control_switch_camera)
FlipView cameraSwitchButton;
+ @BindView(R.id.connectingRelativeLayoutView)
+ RelativeLayout connectingView;
+
+ @BindView(R.id.conversationRelativeLayoutView)
+ RelativeLayout conversationView;
@Inject
NcApi ncApi;
@@ -178,8 +178,6 @@ public class CallActivity extends AppCompatActivity {
@Inject
UserUtils userUtils;
@Inject
- CookieManager cookieManager;
- @Inject
AppPreferences appPreferences;
@Inject
Cache cache;
@@ -216,7 +214,7 @@ public class CallActivity extends AppCompatActivity {
private boolean isMultiSession = false;
private boolean hasChatSupport = false;
private boolean isVoiceOnlyCall = false;
-
+ private boolean isFromNotification;
private Handler handler = new Handler();
private boolean isPTTActive = false;
@@ -228,58 +226,70 @@ public class CallActivity extends AppCompatActivity {
private SpotlightView spotlightView;
-
- private static int getSystemUiVisibility() {
- int flags = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN;
- flags |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
- return flags;
- }
-
- @SuppressLint("ClickableViewAccessibility")
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
+ public CallController(Bundle args) {
+ super(args);
NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this);
- requestWindowFeature(Window.FEATURE_NO_TITLE);
- getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN |
- WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON |
- WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
- WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
- getWindow().getDecorView().setSystemUiVisibility(getSystemUiVisibility());
+ roomId = args.getString(BundleKeys.KEY_ROOM_ID, "");
+ roomToken = args.getString(BundleKeys.KEY_ROOM_TOKEN, "");
+ userEntity = Parcels.unwrap(args.getParcelable(BundleKeys.KEY_USER_ENTITY));
- setContentView(R.layout.activity_call);
- ButterKnife.bind(this);
+ if (userEntity == null) {
+ userEntity = userUtils.getCurrentUser();
+ }
- microphoneControlButton.setOnTouchListener(new microphoneButtonTouchListener());
- videoOnClickListener = new videoClickListener();
+ callSession = args.getString(BundleKeys.KEY_CALL_SESSION, "0");
+ credentials = ApiUtils.getCredentials(userEntity.getUsername(), userEntity.getToken());
+ isVoiceOnlyCall = args.getBoolean(BundleKeys.KEY_CALL_VOICE_ONLY, false);
+
+ if (userEntity.getUserId().equals("-1")) {
+ credentials = null;
+ }
+
+ baseUrl = args.getString(BundleKeys.KEY_MODIFIED_BASE_URL, "");
+
+ if (TextUtils.isEmpty(baseUrl)) {
+ baseUrl = userEntity.getBaseUrl();
+ }
+
+ isFromNotification = args.containsKey(BundleKeys.KEY_FROM_NOTIFICATION_START_CALL) && TextUtils.isEmpty
+ (roomToken);
+ }
+
+ @Override
+ protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
+ return inflater.inflate(R.layout.controller_call, container, false);
+ }
+
+ 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");
+ }
+
+ if (camera2EnumeratorIsSupported) {
+ cameraEnumerator = new Camera2Enumerator(getActivity());
+ } else {
+ cameraEnumerator = new Camera1Enumerator(MagicWebRTCUtils.shouldEnableVideoHardwareAcceleration());
+ }
+ }
+ }
+
+ @Override
+ protected void onViewBound(@NonNull View view) {
+ super.onViewBound(view);
+
+ microphoneControlButton.setOnTouchListener(new MicrophoneButtonTouchListener());
+ videoOnClickListener = new VideoClickListener();
pulseAnimation = PulseAnimation.create().with(microphoneControlButton.getFrontImageView())
.setDuration(310)
.setRepeatCount(PulseAnimation.INFINITE)
.setRepeatMode(PulseAnimation.REVERSE);
- roomId = getIntent().getExtras().getString(BundleKeys.KEY_ROOM_ID, "");
- roomToken = getIntent().getExtras().getString(BundleKeys.KEY_ROOM_TOKEN, "");
- userEntity = Parcels.unwrap(getIntent().getExtras().getParcelable(BundleKeys.KEY_USER_ENTITY));
-
- if (userEntity == null) {
- userEntity = userUtils.getCurrentUser();
- }
-
- callSession = getIntent().getExtras().getString(BundleKeys.KEY_CALL_SESSION, "0");
- credentials = ApiUtils.getCredentials(userEntity.getUsername(), userEntity.getToken());
- isVoiceOnlyCall = getIntent().getExtras().getBoolean(BundleKeys.KEY_CALL_VOICE_ONLY, false);
-
- if (userEntity.getUserId().equals("-1")) {
- credentials = null;
- }
-
- baseUrl = getIntent().getExtras().getString(BundleKeys.KEY_MODIFIED_BASE_URL, "");
-
- if (TextUtils.isEmpty(baseUrl)) {
- baseUrl = userEntity.getBaseUrl();
- }
try {
cache.evictAll();
@@ -290,8 +300,7 @@ public class CallActivity extends AppCompatActivity {
callControls.setZ(100.0f);
basicInitialization();
- if (getIntent().getExtras().containsKey(BundleKeys.KEY_FROM_NOTIFICATION_START_CALL) && TextUtils.isEmpty
- (roomToken)) {
+ if (isFromNotification) {
handleFromNotification();
} else {
initViews();
@@ -299,6 +308,53 @@ public class CallActivity extends AppCompatActivity {
}
}
+ private void basicInitialization() {
+ rootEglBase = EglBase.create();
+ createCameraEnumerator();
+
+ //Create a new PeerConnectionFactory instance.
+ PeerConnectionFactory.Options options = new PeerConnectionFactory.Options();
+ peerConnectionFactory = PeerConnectionFactory.builder().createPeerConnectionFactory();
+
+ peerConnectionFactory.setVideoHwAccelerationOptions(rootEglBase.getEglBaseContext(),
+ rootEglBase.getEglBaseContext());
+
+ //Create MediaConstraints - Will be useful for specifying video and audio constraints.
+ audioConstraints = new MediaConstraints();
+ videoConstraints = new MediaConstraints();
+
+ localMediaStream = peerConnectionFactory.createLocalMediaStream("NCMS");
+
+ // Create and audio manager that will take care of audio routing,
+ // audio modes, audio device enumeration etc.
+ audioManager = MagicAudioManager.create(getApplicationContext());
+ // Store existing audio settings and change audio mode to
+ // MODE_IN_COMMUNICATION for best possible VoIP performance.
+ Log.d(TAG, "Starting the audio manager...");
+ audioManager.start(this::onAudioManagerDevicesChanged);
+
+ iceServers = new ArrayList<>();
+
+ //create sdpConstraints
+ sdpConstraints = new MediaConstraints();
+ sdpConstraints.mandatory.add(new MediaConstraints.KeyValuePair("OfferToReceiveAudio", "true"));
+ String offerToReceiveVideoString = "true";
+
+ if (isVoiceOnlyCall) {
+ offerToReceiveVideoString = "false";
+ }
+
+ sdpConstraints.mandatory.add(new MediaConstraints.KeyValuePair("OfferToReceiveVideo",
+ offerToReceiveVideoString));
+ sdpConstraints.optional.add(new MediaConstraints.KeyValuePair("internalSctpDataChannels", "true"));
+ sdpConstraints.optional.add(new MediaConstraints.KeyValuePair("DtlsSrtpKeyAgreement", "true"));
+
+ if (!isVoiceOnlyCall) {
+ cameraInitialization();
+ }
+ microphoneInitialization();
+ }
+
private void handleFromNotification() {
ncApi.getRooms(credentials, ApiUtils.getUrlForGetRooms(baseUrl))
.retry(3)
@@ -335,6 +391,313 @@ public class CallActivity extends AppCompatActivity {
});
}
+ private void initViews() {
+ if (isVoiceOnlyCall) {
+ cameraSwitchButton.setVisibility(View.GONE);
+ cameraControlButton.setVisibility(View.GONE);
+ pipVideoView.setVisibility(View.GONE);
+ } else {
+ if (cameraEnumerator.getDeviceNames().length < 2) {
+ cameraSwitchButton.setVisibility(View.GONE);
+ }
+
+ // setting this to true because it's not shown by default
+ pipVideoView.setMirror(false);
+ pipVideoView.init(rootEglBase.getEglBaseContext(), null);
+ pipVideoView.setZOrderMediaOverlay(true);
+ // disabled because it causes some devices to crash
+ pipVideoView.setEnableHardwareScaler(false);
+ pipVideoView.setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_FIT);
+ }
+ }
+
+
+ private void checkPermissions() {
+ if (isVoiceOnlyCall) {
+ onMicrophoneClick();
+ } else if (getActivity() != null) {
+ EffortlessPermissions.requestPermissions(getActivity(), R.string.nc_permissions,
+ R.string.nc_proceed, R.string.nc_empty, 100, PERMISSIONS_CALL);
+ }
+
+ }
+
+ @AfterPermissionGranted(100)
+ private void onPermissionsGranted() {
+ if (getActivity() != null && EffortlessPermissions.hasPermissions(getActivity(), PERMISSIONS_CALL)) {
+ if (!videoOn && !isVoiceOnlyCall) {
+ onCameraClick();
+ }
+
+ if (!audioOn) {
+ onMicrophoneClick();
+ }
+
+ if (!isVoiceOnlyCall) {
+ if (cameraEnumerator.getDeviceNames().length == 0) {
+ cameraControlButton.setVisibility(View.GONE);
+ }
+
+ if (cameraEnumerator.getDeviceNames().length > 1) {
+ cameraSwitchButton.setVisibility(View.VISIBLE);
+ }
+ }
+
+ if (!inCall) {
+ startCall();
+ }
+ } else if (getActivity() != null && EffortlessPermissions.somePermissionPermanentlyDenied(getActivity(),
+ PERMISSIONS_CALL)) {
+ checkIfSomeAreApproved();
+ }
+
+ }
+
+ private void checkIfSomeAreApproved() {
+ if (!isVoiceOnlyCall) {
+ if (cameraEnumerator.getDeviceNames().length == 0) {
+ cameraControlButton.setVisibility(View.GONE);
+ }
+
+ if (cameraEnumerator.getDeviceNames().length > 1) {
+ cameraSwitchButton.setVisibility(View.VISIBLE);
+ }
+
+ if (getActivity() != null && EffortlessPermissions.hasPermissions(getActivity(), PERMISSIONS_CAMERA)) {
+ if (!videoOn) {
+ onCameraClick();
+ }
+ } else {
+ cameraControlButton.getFrontImageView().setImageResource(R.drawable.ic_videocam_off_white_24px);
+ cameraControlButton.setAlpha(0.7f);
+ cameraSwitchButton.setVisibility(View.GONE);
+ }
+ }
+
+ if (getActivity() != null && EffortlessPermissions.hasPermissions(getActivity(), PERMISSIONS_MICROPHONE)) {
+ if (!audioOn) {
+ onMicrophoneClick();
+ }
+ } else {
+ microphoneControlButton.getFrontImageView().setImageResource(R.drawable.ic_mic_off_white_24px);
+ }
+
+ if (!inCall) {
+ startCall();
+ }
+ }
+
+ @AfterPermissionDenied(100)
+ private void onPermissionsDenied() {
+ if (!isVoiceOnlyCall) {
+ if (cameraEnumerator.getDeviceNames().length == 0) {
+ cameraControlButton.setVisibility(View.GONE);
+ } else if (cameraEnumerator.getDeviceNames().length == 1) {
+ cameraSwitchButton.setVisibility(View.GONE);
+ }
+ }
+
+ if (getActivity() != null && (EffortlessPermissions.hasPermissions(getActivity(), PERMISSIONS_CAMERA) ||
+ EffortlessPermissions.hasPermissions(getActivity(), PERMISSIONS_MICROPHONE))) {
+ checkIfSomeAreApproved();
+ } else if (!inCall) {
+ startCall();
+ }
+ }
+
+ private void onAudioManagerDevicesChanged(
+ final MagicAudioManager.AudioDevice device, final Set availableDevices) {
+ Log.d(TAG, "onAudioManagerDevicesChanged: " + availableDevices + ", "
+ + "selected: " + device);
+ }
+
+ private void cameraInitialization() {
+ videoCapturer = createCameraCapturer(cameraEnumerator);
+
+ //Create a VideoSource instance
+ if (videoCapturer != null) {
+ videoSource = peerConnectionFactory.createVideoSource(videoCapturer);
+ localVideoTrack = peerConnectionFactory.createVideoTrack("NCv0", videoSource);
+ localMediaStream.addTrack(localVideoTrack);
+ localVideoTrack.setEnabled(false);
+
+ localVideoTrack.addSink(pipVideoView);
+ }
+
+ }
+
+ private void microphoneInitialization() {
+ //create an AudioSource instance
+ audioSource = peerConnectionFactory.createAudioSource(audioConstraints);
+ localAudioTrack = peerConnectionFactory.createAudioTrack("NCa0", audioSource);
+ localAudioTrack.setEnabled(false);
+ localMediaStream.addTrack(localAudioTrack);
+ }
+
+ private VideoCapturer createCameraCapturer(CameraEnumerator enumerator) {
+ final String[] deviceNames = enumerator.getDeviceNames();
+
+ // First, try to find front facing camera
+ Logging.d(TAG, "Looking for front facing cameras.");
+ for (String deviceName : deviceNames) {
+ if (enumerator.isFrontFacing(deviceName)) {
+ Logging.d(TAG, "Creating front facing camera capturer.");
+ VideoCapturer videoCapturer = enumerator.createCapturer(deviceName, null);
+
+ if (videoCapturer != null) {
+ return videoCapturer;
+ }
+ }
+ }
+
+
+ // Front facing camera not found, try something else
+ Logging.d(TAG, "Looking for other cameras.");
+ for (String deviceName : deviceNames) {
+ if (!enumerator.isFrontFacing(deviceName)) {
+ Logging.d(TAG, "Creating other camera capturer.");
+ VideoCapturer videoCapturer = enumerator.createCapturer(deviceName, null);
+
+ if (videoCapturer != null) {
+ pipVideoView.setMirror(false);
+ return videoCapturer;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ @OnLongClick(R.id.call_control_microphone)
+ public boolean onMicrophoneLongClick() {
+ if (!audioOn) {
+ handler.removeCallbacksAndMessages(null);
+ isPTTActive = true;
+ callControls.setVisibility(View.VISIBLE);
+ }
+
+ onMicrophoneClick();
+ return true;
+ }
+
+ @OnClick(R.id.call_control_microphone)
+ public void onMicrophoneClick() {
+ if (getActivity() != null && EffortlessPermissions.hasPermissions(getActivity(), 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.white))
+ .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();
+
+ appPreferences.setPushToTalkIntroShown(true);
+ }
+
+ if (!isPTTActive) {
+ audioOn = !audioOn;
+
+ if (audioOn) {
+ microphoneControlButton.getFrontImageView().setImageResource(R.drawable.ic_mic_white_24px);
+ } else {
+ microphoneControlButton.getFrontImageView().setImageResource(R.drawable.ic_mic_off_white_24px);
+ }
+
+ toggleMedia(audioOn, false);
+ } else {
+ microphoneControlButton.getFrontImageView().setImageResource(R.drawable.ic_mic_white_24px);
+ pulseAnimation.start();
+ toggleMedia(true, false);
+ }
+
+ if (isVoiceOnlyCall && !inCall) {
+ startCall();
+ }
+
+ } else if (getActivity() != null && EffortlessPermissions.somePermissionPermanentlyDenied(getActivity(),
+ 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());
+ } else {
+ EffortlessPermissions.requestPermissions(getActivity(), R.string.nc_permissions_audio,
+ R.string.nc_proceed, R.string.nc_empty, 100, PERMISSIONS_MICROPHONE);
+ }
+ }
+
+ @OnClick(R.id.call_control_hangup)
+ public void onHangupClick() {
+ if (inCall) {
+ hangup(false);
+ } else {
+ hangup(true);
+ }
+ }
+
+ @OnClick(R.id.call_control_camera)
+ public void onCameraClick() {
+ if (EffortlessPermissions.hasPermissions(getActivity(), PERMISSIONS_CAMERA)) {
+ videoOn = !videoOn;
+
+ if (videoOn) {
+ cameraControlButton.getFrontImageView().setImageResource(R.drawable.ic_videocam_white_24px);
+ if (cameraEnumerator.getDeviceNames().length > 1) {
+ cameraSwitchButton.setVisibility(View.VISIBLE);
+ }
+ } else {
+ cameraControlButton.getFrontImageView().setImageResource(R.drawable.ic_videocam_off_white_24px);
+ cameraSwitchButton.setVisibility(View.GONE);
+ }
+
+ toggleMedia(videoOn, true);
+ } else if (getActivity() != null && EffortlessPermissions.somePermissionPermanentlyDenied(getActivity(),
+ 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());
+ } else {
+ if (getActivity() != null) {
+ EffortlessPermissions.requestPermissions(getActivity(), R.string.nc_permissions_video,
+ R.string.nc_proceed, R.string.nc_empty, 100, PERMISSIONS_CAMERA);
+ }
+ }
+
+ }
+
+ @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 b) {
+ pipVideoView.setMirror(false);
+ }
+
+ @Override
+ public void onCameraSwitchError(String s) {
+
+ }
+ });
+ }
+ }
private void toggleMedia(boolean enable, boolean video) {
String message;
@@ -385,371 +748,6 @@ public class CallActivity extends AppCompatActivity {
}
}
- @OnLongClick(R.id.call_control_microphone)
- public boolean onMicrophoneLongClick() {
- if (!audioOn) {
- handler.removeCallbacksAndMessages(null);
- isPTTActive = true;
- callControls.setVisibility(View.VISIBLE);
- }
-
- onMicrophoneClick();
- return true;
- }
-
- @OnClick(R.id.call_control_microphone)
- public void onMicrophoneClick() {
- if (EffortlessPermissions.hasPermissions(this, PERMISSIONS_MICROPHONE)) {
-
- 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(getString(R.string.nc_push_to_talk))
- .subHeadingTvColor(getResources().getColor(R.color.white))
- .subHeadingTvSize(16)
- .subHeadingTvText(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();
-
- appPreferences.setPushToTalkIntroShown(true);
- }
-
- if (!isPTTActive) {
- audioOn = !audioOn;
-
- if (audioOn) {
- microphoneControlButton.getFrontImageView().setImageResource(R.drawable.ic_mic_white_24px);
- } else {
- microphoneControlButton.getFrontImageView().setImageResource(R.drawable.ic_mic_off_white_24px);
- }
-
- toggleMedia(audioOn, false);
- } else {
- microphoneControlButton.getFrontImageView().setImageResource(R.drawable.ic_mic_white_24px);
- pulseAnimation.start();
- toggleMedia(true, false);
- }
-
- if (isVoiceOnlyCall && !inCall) {
- startCall();
- }
-
- } else if (EffortlessPermissions.somePermissionPermanentlyDenied(this, PERMISSIONS_MICROPHONE)) {
- // Microphone permission is permanently denied so we cannot request it normally.
- OpenAppDetailsDialogFragment.show(
- R.string.nc_microphone_permission_permanently_denied,
- R.string.nc_permissions_settings, this);
- } else {
- EffortlessPermissions.requestPermissions(this, R.string.nc_permissions_audio,
- R.string.nc_proceed, R.string.nc_empty, 100, PERMISSIONS_MICROPHONE);
- }
- }
-
- @OnClick(R.id.call_control_hangup)
- public void onHangupClick() {
- if (inCall) {
- hangup(false);
- } else {
- hangup(true);
- }
- }
-
- @OnClick(R.id.call_control_camera)
- public void onCameraClick() {
- if (EffortlessPermissions.hasPermissions(this, PERMISSIONS_CAMERA)) {
- videoOn = !videoOn;
-
- if (videoOn) {
- cameraControlButton.getFrontImageView().setImageResource(R.drawable.ic_videocam_white_24px);
- if (cameraEnumerator.getDeviceNames().length > 1) {
- cameraSwitchButton.setVisibility(View.VISIBLE);
- }
- } else {
- cameraControlButton.getFrontImageView().setImageResource(R.drawable.ic_videocam_off_white_24px);
- cameraSwitchButton.setVisibility(View.GONE);
- }
-
- toggleMedia(videoOn, true);
- } 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, this);
- } else {
- EffortlessPermissions.requestPermissions(this, R.string.nc_permissions_video,
- R.string.nc_proceed, R.string.nc_empty, 100, PERMISSIONS_CAMERA);
- }
-
- }
-
-
- @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 b) {
- pipVideoView.setMirror(false);
- }
-
- @Override
- public void onCameraSwitchError(String s) {
-
- }
- });
- }
- }
-
- 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 VideoCapturer createCameraCapturer(CameraEnumerator enumerator) {
- final String[] deviceNames = enumerator.getDeviceNames();
-
- // First, try to find front facing camera
- Logging.d(TAG, "Looking for front facing cameras.");
- for (String deviceName : deviceNames) {
- if (enumerator.isFrontFacing(deviceName)) {
- Logging.d(TAG, "Creating front facing camera capturer.");
- VideoCapturer videoCapturer = enumerator.createCapturer(deviceName, null);
-
- if (videoCapturer != null) {
- return videoCapturer;
- }
- }
- }
-
-
- // Front facing camera not found, try something else
- Logging.d(TAG, "Looking for other cameras.");
- for (String deviceName : deviceNames) {
- if (!enumerator.isFrontFacing(deviceName)) {
- Logging.d(TAG, "Creating other camera capturer.");
- VideoCapturer videoCapturer = enumerator.createCapturer(deviceName, null);
-
- if (videoCapturer != null) {
- pipVideoView.setMirror(false);
- return videoCapturer;
- }
- }
- }
-
- return null;
- }
-
- public void initViews() {
- if (isVoiceOnlyCall) {
- cameraSwitchButton.setVisibility(View.GONE);
- cameraControlButton.setVisibility(View.GONE);
- pipVideoView.setVisibility(View.GONE);
- } else {
- if (cameraEnumerator.getDeviceNames().length < 2) {
- cameraSwitchButton.setVisibility(View.GONE);
- }
-
- // setting this to true because it's not shown by default
- pipVideoView.setMirror(false);
- pipVideoView.init(rootEglBase.getEglBaseContext(), null);
- pipVideoView.setZOrderMediaOverlay(true);
- // disabled because it causes some devices to crash
- pipVideoView.setEnableHardwareScaler(false);
- pipVideoView.setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_FIT);
- }
- }
-
- private void checkPermissions() {
- if (isVoiceOnlyCall) {
- onMicrophoneClick();
- } else {
- EffortlessPermissions.requestPermissions(this, R.string.nc_permissions,
- R.string.nc_proceed, R.string.nc_empty, 100, PERMISSIONS_CALL);
- }
-
- }
-
- @AfterPermissionGranted(100)
- private void onPermissionsGranted() {
- if (EffortlessPermissions.hasPermissions(this, PERMISSIONS_CALL)) {
- if (!videoOn && !isVoiceOnlyCall) {
- onCameraClick();
- }
-
- if (!audioOn) {
- onMicrophoneClick();
- }
-
- if (!isVoiceOnlyCall) {
- if (cameraEnumerator.getDeviceNames().length == 0) {
- cameraControlButton.setVisibility(View.GONE);
- }
-
- if (cameraEnumerator.getDeviceNames().length > 1) {
- cameraSwitchButton.setVisibility(View.VISIBLE);
- }
- }
-
- if (!inCall) {
- startCall();
- }
- } else if (EffortlessPermissions.somePermissionPermanentlyDenied(this,
- PERMISSIONS_CALL)) {
- checkIfSomeAreApproved();
- }
-
- }
-
- private void checkIfSomeAreApproved() {
- if (!isVoiceOnlyCall) {
- if (cameraEnumerator.getDeviceNames().length == 0) {
- cameraControlButton.setVisibility(View.GONE);
- }
-
- if (cameraEnumerator.getDeviceNames().length > 1) {
- cameraSwitchButton.setVisibility(View.VISIBLE);
- }
-
- if (EffortlessPermissions.hasPermissions(this, PERMISSIONS_CAMERA)) {
- if (!videoOn) {
- onCameraClick();
- }
- } else {
- cameraControlButton.getFrontImageView().setImageResource(R.drawable.ic_videocam_off_white_24px);
- cameraControlButton.setAlpha(0.7f);
- cameraSwitchButton.setVisibility(View.GONE);
- }
- }
-
- if (EffortlessPermissions.hasPermissions(this, PERMISSIONS_MICROPHONE)) {
- if (!audioOn) {
- onMicrophoneClick();
- }
- } else {
- microphoneControlButton.getFrontImageView().setImageResource(R.drawable.ic_mic_off_white_24px);
- }
-
- if (!inCall) {
- startCall();
- }
- }
-
- @AfterPermissionDenied(100)
- private void onPermissionsDenied() {
- if (!isVoiceOnlyCall) {
- if (cameraEnumerator.getDeviceNames().length == 0) {
- cameraControlButton.setVisibility(View.GONE);
- } else if (cameraEnumerator.getDeviceNames().length == 1) {
- cameraSwitchButton.setVisibility(View.GONE);
- }
- }
-
- if (EffortlessPermissions.hasPermissions(this, PERMISSIONS_CAMERA) ||
- EffortlessPermissions.hasPermissions(this, PERMISSIONS_MICROPHONE)) {
- checkIfSomeAreApproved();
- } else if (!inCall) {
- startCall();
- }
- }
-
- private void basicInitialization() {
- rootEglBase = EglBase.create();
- createCameraEnumerator();
-
- //Create a new PeerConnectionFactory instance.
- PeerConnectionFactory.Options options = new PeerConnectionFactory.Options();
- peerConnectionFactory = PeerConnectionFactory.builder().createPeerConnectionFactory();
-
- peerConnectionFactory.setVideoHwAccelerationOptions(rootEglBase.getEglBaseContext(),
- rootEglBase.getEglBaseContext());
-
- //Create MediaConstraints - Will be useful for specifying video and audio constraints.
- audioConstraints = new MediaConstraints();
- videoConstraints = new MediaConstraints();
-
- localMediaStream = peerConnectionFactory.createLocalMediaStream("NCMS");
-
- // Create and audio manager that will take care of audio routing,
- // audio modes, audio device enumeration etc.
- audioManager = MagicAudioManager.create(getApplicationContext());
- // Store existing audio settings and change audio mode to
- // MODE_IN_COMMUNICATION for best possible VoIP performance.
- Log.d(TAG, "Starting the audio manager...");
- audioManager.start(new MagicAudioManager.AudioManagerEvents() {
- @Override
- public void onAudioDeviceChanged(MagicAudioManager.AudioDevice selectedAudioDevice,
- Set availableAudioDevices) {
- onAudioManagerDevicesChanged(selectedAudioDevice, availableAudioDevices);
- }
- });
-
- iceServers = new ArrayList<>();
-
- //create sdpConstraints
- sdpConstraints = new MediaConstraints();
- sdpConstraints.mandatory.add(new MediaConstraints.KeyValuePair("OfferToReceiveAudio", "true"));
- String offerToReceiveVideoString = "true";
-
- if (isVoiceOnlyCall) {
- offerToReceiveVideoString = "false";
- }
-
- sdpConstraints.mandatory.add(new MediaConstraints.KeyValuePair("OfferToReceiveVideo",
- offerToReceiveVideoString));
- sdpConstraints.optional.add(new MediaConstraints.KeyValuePair("internalSctpDataChannels", "true"));
- sdpConstraints.optional.add(new MediaConstraints.KeyValuePair("DtlsSrtpKeyAgreement", "true"));
-
- if (!isVoiceOnlyCall) {
- cameraInitialization();
- }
- microphoneInitialization();
- }
-
- private void cameraInitialization() {
- videoCapturer = createCameraCapturer(cameraEnumerator);
-
- //Create a VideoSource instance
- if (videoCapturer != null) {
- videoSource = peerConnectionFactory.createVideoSource(videoCapturer);
- localVideoTrack = peerConnectionFactory.createVideoTrack("NCv0", videoSource);
- localMediaStream.addTrack(localVideoTrack);
- localVideoTrack.setEnabled(false);
-
- localVideoTrack.addSink(pipVideoView);
- }
-
- }
-
- private void microphoneInitialization() {
- //create an AudioSource instance
- audioSource = peerConnectionFactory.createAudioSource(audioConstraints);
- localAudioTrack = peerConnectionFactory.createAudioTrack("NCa0", audioSource);
- localAudioTrack.setEnabled(false);
- localMediaStream.addTrack(localAudioTrack);
- }
-
private void startCall() {
if (!isPTTActive) {
animateCallControls(false, 7500);
@@ -757,9 +755,73 @@ public class CallActivity extends AppCompatActivity {
startPullingSignalingMessages();
}
- @OnClick({R.id.pip_video_view, R.id.remote_renderers_layout})
- public void showCallControls() {
- animateCallControls(true, 0);
+ private void animateCallControls(boolean show, long startDelay) {
+ if (!isPTTActive) {
+ float alpha;
+ long duration;
+
+ if (show) {
+ handler.removeCallbacksAndMessages(null);
+ alpha = 1.0f;
+ duration = 1000;
+ if (callControls.getVisibility() != View.VISIBLE) {
+ callControls.setAlpha(0.0f);
+ callControls.setVisibility(View.VISIBLE);
+ } else {
+ handler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ animateCallControls(false, 0);
+
+ }
+ }, 5000);
+ return;
+ }
+ } else {
+ alpha = 0.0f;
+ 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);
+ }
+ } else {
+ handler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ if (!isPTTActive) {
+ animateCallControls(false, 0);
+ }
+ }
+ }, 7500);
+ }
+
+ callControls.setEnabled(true);
+ }
+ }
+ });
+ }
+ }
+ }
+
+ @Override
+ public void onDestroy() {
+ onHangupClick();
+ super.onDestroy();
}
public void startPullingSignalingMessages() {
@@ -825,12 +887,6 @@ public class CallActivity extends AppCompatActivity {
});
}
- private void startVideoCapture() {
- if (videoCapturer != null) {
- videoCapturer.startCapture(1280, 720, 30);
- }
- }
-
private void checkCapabilities() {
ncApi.getCapabilities(credentials, ApiUtils.getUrlForCapabilities(baseUrl))
.retry(3)
@@ -926,6 +982,8 @@ public class CallActivity extends AppCompatActivity {
public void onNext(GenericOverall genericOverall) {
inCall = true;
+ connectingView.setVisibility(View.GONE);
+ conversationView.setVisibility(View.VISIBLE);
// start pinging the call
if (!hasChatSupport) {
@@ -1020,6 +1078,28 @@ public class CallActivity extends AppCompatActivity {
});
}
+ @OnClick({R.id.pip_video_view, R.id.remote_renderers_layout})
+ public void showCallControls() {
+ animateCallControls(true, 0);
+ }
+
+ private void dispose(@Nullable Disposable disposable) {
+ if (disposable != null && !disposable.isDisposed()) {
+ disposable.dispose();
+ } else if (disposable == null) {
+
+ if (pingDisposable != null && !pingDisposable.isDisposed()) {
+ pingDisposable.dispose();
+ pingDisposable = null;
+ }
+
+ if (signalingDisposable != null && !signalingDisposable.isDisposed()) {
+ signalingDisposable.dispose();
+ signalingDisposable = null;
+ }
+ }
+ }
+
private void receivedSignalingMessage(Signaling signaling) throws IOException {
String messageType = signaling.getType();
@@ -1083,12 +1163,127 @@ public class CallActivity extends AppCompatActivity {
}
}
- // This method is called when the audio manager reports audio device change,
- // e.g. from wired headset to speakerphone.
- private void onAudioManagerDevicesChanged(
- final MagicAudioManager.AudioDevice device, final Set availableDevices) {
- Log.d(TAG, "onAudioManagerDevicesChanged: " + availableDevices + ", "
- + "selected: " + device);
+ private void hangup(boolean dueToNetworkChange) {
+
+ leavingCall = true;
+ inCall = false;
+
+ if (videoCapturer != null) {
+ try {
+ videoCapturer.stopCapture();
+ } catch (InterruptedException e) {
+ Log.e(TAG, "Failed to stop capturing while hanging up");
+ }
+ videoCapturer.dispose();
+ videoCapturer = null;
+ }
+
+ for (int i = 0; i < magicPeerConnectionWrapperList.size(); i++) {
+ endPeerConnection(magicPeerConnectionWrapperList.get(i).getSessionId());
+
+ }
+
+ if (pipVideoView != null) {
+ pipVideoView.release();
+ }
+
+ if (audioSource != null) {
+ audioSource.dispose();
+ audioSource = null;
+ }
+
+ if (audioManager != null) {
+ audioManager.stop();
+ audioManager = null;
+ }
+
+ if (videoSource != null) {
+ videoSource = null;
+ }
+
+ if (peerConnectionFactory != null) {
+ peerConnectionFactory = null;
+ }
+
+ localMediaStream = null;
+ localAudioTrack = null;
+ localVideoTrack = null;
+
+ if (!dueToNetworkChange) {
+ hangupNetworkCalls();
+ } else {
+ if (getActivity() != null) {
+ getActivity().finish();
+ }
+ }
+ }
+
+ private void hangupNetworkCalls() {
+ ncApi.leaveCall(credentials, ApiUtils.getUrlForCall(baseUrl, roomToken))
+ .subscribeOn(Schedulers.newThread())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(new Observer() {
+ @Override
+ public void onSubscribe(Disposable d) {
+
+ }
+
+ @Override
+ public void onNext(GenericOverall genericOverall) {
+ if (isMultiSession) {
+ if (getActivity() != null) {
+ getActivity().finish();
+ }
+ } else {
+ leaveRoom();
+ }
+ }
+
+ @Override
+ public void onError(Throwable e) {
+
+ }
+
+ @Override
+ public void onComplete() {
+
+ }
+ });
+ }
+
+ private void leaveRoom() {
+ ncApi.leaveRoom(credentials, ApiUtils.getUrlForSettingMyselfAsActiveParticipant(baseUrl, roomToken))
+ .subscribeOn(Schedulers.newThread())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(new Observer() {
+ @Override
+ public void onSubscribe(Disposable d) {
+
+ }
+
+ @Override
+ public void onNext(GenericOverall genericOverall) {
+ if (getActivity() != null) {
+ getActivity().finish();
+ }
+ }
+
+ @Override
+ public void onError(Throwable e) {
+
+ }
+
+ @Override
+ public void onComplete() {
+
+ }
+ });
+ }
+
+ private void startVideoCapture() {
+ if (videoCapturer != null) {
+ videoCapturer.startCapture(1280, 720, 30);
+ }
}
private void processUsersInRoom(List> users) {
@@ -1133,7 +1328,6 @@ public class CallActivity extends AppCompatActivity {
}
}
-
private void getPeersForCall() {
ncApi.getPeersForCall(credentials, ApiUtils.getUrlForCall(baseUrl, roomToken))
.subscribeOn(Schedulers.newThread())
@@ -1148,7 +1342,9 @@ public class CallActivity extends AppCompatActivity {
participantMap = new HashMap<>();
for (Participant participant : participantsOverall.getOcs().getData()) {
participantMap.put(participant.getSessionId(), participant);
- runOnUiThread(() -> setupAvatarForSession(participant.getSessionId()));
+ if (getActivity() != null) {
+ getActivity().runOnUiThread(() -> setupAvatarForSession(participant.getSessionId()));
+ }
}
}
@@ -1190,317 +1386,11 @@ public class CallActivity extends AppCompatActivity {
return null;
}
- private void hangup(boolean dueToNetworkChange) {
-
- leavingCall = true;
- inCall = false;
-
- if (videoCapturer != null) {
- try {
- videoCapturer.stopCapture();
- } catch (InterruptedException e) {
- Log.e(TAG, "Failed to stop capturing while hanging up");
- }
- videoCapturer.dispose();
- videoCapturer = null;
- }
-
- for (int i = 0; i < magicPeerConnectionWrapperList.size(); i++) {
- endPeerConnection(magicPeerConnectionWrapperList.get(i).getSessionId());
-
- }
-
- pipVideoView.release();
-
- if (audioSource != null) {
- audioSource.dispose();
- audioSource = null;
- }
-
- if (audioManager != null) {
- audioManager.stop();
- audioManager = null;
- }
-
- if (videoSource != null) {
- videoSource = null;
- }
-
- if (peerConnectionFactory != null) {
- peerConnectionFactory = null;
- }
-
- localMediaStream = null;
- localAudioTrack = null;
- localVideoTrack = null;
-
- if (!dueToNetworkChange) {
- hangupNetworkCalls();
- } else {
- finish();
- }
- }
-
- private void leaveRoom() {
- ncApi.leaveRoom(credentials, ApiUtils.getUrlForSettingMyselfAsActiveParticipant(baseUrl, roomToken))
- .subscribeOn(Schedulers.newThread())
- .observeOn(AndroidSchedulers.mainThread())
- .subscribe(new Observer() {
- @Override
- public void onSubscribe(Disposable d) {
-
- }
-
- @Override
- public void onNext(GenericOverall genericOverall) {
- finish();
- }
-
- @Override
- public void onError(Throwable e) {
-
- }
-
- @Override
- public void onComplete() {
-
- }
- });
- }
-
- private void hangupNetworkCalls() {
- ncApi.leaveCall(credentials, ApiUtils.getUrlForCall(baseUrl, roomToken))
- .subscribeOn(Schedulers.newThread())
- .observeOn(AndroidSchedulers.mainThread())
- .subscribe(new Observer() {
- @Override
- public void onSubscribe(Disposable d) {
-
- }
-
- @Override
- public void onNext(GenericOverall genericOverall) {
- if (isMultiSession) {
- finish();
- } else {
- leaveRoom();
- }
- }
-
- @Override
- public void onError(Throwable e) {
-
- }
-
- @Override
- public void onComplete() {
-
- }
- });
- }
-
- private void gotNick(String sessionId, String nick) {
- RelativeLayout relativeLayout = remoteRenderersLayout.findViewWithTag(sessionId);
- if (relativeLayout != null) {
- TextView textView = relativeLayout.findViewById(R.id.peer_nick_text_view);
- textView.setText(nick);
- }
- }
-
- private void gotAudioOrVideoChange(boolean video, String sessionId, boolean change) {
- RelativeLayout relativeLayout = remoteRenderersLayout.findViewWithTag(sessionId);
- if (relativeLayout != null) {
- ImageView imageView;
- ImageView avatarImageView = relativeLayout.findViewById(R.id.avatarImageView);
- SurfaceViewRenderer surfaceViewRenderer = relativeLayout.findViewById(R.id.surface_view);
-
- if (video) {
- imageView = relativeLayout.findViewById(R.id.remote_video_off);
-
- if (change) {
- avatarImageView.setVisibility(View.INVISIBLE);
- surfaceViewRenderer.setVisibility(View.VISIBLE);
- } else {
- avatarImageView.setVisibility(View.VISIBLE);
- surfaceViewRenderer.setVisibility(View.INVISIBLE);
- }
- } else {
- imageView = relativeLayout.findViewById(R.id.remote_audio_off);
- }
-
- if (change && imageView.getVisibility() != View.INVISIBLE) {
- imageView.setVisibility(View.INVISIBLE);
- } else if (!change && imageView.getVisibility() != View.VISIBLE) {
- imageView.setVisibility(View.VISIBLE);
- }
- }
- }
-
- private void setupAvatarForSession(String session) {
- RelativeLayout relativeLayout = remoteRenderersLayout.findViewWithTag(session);
- if (relativeLayout != null) {
- ImageView avatarImageView = relativeLayout.findViewById(R.id.avatarImageView);
-
- if (participantMap.containsKey(session) && avatarImageView.getDrawable() == null) {
-
- int size = Math.round(getResources().getDimension(R.dimen.avatar_size_big));
-
- GlideApp.with(this)
- .asBitmap()
- .diskCacheStrategy(DiskCacheStrategy.NONE)
- .load(ApiUtils.getUrlForAvatarWithName(baseUrl, participantMap.get(session).getUserId(), R.dimen.avatar_size_big))
- .centerInside()
- .override(size, size)
- .apply(RequestOptions.bitmapTransform(new CircleCrop()))
- .into(avatarImageView);
- }
- }
- }
-
- private void setupNewPeerLayout(String session) {
- if (remoteRenderersLayout.findViewWithTag(session) == null) {
- runOnUiThread(() -> {
- RelativeLayout relativeLayout = (RelativeLayout)
- getLayoutInflater().inflate(R.layout.call_item, remoteRenderersLayout,
- false);
- relativeLayout.setTag(session);
- SurfaceViewRenderer surfaceViewRenderer = relativeLayout.findViewById(R.id
- .surface_view);
-
- surfaceViewRenderer.setMirror(false);
- surfaceViewRenderer.init(rootEglBase.getEglBaseContext(), null);
- surfaceViewRenderer.setZOrderMediaOverlay(false);
- // disabled because it causes some devices to crash
- surfaceViewRenderer.setEnableHardwareScaler(false);
- surfaceViewRenderer.setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_FIT);
- surfaceViewRenderer.setOnClickListener(videoOnClickListener);
- remoteRenderersLayout.addView(relativeLayout);
- gotNick(session, getPeerConnectionWrapperForSessionId(session).getNick());
- setupAvatarForSession(session);
-
- callControls.setZ(100.0f);
- });
- }
- }
-
- private void setupVideoStreamForLayout(@Nullable MediaStream mediaStream, String session, boolean enable) {
- boolean isInitialLayoutSetupForPeer = false;
- if (remoteRenderersLayout.findViewWithTag(session) == null) {
- setupNewPeerLayout(session);
- isInitialLayoutSetupForPeer = true;
- }
-
- RelativeLayout relativeLayout = remoteRenderersLayout.findViewWithTag(session);
- SurfaceViewRenderer surfaceViewRenderer = relativeLayout.findViewById(R.id.surface_view);
- ImageView imageView = relativeLayout.findViewById(R.id.avatarImageView);
-
- if (mediaStream != null && mediaStream.videoTracks != null && mediaStream.videoTracks.size() > 0 && enable) {
- VideoTrack videoTrack = mediaStream.videoTracks.get(0);
-
- videoTrack.addSink(surfaceViewRenderer);
-
- imageView.setVisibility(View.INVISIBLE);
- surfaceViewRenderer.setVisibility(View.VISIBLE);
- } else {
- imageView.setVisibility(View.VISIBLE);
- surfaceViewRenderer.setVisibility(View.INVISIBLE);
-
- if (isInitialLayoutSetupForPeer && isVoiceOnlyCall) {
- gotAudioOrVideoChange(true, session, false);
- }
- }
-
- callControls.setZ(100.0f);
- }
-
- @Override
- public void onDestroy() {
- if (inCall) {
- hangup(false);
- }
-
- if (hasChatSupport) {
- ApplicationWideCurrentRoomHolder.getInstance().setInCall(false);
- } else {
- ApplicationWideCurrentRoomHolder.getInstance().clear();
- }
- //this.unregisterReceiver(networkBroadcastReceier);
- rootEglBase.release();
- super.onDestroy();
- }
-
- private void dispose(@Nullable Disposable disposable) {
- if (disposable != null && !disposable.isDisposed()) {
- disposable.dispose();
- } else if (disposable == null) {
-
- if (pingDisposable != null && !pingDisposable.isDisposed()) {
- pingDisposable.dispose();
- pingDisposable = null;
- }
-
- if (signalingDisposable != null && !signalingDisposable.isDisposed()) {
- signalingDisposable.dispose();
- signalingDisposable = null;
- }
- }
- }
-
- @Override
- public void onStart() {
- super.onStart();
- eventBus.register(this);
- if (videoOn && EffortlessPermissions.hasPermissions(this, PERMISSIONS_CAMERA)) {
- startVideoCapture();
- }
- }
-
- @Override
- public void onStop() {
- super.onStop();
- eventBus.unregister(this);
- if (videoCapturer != null && EffortlessPermissions.hasPermissions(this, PERMISSIONS_CAMERA)) {
- try {
- videoCapturer.stopCapture();
- } catch (InterruptedException e) {
- Log.e(TAG, "Failed to stop the capturing process");
- }
- }
- }
-
- @Subscribe(threadMode = ThreadMode.BACKGROUND)
- public void onMessageEvent(PeerConnectionEvent peerConnectionEvent) {
- if (peerConnectionEvent.getPeerConnectionEventType().equals(PeerConnectionEvent.PeerConnectionEventType
- .PEER_CLOSED)) {
- endPeerConnection(peerConnectionEvent.getSessionId());
- } else if (peerConnectionEvent.getPeerConnectionEventType().equals(PeerConnectionEvent
- .PeerConnectionEventType.SENSOR_FAR) ||
- peerConnectionEvent.getPeerConnectionEventType().equals(PeerConnectionEvent
- .PeerConnectionEventType.SENSOR_NEAR)) {
- boolean enableVideo = peerConnectionEvent.getPeerConnectionEventType().equals(PeerConnectionEvent
- .PeerConnectionEventType.SENSOR_FAR) && videoOn;
- if (EffortlessPermissions.hasPermissions(this, PERMISSIONS_CAMERA) && inCall && videoOn
- && enableVideo != localVideoTrack.enabled()) {
- runOnUiThread(() -> toggleMedia(enableVideo, true));
- }
- } else if (peerConnectionEvent.getPeerConnectionEventType().equals(PeerConnectionEvent
- .PeerConnectionEventType.NICK_CHANGE)) {
- runOnUiThread(() -> gotNick(peerConnectionEvent.getSessionId(), peerConnectionEvent.getNick()));
- } else if (peerConnectionEvent.getPeerConnectionEventType().equals(PeerConnectionEvent
- .PeerConnectionEventType.VIDEO_CHANGE) && !isVoiceOnlyCall) {
- runOnUiThread(() -> gotAudioOrVideoChange(true, peerConnectionEvent.getSessionId(),
- peerConnectionEvent.getChangeValue()));
- } else if (peerConnectionEvent.getPeerConnectionEventType().equals(PeerConnectionEvent
- .PeerConnectionEventType.AUDIO_CHANGE)) {
- runOnUiThread(() -> gotAudioOrVideoChange(false, peerConnectionEvent.getSessionId(),
- peerConnectionEvent.getChangeValue()));
- }
- }
-
private void endPeerConnection(String sessionId) {
MagicPeerConnectionWrapper magicPeerConnectionWrapper;
- if ((magicPeerConnectionWrapper = getPeerConnectionWrapperForSessionId(sessionId)) != null) {
- runOnUiThread(() -> removeMediaStream(sessionId));
+ if ((magicPeerConnectionWrapper = getPeerConnectionWrapperForSessionId(sessionId)) != null && getActivity()
+ != null) {
+ getActivity().runOnUiThread(() -> removeMediaStream(sessionId));
deleteMagicPeerConnection(magicPeerConnectionWrapper);
}
}
@@ -1610,19 +1500,6 @@ public class CallActivity extends AppCompatActivity {
});
}
- @Override
- public void onConfigurationChanged(Configuration newConfig) {
-
- // Checks the orientation of the screen
- if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
- remoteRenderersLayout.setOrientation(LinearLayout.HORIZONTAL);
- } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
- remoteRenderersLayout.setOrientation(LinearLayout.VERTICAL);
- }
-
- super.onConfigurationChanged(newConfig);
- }
-
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
@@ -1632,73 +1509,135 @@ public class CallActivity extends AppCompatActivity {
this);
}
- private void animateCallControls(boolean show, long startDelay) {
- if (!isPTTActive) {
- float alpha;
- long duration;
+ private void setupAvatarForSession(String session) {
+ RelativeLayout relativeLayout = remoteRenderersLayout.findViewWithTag(session);
+ if (relativeLayout != null) {
+ ImageView avatarImageView = relativeLayout.findViewById(R.id.avatarImageView);
- if (show) {
- handler.removeCallbacksAndMessages(null);
- alpha = 1.0f;
- duration = 1000;
- if (callControls.getVisibility() != View.VISIBLE) {
- callControls.setAlpha(0.0f);
- callControls.setVisibility(View.VISIBLE);
+ if (participantMap.containsKey(session) && avatarImageView.getDrawable() == null) {
+
+ int size = Math.round(getResources().getDimension(R.dimen.avatar_size_big));
+
+ if (getActivity() != null) {
+ GlideApp.with(getActivity())
+ .asBitmap()
+ .diskCacheStrategy(DiskCacheStrategy.NONE)
+ .load(ApiUtils.getUrlForAvatarWithName(baseUrl, participantMap.get(session).getUserId(), R.dimen.avatar_size_big))
+ .centerInside()
+ .override(size, size)
+ .apply(RequestOptions.bitmapTransform(new CircleCrop()))
+ .into(avatarImageView);
+ }
+ }
+ }
+ }
+
+ private void setupVideoStreamForLayout(@Nullable MediaStream mediaStream, String session, boolean enable) {
+ boolean isInitialLayoutSetupForPeer = false;
+ if (remoteRenderersLayout.findViewWithTag(session) == null) {
+ setupNewPeerLayout(session);
+ isInitialLayoutSetupForPeer = true;
+ }
+
+ RelativeLayout relativeLayout = remoteRenderersLayout.findViewWithTag(session);
+ SurfaceViewRenderer surfaceViewRenderer = relativeLayout.findViewById(R.id.surface_view);
+ ImageView imageView = relativeLayout.findViewById(R.id.avatarImageView);
+
+ if (mediaStream != null && mediaStream.videoTracks != null && mediaStream.videoTracks.size() > 0 && enable) {
+ VideoTrack videoTrack = mediaStream.videoTracks.get(0);
+
+ videoTrack.addSink(surfaceViewRenderer);
+
+ imageView.setVisibility(View.INVISIBLE);
+ surfaceViewRenderer.setVisibility(View.VISIBLE);
+ } else {
+ imageView.setVisibility(View.VISIBLE);
+ surfaceViewRenderer.setVisibility(View.INVISIBLE);
+
+ if (isInitialLayoutSetupForPeer && isVoiceOnlyCall) {
+ gotAudioOrVideoChange(true, session, false);
+ }
+ }
+
+ callControls.setZ(100.0f);
+ }
+
+ private void gotAudioOrVideoChange(boolean video, String sessionId, boolean change) {
+ RelativeLayout relativeLayout = remoteRenderersLayout.findViewWithTag(sessionId);
+ if (relativeLayout != null) {
+ ImageView imageView;
+ ImageView avatarImageView = relativeLayout.findViewById(R.id.avatarImageView);
+ SurfaceViewRenderer surfaceViewRenderer = relativeLayout.findViewById(R.id.surface_view);
+
+ if (video) {
+ imageView = relativeLayout.findViewById(R.id.remote_video_off);
+
+ if (change) {
+ avatarImageView.setVisibility(View.INVISIBLE);
+ surfaceViewRenderer.setVisibility(View.VISIBLE);
} else {
- handler.postDelayed(new Runnable() {
- @Override
- public void run() {
- animateCallControls(false, 0);
-
- }
- }, 5000);
- return;
+ avatarImageView.setVisibility(View.VISIBLE);
+ surfaceViewRenderer.setVisibility(View.INVISIBLE);
}
} else {
- alpha = 0.0f;
- duration = 1000;
+ imageView = relativeLayout.findViewById(R.id.remote_audio_off);
}
- 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);
- }
- } else {
- handler.postDelayed(new Runnable() {
- @Override
- public void run() {
- if (!isPTTActive) {
- animateCallControls(false, 0);
- }
- }
- }, 7500);
- }
+ if (change && imageView.getVisibility() != View.INVISIBLE) {
+ imageView.setVisibility(View.INVISIBLE);
+ } else if (!change && imageView.getVisibility() != View.VISIBLE) {
+ imageView.setVisibility(View.VISIBLE);
+ }
+ }
+ }
- callControls.setEnabled(true);
- }
- }
- });
+ private void setupNewPeerLayout(String session) {
+ if (remoteRenderersLayout.findViewWithTag(session) == null && getActivity() != null) {
+ getActivity().runOnUiThread(() -> {
+ RelativeLayout relativeLayout = (RelativeLayout)
+ getActivity().getLayoutInflater().inflate(R.layout.call_item, remoteRenderersLayout,
+ false);
+ relativeLayout.setTag(session);
+ SurfaceViewRenderer surfaceViewRenderer = relativeLayout.findViewById(R.id
+ .surface_view);
+
+ surfaceViewRenderer.setMirror(false);
+ surfaceViewRenderer.init(rootEglBase.getEglBaseContext(), null);
+ surfaceViewRenderer.setZOrderMediaOverlay(false);
+ // disabled because it causes some devices to crash
+ surfaceViewRenderer.setEnableHardwareScaler(false);
+ surfaceViewRenderer.setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_FIT);
+ surfaceViewRenderer.setOnClickListener(videoOnClickListener);
+ remoteRenderersLayout.addView(relativeLayout);
+ gotNick(session, getPeerConnectionWrapperForSessionId(session).getNick());
+ setupAvatarForSession(session);
+
+ callControls.setZ(100.0f);
+ });
+ }
+ }
+
+ private void gotNick(String sessionId, String nick) {
+ RelativeLayout relativeLayout = remoteRenderersLayout.findViewWithTag(sessionId);
+ if (relativeLayout != null) {
+ TextView textView = relativeLayout.findViewById(R.id.peer_nick_text_view);
+ textView.setText(nick);
}
}
@Override
- public void onBackPressed() {
- onHangupClick();
+ protected void onAttach(@NonNull View view) {
+ super.onAttach(view);
+ eventBus.register(this);
}
- private class microphoneButtonTouchListener implements View.OnTouchListener {
+ @Override
+ protected void onDetach(@NonNull View view) {
+ super.onDetach(view);
+ eventBus.unregister(this);
+ }
+
+ private class MicrophoneButtonTouchListener implements View.OnTouchListener {
@SuppressLint("ClickableViewAccessibility")
@Override
@@ -1715,11 +1654,11 @@ public class CallActivity extends AppCompatActivity {
}
}
- private class videoClickListener implements View.OnClickListener {
+ private class VideoClickListener implements View.OnClickListener {
@Override
public void onClick(View v) {
showCallControls();
}
}
-}
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/nextcloud/talk/controllers/CallNotificationController.java b/app/src/main/java/com/nextcloud/talk/controllers/CallNotificationController.java
index db0935c28..13de6bcd5 100644
--- a/app/src/main/java/com/nextcloud/talk/controllers/CallNotificationController.java
+++ b/app/src/main/java/com/nextcloud/talk/controllers/CallNotificationController.java
@@ -117,7 +117,10 @@ public class CallNotificationController extends BaseController {
@OnClick(R.id.callControlHangupView)
void hangup() {
leavingScreen = true;
- getRouter().popCurrentController();
+
+ if (getActivity() != null) {
+ getActivity().finish();
+ }
}
@OnClick(R.id.callAnswerCameraView)
@@ -135,12 +138,9 @@ public class CallNotificationController extends BaseController {
private void setBackstackAndProceed() {
originalBundle.putString(BundleKeys.KEY_ROOM_TOKEN, currentRoom.getToken());
- List routerTransactions = new ArrayList<>();
- routerTransactions.add(RouterTransaction.with(new MagicBottomNavigationController())
- .popChangeHandler(new HorizontalChangeHandler()).pushChangeHandler(new HorizontalChangeHandler()));
- routerTransactions.add(RouterTransaction.with(new ChatController(originalBundle)).popChangeHandler(new
- HorizontalChangeHandler()).pushChangeHandler(new HorizontalChangeHandler()));
- getRouter().setBackstack(routerTransactions, new HorizontalChangeHandler());
+ getRouter().setRoot(RouterTransaction.with(new CallController(originalBundle))
+ .popChangeHandler(new HorizontalChangeHandler())
+ .pushChangeHandler(new HorizontalChangeHandler()));
}
private void checkIfAnyParticipantsRemainInRoom() {
@@ -235,8 +235,6 @@ public class CallNotificationController extends BaseController {
protected void onViewBound(@NonNull View view) {
super.onViewBound(view);
- getActionBar().hide();
-
handleFromNotification();
String callRingtonePreferenceString = appPreferences.getCallRingtoneUri();
diff --git a/app/src/main/java/com/nextcloud/talk/controllers/CallsListController.java b/app/src/main/java/com/nextcloud/talk/controllers/CallsListController.java
index ca5fb2b3c..e97791a50 100644
--- a/app/src/main/java/com/nextcloud/talk/controllers/CallsListController.java
+++ b/app/src/main/java/com/nextcloud/talk/controllers/CallsListController.java
@@ -50,7 +50,7 @@ import com.bluelinelabs.conductor.changehandler.VerticalChangeHandler;
import com.bluelinelabs.conductor.internal.NoOpControllerChangeHandler;
import com.kennyc.bottomsheet.BottomSheet;
import com.nextcloud.talk.R;
-import com.nextcloud.talk.activities.CallActivity;
+import com.nextcloud.talk.activities.MagicCallActivity;
import com.nextcloud.talk.adapters.items.CallItem;
import com.nextcloud.talk.api.NcApi;
import com.nextcloud.talk.application.NextcloudTalkApplication;
@@ -508,7 +508,7 @@ public class CallsListController extends BaseController implements SearchView.On
} else {
overridePushHandler(new NoOpControllerChangeHandler());
overridePopHandler(new NoOpControllerChangeHandler());
- Intent callIntent = new Intent(getActivity(), CallActivity.class);
+ Intent callIntent = new Intent(getActivity(), MagicCallActivity.class);
callIntent.putExtras(bundle);
startActivity(callIntent);
}
diff --git a/app/src/main/java/com/nextcloud/talk/controllers/ChatController.java b/app/src/main/java/com/nextcloud/talk/controllers/ChatController.java
index 6a5acded7..7df10c678 100644
--- a/app/src/main/java/com/nextcloud/talk/controllers/ChatController.java
+++ b/app/src/main/java/com/nextcloud/talk/controllers/ChatController.java
@@ -56,7 +56,7 @@ import com.bumptech.glide.request.RequestListener;
import com.bumptech.glide.request.RequestOptions;
import com.bumptech.glide.request.target.Target;
import com.nextcloud.talk.R;
-import com.nextcloud.talk.activities.CallActivity;
+import com.nextcloud.talk.activities.MagicCallActivity;
import com.nextcloud.talk.adapters.messages.MagicIncomingTextMessageViewHolder;
import com.nextcloud.talk.adapters.messages.MagicOutcomingTextMessageViewHolder;
import com.nextcloud.talk.api.NcApi;
@@ -831,7 +831,7 @@ public class ChatController extends BaseController implements MessagesListAdapte
bundle.putBoolean(BundleKeys.KEY_CALL_VOICE_ONLY, true);
}
- Intent callIntent = new Intent(getActivity(), CallActivity.class);
+ Intent callIntent = new Intent(getActivity(), MagicCallActivity.class);
callIntent.putExtras(bundle);
return callIntent;
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 4d346cb54..8227bb909 100644
--- a/app/src/main/java/com/nextcloud/talk/controllers/ContactsController.java
+++ b/app/src/main/java/com/nextcloud/talk/controllers/ContactsController.java
@@ -51,7 +51,7 @@ import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler;
import com.bluelinelabs.conductor.changehandler.VerticalChangeHandler;
import com.kennyc.bottomsheet.BottomSheet;
import com.nextcloud.talk.R;
-import com.nextcloud.talk.activities.CallActivity;
+import com.nextcloud.talk.activities.MagicCallActivity;
import com.nextcloud.talk.adapters.items.ProgressItem;
import com.nextcloud.talk.adapters.items.UserHeaderItem;
import com.nextcloud.talk.adapters.items.UserItem;
@@ -295,7 +295,7 @@ public class ContactsController extends BaseController implements SearchView.OnQ
@Override
public void onNext(RoomOverall roomOverall) {
- Intent conversationIntent = new Intent(getActivity(), CallActivity.class);
+ Intent conversationIntent = new Intent(getActivity(), MagicCallActivity.class);
Bundle bundle = new Bundle();
bundle.putString(BundleKeys.KEY_ROOM_TOKEN, roomOverall.getOcs().getData().getToken());
bundle.putString(BundleKeys.KEY_ROOM_ID, roomOverall.getOcs().getData().getRoomId());
@@ -828,7 +828,7 @@ public class ContactsController extends BaseController implements SearchView.OnQ
@Override
public void onNext(RoomOverall roomOverall) {
if (getActivity() != null) {
- Intent conversationIntent = new Intent(getActivity(), CallActivity.class);
+ Intent conversationIntent = new Intent(getActivity(), MagicCallActivity.class);
Bundle bundle = new Bundle();
bundle.putString(BundleKeys.KEY_ROOM_TOKEN, roomOverall.getOcs().getData().getToken());
bundle.putString(BundleKeys.KEY_ROOM_ID, roomOverall.getOcs().getData().getRoomId());
diff --git a/app/src/main/java/com/nextcloud/talk/controllers/base/BaseController.java b/app/src/main/java/com/nextcloud/talk/controllers/base/BaseController.java
index 6f4e5949b..6d1056d3f 100644
--- a/app/src/main/java/com/nextcloud/talk/controllers/base/BaseController.java
+++ b/app/src/main/java/com/nextcloud/talk/controllers/base/BaseController.java
@@ -92,7 +92,7 @@ public abstract class BaseController extends RefWatchingController {
@Override
protected void onAttach(@NonNull View view) {
setTitle();
- if (!MagicBottomNavigationController.class.getName().equals(getClass().getName())) {
+ if (!MagicBottomNavigationController.class.getName().equals(getClass().getName()) && getActionBar() != null) {
getActionBar().setDisplayHomeAsUpEnabled(false);
}
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 c9a920311..6a5d539d6 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
@@ -40,7 +40,7 @@ import android.widget.TextView;
import com.bluelinelabs.conductor.RouterTransaction;
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler;
import com.nextcloud.talk.R;
-import com.nextcloud.talk.activities.CallActivity;
+import com.nextcloud.talk.activities.MagicCallActivity;
import com.nextcloud.talk.api.NcApi;
import com.nextcloud.talk.application.NextcloudTalkApplication;
import com.nextcloud.talk.controllers.ChatController;
@@ -542,7 +542,7 @@ public class OperationsMenuController extends BaseController {
eventBus.post(new BottomSheetLockEvent(true, 0,
true, true, dismissView));
- Intent conversationIntent = new Intent(getActivity(), CallActivity.class);
+ Intent conversationIntent = new Intent(getActivity(), MagicCallActivity.class);
bundle.putString(BundleKeys.KEY_ROOM_TOKEN, room.getToken());
bundle.putString(BundleKeys.KEY_ROOM_ID, room.getRoomId());
bundle.putString(BundleKeys.KEY_CONVERSATION_NAME, room.getDisplayName());
@@ -582,7 +582,7 @@ public class OperationsMenuController extends BaseController {
if (getActivity() != null) {
- Intent callIntent = new Intent(getActivity(), CallActivity.class);
+ Intent callIntent = new Intent(getActivity(), MagicCallActivity.class);
callIntent.putExtras(bundle);
InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Activity.INPUT_METHOD_SERVICE);
diff --git a/app/src/main/java/com/nextcloud/talk/jobs/NotificationJob.java b/app/src/main/java/com/nextcloud/talk/jobs/NotificationJob.java
index c8860e8e2..96a1a8384 100644
--- a/app/src/main/java/com/nextcloud/talk/jobs/NotificationJob.java
+++ b/app/src/main/java/com/nextcloud/talk/jobs/NotificationJob.java
@@ -26,10 +26,7 @@ import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.media.MediaPlayer;
import android.net.Uri;
-import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.text.TextUtils;
@@ -40,14 +37,13 @@ import com.bluelinelabs.logansquare.LoganSquare;
import com.evernote.android.job.Job;
import com.evernote.android.job.util.support.PersistableBundleCompat;
import com.nextcloud.talk.R;
-import com.nextcloud.talk.activities.CallActivity;
+import com.nextcloud.talk.activities.MagicCallActivity;
import com.nextcloud.talk.activities.MainActivity;
import com.nextcloud.talk.application.NextcloudTalkApplication;
import com.nextcloud.talk.models.RingtoneSettings;
import com.nextcloud.talk.models.SignatureVerification;
import com.nextcloud.talk.models.json.push.DecryptedPushMessage;
import com.nextcloud.talk.utils.ApplicationWideCurrentRoomHolder;
-import com.nextcloud.talk.utils.NotificationUtils;
import com.nextcloud.talk.utils.PushUtils;
import com.nextcloud.talk.utils.bundle.BundleKeys;
import com.nextcloud.talk.utils.database.user.UserUtils;
@@ -59,8 +55,6 @@ import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
-import java.util.Calendar;
-import java.util.zip.CRC32;
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
@@ -129,10 +123,11 @@ public class NotificationJob extends Job {
Bundle bundle = new Bundle();
- if (hasChatSupport) {
- intent = new Intent(context, MainActivity.class);
+ boolean startACall = decryptedPushMessage.getType().equals("call") || !hasChatSupport;
+ if (startACall) {
+ intent = new Intent(context, MagicCallActivity.class);
} else {
- intent = new Intent(context, CallActivity.class);
+ intent = new Intent(context, MainActivity.class);
}
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
@@ -141,7 +136,7 @@ public class NotificationJob extends Job {
.getUserEntity()));
bundle.putBoolean(BundleKeys.KEY_FROM_NOTIFICATION_START_CALL,
- decryptedPushMessage.getType().equals("call") || !hasChatSupport);
+ startACall);
intent.putExtras(bundle);
@@ -154,8 +149,7 @@ public class NotificationJob extends Job {
String ringtonePreferencesString;
switch (decryptedPushMessage.getType()) {
case "call":
- smallIcon = R.drawable.ic_call_white_24dp;
- category = Notification.CATEGORY_CALL;
+ getContext().startActivity(intent);
break;
case "room":
smallIcon = R.drawable.ic_notifications_white_24dp;
@@ -183,7 +177,7 @@ public class NotificationJob extends Job {
smallIcon = R.drawable.ic_logo;
}
- largeIcon = BitmapFactory.decodeResource(context.getResources(), smallIcon);
+ /*largeIcon = BitmapFactory.decodeResource(context.getResources(), smallIcon);
CRC32 crc32 = new CRC32();
Notification.Builder notificationBuilder = new Notification.Builder(context)
@@ -258,7 +252,7 @@ public class NotificationJob extends Job {
mediaPlayer.setOnCompletionListener(MediaPlayer::release);
}
- }
+ }*/
}
}
diff --git a/app/src/main/res/layout/activity_magic_call.xml b/app/src/main/res/layout/activity_magic_call.xml
new file mode 100644
index 000000000..acc95508e
--- /dev/null
+++ b/app/src/main/res/layout/activity_magic_call.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/controller_call.xml b/app/src/main/res/layout/controller_call.xml
new file mode 100644
index 000000000..9c58dc482
--- /dev/null
+++ b/app/src/main/res/layout/controller_call.xml
@@ -0,0 +1,144 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index e91b71e18..0747453c4 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -114,6 +114,7 @@
Open settings
+ Connecting…
Incoming call from
Guest
New public conversation