This commit modifies the way Linphone reports the calls to CallKit :

- Instead of reporting the Display name inside the remoteHandle of CXCallUpdate it now reports the SIP URI
- The display name is now inserted into localizedCallerName

The benefit of doing this is that is that it enables calling from the Phone Call History, and it is required if tel URI are activated (unless calls are not reported in phone history)

This commit also enables the ability to place calls using Linphone by long pressing tel URIs.
This commit is contained in:
Christophe Deschamps 2020-12-02 01:18:18 +01:00
parent 537cda59aa
commit 43f303fa43
3 changed files with 67 additions and 18 deletions

View file

@ -171,7 +171,7 @@ import AVFoundation
let callInfo = providerDelegate.callInfos[uuid!]
if (callInfo?.declined ?? false) {
// This call was declined.
providerDelegate.reportIncomingCall(call:nil, uuid: uuid!, handle: "Calling", hasVideo: true)
providerDelegate.reportIncomingCall(call:nil, uuid: uuid!, handle: "Calling", hasVideo: true, displayName: callInfo?.displayName ?? "Calling")
providerDelegate.endCall(uuid: uuid!)
}
return
@ -179,21 +179,22 @@ import AVFoundation
let call = CallManager.instance().callByCallId(callId: callId)
if (call != nil) {
let addr = FastAddressBook.displayName(for: call?.remoteAddress?.getCobject) ?? "Unknow"
let displayName = FastAddressBook.displayName(for: call?.remoteAddress?.getCobject) ?? "Unknow"
let video = UIApplication.shared.applicationState == .active && (lc!.videoActivationPolicy?.automaticallyAccept ?? false) && (call!.remoteParams?.videoEnabled ?? false)
displayIncomingCall(call: call, handle: addr, hasVideo: video, callId: callId)
displayIncomingCall(call: call, handle: (call!.remoteAddress?.asStringUriOnly())!, hasVideo: video, callId: callId, displayName: displayName)
} else {
displayIncomingCall(call: nil, handle: "Calling", hasVideo: true, callId: callId)
displayIncomingCall(call: nil, handle: "Calling", hasVideo: true, callId: callId, displayName: "Calling")
}
}
func displayIncomingCall(call:Call?, handle: String, hasVideo: Bool, callId: String) {
func displayIncomingCall(call:Call?, handle: String, hasVideo: Bool, callId: String, displayName:String) {
let uuid = UUID()
let callInfo = CallInfo.newIncomingCallInfo(callId: callId)
providerDelegate.callInfos.updateValue(callInfo, forKey: uuid)
providerDelegate.uuids.updateValue(uuid, forKey: callId)
providerDelegate.reportIncomingCall(call:call, uuid: uuid, handle: handle, hasVideo: hasVideo)
providerDelegate.reportIncomingCall(call:call, uuid: uuid, handle: handle, hasVideo: hasVideo, displayName: displayName)
}
@objc func acceptCall(call: OpaquePointer?, hasVideo:Bool) {
@ -240,11 +241,11 @@ import AVFoundation
if (CallManager.callKitEnabled() && !CallManager.instance().nextCallIsTransfer) {
let uuid = UUID()
let name = FastAddressBook.displayName(for: addr) ?? "unknow"
let handle = CXHandle(type: .generic, value: name)
let handle = CXHandle(type: .generic, value: sAddr.asStringUriOnly())
let startCallAction = CXStartCallAction(call: uuid, handle: handle)
let transaction = CXTransaction(action: startCallAction)
let callInfo = CallInfo.newOutgoingCallInfo(addr: sAddr, isSas: isSas)
let callInfo = CallInfo.newOutgoingCallInfo(addr: sAddr, isSas: isSas, displayName: name)
providerDelegate.callInfos.updateValue(callInfo, forKey: uuid)
providerDelegate.uuids.updateValue(uuid, forKey: "")
@ -406,10 +407,31 @@ import AVFoundation
}
}
}
@objc func performActionWhenCoreIsOn(action: @escaping ()->Void ) {
if (manager.globalState == .On) {
action()
} else {
manager.actionsToPerformOnceWhenCoreIsOn.append(action)
}
}
}
class CoreManagerDelegate: CoreDelegate {
static var speaker_already_enabled : Bool = false
var globalState : GlobalState = .Off
var actionsToPerformOnceWhenCoreIsOn : [(()->Void)] = []
override func onGlobalStateChanged(lc: Core, gstate: GlobalState, message: String) {
if (gstate == .On) {
actionsToPerformOnceWhenCoreIsOn.forEach {
$0()
}
actionsToPerformOnceWhenCoreIsOn.removeAll()
}
globalState = gstate
}
override func onRegistrationStateChanged(lc: Core, cfg: ProxyConfig, cstate: RegistrationState, message: String) {
if lc.proxyConfigList.count == 1 && (cstate == .Failed || cstate == .Cleared){
@ -425,7 +447,7 @@ class CoreManagerDelegate: CoreDelegate {
override func onCallStateChanged(lc: Core, call: Call, cstate: Call.State, message: String) {
let addr = call.remoteAddress;
let address = FastAddressBook.displayName(for: addr?.getCobject) ?? "Unknow"
let displayName = FastAddressBook.displayName(for: addr?.getCobject) ?? "Unknow"
let callLog = call.callLog
let callId = callLog?.callId
let video = UIApplication.shared.applicationState == .active && (lc.videoActivationPolicy?.automaticallyAccept ?? false) && (call.remoteParams?.videoEnabled ?? false)
@ -445,7 +467,7 @@ class CoreManagerDelegate: CoreDelegate {
let uuid = CallManager.instance().providerDelegate.uuids["\(callId!)"]
if (uuid != nil) {
// Tha app is now registered, updated the call already existed.
CallManager.instance().providerDelegate.updateCall(uuid: uuid!, handle: address, hasVideo: video)
CallManager.instance().providerDelegate.updateCall(uuid: uuid!, handle: addr!.asStringUriOnly(), hasVideo: video, displayName: displayName)
let callInfo = CallManager.instance().providerDelegate.callInfos[uuid!]
if (callInfo?.declined ?? false) {
DispatchQueue.main.asyncAfter(deadline: .now()) {try? call.decline(reason: callInfo!.reason)}
@ -454,13 +476,13 @@ class CoreManagerDelegate: CoreDelegate {
CallManager.instance().acceptCall(call: call, hasVideo: video)
}
} else {
CallManager.instance().displayIncomingCall(call: call, handle: address, hasVideo: video, callId: callId!)
CallManager.instance().displayIncomingCall(call: call, handle: addr!.asStringUriOnly(), hasVideo: video, callId: callId!, displayName: displayName)
}
} else if (UIApplication.shared.applicationState != .active) {
// not support callkit , use notif
let content = UNMutableNotificationContent()
content.title = NSLocalizedString("Incoming call", comment: "")
content.body = address
content.body = displayName
content.sound = UNNotificationSound.init(named: UNNotificationSoundName.init("notes_of_the_optimistic.caf"))
content.categoryIdentifier = "call_cat"
content.userInfo = ["CallId" : callId!]
@ -524,7 +546,7 @@ class CoreManagerDelegate: CoreDelegate {
// Configure the notification's payload.
let content = UNMutableNotificationContent()
content.title = NSString.localizedUserNotificationString(forKey: NSLocalizedString("Missed call", comment: ""), arguments: nil)
content.body = NSString.localizedUserNotificationString(forKey: address, arguments: nil)
content.body = NSString.localizedUserNotificationString(forKey: displayName, arguments: nil)
// Deliver the notification.
let request = UNNotificationRequest(identifier: "call_request", content: content, trigger: nil) // Schedule the notification.

View file

@ -31,6 +31,9 @@
#include "LinphoneManager.h"
#include "linphone/linphonecore.h"
#import <Intents/Intents.h>
#import <IntentsUI/IntentsUI.h>
#ifdef USE_CRASHLYTICS
#include "FIRApp.h"
#endif
@ -256,7 +259,6 @@
#ifdef USE_CRASHLYTICS
[FIRApp configure];
#endif
UIApplication *app = [UIApplication sharedApplication];
UIApplicationState state = app.applicationState;
@ -404,11 +406,24 @@
// used for callkit. Called when active video.
- (BOOL)application:(UIApplication *)application continueUserActivity:(nonnull NSUserActivity *)userActivity restorationHandler:(nonnull void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler
{
if ([userActivity.activityType isEqualToString:@"INStartVideoCallIntent"]) {
LOGI(@"CallKit: satrt video.");
CallView *view = VIEW(CallView);
[view.videoButton setOn];
}
if ([userActivity.activityType isEqualToString:@"INStartAudioCallIntent"]) { // tel URI handler.
INInteraction *interaction = userActivity.interaction;
INStartAudioCallIntent *startAudioCallIntent = (INStartAudioCallIntent *)interaction.intent;
INPerson *contact = startAudioCallIntent.contacts[0];
INPersonHandle *personHandle = contact.personHandle;
[CallManager.instance performActionWhenCoreIsOnAction:^(void) {
[LinphoneManager.instance call: [LinphoneUtils normalizeSipOrPhoneAddress:personHandle.value]];
}];
}
return YES;
}

View file

@ -33,6 +33,7 @@ import os
var declined = false
var connected = false
var reason: Reason = Reason.None
var displayName: String?
static func newIncomingCallInfo(callId: String) -> CallInfo {
let callInfo = CallInfo()
@ -40,11 +41,12 @@ import os
return callInfo
}
static func newOutgoingCallInfo(addr: Address, isSas: Bool) -> CallInfo {
static func newOutgoingCallInfo(addr: Address, isSas: Bool, displayName: String) -> CallInfo {
let callInfo = CallInfo()
callInfo.isOutgoing = true
callInfo.sasEnabled = isSas
callInfo.toAddr = addr
callInfo.displayName = displayName
return callInfo
}
}
@ -68,7 +70,7 @@ class ProviderDelegate: NSObject {
providerConfiguration.ringtoneSound = "notes_of_the_optimistic.caf"
providerConfiguration.supportsVideo = true
providerConfiguration.iconTemplateImageData = UIImage(named: "callkit_logo")?.pngData()
providerConfiguration.supportedHandleTypes = [.generic]
providerConfiguration.supportedHandleTypes = [.generic, .phoneNumber, .emailAddress]
providerConfiguration.maximumCallsPerCallGroup = 10
providerConfiguration.maximumCallGroups = 2
@ -79,10 +81,11 @@ class ProviderDelegate: NSObject {
return providerConfiguration
}()
func reportIncomingCall(call:Call?, uuid: UUID, handle: String, hasVideo: Bool) {
func reportIncomingCall(call:Call?, uuid: UUID, handle: String, hasVideo: Bool, displayName:String) {
let update = CXCallUpdate()
update.remoteHandle = CXHandle(type:.generic, value: handle)
update.hasVideo = hasVideo
update.localizedCallerName = displayName
let callInfo = callInfos[uuid]
let callId = callInfo?.callId
@ -112,9 +115,10 @@ class ProviderDelegate: NSObject {
}
}
func updateCall(uuid: UUID, handle: String, hasVideo: Bool = false) {
func updateCall(uuid: UUID, handle: String, hasVideo: Bool = false, displayName:String) {
let update = CXCallUpdate()
update.remoteHandle = CXHandle(type:.generic, value:handle)
update.localizedCallerName = displayName
update.hasVideo = hasVideo
provider.reportCall(with:uuid, updated:update);
}
@ -221,9 +225,17 @@ extension ProviderDelegate: CXProviderDelegate {
}
func provider(_ provider: CXProvider, perform action: CXStartCallAction) {
do {
let uuid = action.callUUID
let callInfo = callInfos[uuid]
let update = CXCallUpdate()
update.remoteHandle = action.handle
update.localizedCallerName = callInfo?.displayName
self.provider.reportCall(with: action.callUUID, updated: update)
let addr = callInfo?.toAddr
if (addr == nil) {
Log.directLog(BCTBX_LOG_ERROR, text: "CallKit: can not call a null address!")