Giter VIP home page Giter VIP logo

react-native-callkeep's Introduction

React Native CallKeep

npm version npm downloads

React Native CallKeep utilises a brand new iOS 10 framework CallKit and Android ConnectionService to make the life easier for VoIP developers using React Native.

For more information about CallKit on iOS, please see Official CallKit Framework Document or Introduction to CallKit by Xamarin

For more information about ConnectionService on Android, please see Android Documentation and Build a calling app

⚠️ CallKit and ConnectionService are only available on real devices, this library will not work on simulators.

Summary

Demo

A demo of react-native-callkeep is available in the wazo-react-native-demo repository.

Android

Connection Service

iOS

Connection Service

Installation

npm install --save react-native-callkeep
# or
yarn add react-native-callkeep

Usage

Setup

import RNCallKeep from 'react-native-callkeep';

const options = {
  ios: {
    appName: 'My app name',
  },
  android: {
    alertTitle: 'Permissions required',
    alertDescription: 'This application needs to access your phone accounts',
    cancelButton: 'Cancel',
    okButton: 'ok',
    imageName: 'phone_account_icon',
    additionalPermissions: [PermissionsAndroid.PERMISSIONS.example],
    // Required to get audio in background when using Android 11
    foregroundService: {
      channelId: 'com.company.my',
      channelName: 'Foreground service for my app',
      notificationTitle: 'My app is running on background',
      notificationIcon: 'Path to the resource icon of the notification',
    }, 
  }
};

RNCallKeep.setup(options).then(accepted => {});

iOS only.

Alternative on iOS you can perform setup in AppDelegate.m. Doing this allows capturing events prior to the react native event bridge being up. Please be aware that calling setup in AppDelegate.m will ignore any subsequent calls to RNCallKeep.setup();.

@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{ 
  self.bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];

  [RNCallKeep setup:@{
    @"appName": @"Awesome App",
    @"maximumCallGroups": @3,
    @"maximumCallsPerCallGroup": @1,
    @"supportsVideo": @NO,
  }];

  RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:self.bridge
                                                   moduleName:@"App"
                                            initialProperties:nil];

  // ======== OTHER CODE REDACTED ==========

  return YES;
}
  • options: Object
    • ios: object
      • appName: string (required) It will be displayed on system UI when incoming calls received
      • imageName: string (optional) If provided, it will be displayed on system UI during the call
      • ringtoneSound: string (optional) If provided, it will be played when incoming calls received; the system will use the default ringtone if this is not provided
      • handleType: string|array (optional) If provided, it will tell iOS what kind of handle(s) (number) your app can handle.
        • generic
        • number (default)
        • email
      • includesCallsInRecents: boolean (optional) If provided, calls will be shown in the recent calls when true and not when false (ios 11 and above) (Default: true)
      • maximumCallGroups: string (optional) If provided, the maximum number of call groups supported by this application (Default: 3)
      • maximumCallsPerCallGroup: string (optional) If provided, the maximum number of calls in a single group, used for conferencing (Default: 1, no conferencing)
      • supportsVideo: boolean (optional) If provided, whether or not the application supports video calling (Default: true)
      • displayCallReachabilityTimeout: number in ms (optional) If provided, starts a timeout that checks if the application is reachable and ends the call if not (Default: null) You'll have to call setReachable() as soon as your Javascript application is started.
      • audioSession: object
        • categoryOptions: AudioSessionCategoryOption|number (optional) If provided, it will override the default AVAudioSession setCategory options.
        • mode: AudioSessionMode|string (optional) If provided, it will override the default AVAudioSession setMode mode.
    • android: object
      • alertTitle: string (required) When asking for phone account permission, we need to provider a title for the Alert to ask the user for it
      • alertDescription: string (required) When asking for phone account permission, we need to provider a description for the Alert to ask the user for it
      • cancelButton: string (required) Cancel button label
      • okButton: string (required) Ok button label
      • imageName: string (optional) The image to use in the Android Phone application's native UI for enabling/disabling calling accounts. Should be a 48x48 HDPI grayscale PNG image. Must be in your drawable resources for the parent application. Must be lowercase and underscore (_) characters only, as Java doesn't like capital letters on resources.
      • additionalPermissions: [PermissionsAndroid] (optional) Any additional permissions you'd like your app to have at first launch. Can be used to simplify permission flows and avoid multiple popups to the user at different times.
      • selfManaged: boolean (optional) When set to true, call keep will configure itself to run as a self managed connection service. This is an advanced topic, and it's best to refer to Googles Documentation on the matter.
        • displayCallReachabilityTimeout: number in ms (optional) If provided, starts a timeout that checks if the application is reachable and ends the call if not (Default: null) You'll have to call setReachable() as soon as your Javascript application is started.

setup calls internally registerPhoneAccount, registerEvents and setSettings.

You can alternatively just call setSettings() with the same option as setup() to define only your settings.

Usage with Expo

To use this library with Expo, you will need to create a development build. Expo Go does not support custom native modules. For information on how to create and run a development build, visit: Create a development build - Expo Documentation. You can use and test this library with a development build installed on your physical device (iOS and Android).

Constants

To make passing the right integer into methods easier, there are constants that are exported from the module.

const CONSTANTS = {
  END_CALL_REASONS: {
    FAILED: 1,
    REMOTE_ENDED: 2,
    UNANSWERED: 3,
    ANSWERED_ELSEWHERE: 4,
    DECLINED_ELSEWHERE: 5,
    MISSED: 6
  }
};

const { CONSTANTS as CK_CONSTANTS, RNCallKeep } from 'react-native-callkeep';

console.log(CK_CONSTANTS.END_CALL_REASONS.FAILED) // outputs 1

Android Self Managed Mode

This feature is available only on Android.

Android supports calling apps running in what's called "Self Managed". This means the apps are able (and required) to provide their own UI for managing calls. This includes both in call UI elements and incoming call notification UI. This method is all or nothing. You can't mix partial elements, such as having a custom in call view, but use the default incoming call UI.

To implement a self managed calling app, the following steps are necessary:

  • Set selfManaged: true in setup.
  • On an incoming call, from react native, call RNCallKeep.displayIncomingCall
  • CallKeep will then fire the showIncomingCallUi event.
  • When showIncomingCallUi is fired, you must show an incoming call UI. This would be a high priority notification (Android: Display time-sensitive notifications).
  • If the user answers the call, you call the appropriate RNCallKeep actions such as answerCall or endCall
  • In certain cases Android will not allow you to show an incoming call notification. In that case the 'createIncomingConnectionFailed' event is fired and you should reject the incoming SIP Invite.

Self Managed calling apps are an advanced topic, and there are many steps involved in implementing them, but here are some things to keep in mind:

  • React Native Headless Tasks are a great way to execute React Native code. Remember to start up the headless task as a Foreground Service.
  • Android will deprioritize your high priority FCM notifications if you fail to show an incoming call ui when receiving them.
  • You can avoid getting flooded with sticky foreground service notifications by not defining a Foreground Service for CallKeep, and instead managing this on your own.

⚠️ To be able to use the self managed mode, you'll have to add the READ_CALL_LOG permission in your android/src/main/AndroidManifest.xml file:

<uses-permission android:name="android.permission.READ_CALL_LOG" />

API

Method Return Type iOS Android
getInitialEvents() Promise<String[]>
clearInitialEvents() void>
setAvailable() Promise<void>
setForegroundServiceSettings() Promise<void>
canMakeMultipleCalls() Promise<void>
setCurrentCallActive() Promise<void>
checkIsInManagedCall() Promise<Boolean>
isCallActive() Promise<Boolean>
getCalls() Promise<Object[]>
displayIncomingCall() Promise<void>
answerIncomingCall() Promise<void>
startCall() Promise<void>
updateDisplay() Promise<void>
endCall() Promise<void>
endAllCalls() Promise<void>
rejectCall() Promise<void>
reportEndCallWithUUID() Promise<void>
setMutedCall() Promise<void>
setOnHold() Promise<void>
setConnectionState() Promise<void>
checkIfBusy() Promise<Boolean>
checkSpeaker() Promise<Boolean>
toggleAudioRouteSpeaker() Promise<void>
supportConnectionService() Promise<Boolean>
hasPhoneAccount() Promise<Boolean>
hasOutgoingCall() Promise<Boolean>
hasDefaultPhoneAccount() Promise<Boolean>
checkPhoneAccountEnabled() Promise<Boolean>
isConnectionServiceAvailable() Promise<Boolean>
backToForeground() Promise<void>
removeEventListener() void
registerPhoneAccount() void
registerAndroidEvents() void

getInitialEvents

If there were some actions performed by user before JS context has been created, this method would return early fired events. This is alternative to "didLoadWithEvents" event.

RNCallKeep.getInitialEvents();

clearInitialEvents

Clear all pending actions returned by getInitialEvents().

RNCallKeep.clearInitialEvents();

setAvailable

This feature is available only on Android.

Tell ConnectionService that the device is ready to make outgoing calls via the native Phone app. If not the user will be stuck in the build UI screen without any actions. Eg: Call it with false when disconnected from the sip client, when your token expires, when your user log out ... Eg: When your used log out (or the connection to your server is broken, etc..), you have to call setAvailable(false) so CallKeep will refuse the call and your user will not be stuck in the native UI.

RNCallKeep.setAvailable(true);

setForegroundServiceSettings

This feature is available only on Android.

Configures the Foreground Service used for Android 11 to get microphone access on background. Similar to set the foregroundService key in the setup() method.

RNCallKeep.setForegroundServiceSettings({
    channelId: 'com.company.my',
    channelName: 'Foreground service for my app',
    notificationTitle: 'My app is running on background',
    notificationIcon: 'Path to the resource icon of the notification',
});

canMakeMultipleCalls

This feature is available only on Android.

Disable the "Add call" button in ConnectionService UI.

RNCallKeep.canMakeMultipleCalls(false); // Enabled by default
  • active: boolean
    • Tell whether the app is ready or not

setCurrentCallActive

This feature is available only on Android.

Mark the current call as active (eg: when the callee has answered). Necessary to set the correct Android capabilities (hold, mute) once the call is set as active. Be sure to set this only after your call is ready for two way audio; used both incoming and outgoing calls.

RNCallKeep.setCurrentCallActive(uuid);
  • uuid: string
    • The uuid used for startCall or displayIncomingCall

checkIsInManagedCall

This feature is available only on Android.

Returns true if there is an active native call

RNCallKeep.checkIsInManagedCall();

isCallActive

This feature is available only on IOS.

Returns true if the UUID passed matches an existing and answered call. This will return true ONLY if the call exists and the user has already answered the call. It will return false if the call does not exist or has not been answered. This is exposed to both React Native and Native sides. This was exposed so a call can be canceled if ringing and the user answered on a different device.

RNCallKeep.isCallActive(uuid);
  • uuid: string
    • The uuid used for startCall or displayIncomingCall

getCalls

This feature is available only on IOS.

Returns a Promise. The result will be an array with all current calls and their states.

RNCallKeep.getCalls();

response:
[{
  callUUID: "E26B14F7-2CDF-48D0-9925-532199AE7C48",
  hasConnected: true,
  hasEnded: false,
  onHold: false,
  outgoing: false,
}]

displayIncomingCall

Display system UI for incoming calls

RNCallKeep.displayIncomingCall(uid, handle, localizedCallerName = '', handleType = 'number', hasVideo = false, options = null);
  • uuid: string
    • An uuid that should be stored and re-used for stopCall.
  • handle: string
    • Phone number of the caller
  • localizedCallerName: string (optional)
    • Name of the caller to be displayed on the native UI
  • handleType: string (optional, iOS only)
    • generic
    • number (default)
    • email
  • hasVideo: boolean (optional, iOS only)
    • false (default)
    • true (you know... when not false)
  • options: object (optional)
    • ios: object
      • supportsHolding: boolean (optional, default true)
      • supportsDTMF: boolean (optional, default true)
      • supportsGrouping: boolean (optional, default true)
      • supportsUngrouping: boolean (optional, default true)
    • android: object (currently no-op)

answerIncomingCall

Use this to tell the sdk a user answered a call from the app UI.

RNCallKeep.answerIncomingCall(uuid)
  • uuid: string
    • The uuid used for startCall or displayIncomingCall

startCall

When you make an outgoing call, tell the device that a call is occurring. The argument list is slightly different on iOS and Android:

iOS:

RNCallKeep.startCall(uuid, handle, contactIdentifier, handleType, hasVideo);

Android:

RNCallKeep.startCall(uuid, handle, contactIdentifier);
  • uuid: string
    • An uuid that should be stored and re-used for stopCall.
  • handle: string
    • Phone number of the callee
  • contactIdentifier: string
    • The identifier is displayed in the native call UI, and is typically the name of the call recipient.
  • handleType: string (optional, iOS only)
    • generic
    • number (default)
    • email
  • hasVideo: boolean (optional, iOS only)
    • false (default)
    • true (you know... when not false)

updateDisplay

Use this to update the display after an outgoing call has started.

RNCallKeep.updateDisplay(uuid, displayName, handle)
  • uuid: string
    • The uuid used for startCall or displayIncomingCall
  • displayName: string (optional)
    • Name of the caller to be displayed on the native UI
  • handle: string
    • Phone number of the caller
  • options: object (optional)
    • ios: object
      • hasVideo: boolean (optional)
      • supportsHolding: boolean (optional)
      • supportsDTMF: boolean (optional)
      • supportsGrouping: boolean (optional)
      • supportsUngrouping: boolean (optional)
    • android: object (currently no-op)

endCall

When finish an incoming/outgoing call.
(When user actively chooses to end the call from your app's UI.)

RNCallKeep.endCall(uuid);
  • uuid: string
    • The uuid used for startCall or displayIncomingCall

endAllCalls

End all ongoing calls.

RNCallKeep.endAllCalls();

rejectCall

When you reject an incoming call.

RNCallKeep.rejectCall(uuid);
  • uuid: string
    • The uuid used for startCall or displayIncomingCall

reportEndCallWithUUID

Report that the call ended without the user initiating.
(Not ended by user, is usually due to the following reasons)

RNCallKeep.reportEndCallWithUUID(uuid, reason);
  • uuid: string
    • The uuid used for startCall or displayIncomingCall
  • reason: int
    • Reason for the end call
      • Call failed: 1
      • Remote user ended call: 2
      • Remote user did not answer: 3
      • Call Answered elsewhere: 4
      • Call declined elsewhere: 5 (on Android this will map to Remote user ended call if you use the constants)
      • Missed: 6 (on iOS this will map to remote user ended call)
    • Access reasons as constants
    const { CONSTANTS as CK_CONSTANTS, RNCallKeep } from 'react-native-callkeep';
    
    RNCallKeep.reportEndCallWithUUID(uuid, CK_CONSTANTS.END_CALL_REASONS.FAILED);

setMutedCall

Switch the mic on/off.

RNCallKeep.setMutedCall(uuid, true);
  • uuid: string
    • uuid of the current call.
  • muted: boolean

setOnHold

Set a call on/off hold.

RNCallKeep.setOnHold(uuid, true)
  • uuid: string
    • uuid of the current call.
  • hold: boolean

setConnectionState

This feature is available only on Android.

Change the state of the call

RNCallKeep.setConnectionState(uuid, state)

checkIfBusy

This feature is available only on IOS.

Checks if there are any active calls on the device and returns a promise with a boolean value (true if there're active calls, false otherwise).

RNCallKeep.checkIfBusy();

checkSpeaker

This feature is available only on IOS.

Checks if the device speaker is on and returns a promise with a boolean value (true if speaker is on, false otherwise).

RNCallKeep.checkSpeaker();

toggleAudioRouteSpeaker

This feature is available only on Android.

Update the audio route of Audio Service on Android with a routeSpeaker boolean value (true if speaker need on, false otherwise). When Phone call is active, Android control the audio via connection service. so this function help to toggle the audio to Speaker or wired/ear-piece or vice-versa

RNCallKeep.toggleAudioRouteSpeaker(uuid, true);
  • uuid: string
    • uuid of the current call.
  • routeSpeaker: boolean

getAudioRoutes

Get the list of available audio routes. i.e. bluetooth, wired/ear-piece, speaker and phone.

await RNCallKeep.getAudioRoutes(): AudioRoute;
type AudioRoute = {
    name: string,
    type: string
}

setAudioRoute

Set audio route using a route from getAudioRoutes.

await RNCallKeep.setAudioRoute(uuid, routeName);
  • uuid: string
    • uuid of the current call.
  • routeName: String
    • AudioRoute.name.

supportConnectionService

This feature is available only on Android.

Tells if ConnectionService is available on the device (returns a boolean).

RNCallKeep.supportConnectionService();

hasPhoneAccount (async)

This feature is available only on Android.

Checks if the user has enabled the phone account for your application. A phone account must be enable to be able to display UI screen on incoming call and make outgoing calls from native Contact application.

Returns a promise of a boolean.

await RNCallKeep.hasPhoneAccount();

hasOutgoingCall (async)

This feature is available only on Android, useful when waking up the application for an outgoing call.

When waking up the Android application in background mode (eg: when the application is killed and the user make a call from the native Phone application). The user can hang up the call before your application has been started in background mode, and you can lost the RNCallKeepPerformEndCallAction event.

To be sure that the outgoing call is still here, you can call hasOutgoingCall when you app waken up.

const hasOutgoingCall = await RNCallKeep.hasOutgoingCall();

hasDefaultPhoneAccount

This feature is available only on Android.

Checks if the user has set a default phone account. If the user has not set a default they will be prompted to do so with an alert.

This is a workaround for an issue affecting some Samsung devices.

const options = {
  alertTitle: 'Default not set',
  alertDescription: 'Please set the default phone account'
};

RNCallKeep.hasDefaultPhoneAccount(options);

checkPhoneAccountEnabled

This feature is available only on Android.

Checks if the user has set a default phone account and it's enabled.

It's useful for custom permission prompts. It should be used in pair with registerPhoneAccount Similar to hasDefaultPhoneAccount but without trigering a prompt if the user doesn't have a phone account.

RNCallKeep.checkPhoneAccountEnabled();

isConnectionServiceAvailable

This feature is available only on Android.

Check if the device support ConnectionService.

RNCallKeep.checkPhoneAccountEnabled();

backToForeground

This feature is available only on Android.

Use this to display the application in foreground if the application was in background state. This method will open the application if it was closed.

RNCallKeep.backToForeground();

removeEventListener

Allows to remove the listener on an event.

RNCallKeep.removeEventListener('checkReachability');

registerPhoneAccount

Registers Android phone account manually, useful for custom permission prompts when you don't want to call setup(). This method is called by setup, if you already use setup you don't need it.

This feature is available only on Android. On iOS you still have to call setup().

RNCallKeep.registerPhoneAccount(options);

registerAndroidEvents

Registers Android UI events, useful when you don't want to call setup(). This method is called by setup, if you already use setup you don't need it.

This feature is available only on Android. On iOS you still have to call setup().

RNCallKeep.registerAndroidEvents();

Events

Event iOS Android
didReceiveStartCallAction
answerCall
endCall
didActivateAudioSession
didDisplayIncomingCall
didPerformSetMutedCallAction
didToggleHoldCallAction
didPerformDTMFAction
didLoadWithEvents
showIncomingCallUi
silenceIncomingCall
checkReachability
didChangeAudioRoute
onHasActiveCall

didReceiveStartCallAction

Device sends this event once it decides the app is allowed to start a call, either from the built-in phone screens (iOS/Recents, Android/Contact), or by the app calling RNCallKeep.startCall.

Try to start your app call action from here (e.g. get credentials of the user by data.handle and/or send INVITE to your SIP server)

Note: on iOS callUUID is not defined as the call is not yet managed by CallKit. You have to generate your own and call startCall.

RNCallKeep.addEventListener('didReceiveStartCallAction', ({ handle, callUUID, name }) => {

});
  • handle (string)
    • Phone number of the callee
  • callUUID (string)
    • The UUID of the call that is to be answered
  • name (string)
    • Name of the callee

answerCall

User answer the incoming call

RNCallKeep.addEventListener('answerCall', ({ callUUID }) => {
  // Do your normal `Answering` actions here.
});
  • callUUID (string)
    • The UUID of the call that is to be answered.

endCall

User finish the call.

RNCallKeep.addEventListener('endCall', ({ callUUID }) => {
  // Do your normal `Hang Up` actions here
});
  • callUUID (string)
    • The UUID of the call that is to be ended.

didActivateAudioSession

The AudioSession has been activated by RNCallKeep.

RNCallKeep.addEventListener('didActivateAudioSession', () => {
  // you might want to do following things when receiving this event:
  // - Start playing ringback if it is an outgoing call
});

didDisplayIncomingCall

Callback for RNCallKeep.displayIncomingCall

RNCallKeep.addEventListener('didDisplayIncomingCall', ({ error, callUUID, handle, localizedCallerName, hasVideo, fromPushKit, payload }) => {
  // you might want to do following things when receiving this event:
  // - Start playing ringback if it is an outgoing call
});
  • error (string)
    • iOS only.
  • errorCode (string)
  • callUUID (string)
    • The UUID of the call.
  • handle (string)
    • Phone number of the caller
  • localizedCallerName (string)
    • Name of the caller to be displayed on the native UI
  • hasVideo (string)
    • 1 (video enabled)
    • 0 (video not enabled)
  • fromPushKit (string)
    • 1 (call triggered from PushKit)
    • 0 (call not triggered from PushKit)
  • payload (object)
    • VOIP push payload.

didPerformSetMutedCallAction

A call was muted by the system or the user:

RNCallKeep.addEventListener('didPerformSetMutedCallAction', ({ muted, callUUID }) => {

});
  • muted (boolean)
  • callUUID (string)
    • The UUID of the call.

didToggleHoldCallAction

A call was held or unheld by the current user

RNCallKeep.addEventListener('didToggleHoldCallAction', ({ hold, callUUID }) => {

});
  • hold (boolean)
  • callUUID (string)
    • The UUID of the call.

didChangeAudioRoute

Triggered when the audio route has been changed.

RNCallKeep.addEventListener('didChangeAudioRoute', ({ output }) => {

});

didPerformDTMFAction

Used type a number on his dialer

RNCallKeep.addEventListener('didPerformDTMFAction', ({ digits, callUUID }) => {

});
  • digits (string)
    • The digits that emit the dtmf tone
  • callUUID (string)
    • The UUID of the call.

didLoadWithEvents

iOS only.

Called as soon as JS context initializes if there were some actions performed by user before JS context has been created.

Since iOS 13, you must display incoming call on receiving PushKit push notification. But if app was killed, it takes some time to create JS context. If user answers the call (or ends it) before JS context has been initialized, user actions will be passed as events array of this event. Similar situation can happen if user would like to start a call from Recents or similar iOS app, assuming that your app was in killed state.

In order for this event to reliably fire, it's necessary to perform setup in AppDelegate.m

NOTE: You still need to subscribe / handle the rest events as usuall. This is just a helper whcih cache and propagate early fired events if and only if for "the native events which DID fire BEFORE js bridge is initialed", it does NOT mean this will have events each time when the app reopened.

// register `didLoadWithEvents` somewhere early in your app when it is ready to handle callkeep events.

RNCallKeep.addEventListener('didLoadWithEvents', (events) => {
  // `events` is passed as an Array chronologically, handle or ignore events based on the app's logic
  // see example usage in https://github.com/react-native-webrtc/react-native-callkeep/pull/169 or https://github.com/react-native-webrtc/react-native-callkeep/pull/205
});
  • events Array
    • name: string Native event name like: RNCallKeepPerformAnswerCallAction
    • data: object Object with data passed together with specific event so it can be handled in the same way like original event, for example ({ callUUID }) for answerCall event if name is RNCallKeepPerformAnswerCallAction

showIncomingCallUi

Android only. Self Managed only.

Only when CallKeep is setup to be in self managed mode. Signals that the app must show an incoming call UI. The implementor must either call displayIncomingCall from react native or native android code to make this event fire.

RNCallKeep.addEventListener('showIncomingCallUi', ({ handle, callUUID, name }) => {

});

The following values will match those initially passed to displayIncomingCall

  • handle (string)
    • Phone number of the incoming caller.
  • callUUID (string)
    • The UUID of the call.
  • name (string)
    • Caller Name.

silenceIncomingCall

Android only. Self Managed only.

Corresponds to the native onSilence event. The implementor should silence the corresponding incoming calls notification sound when and if this event is fired.

RNCallKeep.addEventListener('silenceIncomingCall', ({ handle, callUUID, name }) => {

});

The following values will match those initially passed to silenceIncomingCall

  • handle (string)
    • Phone number of the incoming caller.
  • callUUID (string)
    • The UUID of the call.
  • name (string)
    • Caller Name.

createIncomingConnectionFailed

Android only. Self Managed only.

Corresponds to the native onCreateIncomingConnectionFailed callback. The implementor should reject the incoming SIP INVITE with an appropriate status code, such as 483 User Busy. Android unfortunately does not provide the exact reason for refusing to let you accept an incoming call, but they do list a set of reasons here

RNCallKeep.addEventListener('createIncomingConnectionFailed', ({ handle, callUUID, name }) => {

});

The following values will match those initially passed to silenceIncomingCall

  • handle (string)
    • Phone number of the incoming caller.
  • callUUID (string)
    • The UUID of the call.
  • name (string)
    • Caller Name.

checkReachability

Android only.

On Android when the application is in background, after a certain delay the OS will close every connection with informing about it. So we have to check if the application is reachable before making a call from the native phone application.

RNCallKeep.addEventListener('checkReachability', () => {
  RNCallKeep.setReachable();
});

onHasActiveCall

Android only.

A listener that tells the JS side if a native call has been answered while there was an active self-managed call

RNCallKeep.addEventListener('onHasActiveCall', () => {
  // eg: End active app call if native call is answered
});

Example

A full example is available in the example folder.

import React from 'react';
import RNCallKeep from 'react-native-callkeep';
import uuid from 'uuid';

class RNCallKeepExample extends React.Component {
  constructor(props) {
    super(props);

    this.currentCallId = null;

    // Add RNCallKeep Events
    RNCallKeep.addEventListener('didReceiveStartCallAction', this.didReceiveStartCallAction);
    RNCallKeep.addEventListener('answerCall', this.onAnswerCallAction);
    RNCallKeep.addEventListener('endCall', this.onEndCallAction);
    RNCallKeep.addEventListener('didDisplayIncomingCall', this.onIncomingCallDisplayed);
    RNCallKeep.addEventListener('didPerformSetMutedCallAction', this.onToggleMute);
    RNCallKeep.addEventListener('didToggleHoldCallAction', this.onToggleHold);
    RNCallKeep.addEventListener('didPerformDTMFAction', this.onDTMFAction);
    RNCallKeep.addEventListener('didActivateAudioSession', this.audioSessionActivated);
  }

  // Initialise RNCallKeep
  setup = () => {
    const options = {
      ios: {
        appName: 'ReactNativeWazoDemo',
        imageName: 'sim_icon',
        supportsVideo: false,
        maximumCallGroups: '1',
        maximumCallsPerCallGroup: '1'
      },
      android: {
        alertTitle: 'Permissions Required',
        alertDescription:
          'This application needs to access your phone calling accounts to make calls',
        cancelButton: 'Cancel',
        okButton: 'ok',
        imageName: 'sim_icon',
        additionalPermissions: [PermissionsAndroid.PERMISSIONS.READ_CONTACTS]
      }
    };

    try {
      RNCallKeep.setup(options);
      RNCallKeep.setAvailable(true); // Only used for Android, see doc above.
    } catch (err) {
      console.error('initializeCallKeep error:', err.message);
    }
  }

  // Use startCall to ask the system to start a call - Initiate an outgoing call from this point
  startCall = ({ handle, localizedCallerName }) => {
    // Your normal start call action
    RNCallKeep.startCall(this.getCurrentCallId(), handle, localizedCallerName);
  };

  reportEndCallWithUUID = (callUUID, reason) => {
    RNCallKeep.reportEndCallWithUUID(callUUID, reason);
  }

  // Event Listener Callbacks

  didReceiveStartCallAction = (data) => {
    let { handle, callUUID, name } = data;
    // Get this event after the system decides you can start a call
    // You can now start a call from within your app
  };

  onAnswerCallAction = (data) => {
    let { callUUID } = data;
    // Called when the user answers an incoming call
  };

  onEndCallAction = (data) => {
    let { callUUID } = data;
    RNCallKeep.endCall(this.getCurrentCallId());

    this.currentCallId = null;
  };

  // Currently iOS only
  onIncomingCallDisplayed = (data) => {
    let { error } = data;
    // You will get this event after RNCallKeep finishes showing incoming call UI
    // You can check if there was an error while displaying
  };

  onToggleMute = (data) => {
    let { muted, callUUID } = data;
    // Called when the system or user mutes a call
  };

  onToggleHold = (data) => {
    let { hold, callUUID } = data;
    // Called when the system or user holds a call
  };

  onDTMFAction = (data) => {
    let { digits, callUUID } = data;
    // Called when the system or user performs a DTMF action
  };

  audioSessionActivated = (data) => {
    // you might want to do following things when receiving this event:
    // - Start playing ringback if it is an outgoing call
  };

  getCurrentCallId = () => {
    if (!this.currentCallId) {
      this.currentCallId = uuid.v4();
    }

    return this.currentCallId;
  };

  render() {
  }
}

Receiving a call when the application is not reachable.

In some case your application can be unreachable :

  • when the user kill the application
  • when it's in background since a long time (eg: after ~5mn the os will kill all connections).

To be able to wake up your application to display the incoming call, you can use https://github.com/react-native-webrtc/react-native-voip-push-notification on iOS or BackgroundMessaging from react-native-firebase-(Optional)(Android-only)-Listen-for-FCM-messages-in-the-background).

You have to send a push to your application, like with Firebase for Android and with a library supporting PushKit pushes for iOS.

PushKit

Since iOS 13, you'll have to report the incoming calls that wakes up your application with a VoIP push. Add this in your AppDelegate.m if you're using VoIP pushes to wake up your application :

- (void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(PKPushType)type withCompletionHandler:(void (^)(void))completion {
  // Process the received push
  [RNVoipPushNotificationManager didReceiveIncomingPushWithPayload:payload forType:(NSString *)type];

  // Retrieve information like handle and callerName here
  // NSString *uuid = /* fetch for payload or ... */ [[[NSUUID UUID] UUIDString] lowercaseString];
  // NSString *callerName = @"caller name here";
  // NSString *handle = @"caller number here";
  // NSDictionary *extra = [payload.dictionaryPayload valueForKeyPath:@"custom.path.to.data"]; /* use this to pass any special data (ie. from your notification) down to RN. Can also be `nil` */

  [RNCallKeep reportNewIncomingCall: uuid
                             handle: handle
                         handleType: @"generic"
                           hasVideo: NO
                localizedCallerName: callerName
                    supportsHolding: YES
                       supportsDTMF: YES
                   supportsGrouping: YES
                 supportsUngrouping: YES
                        fromPushKit: YES
                            payload: extra
              withCompletionHandler: completion];
}

Android 11

Since Android 11, your application requires to start a foregroundService in order to access the microphone in background. You'll need to upgrade your compileSdkVersion to 30 to be able to use this feature.

You have to set the foregroundService key in the setup() method and add a foregroundServiceType in the AndroidManifest file.

Debug

Android

adb logcat *:S RNCallKeep:V

Troubleshooting

  • Ensure that you construct a valid uuid by importing the uuid library and running uuid.v4() as shown in the examples. If you don't do this and use a custom string, the incoming call screen will never be shown on iOS.

Contributing

Any pull request, issue report and suggestion are highly welcome!

License

This work is dual-licensed under ISC and MIT. Previous work done by @ianlin on iOS is on ISC Licence. We choose MIT for the rest of the project.

SPDX-License-Identifier: ISC OR MIT

react-native-callkeep's People

Contributors

aarkalyk avatar ajnozari avatar aroldogoulart avatar captainjeff avatar chevonc avatar danjenkins avatar dependabot[bot] avatar dtsolis avatar dy93 avatar geraintwhite avatar homersimpsons avatar ianlin avatar jol0712 avatar jonastelzio avatar jorritkeijzer avatar kasperkberg avatar killian90 avatar konradkierus avatar linusu avatar lrorthmann avatar manuquentin avatar mariouzae avatar markgibaud avatar mathias5r avatar maximvoven avatar mrhertal avatar remigijusa avatar sboily avatar vtn-dev-prithipal avatar zxcpoiu avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-native-callkeep's Issues

TypeError: null is not an object (evaluating 'RNCallKeepModule.setAvailable')

I am getting TypeError: null is not an object (evaluating 'RNCallKeepModule.setAvailable'), with remote debugging turn off and TypeError: Cannot read property 'setAvailable' of undefined with remote debugging on.

import RNCallKeep from 'react-native-callkeep';

const App = () => {

  const options = {
    ios: {
      appName: 'My app name',
    },
    android: {
      alertTitle: 'Permissions required',
      alertDescription: 'This application needs to access your phone accounts',
      cancelButton: 'Cancel',
      okButton: 'ok',
    },
  };

  RNCallKeep.setup(options);
  RNCallKeep.setAvailable(true);

  return (
    <Fragment>
      <Text>
        hello
      </Text>
      <Button title="Press Me" />
    </Fragment>
  );
};

No Audio on iOS

"react-native-callkeep": "^2.0.3"
"react-native-webrtc": "^1.75.0"

I am not receiving any audio when I answer an inbound call on iOS (android is fine). I do get the following in the logs.
[RNCallKeep][configureAudioSession] Activating audio session
[RNCallKeep][CXProviderDelegate][provider:didActivateAudioSession]

Starting an android call when app in killed state behaves weirdly

With the update in master, we get the event into the background service and then open up the app from there with the uuid for connection service. If I run startCall I get the connection service UI but I don't get a start call event. I have to assume that the event isn't going to happen and force the call to happen as though I got the start call action.

How did you envisage this working @manuquentin ?

Should the underlying callkeep code show the UI as though you've called startCall ?

Oh looks like this does actually act like this... and I was getting confused due to reloading the RN App inside the app during debugging

Update explanation in readme

I'm looking for a better incoming call-notification than push notifications for a WebRTC videocalling app, when i read the readme it is not immediately clear for me what happens on ios and android when the answer button is pressed?
Will my app be opened with some extra data?
Can we use it with WebRTC (and custom UI) instead of VOIP?
Can it be used when app is not active or in background?

Aside from this., great that someone converted the callkit lib into a cross platform one! I really hate one platform react-native packages or packages that behave completely different on both platforms!

iOS: endCall and endAllCalls not working after second setup

To show incoming call screen we call

  1. RNCallKeep.setup(options)
  2. createNewUdid()
  3. RNCallKeep.displayIncomingCall(getCurrentUuid() .......)

To close incoming call screen we call

  1. RNCallKeep.endCall(getCurrentUuid())

It works great for the first time.

### But -------------------------------------------------------------------------------
when we receive a new call and again do the same flow:

  1. RNCallKeep.setup(options)
  2. createNewUdid()
  3. RNCallKeep.displayIncomingCall(getCurrentUuid() .......)

and when we need to close the incoming call screen by
RNCallKeep.endCall(getCurrentUuid()) it is not working.

  • RNCallKeep.endAllCalls() also not working
  • UUID for displayIncomingCall and for endCall are the same.
  • If we will displayIncomingCall with old UUID endCall will work, but we can't open the app from native incoming call screen, and the app will crash after 5-6 seconds...

Android - answerCall and endCall come with no params to decide which call should be terminated

If your app is able to handle multiple calls, how do you decide which to terminate? Lets say you have an active call and and inbound call.

How do you know which call is being ended? Should we be using

ACTION_HANGUP_CALL and ACTION_REJECT_CALL

https://github.com/hoxfon/react-native-twilio-programmable-voice/blob/master/android/src/main/java/com/hoxfon/react/RNTwilioVoice/CallNotificationManager.java#L31

Feels like I can take a stab at doing the right thing but there will be edge cases where I'm unable to choose which call I should be ending - right?

Or can we get a callId in the event like there is on ios - which would make this like for like

iOS native phone UI is minimizing when the call is accepted

Hi,

I don't know if this is the standard behavior but, when I accept the call on iOS through the native phone screen, it is minimized and it goes to my app screen. I see the native phone UI on the tray. Is there some way to configure to have this call activity screen don't minimize?

Many thanks.

bug: RNCallKeep.endCall(uuid) is not disconnecting the call

I'm integerating my app with react-native-pjsip library and I've used react-native-callkeep for call-kit handeling. When remote user hangup the call then my react-native-pjsip's endpoint method notify me to terminate the call so I'm calling RNCallKeep.endCall(uuid) but it's not disconnecting the call from my screen

Debug: I've thought that maybe RNCallKeep.endCall and RNCallKeep.startCall is getting different uids but after printing out the results it's the same uuid = "cec47dc0-4017-11e9-b085-e3a9fec010a6".

Please let me know If I'm doing anything wrong

@manuquentin can you help me?

can't dismiss the callscreen iOS

I have everything working and the call coming through to my device but when I call RNCallKeep.endCall(callUUID); this doesn't dismiss the native call screen.

I have it wrapped in a timer so if there's no answer after 20seconds the call should stop but it isn't working

Can anyone help?

Update readme

Should the line:

"Tell ConnectionService that the device is ready to accept outgoing calls"

not read:

"Tell ConnectionService that the device is ready to accept incoming calls"?

No sound when using callkit

I got no sound when I answer with callkit. Do you know why this can be?

Everything works if I use
RNCallKeep.startCall(session.ID, "User", 'generic');

But it doesn't work when I answer from native UI
RNCallKeep.displayIncomingCall(session.ID, user.username, user.username, 'generic', isVideoCall);

The problem is related with this actually.
react-native-webrtc/react-native-callkit#45

Sometimes connection keeps long so I want to show users that it is still connecting but when I do that
no one can hear each other. To solve that I am doing disabling & enabling microphone on receiver. Now caller can hear receiver but receiver can't hear caller. Is there a better way to apply this PR?

Can't display start call screen on iOS 12

Hi,
I have set up callkeep for iOS platform but I'm able to see only some screens.
For example I can see Incoming call screen without problems. But when I run this line of code RNCallKeep.startCall('b0074838-a352-11e9-a2a3-2a2ae2dbcce4', '123456789'); I can't see start call screen on the iPhone, moreover, when I set app in background I can see iPhone's status bar in green indicating that there is a call running, but when I click there only open my app and not the callKit screen. There are no errors in Xcode console and the logs are ok.
Could be a phone setup problem? Any clue or tip?

Android Call with dialog empty

On some Samsung devices there is a problem when a default calling account has not been chosen. When a call is made from the Phone app, the call with dialog should show the SIM and the CallKeep app but it is blank.

This has been reproduced on Samsung S9 with Android 9 (but was fixed in a security patch from Samsung) and Samsung Note 9 with Android 9 (no security patch available yet), but works correctly on Samsung S8 with Android 9.

I know this is not a problem with the library and is a Samsung OS issue, but a possible workaround could be checking if a default is set (with telecomManager.getDefaultOutgoingPhoneAccount("tel")) and sending the user to the calling accounts settings (TelecomManager.ACTION_CHANGE_PHONE_ACCOUNTS) for them to set a default.

Screenshot 2019-03-29 at 09 41 03

RNCallKeep.addEventListener() not working.

Hi, guys.
I have tried more times to debug catch events and output result, but all RNCallKeep.addEventListener subscriptions are not working.
Maybe I have some missing configuration?
I am testing TextNow voip services on my phone and mac.
Here is my code.

import React, { Component } from 'react';
import {
  View,
  Dimensions,
  PermissionsAndroid,
  Platform,
  Text,
  TouchableOpacity
} from 'react-native';
import PropTypes from 'prop-types';
import Contacts from 'react-native-contacts';
import Icon from 'react-native-vector-icons/FontAwesome';
import RNCallKeep from 'react-native-callkeep';
import uuid from 'uuid';
import { AppContext, Navbar } from 'app/components';
import styles from './style';

const dm = Dimensions.get('screen');
class MainScreen extends Component {
  constructor(props) {
    super(props);

    this.state = {
      lastCallNumber: ''
    };
    this.currentCallId = null;

    // Initialise RNCallKeep
    const options = {
      ios: {
        appName: 'Nope'
      },
      android: {
        alertTitle: 'Permissions required',
        alertDescription:
          'This application needs to access your phone accounts',
        cancelButton: 'Cancel',
        okButton: 'ok'
      }
    };

    try {
      RNCallKeep.setup(options);
      RNCallKeep.setAvailable(true); // Only used for Android, see doc above.
    } catch (err) {
      console.error('initializeCallKeep error:', err.message);
    }

    // Add RNCallKeep Events
    RNCallKeep.addEventListener('didReceiveStartCallAction', this.onNativeCall);
    RNCallKeep.addEventListener('answerCall', this.onAnswerCallAction);
    RNCallKeep.addEventListener('endCall', this.onEndCallAction);
    RNCallKeep.addEventListener(
      'didDisplayIncomingCall',
      this.onIncomingCallDisplayed
    );
    RNCallKeep.addEventListener(
      'didPerformSetMutedCallAction',
      this.onToggleMute
    );
    RNCallKeep.addEventListener(
      'didActivateAudioSession',
      this.audioSessionActivated
    );
  }

  onNativeCall = ({ handle }) => {
    // Your normal start call action
    alert('call');
    RNCallKeep.startCall(this.getCurrentCallId(), handle);
  };

  onAnswerCallAction = ({ callUUID }) => {
    // called when the user answer the incoming call
  };

  onEndCallAction = ({ callUUID }) => {
    RNCallKeep.endCall(this.getCurrentCallId());

    this.currentCallId = null;
  };

  onIncomingCallDisplayed = (error) => {

    alert('call');
    // You will get this event after RNCallKeep finishes showing incoming call UI
    // You can check if there was an error while displaying
  };

  onToggleMute = (muted) => {
    // Called when the system or the user mutes a call
  };

  audioSessionActivated = (data) => {
    // you might want to do following things when receiving this event:
    // - Start playing ringback if it is an outgoing call
  };

  getCurrentCallId = () => {
    if (!this.currentCallId) {
      this.currentCallId = uuid.v4();
    }

    return this.currentCallId;
  };

  async componentDidMount() {
    this.reload();
    if (Platform.OS === 'android') {
      PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.READ_CONTACTS, {
        title: 'Contacts',
        message: 'This app would like to view your contacts.'
      }).then(() => {
        Contacts.getAll((err, contacts) => {
          if (err === 'denied') {
            // error
            throw err;
          } else {
            // contacts returned in Array
            this.parseContacts(contacts);
          }
        });
      });
    } else {
      Contacts.getAll((err, contacts) => {
        if (err) {
          throw err;
        }
        // contacts returned
     
      });
    }
  }

  reload = async () => {
    await this.context.showLoading();

    this.context.hideLoading();
  };

  leftHandler = () => {
    this.props.navigation.toggleDrawer();
  };

  upVote() {
    alert('Yep!');
  }

  downVote() {
    alert('Nope!');
  }

  render() {
    return (
      <View style={styles.container}>
        <Navbar
          left="ios-menu"
          leftHandler={this.leftHandler}
          title="Dashboard"
        />
        <View style={styles.container}>
          <Text style={styles.title}>Nope</Text>
          <Text style={styles.description}>Please rate the calls below:</Text>
          <View style={styles.box}>
            <Text style={styles.description}>Was this call legit?</Text>
            <Text style={styles.description}>{this.state.lastCallNumber}</Text>
          </View>
          <View style={styles.voteBox}>
            <View style={styles.leftBox}>
              <TouchableOpacity onPress={() => this.upVote()}>
                <Text style={styles.voteTitle}>
                  Yep
                  <Icon name="thumbs-up" size={30} color="grey" />
                </Text>
              </TouchableOpacity>
            </View>
            <View style={styles.rightBox}>
              <TouchableOpacity onPress={() => this.downVote()}>
                <Text style={styles.voteTitle}>
                  Nope!
                  <Icon name="thumbs-down" size={30} color="grey" />
                </Text>
              </TouchableOpacity>
            </View>
          </View>
        </View>
      </View>
    );
  }
}

MainScreen.contextType = AppContext;

MainScreen.propTypes = {
  navigation: PropTypes.object
};

export default MainScreen;

iOS and Android packages are correctly imported and running without any errors.
But can't catch event as I desired.
Thanks.

add ios support for performSetGroupCallAction

Just trying to work out whats needed to utilise the new callkit ios flag in RN-WebRTC 75 and realised we still don't support performSetGroupCallAction

I plan on submitting a PR for it but making the issue so it doesn't get forgotten about

Can only use lower 16 bits for requestCode

Hi Callkeep team,

I'm getting this error on android when running the sample code. I tried to unlink and link the package again, and finally checked everything manually, but it keeps happening.

This error disappears if i manually authorize my app to access the phone (settings -> Apps permissions -> myapp -> permissions -> phone).

Any idea ?

Manu

Screenshot_1557148066

react-native-cli: 2.0.1
react-native: 0.59.5

phone account enable issue

Trying to do
RNCallKeep.displayIncomingCall

but always popup the Permission required,
what's the phone account enable mean?

using ASUS (Android 7.0) dual-sim device with 1 sim-card,

any suggestion? thanks.

Incoming call UI not displaying.

Hi,

I am using this plugin to show incoming video call ui into react-native, I am trying to display a incoming call UI as per document I used this function after installing plugin and linked.

 RNCallKeep.displayIncomingCall(uuid.v4(), '44534534543', 'jaawant','number', true);

I also tried old comments on display incoming call and follow instructions but there was no luck.
I also updated this into RNCallKeep.m file
callUpdate.hasVideo = hasVideo;

Please help me , as it is not showing any error so can't fix it.

Thanks in advance.

Small issue in android auto-linking

Not a big deal, but when running
react-native link react-native-callkeep

We get
import com.wazo.callkeep.RNCallKeepPackage;
instead of
import io.wazo.callkeep.RNCallKeepPackage;
in our MainApplication.java

This prevents from building the app on android.

Incoming call not displaying it's a video call

I have a function that is being called when I get a notification but I can't get it to say Video and not audio. Bellow is the function

onIncomingCall(callUuid) {
   RNCallKeep.displayIncomingCall(callUuid, "Thomas Large", null, true);
}

True is the way the docs tells you how to set it

Can anyone help?

Possibility of self-managed react-native-callkeep, i.e. with "setConnectionProperties(PROPERTY_SELF_MANAGED)"?

UPDATE: This is now a feature request. Can react-native-callkeep be updated so that it can be used with setConnectionProperties(PROPERTY_SELF_MANAGED)?


Our use case is this: we have a cross-platform video chat app that uses opentok-react-native, and we currently use just push notifications to get users to pair with each other (using react-native-onesignal). When our users tap the push notification, they simply get dropped into our app.

We would instead want these video chat requests to look like phone calls. This means that we want the phone-call-esque screen to just act as a glorified push notification (tapping the answer button would trigger the exact same behavior that our push notification currently triggers -- opening the app, nothing more and nothing less).

It seems to me that such a functionality must be possible to do in CallKit and ConnectionService without all the other things that other typical VoIP apps need. For example, requesting the BIND_TELECOM_CONNECTION_SERVICE permission on Android shouldn't be needed, and it would be great to not have to show this to the user. (Or I may be misunderstanding ConnectionService.)

Is it possible to use react-native-callkeep as something like a full-screen push notification that just happens to look like an incoming phone call?

manifest merger error

Just adding callkeep to a project and I'm getting an error

Gradle sync failed: Could not find manifest-merger.jar (com.android.tools.build:manifest-merger:26.0.1).
			Searched in the following locations:
			https://jcenter.bintray.com/com/android/tools/build/manifest-merger/26.0.1/manifest-merger-26.0.1.jar
			Consult IDE log for more details (Help | Show Log) (6s 297ms)
Could not find manifest-merger.jar (com.android.tools.build:manifest-merger:26.0.1).
Searched in the following locations:
    https://jcenter.bintray.com/com/android/tools/build/manifest-merger/26.0.1/manifest-merger-26.0.1.jar

It looks like the latest version available is
https://repo.jfrog.org/artifactory/libs-release-bintray/com/android/tools/build/manifest-merger/25.3.0/

Completely flumoxed as to why this is even happening - I've used callkeep in another projects fine

Android dial from Contacts/Dialer History when app killed

Calling using callkeep integration on android works great when the android app is open. If its closed, it doesn't work. It opens the native GUI for making an outbound call but then gives up.

Tried to look through the logs and figure out whats missing but it doesn't make too much sense to me. Got any pointers?

I'm assuming I need to put another intent filter for MainActivity into AndroidManifest but I'm a JS dev, not a native one

Add an event when the speaker button is pressed

For now when the user change the speaker output, we don't have any event for that.

We need also a method to tell CallKeep to change the speaker button when we change it in the application.

Issue with fresh install of app on android

I've got an issue on a fresh install of the app (or one where i remove the permission to make phone calls)

On fresh install load I get a OS alert asking for permission to make phone calls, I approve and then nothing happens after that.

If I then close the app and restart it, I then get the custom Alert box saying "we need you the phone account", you press ok and it takes you through to the phone accounts settings.

My feeling is that the custom Alert should happen straight after the requested making a phone call permission. I'm going to investigate this a bit today but wanted to make an issue on how to recreate it.

I'm running RNCallKeep.setup within componentDidMount()

should there be a yarn.lock file?

This repo has no dependencies so why is there a yarn lockfile? I feel as though its causing issues with conflicting dependencies but I can't 100% put my finger on it. Anyway..... why the yarn.lock ?

Ability to use react-native-callkeep when app is backgrounded/killed

The react-native-callkeep library works when the app's JS is active (open/backgrounded for Android, open for iOS). However, the react-native-callkeep JS API, as documented in the readme, doesn't work when the app is in the other states (killed for Android, backgrounded/killed for iOS).

Can react-native-callkeep possibly be made to work in those scenarios (i.e. from a push notification via a native notification service, etc.)?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.