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:
@@ -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";
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
@@ -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) {
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user