Change incoming call detection, use push notification instead. TODO : use appropriate certificate (currently recycling the one from linphone-swift-tutorial app)

This commit is contained in:
QuentinArguillere
2020-08-10 16:40:24 +02:00
parent b0b6f29e99
commit 9974108511
6 changed files with 107 additions and 61 deletions

View File

@@ -29,6 +29,7 @@
6604166224D451F40064FC6C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
6604166424D451F40064FC6C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
6604166A24D453240064FC6C /* CallExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallExample.swift; sourceTree = "<group>"; };
66A3B37A24E138ED00E94540 /* CallTutorial.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = CallTutorial.entitlements; sourceTree = "<group>"; };
66B14FBA24DAF68E0041952F /* CallKitProviderDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallKitProviderDelegate.swift; sourceTree = "<group>"; };
79CE65CD0070AF94E21BFCE7 /* Pods-CallTutorial.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CallTutorial.debug.xcconfig"; path = "Target Support Files/Pods-CallTutorial/Pods-CallTutorial.debug.xcconfig"; sourceTree = "<group>"; };
C26219FCE26251F1C3C2E96E /* Pods-CallTutorial.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CallTutorial.release.xcconfig"; path = "Target Support Files/Pods-CallTutorial/Pods-CallTutorial.release.xcconfig"; sourceTree = "<group>"; };
@@ -84,6 +85,7 @@
6604165524D451F10064FC6C /* CallTutorial */ = {
isa = PBXGroup;
children = (
66A3B37A24E138ED00E94540 /* CallTutorial.entitlements */,
6604165624D451F10064FC6C /* AppDelegate.swift */,
6604165824D451F10064FC6C /* SceneDelegate.swift */,
66B14FBA24DAF68E0041952F /* CallKitProviderDelegate.swift */,
@@ -361,6 +363,7 @@
baseConfigurationReference = 79CE65CD0070AF94E21BFCE7 /* Pods-CallTutorial.debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = CallTutorial/CallTutorial.entitlements;
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_ASSET_PATHS = "\"CallTutorial/Preview Content\"";
DEVELOPMENT_TEAM = Z2V957B3D6;
@@ -370,7 +373,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = BC.CallTutorial;
PRODUCT_BUNDLE_IDENTIFIER = com.belledonne.Wtest;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
@@ -382,6 +385,7 @@
baseConfigurationReference = C26219FCE26251F1C3C2E96E /* Pods-CallTutorial.release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = CallTutorial/CallTutorial.entitlements;
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_ASSET_PATHS = "\"CallTutorial/Preview Content\"";
DEVELOPMENT_TEAM = Z2V957B3D6;
@@ -391,7 +395,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = BC.CallTutorial;
PRODUCT_BUNDLE_IDENTIFIER = com.belledonne.Wtest;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";

View File

@@ -22,8 +22,10 @@ class CallExampleContext : ObservableObject
/*------------ Call tutorial related variables ---------------*/
let mCallStateTracer = CallStateDelegate()
var mCall: Call!
var proxy_cfg : ProxyConfig!
var mVideoDevices : [String] = []
var mUsedVideoDeviceId : Int = 0
var callAlreadyStopped = false;
@Published var audioEnabled : Bool = true
@Published var videoEnabled : Bool = false
@@ -41,10 +43,9 @@ class CallExampleContext : ObservableObject
let outgoingCallName = "Outgoing call example"
let incomingCallName = "Incoming call example"
@Published var enableCallKit = false;
init()
{
mProviderDelegate = CallKitProviderDelegate(context : self)
mCallStateTracer.tutorialContext = self
mRegistrationDelegate.tutorialContext = self
@@ -63,6 +64,7 @@ class CallExampleContext : ObservableObject
// main loop for receiving notifications and doing background linphonecore work:
mCore.autoIterateEnabled = true
mCore.callkitEnabled = true
mCore.pushNotificationEnabled = true
try? mCore.start()
mVideoDevices = mCore.videoDevicesList
@@ -70,14 +72,13 @@ class CallExampleContext : ObservableObject
mCore.addDelegate(delegate: mCallStateTracer)
mCore.addDelegate(delegate: mRegistrationDelegate)
mProviderDelegate = CallKitProviderDelegate(context : self)
}
func registrationExample()
{
let factory = Factory.Instance
do {
let proxy_cfg = try mCore.createProxyConfig()
proxy_cfg = try mCore.createProxyConfig()
let address = try factory.createAddress(addr: id)
let info = try factory.createAuthInfo(username: address.username, userid: "", passwd: passwd, ha1: "", realm: "", domain: address.domain)
mCore.addAuthInfo(info: info)
@@ -122,6 +123,7 @@ class CallExampleContext : ObservableObject
print("Could not place call to \(dest)\n")
} else {
print("Call to \(dest) is in progress...")
mProviderDelegate.outgoingCallUUID = UUID()
}
}
else
@@ -139,20 +141,10 @@ class CallExampleContext : ObservableObject
{
if ((callRunning || isCallIncoming) && mCall.state != Call.State.End)
{
callAlreadyStopped = true;
// terminate the call
print("Terminating the call...\n")
do {
if (enableCallKit)
{
mProviderDelegate.stopCall()
}
else
{
try mCall.terminate()
}
} catch {
print(error)
}
mProviderDelegate.stopCall()
}
}
@@ -200,6 +192,10 @@ class LinphoneRegistrationDelegate: CoreDelegate {
print("New registration state \(cstate) for user id \( String(describing: cfg.identityAddress?.asString()))\n")
if (cstate == .Ok)
{
if (!tutorialContext.loggedIn)
{
tutorialContext.mProviderDelegate.registerForVoIPPushes()
}
tutorialContext.loggedIn = true
}
}
@@ -230,29 +226,27 @@ class CallStateDelegate: CoreDelegate {
// We're being called by someone
tutorialContext.mCall = call
tutorialContext.isCallIncoming = true
if (tutorialContext.enableCallKit)
{
// Report the incoming call for CallKit
tutorialContext.mProviderDelegate.incomingCall()
}
} else if (cstate == .OutgoingRinging) {
// We're calling someone
tutorialContext.callRunning = true
} else if (cstate == .End) {
// Call has been terminated by any side
tutorialContext.callRunning = false
tutorialContext.isCallIncoming = false;
if (tutorialContext.enableCallKit)
if (!tutorialContext.callAlreadyStopped)
{
// Report to CallKit that the call is over
tutorialContext.mProviderDelegate.stopCall()
tutorialContext.callAlreadyStopped = false
}
tutorialContext.callRunning = false
tutorialContext.isCallIncoming = false
} else if (cstate == .StreamsRunning)
{
// Call has successfully began
tutorialContext.callRunning = true
tutorialContext.isCallIncoming = false
} else if (cstate == .PushIncomingReceived)
{
print("PushTrace -- push incoming")
}
}
}

View File

@@ -8,12 +8,14 @@
import Foundation
import CallKit
import PushKit
import linphonesw
import AVFoundation
class CallKitProviderDelegate : NSObject
{
private var voipRegistry: PKPushRegistry!
private let provider: CXProvider
let mCallController = CXCallController()
var tutorialContext : CallExampleContext!
@@ -53,16 +55,30 @@ class CallKitProviderDelegate : NSObject
let startCallAction = CXStartCallAction(call: outgoingCallUUID, handle: handle)
let transaction = CXTransaction(action: startCallAction)
provider.reportOutgoingCall(with: outgoingCallUUID, connectedAt: nil)
mCallController.request(transaction, completion: { error in })
}
func stopCall()
{
let endCallAction = CXEndCallAction(call: incomingCallUUID)
var callId = UUID();
if (tutorialContext.isCallIncoming) {
callId = incomingCallUUID
} else if (tutorialContext.callRunning) {
callId = outgoingCallUUID
}
let endCallAction = CXEndCallAction(call: callId)
let transaction = CXTransaction(action: endCallAction)
mCallController.request(transaction, completion: { error in })
}
func registerForVoIPPushes() {
voipRegistry = PKPushRegistry(queue: nil)
voipRegistry.delegate = self
voipRegistry.desiredPushTypes = [PKPushType.voIP]
}
}
@@ -116,3 +132,40 @@ extension CallKitProviderDelegate: CXProviderDelegate {
tutorialContext.mCore.activateAudioSession(actived: false)
}
}
extension CallKitProviderDelegate: PKPushRegistryDelegate {
func pushRegistry(_ registry: PKPushRegistry, didUpdate pushCredentials: PKPushCredentials, for type: PKPushType) {
print("PushTrace -- pushRegistry 1")
/*
let deviceTokenString = pushCredentials.token.map { String(format: "%02x", $0) }.joined() /*convert push tocken into hex string to be compliant with flexisip format*/
let aStr = String(format: "pn-provider=apns.dev;pn-prid=%@:voip;pn-param=Z2V957B3D6.org.linphone.tutorials.callkit.voip"
,deviceTokenString)
*/
let deviceTokenString = pushCredentials.token.map { String(format: "%02x", $0) }.joined() /*convert push tocken into hex string to be compliant with flexisip format*/
let aStr = String(format: "pn-provider=apns.dev;pn-prid=%@:voip;pn-param=Z2V957B3D6.com.belledonne.Wtest.voip"
,deviceTokenString)
tutorialContext.proxy_cfg.edit()
tutorialContext.proxy_cfg.pushNotificationAllowed = true
tutorialContext.proxy_cfg.contactUriParameters = aStr
do {
try tutorialContext.proxy_cfg.done()
} catch {
print(error)
}
}
func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType, completion: @escaping () -> Void) {
print("PushTrace -- pushRegistry 2")
incomingCall();
}
func pushRegistry(_ registry: PKPushRegistry, didInvalidatePushTokenFor: PKPushType)
{
print("PushTrace -- pushRegistry 3")
}
}

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>aps-environment</key>
<string>development</string>
</dict>
</plist>

View File

@@ -14,12 +14,12 @@ struct ContentView: View {
func getCallButtonText() -> String
{
if (tutorialContext.isCallIncoming) {
return "Answer"
}
else if (tutorialContext.callRunning) {
if (tutorialContext.callRunning) {
return "Update Call"
}
else if (tutorialContext.isCallIncoming) {
return "Answer"
}
else {
return "Call"
}
@@ -27,12 +27,12 @@ struct ContentView: View {
func callStateString() -> String
{
if (tutorialContext.isCallIncoming) {
return "Incoming call"
}
else if (tutorialContext.callRunning) {
if (tutorialContext.callRunning) {
return "Call running"
}
else if (tutorialContext.isCallIncoming) {
return "Incoming call"
}
else {
return "No Call"
}
@@ -64,7 +64,7 @@ struct ContentView: View {
}
Text("Login State : ")
.font(.footnote)
Text(tutorialContext.loggedIn ? "Looged in" : "Unregistered")
Text(tutorialContext.loggedIn ? "Logged in" : "Unregistered")
.font(.footnote)
.foregroundColor(tutorialContext.loggedIn ? Color.green : Color.black)
}
@@ -116,7 +116,7 @@ struct ContentView: View {
self.tutorialContext.acceptCall()
}
else {
self.tutorialContext.outgoingCallExample()
self.tutorialContext.mProviderDelegate.outgoingCall()
}
})
{
@@ -141,19 +141,6 @@ struct ContentView: View {
}
.padding(.top)
}
VStack(alignment: .leading) {
Button(action: tutorialContext.mProviderDelegate.outgoingCall) {
Text("CallKit Call")
.font(.largeTitle)
.foregroundColor(Color.white)
.frame(width: 180.0, height: 42.0)
.background(Color.green)
}
Toggle(isOn: $tutorialContext.enableCallKit) {
Text("CallKit incoming Call detection")
}.frame(width : 290.0)
}.padding(.top, 10.0)
Spacer()
Group {
Toggle(isOn: $tutorialContext.logsEnabled) {

View File

@@ -2,16 +2,6 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>UIBackgroundModes</key>
<array>
<string>voip</string>
</array>
<key>NSCameraUsageDescription</key>
<string>Camera access</string>
<key>NSMicrophoneUsageDescription</key>
<string>Microphone access</string>
<key>LSApplicationCategoryType</key>
<string></string>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
@@ -28,8 +18,14 @@
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSApplicationCategoryType</key>
<string></string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSCameraUsageDescription</key>
<string>Camera access</string>
<key>NSMicrophoneUsageDescription</key>
<string>Microphone access</string>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
@@ -47,6 +43,10 @@
</array>
</dict>
</dict>
<key>UIBackgroundModes</key>
<array>
<string>voip</string>
</array>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIRequiredDeviceCapabilities</key>