Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Android: Why is the event called callInviteEventTypeValueCallInviteNotificationTapped #473

Open
jhutchins opened this issue Feb 11, 2025 · 11 comments

Comments

@jhutchins
Copy link

I don't understand why the event callInviteEventTypeValueCallInviteNotificationTapped is called this.

As best I can tell, this event is only ever triggered from Android and is done unconditionally whenever a call comes in while the phone is locked. This has nothing to do with the notification being tapped in the sense of physical interaction. I suppose that it could make sense that you've tapped into the incoming call invite, but it's a confusing name.

@jhutchins jhutchins changed the title Why is the event called callInviteEventTypeValueCallInviteNotificationTapped Android: Why is the event called callInviteEventTypeValueCallInviteNotificationTapped Feb 11, 2025
@mhuynh5757
Copy link
Collaborator

Hi @jhutchins it's a long-winded name haha, I can understand the potential for confusion.

The event is supposed to fire when you have the app backgrounded or foregrounded (not closed) and you tap on the body of the notification of the incoming call. It should also be somewhat obfuscated, that whole callInviteEventTypeValueCallInviteNotificationTapped string should be internally handled by the SDK and re-emitted by the CallInvite.on(CallInvite.Event.NotificationTapped, ...) listener.

Are you seeing the raw string somewhere in a public API? That would be indicative of a bug somewhere in our event handling and we can attempt to investigate.

@jhutchins
Copy link
Author

In the public api it's called NotificationTapped. My confusion is not that the internal constant is an entire sentence, it's that the triggering of that handler has nothing to do with the notification actually being tapped on. The only place that triggers that handler is VoiceService.foregroundAndDeprioritizeIncomingCallNotification and that is only called when the device is locked and receives a call.

@mhuynh5757
Copy link
Collaborator

Can you describe the exact steps you're performing to reproduce this issue? For what it's worth, I just did the following and analyzed the Android logcat:

Boot an Android emulator with API 35 on a Pixel 9.
Create a valid token, register, and validate the emulator was receiving incoming calls.
Lock the emulator.
Create an incoming call.

I did not observe within the Android logcat the intent that you're referring to being fired.

@jhutchins
Copy link
Author

It appears we may be talking past each other, so please give me one more attempt to explain.

My thesis is that the event name NotificationTapped has nothing to do with user interaction with the notification.

This is easily evidenced by interacting with the sample application. If you look at this code from the sample application that you wrote

      /**
       * Handle the call invite notification tapped event.
       */
      const handleCallInviteNotificationTapped = () => {
        navigate('Incoming Call');
      };
      callInvite.on(
        TwilioCallInvite.Event.NotificationTapped,
        handleCallInviteNotificationTapped,
      );

You can see that on the NotificationTapped event, the app navigates to an Incoming Call screen even though that's an action that makes no sense if a user has clicked on a notification with an accept and reject button. If a user had tapped the notification, the call would either be active or terminated, and yet the app works because that's not what triggers the event.

If you read the Android code from this repository you will see that the only place that event is fired is in this method

  private void foregroundAndDeprioritizeIncomingCallNotification(final CallRecordDatabase.CallRecord callRecord) {
    logger.debug("foregroundAndDeprioritizeIncomingCallNotification: " + callRecord.getUuid());

    // cancel existing notification & put up in call
    Notification notification = NotificationUtility.createIncomingCallNotification(
      VoiceService.this,
      callRecord,
      VOICE_CHANNEL_DEFAULT_IMPORTANCE);
    createOrReplaceNotification(callRecord.getNotificationId(), notification);

    // notify JS layer
    sendJSEvent(
      ScopeCallInvite,
      constructJSMap(
        new Pair<>(CallInviteEventKeyType, CallInviteEventTypeValueNotificationTapped),
        new Pair<>(CallInviteEventKeyCallSid, callRecord.getCallSid())));
  }

That method is invoked from only one place in the library

        case ACTION_FOREGROUND_AND_DEPRIORITIZE_INCOMING_CALL_NOTIFICATION:
          foregroundAndDeprioritizeIncomingCallNotification(
            getCallRecord(Objects.requireNonNull(getMessageUUID(intent))));
          break;

which is executed when the VoiceService is started with an Intent action of ACTION_FOREGROUND_AND_DEPRIORITIZE_INCOMING_CALL_NOTIFICATION

@mhuynh5757
Copy link
Collaborator

Hi @jhutchins apologies for any miscommunication on my part. Let's see if we can sort this out together.

The callInvite.on(CallInvite.Event.NotificationTapped, ...) event is supposed to fire when you tap on the content body of the incoming call notification. Indeed, we test this code path in our QA cycles and I tested just now to see if any regression has slipped through. I can confirm with the same setup I mentioned above that I'm still seeing the expected behavior. To clarify:

Boot a Pixel 9 emulator with API 35.
Ensure said emulator is registered and can receive incoming calls using the sample app.
Stay idle at main screen.
Receive an incoming call.
Tap on the notification body.
Observe the CallInvite.Event.NotificationTapped event firing.

Another scenario I've tested:

Boot a Pixel 9 emulator with API 35.
Ensure said emulator is registered and can receive incoming calls using the sample app.
Lock the device.
Receive an incoming call.

What I also see is that that foregroundAndDeprioritizeIncomingCallNotification intent on the native Android layer is not being constructed in this situation, that code path is not firing according to breakpoints and logcats.

Perhaps it's important to note that this event is intended to fire when tapping on the body of the notification, not an action button such as "Accept" or "Reject".

@mhuynh5757
Copy link
Collaborator

One such use-case for this event, where a user taps on the body of the notification instead of either rejecting or accepting it from the notification, is so that you can update your UI in the React Native app to show a fullscreen incoming call. This way you can display extra info about the incoming call, for example "Nickname" or "Mutual friends" etc. You can see how we create a fullscreen incoming call in our Reference App and how we use it there: https://github.com/twilio/twilio-voice-react-native-app/blob/main/app/src/store/bootstrap.ts#L179

@mhuynh5757
Copy link
Collaborator

In one of your messages, you observe that the intent that fires this event occurs when you lock the screen and receive an incoming call, I am assuming that you are not tapping the content body of the incoming call notification. This indeed would be a bug, I would like to ask you to confirm if this is the issue that you're trying to report? I would also like to confirm that I tested this on my end and I'm not seeing the event fire or the intent being constructed.

If this is the case, can you provide more details on your development environment? If you could fill out the issue template and include all the relevant version info, it may provide insight into this problem. For example, I'm testing with latest Android API 35 on a virtual Pixel 9, you may be seeing different things because you're on a different setup, i.e. a real device or an older API.

@dwbelliston
Copy link

@mhuynh5757 thanks for the work you have done on this. can you confirm that if you kill the app and then lock, you are still able to receive incoming call okay?

So these steps...

Boot a Pixel 9 emulator with API 35.
Ensure said emulator is registered and can receive incoming calls using the sample app.
>> Kill the app <<
Lock the device.
Receive an incoming call.

@jhutchins
Copy link
Author

@mhuynh5757 are you saying that when you lock the screen and receive a call it doesn't call the NotificationTapped handler? What does happen?

@mhuynh5757
Copy link
Collaborator

@dwbelliston let me give that a shot, I'll get back to you when I have some results to share.

@jhutchins that's correct, when I lock the screen and receive a call, I do not see the NotificationTapped handler. I just see the notification. If I don't interact with it, no event fires. Just the voice.on(Voice.Event.CallInvite, ...) event fires. Are you using a physical device? What OS version and device?

@jhutchins
Copy link
Author

@mhuynh5757 I'm using a physical Pixel 7 running Android 15 (aka Vanilla Ice Cream).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants