MrHertal / react-native-twilio-phone

Twilio Voice React Native module.
MIT License
154 stars 67 forks source link

Receiving Events in the Background on Android #21

Closed hsandhu closed 3 years ago

hsandhu commented 3 years ago

Thanks so much for your great library @MrHertal!

Running on Android 11 with Firebase Messaging configured, I can receive FCM notifications in the background from an incoming call and answer this call as well. I see the following message on logcat as the call is received: D/TwilioPhone: Call did connect

However, this event is not received in the event listener in my App.tsx file (I've defined the listeners as you have in your example project). The events are received as expected in App.tsx if the incoming call is initialed while the app is in the foreground. Any thoughts as to why this event is not sent back through the React context and to the JS listener while the app is in the background?

MrHertal commented 3 years ago

Hi @hsandhu, thanks for your message!

This is normal behavior because when app is in background, code is executed independently of React context.

When you are calling handleBackgroundState, messaging().setBackgroundMessageHandler is registering a headless JS task. The task code is independent and has no access to React context (this context does not even exist since app is in background).

But you can still listen to CallConnected event within that function. You could copy handleBackgroundState and write something like:

import messaging from '@react-native-firebase/messaging';
import { AppRegistry, Platform } from 'react-native';
import RNCallKeep from 'react-native-callkeep';
import {
  RNTwilioPhone,
  TwilioPhone,
  twilioPhoneEmitter,
} from 'react-native-twilio-phone';
import { name as appName } from './app.json';
import { App } from './src/App';

function handleBackgroundState() {
  if (Platform.OS !== 'android') {
    return;
  }

  messaging().setBackgroundMessageHandler(async (remoteMessage) => {
    if (!remoteMessage.data) {
      return;
    }

    RNCallKeep.registerPhoneAccount();
    RNCallKeep.registerAndroidEvents();
    RNCallKeep.setAvailable(true);

    RNTwilioPhone.listenTwilioPhone(); // Listen to events after this line because listeners are removed here
    RNTwilioPhone.listenCallKeep();

    // Here you can listen to events and do what you want
    twilioPhoneEmitter.addListener('CallConnected', (data) => {
      console.log(data);
    })

    TwilioPhone.handleMessage(remoteMessage.data);
  });
}

handleBackgroundState();

AppRegistry.registerComponent(appName, () => App);
hsandhu commented 3 years ago

@MrHertal this is really helpful and makes sense, thank you!