create abstract class for CallActivity and CallNotificationActivity

Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
This commit is contained in:
Marcel Hibbe 2021-11-09 19:37:26 +01:00
parent be9971ad7a
commit 9070153d5c
No known key found for this signature in database
GPG Key ID: C793F8B59F43CE7B
5 changed files with 156 additions and 162 deletions

View File

@ -24,16 +24,12 @@ import android.Manifest;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.annotation.SuppressLint;
import android.app.AppOpsManager;
import android.app.KeyguardManager;
import android.app.PendingIntent;
import android.app.PictureInPictureParams;
import android.app.RemoteAction;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.graphics.Color;
import android.graphics.drawable.Icon;
@ -47,18 +43,14 @@ import android.os.Looper;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.Rational;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.Window;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.RelativeLayout;
import com.bluelinelabs.logansquare.LoganSquare;
import com.nextcloud.talk.BuildConfig;
import com.nextcloud.talk.R;
import com.nextcloud.talk.adapters.ParticipantDisplayItem;
import com.nextcloud.talk.adapters.ParticipantsAdapter;
@ -163,7 +155,7 @@ import okhttp3.Cache;
import pub.devrel.easypermissions.AfterPermissionGranted;
@AutoInjector(NextcloudTalkApplication.class)
public class CallActivity extends BaseActivity {
public class CallActivity extends CallActivityBase {
@Inject
NcApi ncApi;
@ -195,7 +187,7 @@ public class CallActivity extends BaseActivity {
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 PictureInPictureParams.Builder mPictureInPictureParamsBuilder;
private BroadcastReceiver mReceiver;
private PeerConnectionFactory peerConnectionFactory;
@ -258,8 +250,6 @@ public class CallActivity extends BaseActivity {
private Map<String, ParticipantDisplayItem> participantDisplayItems;
private ParticipantsAdapter participantsAdapter;
public Boolean isInPipMode = false;
private CallActivityBinding binding;
@Parcel
@ -270,28 +260,15 @@ public class CallActivity extends BaseActivity {
@SuppressLint("ClickableViewAccessibility")
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate");
super.onCreate(savedInstanceState);
NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
setTheme(R.style.CallTheme);
requestWindowFeature(Window.FEATURE_NO_TITLE);
dismissKeyguard();
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
binding = CallActivityBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
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);
binding.controllerCallLayout.setFitsSystemWindows(false);
}
hideNavigationIfNoPipAvailable();
Bundle extras = getIntent().getExtras();
roomId = extras.getString(BundleKeys.INSTANCE.getKEY_ROOM_ID(), "");
@ -320,10 +297,6 @@ public class CallActivity extends BaseActivity {
setCallState(CallStatus.CONNECTING);
}
if (isGreaterEqualOreo() && isPipModePossible()) {
mPictureInPictureParamsBuilder = new PictureInPictureParams.Builder();
}
initClickListeners();
binding.microphoneButton.setOnTouchListener(new MicrophoneButtonTouchListener());
@ -352,14 +325,6 @@ public class CallActivity extends BaseActivity {
}
}
@Override
public void onStop() {
super.onStop();
if (isInPipMode) {
finish();
}
}
private void initClickListeners() {
binding.pictureInPictureButton.setOnClickListener(l -> enterPipMode());
@ -2461,47 +2426,6 @@ public class CallActivity extends BaseActivity {
}
}
@Override
public void onBackPressed() {
if (isPipModePossible()) {
enterPipMode();
}
}
@Override
public void onUserLeaveHint() {
enterPipMode();
}
void enterPipMode() {
enableKeyguard();
if (isGreaterEqualOreo() && isPipModePossible()) {
Rational pipRatio = new Rational(300, 500);
mPictureInPictureParamsBuilder.setAspectRatio(pipRatio);
enterPictureInPictureMode(mPictureInPictureParamsBuilder.build());
} else {
finish();
}
}
private 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;
}
private boolean isGreaterEqualOreo(){
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;
}
@RequiresApi(api = Build.VERSION_CODES.O)
@Override
public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode, Configuration newConfig) {
@ -2599,34 +2523,16 @@ public class CallActivity extends BaseActivity {
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 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);
}
}
private 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);
}
}
private class SelfVideoTouchListener implements View.OnTouchListener {
@SuppressLint("ClickableViewAccessibility")

View File

@ -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 CallActivityBase extends BaseActivity {
public static final String TAG = "CallActivityBase";
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();
}

View File

@ -21,8 +21,6 @@
package com.nextcloud.talk.activities;
import android.annotation.SuppressLint;
import android.app.KeyguardManager;
import android.app.PictureInPictureParams;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
@ -38,9 +36,7 @@ import android.os.Bundle;
import android.os.Handler;
import android.text.TextUtils;
import android.util.Log;
import android.util.Rational;
import android.view.View;
import android.view.WindowManager;
import com.bluelinelabs.logansquare.LoganSquare;
import com.facebook.common.executors.UiThreadImmediateExecutorService;
@ -96,9 +92,9 @@ import io.reactivex.schedulers.Schedulers;
import okhttp3.Cache;
@AutoInjector(NextcloudTalkApplication.class)
public class CallNotificationActivity extends BaseActivity {
public class CallNotificationActivity extends CallActivityBase {
public static final String TAG = "CallNotificationActivity";
public static final String TAG = "CallNotificationA";
@Inject
NcApi ncApi;
@ -125,22 +121,21 @@ public class CallNotificationActivity extends BaseActivity {
private boolean leavingScreen = false;
private Handler handler;
private CallNotificationActivityBinding binding;
private Boolean isInPipMode = false;
@Override
public void onCreate(Bundle savedInstanceState) {
Log.d(TAG, "onCreate");
super.onCreate(savedInstanceState);
NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
dismissKeyguard();
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
eventBus.post(new CallNotificationClick());
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()));
@ -331,7 +326,7 @@ public class CallNotificationActivity extends BaseActivity {
private void setUpAfterConversationIsKnown() {
binding.conversationNameTextView.setText(currentConversation.getDisplayName());
loadAvatar();
// loadAvatar(); // TODO: loadAvatar always makes problems! also now for PIP mode! needs to be rewritten!
checkIfAnyParticipantsRemainInRoom();
showAnswerControls();
}
@ -346,7 +341,6 @@ public class CallNotificationActivity extends BaseActivity {
binding.avatarImageView.setLayoutParams(layoutParams);
}
private void loadAvatar() {
switch (currentConversation.getType()) {
case ROOM_TYPE_ONE_TO_ONE_CALL:
@ -485,30 +479,6 @@ public class CallNotificationActivity extends BaseActivity {
}
}
public void onBackPressed() {
enterPipMode();
}
public void onUserLeaveHint() {
enterPipMode();
}
void enterPipMode() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
enterPictureInPictureMode(getPipParams());
} else {
finish();
}
}
@RequiresApi(Build.VERSION_CODES.O)
public PictureInPictureParams getPipParams() {
Rational pipRatio = new Rational(300, 500);
return new PictureInPictureParams.Builder()
.setAspectRatio(pipRatio)
.build();
}
@RequiresApi(api = Build.VERSION_CODES.O)
@Override
public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode, Configuration newConfig) {
@ -531,18 +501,8 @@ public class CallNotificationActivity extends BaseActivity {
binding.incomingCallRelativeLayout.setVisibility(View.VISIBLE);
}
// TODO: dismiss keyguard works, but whenever accepting the call and switch to CallActivity by intent, the
// lockscreen is shown (although CallActivity also dismisses the keyguard in the same way.)
private 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);
}
@Override
void suppressFitsSystemWindows() {
binding.controllerCallNotificationLayout.setFitsSystemWindows(false);
}
}

View File

@ -22,6 +22,7 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/controllerCallNotificationLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">

View File

@ -51,10 +51,6 @@
<item name="iconTint">@color/fontAppbar</item>
</style>
<style name="CallTheme" parent="AppTheme">
<item name="android:navigationBarColor">@color/grey950</item>
</style>
<style name="BottomNavigationView" parent="@style/Widget.MaterialComponents.BottomNavigationView">
<item name="elevation">1dp</item>
</style>
@ -189,9 +185,9 @@
<!-- Call Launch screen -->
<style name="AppTheme.CallLauncher">
<item name="android:windowBackground">@color/black</item>
<item name="android:statusBarColor">@color/black</item>
<item name="android:navigationBarColor">@color/black</item>
<item name="android:windowBackground">@color/grey950</item>
<item name="android:statusBarColor">@color/grey950</item>
<item name="android:navigationBarColor">@color/grey950</item>
</style>
<style name="Nextcloud.Material.TextButton" parent="Widget.MaterialComponents.Button.TextButton.Icon">