react-native-callkeep icon indicating copy to clipboard operation
react-native-callkeep copied to clipboard

RNCallKeep is not working on app background and Inactive States

Open pavanMude opened this issue 4 years ago • 10 comments

Bug report

  • I've checked the(https://github.com/react-native-webrtc/react-native-callkeep/tree/master/example) to reproduce the issue.

Description

I have implemented RNCallKeep features in such a way that when a push notification arrives, then it tries to display an incoming UI through RNCallKeepDisplayIncomingUI(). When the app is in foreground as per the logic If I click on answer button, it is redirecting to a specific page; howsoever, the functionality that I am mentioning wasn't working as expected when the app goes to background or inactive state.

In background state, on click of answer button, the expected behaviour is that app should change its state to foreground, open the app automatically and redirect to the specific screen. The navigation logic is working fine but it is not opening the app and behave according to the logic.

Help will be appreciated.

Versions

- Callkeep: 3.0.12
- React Native: 0.59.9
- iOS: 10.15.2
- Android: android 9.0
- Phone model: Nokia 5.1 plus 

pavanMude avatar May 21 '20 04:05 pavanMude

Same here. Killed an app. Calling to this device — no reaction.

@pavanMude Figured out — need to configure, for example, Firebase background messaging (https://bit.ly/3ej3hoN — react-native-firebase v5 docs NOT THE LATEST, but just my case).

Then you need to register headless task.

AppRegistry.registerHeadlessTask(
  'RNFirebaseBackgroundMessage',
  () => CallMessagingManager.backgroundMessageHandler
)

Inside this backgroundMessageHandler it's important to call methods:

RNCallKeep.setup(YOUR_OPTIONS)
RNCallKeep.setAvailable(true)
// rest of your call answer logic

After this at some moment (onAnswer, for example) you need to use something like that — react-native-invoke-app to return your app from background.

isnifer avatar May 23 '20 23:05 isnifer

@isnifer in the backgroundMessageHandler i setup Callkeep and display incomming call and after i call RNCallKeep.setCurrentCallActive(callUUID); i can't recive event endcall when i pressButtom endcall in screen ui can you tell me why and how i can catch event endcall? test in android

JustinBeBoy avatar May 28 '20 18:05 JustinBeBoy

Hi @JustinBeBoy, to receive an event when someone hangup via callkeep, you have to register a listener.

manuquentin avatar Jun 04 '20 16:06 manuquentin

@manuquentin I registered all the events, when I test your example, I still get the endcall event, but when I process the notification in the background firebase, I don't get the endcall event when I click the end call button i test in nexsus 5x android 8.1 react native : 0.62

JustinBeBoy avatar Jun 05 '20 02:06 JustinBeBoy

@JustinBeBoy can you explain what youre trying to do a bit clearer please? We can't help you unless you give us more information to go on

danjenkins avatar Jun 09 '20 08:06 danjenkins

@danjenkins code in file index.js: `function HeadlessCheck({ isHeadless }) { if (isHeadless) { // App has been launched in the background by iOS, ignore return null; }

return <App />;

}

registerMessing()

AppRegistry.registerComponent(appName, () => HeadlessCheck);`

this is my registerMessing function:

export const registerMessing = () => { messaging().setBackgroundMessageHandler(async remoteMessage => { console.log('Message handled in the background!', remoteMessage); try { const messData = remoteMessage.data ?? {} const type = messData.type ?? "" const data = messData.data if (type == NotiType.call) { const objectNoti = JSON.parse(data) console.log('Parse Object', objectNoti) await handlerCall(objectNoti) } console.log('Message handled in the background!', remoteMessage); } catch (err) { console.log('backgoundMessageHandler-error: ', err) } }); }

handlerCall function:

`const handlerCall = (object) => { return new Promise(async (resolve, reject) => { if (object.callStatus == CallStatus.end) { resolve() }

    let client = new StringeeClientCustoms()
    let stringeeCa = new StringeeCallCustoms()

    let mediaConnected = false
    let answered = false
    const callDidChangeSignalingState = ({ callId, code, reason, sipCode, sipReason }) => {}
    const callDidChangeMediaState = ({ callId, code, description }) => {}
    const callDidReceiveLocalStream = ({ callId }) => {
        console.log("CallScreen-callDidReceiveLocalStream: callID=" + callId);
        // updateHasReceivedLocalStream(true)
    };

    const callDidReceiveRemoteStream = ({ callId }) => {
        console.log("CallScreen-callDidReceiveRemoteStream: callID=" + callId);
        // updateHasReceivedRemoteStream(true)
    };

    const didReceiveDtmfDigit = ({ callId, dtmf }) => {
        console.log("CallScreen-didReceiveDtmfDigit: callId=" + callId + " -- dtmf=" + dtmf);
    };

    const didReceiveCallInfo = ({ callId, data }) => {
        console.log("CallScreen-didReceiveCallInfo: callId=" + callId + " -- data=" + data);
    };

    const didHandleOnAnotherDevice = ({ callId, code, description }) => {
        console.log("CallScreen-didHandleOnAnotherDevice: callId=" + callId + " -- code=" + code + " -- des=" + description);
        if (code == 2 || code == 3 || code == 4) {
            // Answered || Busy || End
            console.log("CallScreen-endCallAndDismissView")
            // endCallAndDismissView();
        }
    };
    const callEventHandlers = {
        onChangeSignalingState: callDidChangeSignalingState,
        onChangeMediaState: callDidChangeMediaState,
        onReceiveLocalStream: callDidReceiveLocalStream,
        onReceiveRemoteStream: callDidReceiveRemoteStream,
        onReceiveDtmfDigit: didReceiveDtmfDigit,
        onReceiveCallInfo: didReceiveCallInfo,
        onHandleOnAnotherDevice: didHandleOnAnotherDevice
    };
    const clientDidConnect = ({ userId }) => {
        console.log("_clientDidConnect - " + userId);
    }

    const clientDidDisConnect = () => {
        console.log("_clientDidDisConnect");
    };

    const clientDidFailWithError = () => {
        console.log("_clientDidFailWithError");
    };

    const clientRequestAccessToken = () => {
        console.log("_clientRequestAccessToken");
        // Token để kết nối tới Stringee server đã hết bạn. Bạn cần lấy token mới và gọi connect lại ở đây
        // this.refs.client.connect("NEW_TOKEN");
    };

    // Call events
    const callIncomingCall = ({ callId, from, to, fromAlias, toAlias, callType, isVideoCall, customDataFromYourServer }) => {
        console.log("-----------_callIncomingCall---------------", callId)
        stringeeCa.init(callEventHandlers)

        stringeeCa.initAnswer(object.callId, (status, code, message) => {
            console.log("initAnswer=======>", message);
        });
    };

    const clientEventHandlers = {
        onConnect: clientDidConnect,
        onDisConnect: clientDidDisConnect,
        onFailWithError: clientDidFailWithError,
        onRequestAccessToken: clientRequestAccessToken,
        onIncomingCall: callIncomingCall
    };

    const answerCall = ({ callUUID }) => {

        stringeeCa.answer(object.callId, (status, code, message) => {
            console.log("xxxxxxx" + message);
            RNCallKeep.startCall(callUUID, "LockApp", "Test")
            //@ts-ignore
            RNCallKeep.setCurrentCallActive(callUUID);
        })
    }

    const didReceiveStartCallAction = ({ handle }) => {
        console.log("didReceiveStartCallAction")
    };

    const didPerformSetMutedCallAction = ({ muted, callUUID }) => {
        console.log("didPerformSetMutedCallAction")
    };

    const didToggleHoldCallAction = ({ hold, callUUID }) => {
        console.log("didToggleHoldCallAction")
    };

    const endCall = ({ callUUID }) => {
        console.log("END CALL:=========")
        stringeeCa.hangup(object.callId, (status, code, message) => {
            console.log("CallScreen-callDidChangeSignalingState-hangup: status=3, mess=" + message);
            resolve()
        });
    };

    RNCallKeep.addEventListener('answerCall', answerCall);
    RNCallKeep.addEventListener('didReceiveStartCallAction', didReceiveStartCallAction);
    RNCallKeep.addEventListener('didPerformSetMutedCallAction', didPerformSetMutedCallAction);
    RNCallKeep.addEventListener('didToggleHoldCallAction', didToggleHoldCallAction);
    RNCallKeep.addEventListener('endCall', endCall);

    client.init(clientEventHandlers)
    client.connect(userTest)
    let uuid4 = uuidv4()
    RNCallKeep.displayIncomingCall(uuid4, "LockApp", "Test")
})

}`

when i call this code: RNCallKeep.startCall(callUUID, "LockApp", "Test") //@ts-ignore RNCallKeep.setCurrentCallActive(callUUID); screen call system show, but when i press button endcall in screen i don't get event endcall in RNCallKeep.addEventListener('endCall', endCall); i test in nexsus 5x android 8.1 react native : 0.62

JustinBeBoy avatar Jun 09 '20 09:06 JustinBeBoy

@JustinBeBoy It is because that you are passing different callUUID to end call(). Remember you must pass same UUID on RNCallKeep DisplayUI (), which also be given in end call() as well. This will surely work.

const endCall = ({ callUUID }) => {
        console.log("END CALL:=========")
        stringeeCa.hangup(object.callId, (status, code, message) => {
            console.log("CallScreen-callDidChangeSignalingState-hangup: status=3, mess=" + message);
            resolve()
        });
    };

pavanMude avatar Jun 18 '20 06:06 pavanMude

Same here. Killed an app. Calling to this device — no reaction.

@pavanMude Figured out — need to configure, for example, Firebase background messaging (https://bit.ly/3ej3hoN — react-native-firebase v5 docs NOT THE LATEST, but just my case).

Then you need to register headless task.


AppRegistry.registerHeadlessTask(

  'RNFirebaseBackgroundMessage',

  () => CallMessagingManager.backgroundMessageHandler

)

Inside this backgroundMessageHandler it's important to call methods:


RNCallKeep.setup(YOUR_OPTIONS)

RNCallKeep.setAvailable(true)

// rest of your call answer logic

After this at some moment (onAnswer, for example) you need to use something like that — react-native-invoke-app to return your app from background.

Just a question, This apply to android only right?

jason-shen avatar Nov 10 '20 07:11 jason-shen

RNCallKeep.setAvailable(true)

this part ended 2 days of suffering with RN a big TY!

nikolov9996 avatar Aug 26 '22 13:08 nikolov9996

I am trying to handle the calling when the app is in kille state. I tested the features in the foreground state and the listeners are working perfectly fine, but when the app is killed, the UI is shown but nothing happens when buttons are pressed, no callbacks in listeners are invoked.

Irfanwani avatar Jul 02 '24 14:07 Irfanwani