Signed-off-by: Mario Danic <mario@lovelyhq.com>
This commit is contained in:
Mario Danic 2018-01-17 23:24:38 +01:00
parent 586e6ca9a3
commit 58c2b1ba74
3 changed files with 189 additions and 37 deletions

View file

@ -26,6 +26,7 @@
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
<uses-permission android:name="android.permission.BATTERY_STATS"/>
<uses-permission
android:name="android.permission.USE_CREDENTIALS"
android:maxSdkVersion="22"/>

View file

@ -27,6 +27,7 @@ package com.nextcloud.talk.activities;
import android.Manifest;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.annotation.SuppressLint;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@ -40,6 +41,7 @@ import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
@ -73,6 +75,7 @@ import com.nextcloud.talk.events.MediaStreamEvent;
import com.nextcloud.talk.events.PeerConnectionEvent;
import com.nextcloud.talk.events.SessionDescriptionSendEvent;
import com.nextcloud.talk.persistence.entities.UserEntity;
import com.nextcloud.talk.utils.animations.PulseAnimation;
import com.nextcloud.talk.utils.database.user.UserUtils;
import com.nextcloud.talk.webrtc.MagicAudioManager;
import com.nextcloud.talk.webrtc.MagicPeerConnectionWrapper;
@ -120,6 +123,7 @@ import autodagger.AutoInjector;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import butterknife.OnLongClick;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
@ -204,12 +208,16 @@ public class CallActivity extends AppCompatActivity {
private Handler handler = new Handler();
private boolean isPTTActive = false;
private PulseAnimation pulseAnimation;
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);
@ -225,6 +233,12 @@ public class CallActivity extends AppCompatActivity {
setContentView(R.layout.activity_call);
ButterKnife.bind(this);
microphoneControlButton.setOnTouchListener(new microphoneButtonTouchListener());
pulseAnimation = PulseAnimation.create().with(microphoneControlButton)
.setDuration(310)
.setRepeatCount(PulseAnimation.INFINITE)
.setRepeatMode(PulseAnimation.REVERSE);
roomToken = getIntent().getExtras().getString("roomToken", "");
userEntity = Parcels.unwrap(getIntent().getExtras().getParcelable("userEntity"));
callSession = "0";
@ -380,18 +394,37 @@ 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)) {
audioOn = !audioOn;
if (!isPTTActive) {
audioOn = !audioOn;
if (audioOn) {
microphoneControlButton.setImageResource(R.drawable.ic_mic_white_24px);
if (audioOn) {
microphoneControlButton.setImageResource(R.drawable.ic_mic_white_24px);
} else {
microphoneControlButton.setImageResource(R.drawable.ic_mic_off_white_24px);
}
toggleMedia(audioOn, false);
} else {
microphoneControlButton.setImageResource(R.drawable.ic_mic_off_white_24px);
microphoneControlButton.setImageResource(R.drawable.ic_mic_white_24px);
pulseAnimation.start();
toggleMedia(true, false);
}
toggleMedia(audioOn, false);
} else if (EffortlessPermissions.somePermissionPermanentlyDenied(this, PERMISSIONS_MICROPHONE)) {
// Microphone permission is permanently denied so we cannot request it normally.
OpenAppDetailsDialogFragment.show(
@ -658,7 +691,9 @@ public class CallActivity extends AppCompatActivity {
private void startCall() {
inCall = true;
animateCallControls(false, 7500);
if (!isPTTActive) {
animateCallControls(false, 7500);
}
startPullingSignalingMessages(false);
//registerNetworkReceiver();
}
@ -1367,47 +1402,76 @@ public class CallActivity extends AppCompatActivity {
}
private void animateCallControls(boolean show, long startDelay) {
float alpha;
long duration;
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);
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(() -> animateCallControls(false, 0), 5000);
return;
}
} else {
handler.postDelayed(() -> animateCallControls(false, 0), 5000);
return;
alpha = 0.0f;
duration = 1000;
}
} else {
alpha = 0.0f;
duration = 1000;
}
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.INVISIBLE);
} else {
handler.postDelayed(() -> animateCallControls(false, 0), 5000);
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.INVISIBLE);
} else {
handler.postDelayed(new Runnable() {
@Override
public void run() {
if (!isPTTActive) {
animateCallControls(false, 0);
}
}
}, 7500);
}
callControls.setEnabled(true);
}
}
}
});
});
}
}
@Override
public void onBackPressed() {
hangup(false);
}
private class microphoneButtonTouchListener implements View.OnTouchListener {
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouch(View v, MotionEvent event) {
v.onTouchEvent(event);
if (event.getAction() == MotionEvent.ACTION_UP && isPTTActive) {
isPTTActive = false;
microphoneControlButton.setImageResource(R.drawable.ic_mic_off_white_24px);
pulseAnimation.stop();
toggleMedia(false, false);
animateCallControls(false, 5000);
}
return true;
}
}
}

View file

@ -0,0 +1,87 @@
/*
* Nextcloud Talk application
*
* @author Mario Danic
* Copyright (C) 2017 Mario Danic <mario@lovelyhq.com>
*
* 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 <http://www.gnu.org/licenses/>.
*
* Original code taken from https://github.com/thunderrise/android-TNRAnimationHelper under MIT licence
* and modified by yours truly to fit the needs of this awesome app.
*/
package com.nextcloud.talk.utils.animations;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.animation.ValueAnimator;
import android.support.annotation.NonNull;
import android.view.View;
public class PulseAnimation {
public static final int RESTART = 1;
public static final int REVERSE = 2;
public static final int INFINITE = -1;
private ObjectAnimator scaleDown;
private int duration = 310;
private View view;
private int repeatMode = ValueAnimator.RESTART;
private int repeatCount = INFINITE;
public static PulseAnimation create() {
return new PulseAnimation();
}
public PulseAnimation with(@NonNull View view) {
this.view = view;
return this;
}
public void start() {
if (view == null) throw new NullPointerException("View cant be null!");
scaleDown = ObjectAnimator.ofPropertyValuesHolder(view, PropertyValuesHolder.ofFloat("scaleX", 1.2f), PropertyValuesHolder.ofFloat("scaleY", 1.2f));
scaleDown.setDuration(duration);
scaleDown.setRepeatMode(repeatMode);
scaleDown.setRepeatCount(repeatCount);
scaleDown.setAutoCancel(true);
scaleDown.start();
}
public void stop() {
if (scaleDown != null && view != null) {
scaleDown.end();
scaleDown.cancel();
view.setScaleX(1.0f);
view.setScaleY(1.0f);
}
}
public PulseAnimation setDuration(int duration) {
this.duration = duration;
return this;
}
public PulseAnimation setRepeatMode(int repeatMode) {
this.repeatMode = repeatMode;
return this;
}
public PulseAnimation setRepeatCount(int repeatCount) {
this.repeatCount = repeatCount;
return this;
}
}