replace CallNotificationController with Activity (WIP)

Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
This commit is contained in:
Marcel Hibbe 2021-10-28 12:19:07 +02:00
parent 251d41f7fb
commit c7e38e4859
No known key found for this signature in database
GPG Key ID: C793F8B59F43CE7B
5 changed files with 123 additions and 160 deletions

View File

@ -41,7 +41,7 @@ import com.bluelinelabs.logansquare.LoganSquare
import com.google.firebase.messaging.FirebaseMessagingService import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage import com.google.firebase.messaging.RemoteMessage
import com.nextcloud.talk.R import com.nextcloud.talk.R
import com.nextcloud.talk.activities.CallActivity import com.nextcloud.talk.activities.CallNotificationActivity
import com.nextcloud.talk.api.NcApi import com.nextcloud.talk.api.NcApi
import com.nextcloud.talk.application.NextcloudTalkApplication import com.nextcloud.talk.application.NextcloudTalkApplication
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
@ -178,7 +178,7 @@ class MagicFirebaseMessagingService : FirebaseMessagingService() {
) )
} }
} else if (type == "call") { } else if (type == "call") {
val fullScreenIntent = Intent(applicationContext, CallActivity::class.java) val fullScreenIntent = Intent(applicationContext, CallNotificationActivity::class.java)
val bundle = Bundle() val bundle = Bundle()
bundle.putString(BundleKeys.KEY_ROOM_ID, decryptedPushMessage!!.id) bundle.putString(BundleKeys.KEY_ROOM_ID, decryptedPushMessage!!.id)
bundle.putParcelable(KEY_USER_ENTITY, signatureVerification!!.userEntity) bundle.putParcelable(KEY_USER_ENTITY, signatureVerification!!.userEntity)

View File

@ -131,6 +131,14 @@
android:taskAffinity=".call" android:taskAffinity=".call"
android:excludeFromRecents="true" /> android:excludeFromRecents="true" />
<activity
android:name=".activities.CallNotificationActivity"
android:theme="@style/AppTheme.CallLauncher"
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"
android:launchMode="singleTask"
android:taskAffinity=".call"
android:excludeFromRecents="true" />
<activity <activity
android:name=".activities.FullScreenImageActivity" android:name=".activities.FullScreenImageActivity"
android:theme="@style/FullScreenImageTheme" android:theme="@style/FullScreenImageTheme"

View File

@ -18,7 +18,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package com.nextcloud.talk.controllers; package com.nextcloud.talk.activities;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
@ -32,32 +32,24 @@ import android.media.MediaPlayer;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.renderscript.RenderScript;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.bluelinelabs.logansquare.LoganSquare; import com.bluelinelabs.logansquare.LoganSquare;
import com.facebook.common.executors.UiThreadImmediateExecutorService; import com.facebook.common.executors.UiThreadImmediateExecutorService;
import com.facebook.common.references.CloseableReference; import com.facebook.common.references.CloseableReference;
import com.facebook.datasource.DataSource; import com.facebook.datasource.DataSource;
import com.facebook.drawee.backends.pipeline.Fresco; import com.facebook.drawee.backends.pipeline.Fresco;
import com.facebook.drawee.view.SimpleDraweeView;
import com.facebook.imagepipeline.core.ImagePipeline; import com.facebook.imagepipeline.core.ImagePipeline;
import com.facebook.imagepipeline.datasource.BaseBitmapDataSubscriber; import com.facebook.imagepipeline.datasource.BaseBitmapDataSubscriber;
import com.facebook.imagepipeline.image.CloseableImage; import com.facebook.imagepipeline.image.CloseableImage;
import com.facebook.imagepipeline.postprocessors.BlurPostProcessor; import com.facebook.imagepipeline.postprocessors.BlurPostProcessor;
import com.facebook.imagepipeline.request.ImageRequest; import com.facebook.imagepipeline.request.ImageRequest;
import com.nextcloud.talk.R; import com.nextcloud.talk.R;
import com.nextcloud.talk.activities.CallActivity;
import com.nextcloud.talk.api.NcApi; import com.nextcloud.talk.api.NcApi;
import com.nextcloud.talk.application.NextcloudTalkApplication; import com.nextcloud.talk.application.NextcloudTalkApplication;
import com.nextcloud.talk.controllers.base.BaseController; import com.nextcloud.talk.databinding.CallNotificationActivityBinding;
import com.nextcloud.talk.events.CallNotificationClick; import com.nextcloud.talk.events.CallNotificationClick;
import com.nextcloud.talk.events.ConfigurationChangeEvent; import com.nextcloud.talk.events.ConfigurationChangeEvent;
import com.nextcloud.talk.models.RingtoneSettings; import com.nextcloud.talk.models.RingtoneSettings;
@ -86,11 +78,9 @@ import java.util.List;
import javax.inject.Inject; import javax.inject.Inject;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.constraintlayout.widget.ConstraintLayout; import androidx.constraintlayout.widget.ConstraintLayout;
import autodagger.AutoInjector; import autodagger.AutoInjector;
import butterknife.BindView;
import butterknife.OnClick; import butterknife.OnClick;
import io.reactivex.Observer; import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.android.schedulers.AndroidSchedulers;
@ -99,9 +89,9 @@ import io.reactivex.schedulers.Schedulers;
import okhttp3.Cache; import okhttp3.Cache;
@AutoInjector(NextcloudTalkApplication.class) @AutoInjector(NextcloudTalkApplication.class)
public class CallNotificationController extends BaseController { public class CallNotificationActivity extends BaseActivity {
public static final String TAG = "CallNotificationController"; public static final String TAG = "CallNotificationActivity";
@Inject @Inject
NcApi ncApi; NcApi ncApi;
@ -118,27 +108,6 @@ public class CallNotificationController extends BaseController {
@Inject @Inject
Context context; Context context;
@BindView(R.id.incomingCallVoiceOrVideoTextView)
TextView incomingCallVoiceOrVideoTextView;
@BindView(R.id.conversationNameTextView)
TextView conversationNameTextView;
@BindView(R.id.avatarImageView)
SimpleDraweeView avatarImageView;
@BindView(R.id.callAnswerVoiceOnlyView)
SimpleDraweeView callAnswerVoiceOnlyView;
@BindView(R.id.callAnswerCameraView)
SimpleDraweeView callAnswerCameraView;
@BindView(R.id.backgroundImageView)
ImageView backgroundImageView;
@BindView(R.id.incomingTextRelativeLayout)
RelativeLayout incomingTextRelativeLayout;
private List<Disposable> disposablesList = new ArrayList<>(); private List<Disposable> disposablesList = new ArrayList<>();
private Bundle originalBundle; private Bundle originalBundle;
private String roomId; private String roomId;
@ -147,63 +116,97 @@ public class CallNotificationController extends BaseController {
private Conversation currentConversation; private Conversation currentConversation;
private MediaPlayer mediaPlayer; private MediaPlayer mediaPlayer;
private boolean leavingScreen = false; private boolean leavingScreen = false;
private RenderScript renderScript;
private Handler handler; private Handler handler;
private CallNotificationActivityBinding binding;
public CallNotificationController(Bundle args) { @Override
super(args); public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this); NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
eventBus.post(new CallNotificationClick()); eventBus.post(new CallNotificationClick());
this.roomId = args.getString(BundleKeys.INSTANCE.getKEY_ROOM_ID(), "");
this.currentConversation = Parcels.unwrap(args.getParcelable(BundleKeys.INSTANCE.getKEY_ROOM()));
this.userBeingCalled = args.getParcelable(BundleKeys.INSTANCE.getKEY_USER_ENTITY());
this.originalBundle = args; binding = CallNotificationActivityBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
Bundle extras = getIntent().getExtras();
this.roomId = extras.getString(BundleKeys.INSTANCE.getKEY_ROOM_ID(), "");
this.currentConversation = Parcels.unwrap(extras.getParcelable(BundleKeys.INSTANCE.getKEY_ROOM()));
this.userBeingCalled = extras.getParcelable(BundleKeys.INSTANCE.getKEY_USER_ENTITY());
this.originalBundle = extras;
credentials = ApiUtils.getCredentials(userBeingCalled.getUsername(), userBeingCalled.getToken()); credentials = ApiUtils.getCredentials(userBeingCalled.getUsername(), userBeingCalled.getToken());
setCallDescriptionText();
if (currentConversation == null) {
handleFromNotification();
} else {
runAllThings();
}
if (DoNotDisturbUtils.INSTANCE.shouldPlaySound()) {
playRingtoneSound();
}
initClickListeners();
} }
@SuppressLint({"LongLogTag"})
@Override @Override
protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) { public void onStart() {
return inflater.inflate(R.layout.controller_call_notification, container, false); super.onStart();
if (handler == null) {
handler = new Handler();
try {
cache.evictAll();
} catch (IOException e) {
Log.e(TAG, "Failed to evict cache");
}
}
}
private void initClickListeners() {
binding.callAnswerVoiceOnlyView.setOnClickListener(l -> {
originalBundle.putBoolean(BundleKeys.INSTANCE.getKEY_CALL_VOICE_ONLY(), true);
proceedToCall();
});
binding.callAnswerCameraView.setOnClickListener(l -> {
originalBundle.putBoolean(BundleKeys.INSTANCE.getKEY_CALL_VOICE_ONLY(), false);
proceedToCall();
});
binding.hangupButton.setOnClickListener(l -> hangup());
}
private void setCallDescriptionText() {
String callDescriptionWithoutTypeInfo =
String.format(
getResources().getString(R.string.nc_call_unknown),
getResources().getString(R.string.nc_app_product_name));
binding.incomingCallVoiceOrVideoTextView.setText(callDescriptionWithoutTypeInfo);
} }
private void showAnswerControls() { private void showAnswerControls() {
callAnswerCameraView.setVisibility(View.VISIBLE); binding.callAnswerCameraView.setVisibility(View.VISIBLE);
callAnswerVoiceOnlyView.setVisibility(View.VISIBLE); binding.callAnswerVoiceOnlyView.setVisibility(View.VISIBLE);
} }
@OnClick(R.id.hangupButton) @OnClick(R.id.hangupButton)
void hangup() { void hangup() {
leavingScreen = true; leavingScreen = true;
finish();
if (getActivity() != null) {
getActivity().finish();
}
}
@OnClick(R.id.callAnswerCameraView)
void answerWithCamera() {
originalBundle.putBoolean(BundleKeys.INSTANCE.getKEY_CALL_VOICE_ONLY(), false);
proceedToCall();
}
@OnClick(R.id.callAnswerVoiceOnlyView)
void answerVoiceOnly() {
originalBundle.putBoolean(BundleKeys.INSTANCE.getKEY_CALL_VOICE_ONLY(), true);
proceedToCall();
} }
private void proceedToCall() { private void proceedToCall() {
originalBundle.putString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN(), currentConversation.getToken()); originalBundle.putString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN(), currentConversation.getToken());
originalBundle.putString(BundleKeys.INSTANCE.getKEY_CONVERSATION_NAME(), currentConversation.getDisplayName()); originalBundle.putString(BundleKeys.INSTANCE.getKEY_CONVERSATION_NAME(), currentConversation.getDisplayName());
// getRouter().replaceTopController(RouterTransaction.with(new CallActivity(originalBundle)) Intent intent = new Intent(this, CallActivity.class);
// .popChangeHandler(new HorizontalChangeHandler())
// .pushChangeHandler(new HorizontalChangeHandler())
// .tag(CallActivity.TAG));
Intent intent = new Intent(this.getActivity(), CallActivity.class);
intent.putExtras(originalBundle); intent.putExtras(originalBundle);
startActivity(intent); startActivity(intent);
} }
@ -239,9 +242,7 @@ public class CallNotificationController extends BaseController {
} }
if (!hasParticipantsInCall || inCallOnDifferentDevice) { if (!hasParticipantsInCall || inCallOnDifferentDevice) {
if (getActivity() != null) { runOnUiThread(() -> hangup());
getActivity().runOnUiThread(() -> hangup());
}
} }
} }
@ -285,11 +286,11 @@ public class CallNotificationController extends BaseController {
"conversation-call-flags"); "conversation-call-flags");
if (hasCallFlags) { if (hasCallFlags) {
if (isInCallWithVideo(currentConversation.callFlag)) { if (isInCallWithVideo(currentConversation.callFlag)) {
incomingCallVoiceOrVideoTextView.setText( binding.incomingCallVoiceOrVideoTextView.setText(
String.format(getResources().getString(R.string.nc_call_video), String.format(getResources().getString(R.string.nc_call_video),
getResources().getString(R.string.nc_app_product_name))); getResources().getString(R.string.nc_app_product_name)));
} else { } else {
incomingCallVoiceOrVideoTextView.setText( binding.incomingCallVoiceOrVideoTextView.setText(
String.format(getResources().getString(R.string.nc_call_voice), String.format(getResources().getString(R.string.nc_call_voice),
getResources().getString(R.string.nc_app_product_name))); getResources().getString(R.string.nc_app_product_name)));
} }
@ -316,9 +317,7 @@ public class CallNotificationController extends BaseController {
} }
private void runAllThings() { private void runAllThings() {
if (conversationNameTextView != null) { binding.conversationNameTextView.setText(currentConversation.getDisplayName());
conversationNameTextView.setText(currentConversation.getDisplayName());
}
// TODO: load avatar, but don't block UI! // TODO: load avatar, but don't block UI!
// loadAvatar(); // loadAvatar();
@ -326,67 +325,21 @@ public class CallNotificationController extends BaseController {
showAnswerControls(); showAnswerControls();
} }
@SuppressLint({"LongLogTag"})
@Override
protected void onViewBound(@NonNull View view) {
super.onViewBound(view);
String callDescriptionWithoutTypeInfo =
String.format(
getResources().getString(R.string.nc_call_unknown),
getResources().getString(R.string.nc_app_product_name));
incomingCallVoiceOrVideoTextView.setText(callDescriptionWithoutTypeInfo);
renderScript = RenderScript.create(getActivity());
if (handler == null) {
handler = new Handler();
try {
cache.evictAll();
} catch (IOException e) {
Log.e(TAG, "Failed to evict cache");
}
}
if (currentConversation == null) {
handleFromNotification();
} else {
runAllThings();
}
if (DoNotDisturbUtils.INSTANCE.shouldPlaySound()) {
playRingtoneSound();
}
}
@Subscribe(threadMode = ThreadMode.MAIN) @Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(ConfigurationChangeEvent configurationChangeEvent) { public void onMessageEvent(ConfigurationChangeEvent configurationChangeEvent) {
ConstraintLayout.LayoutParams layoutParams = (ConstraintLayout.LayoutParams) avatarImageView.getLayoutParams(); ConstraintLayout.LayoutParams layoutParams = (ConstraintLayout.LayoutParams) binding.avatarImageView.getLayoutParams();
int dimen = (int) getResources().getDimension(R.dimen.avatar_size_very_big); int dimen = (int) getResources().getDimension(R.dimen.avatar_size_very_big);
layoutParams.width = dimen; layoutParams.width = dimen;
layoutParams.height = dimen; layoutParams.height = dimen;
avatarImageView.setLayoutParams(layoutParams); binding.avatarImageView.setLayoutParams(layoutParams);
} }
@Override
protected void onDetach(@NonNull View view) {
super.onDetach(view);
eventBus.unregister(this);
}
@Override
protected void onAttach(@NonNull View view) {
super.onAttach(view);
eventBus.register(this);
}
private void loadAvatar() { private void loadAvatar() {
switch (currentConversation.getType()) { switch (currentConversation.getType()) {
case ROOM_TYPE_ONE_TO_ONE_CALL: case ROOM_TYPE_ONE_TO_ONE_CALL:
avatarImageView.setVisibility(View.VISIBLE); binding.avatarImageView.setVisibility(View.VISIBLE);
ImageRequest imageRequest = ImageRequest imageRequest =
DisplayUtils.getImageRequestForUrl( DisplayUtils.getImageRequestForUrl(
@ -401,33 +354,30 @@ public class CallNotificationController extends BaseController {
dataSource.subscribe(new BaseBitmapDataSubscriber() { dataSource.subscribe(new BaseBitmapDataSubscriber() {
@Override @Override
protected void onNewResultImpl(@Nullable Bitmap bitmap) { protected void onNewResultImpl(@Nullable Bitmap bitmap) {
if (avatarImageView != null) { binding.avatarImageView.getHierarchy().setImage(new BitmapDrawable(bitmap), 100,
avatarImageView.getHierarchy().setImage(new BitmapDrawable(bitmap), 100, true);
true); if (getResources() != null) {
binding.incomingTextRelativeLayout.setBackground(
getResources().getDrawable(R.drawable.incoming_gradient));
}
if (getResources() != null) { if (AvatarStatusCodeHolder.getInstance().getStatusCode() == 200 ||
incomingTextRelativeLayout.setBackground( AvatarStatusCodeHolder.getInstance().getStatusCode() == 0) {
getResources().getDrawable(R.drawable.incoming_gradient));
}
if (AvatarStatusCodeHolder.getInstance().getStatusCode() == 200 || Bitmap backgroundBitmap = bitmap.copy(bitmap.getConfig(), true);
AvatarStatusCodeHolder.getInstance().getStatusCode() == 0) { new BlurPostProcessor(5, context).process(backgroundBitmap);
if (getActivity() != null) { binding.backgroundImageView.setImageDrawable(new BitmapDrawable(backgroundBitmap));
Bitmap backgroundBitmap = bitmap.copy(bitmap.getConfig(), true);
new BlurPostProcessor(5, getActivity()).process(backgroundBitmap);
backgroundImageView.setImageDrawable(new BitmapDrawable(backgroundBitmap));
}
} else if (AvatarStatusCodeHolder.getInstance().getStatusCode() == 201) {
ColorArt colorArt = new ColorArt(bitmap);
int color = colorArt.getBackgroundColor();
float[] hsv = new float[3]; } else if (AvatarStatusCodeHolder.getInstance().getStatusCode() == 201) {
Color.colorToHSV(color, hsv); ColorArt colorArt = new ColorArt(bitmap);
hsv[2] *= 0.75f; int color = colorArt.getBackgroundColor();
color = Color.HSVToColor(hsv);
backgroundImageView.setImageDrawable(new ColorDrawable(color)); float[] hsv = new float[3];
} Color.colorToHSV(color, hsv);
hsv[2] *= 0.75f;
color = Color.HSVToColor(hsv);
binding.backgroundImageView.setImageDrawable(new ColorDrawable(color));
} }
} }
@ -439,9 +389,9 @@ public class CallNotificationController extends BaseController {
break; break;
case ROOM_GROUP_CALL: case ROOM_GROUP_CALL:
avatarImageView.setImageResource(R.drawable.ic_circular_group); binding.avatarImageView.setImageResource(R.drawable.ic_circular_group);
case ROOM_PUBLIC_CALL: case ROOM_PUBLIC_CALL:
avatarImageView.setImageResource(R.drawable.ic_circular_group); binding.avatarImageView.setImageResource(R.drawable.ic_circular_group);
break; break;
default: default:
} }
@ -502,10 +452,10 @@ public class CallNotificationController extends BaseController {
} }
} }
if (ringtoneUri != null && getActivity() != null) { if (ringtoneUri != null) {
mediaPlayer = new MediaPlayer(); mediaPlayer = new MediaPlayer();
try { try {
mediaPlayer.setDataSource(getActivity(), ringtoneUri); mediaPlayer.setDataSource(this, ringtoneUri);
mediaPlayer.setLooping(true); mediaPlayer.setLooping(true);
AudioAttributes audioAttributes = new AudioAttributes AudioAttributes audioAttributes = new AudioAttributes

View File

@ -40,7 +40,6 @@ import com.google.android.material.snackbar.Snackbar
import com.nextcloud.talk.R import com.nextcloud.talk.R
import com.nextcloud.talk.api.NcApi import com.nextcloud.talk.api.NcApi
import com.nextcloud.talk.application.NextcloudTalkApplication import com.nextcloud.talk.application.NextcloudTalkApplication
import com.nextcloud.talk.controllers.CallNotificationController
import com.nextcloud.talk.controllers.ConversationsListController import com.nextcloud.talk.controllers.ConversationsListController
import com.nextcloud.talk.controllers.LockedController import com.nextcloud.talk.controllers.LockedController
import com.nextcloud.talk.controllers.ServerSelectionController import com.nextcloud.talk.controllers.ServerSelectionController
@ -310,11 +309,17 @@ class MainActivity : BaseActivity(), ActionBarProvider {
handleActionFromContact(intent) handleActionFromContact(intent)
if (intent.hasExtra(BundleKeys.KEY_FROM_NOTIFICATION_START_CALL)) { if (intent.hasExtra(BundleKeys.KEY_FROM_NOTIFICATION_START_CALL)) {
if (intent.getBooleanExtra(BundleKeys.KEY_FROM_NOTIFICATION_START_CALL, false)) { if (intent.getBooleanExtra(BundleKeys.KEY_FROM_NOTIFICATION_START_CALL, false)) {
router!!.pushController(
RouterTransaction.with(CallNotificationController(intent.extras)) // router!!.pushController(
.pushChangeHandler(HorizontalChangeHandler()) // RouterTransaction.with(CallNotificationController(intent.extras))
.popChangeHandler(HorizontalChangeHandler()) // .pushChangeHandler(HorizontalChangeHandler())
) // .popChangeHandler(HorizontalChangeHandler())
// )
val callNotificationIntent = Intent(this, CallNotificationActivity::class.java)
intent.extras?.let { callNotificationIntent.putExtras(it) }
startActivity(callNotificationIntent)
} else { } else {
ConductorRemapping.remapChatController( ConductorRemapping.remapChatController(
router!!, intent.getLongExtra(BundleKeys.KEY_INTERNAL_USER_ID, -1), router!!, intent.getLongExtra(BundleKeys.KEY_INTERNAL_USER_ID, -1),