diff --git a/Bridging-Header.h b/Bridging-Header.h new file mode 100644 index 0000000..69d4759 --- /dev/null +++ b/Bridging-Header.h @@ -0,0 +1,14 @@ +// +// Bridging-Header.h +// ZDKDemo +// +// Copyright © 2019 Securax. All rights reserved. +// + +#ifndef Bridging_Header_h +#define Bridging_Header_h + +#import +#import + +#endif /* Bridging_Header_h */ diff --git a/README b/README new file mode 100644 index 0000000..ab49508 --- /dev/null +++ b/README @@ -0,0 +1,2 @@ +zdk.objc.framework MUST be placed in current folder! + diff --git a/ZDKDemo.xcodeproj/project.pbxproj b/ZDKDemo.xcodeproj/project.pbxproj new file mode 100644 index 0000000..5182507 --- /dev/null +++ b/ZDKDemo.xcodeproj/project.pbxproj @@ -0,0 +1,389 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 50; + objects = { + +/* Begin PBXBuildFile section */ + 2F3A69D522B8DBD00035DC4B /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F3A69D422B8DBD00035DC4B /* AppDelegate.swift */; }; + 2F3A69D722B8DBD00035DC4B /* AccountViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F3A69D622B8DBD00035DC4B /* AccountViewController.swift */; }; + 2F3A69D922B8DBD00035DC4B /* CallViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F3A69D822B8DBD00035DC4B /* CallViewController.swift */; }; + 2F3A69DC22B8DBD00035DC4B /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 2F3A69DA22B8DBD00035DC4B /* Main.storyboard */; }; + 2F3A69DE22B8DBD10035DC4B /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2F3A69DD22B8DBD10035DC4B /* Assets.xcassets */; }; + 2F3A69E122B8DBD10035DC4B /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 2F3A69DF22B8DBD10035DC4B /* LaunchScreen.storyboard */; }; + 2F3A69E922B8DCC00035DC4B /* zdk.objc.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2F3A69E822B8DCC00035DC4B /* zdk.objc.framework */; }; + 2F3A69EA22B8DCC00035DC4B /* zdk.objc.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 2F3A69E822B8DCC00035DC4B /* zdk.objc.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 2F3A69EF22BBB6040035DC4B /* ContextManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F3A69EE22BBB6040035DC4B /* ContextManager.swift */; }; + 2F84D1A222F0581300580002 /* AppLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F84D1A122F0581300580002 /* AppLogger.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 2F3A69EB22B8DCC10035DC4B /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 2F3A69EA22B8DCC00035DC4B /* zdk.objc.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 2F3A69D122B8DBD00035DC4B /* ZDKDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ZDKDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 2F3A69D422B8DBD00035DC4B /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 2F3A69D622B8DBD00035DC4B /* AccountViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountViewController.swift; sourceTree = ""; }; + 2F3A69D822B8DBD00035DC4B /* CallViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallViewController.swift; sourceTree = ""; }; + 2F3A69DB22B8DBD00035DC4B /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 2F3A69DD22B8DBD10035DC4B /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 2F3A69E022B8DBD10035DC4B /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 2F3A69E222B8DBD10035DC4B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 2F3A69E822B8DCC00035DC4B /* zdk.objc.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = zdk.objc.framework; sourceTree = ""; }; + 2F3A69ED22BA23320035DC4B /* Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Bridging-Header.h"; sourceTree = SOURCE_ROOT; }; + 2F3A69EE22BBB6040035DC4B /* ContextManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContextManager.swift; sourceTree = ""; }; + 2F84D1A122F0581300580002 /* AppLogger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLogger.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 2F3A69CE22B8DBD00035DC4B /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 2F3A69E922B8DCC00035DC4B /* zdk.objc.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 2F3A69C822B8DBD00035DC4B = { + isa = PBXGroup; + children = ( + 2F3A69E822B8DCC00035DC4B /* zdk.objc.framework */, + 2F3A69D322B8DBD00035DC4B /* ZDKDemo */, + 2F3A69D222B8DBD00035DC4B /* Products */, + ); + sourceTree = ""; + }; + 2F3A69D222B8DBD00035DC4B /* Products */ = { + isa = PBXGroup; + children = ( + 2F3A69D122B8DBD00035DC4B /* ZDKDemo.app */, + ); + name = Products; + sourceTree = ""; + }; + 2F3A69D322B8DBD00035DC4B /* ZDKDemo */ = { + isa = PBXGroup; + children = ( + 2F3A69D622B8DBD00035DC4B /* AccountViewController.swift */, + 2F3A69D422B8DBD00035DC4B /* AppDelegate.swift */, + 2F84D1A122F0581300580002 /* AppLogger.swift */, + 2F3A69EE22BBB6040035DC4B /* ContextManager.swift */, + 2F3A69D822B8DBD00035DC4B /* CallViewController.swift */, + 2F3A69DA22B8DBD00035DC4B /* Main.storyboard */, + 2F3A69DD22B8DBD10035DC4B /* Assets.xcassets */, + 2F3A69ED22BA23320035DC4B /* Bridging-Header.h */, + 2F3A69DF22B8DBD10035DC4B /* LaunchScreen.storyboard */, + 2F3A69E222B8DBD10035DC4B /* Info.plist */, + ); + path = ZDKDemo; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 2F3A69D022B8DBD00035DC4B /* ZDKDemo */ = { + isa = PBXNativeTarget; + buildConfigurationList = 2F3A69E522B8DBD10035DC4B /* Build configuration list for PBXNativeTarget "ZDKDemo" */; + buildPhases = ( + 2F3A69CD22B8DBD00035DC4B /* Sources */, + 2F3A69CE22B8DBD00035DC4B /* Frameworks */, + 2F3A69CF22B8DBD00035DC4B /* Resources */, + 2F3A69EB22B8DCC10035DC4B /* Embed Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = ZDKDemo; + productName = ZDKDemo; + productReference = 2F3A69D122B8DBD00035DC4B /* ZDKDemo.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 2F3A69C922B8DBD00035DC4B /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 1020; + LastUpgradeCheck = 1020; + ORGANIZATIONNAME = petyo; + TargetAttributes = { + 2F3A69D022B8DBD00035DC4B = { + CreatedOnToolsVersion = 10.2; + }; + }; + }; + buildConfigurationList = 2F3A69CC22B8DBD00035DC4B /* Build configuration list for PBXProject "ZDKDemo" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 2F3A69C822B8DBD00035DC4B; + productRefGroup = 2F3A69D222B8DBD00035DC4B /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 2F3A69D022B8DBD00035DC4B /* ZDKDemo */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 2F3A69CF22B8DBD00035DC4B /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 2F3A69E122B8DBD10035DC4B /* LaunchScreen.storyboard in Resources */, + 2F3A69DE22B8DBD10035DC4B /* Assets.xcassets in Resources */, + 2F3A69DC22B8DBD00035DC4B /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 2F3A69CD22B8DBD00035DC4B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 2F3A69D922B8DBD00035DC4B /* CallViewController.swift in Sources */, + 2F84D1A222F0581300580002 /* AppLogger.swift in Sources */, + 2F3A69D522B8DBD00035DC4B /* AppDelegate.swift in Sources */, + 2F3A69D722B8DBD00035DC4B /* AccountViewController.swift in Sources */, + 2F3A69EF22BBB6040035DC4B /* ContextManager.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 2F3A69DA22B8DBD00035DC4B /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 2F3A69DB22B8DBD00035DC4B /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 2F3A69DF22B8DBD10035DC4B /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 2F3A69E022B8DBD10035DC4B /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 2F3A69E322B8DBD10035DC4B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.2; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 2F3A69E422B8DBD10035DC4B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.2; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 2F3A69E622B8DBD10035DC4B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = 8923WVMRDE; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + ); + INFOPLIST_FILE = ZDKDemo/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.zoiper.zdkemo; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Bridging-Header.h"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 2F3A69E722B8DBD10035DC4B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = 8923WVMRDE; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + ); + INFOPLIST_FILE = ZDKDemo/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.zoiper.zdkemo; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Bridging-Header.h"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 2F3A69CC22B8DBD00035DC4B /* Build configuration list for PBXProject "ZDKDemo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 2F3A69E322B8DBD10035DC4B /* Debug */, + 2F3A69E422B8DBD10035DC4B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 2F3A69E522B8DBD10035DC4B /* Build configuration list for PBXNativeTarget "ZDKDemo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 2F3A69E622B8DBD10035DC4B /* Debug */, + 2F3A69E722B8DBD10035DC4B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 2F3A69C922B8DBD00035DC4B /* Project object */; +} diff --git a/ZDKDemo/AccountViewController.swift b/ZDKDemo/AccountViewController.swift new file mode 100644 index 0000000..59bf61d --- /dev/null +++ b/ZDKDemo/AccountViewController.swift @@ -0,0 +1,109 @@ +// +// FirstViewController.swift +// ZDKDemo +// +// Copyright © 2019 Securax. All rights reserved. +// + +import UIKit + +var accountViewController : AccountViewController? + +class AccountViewController: UIViewController, UITextFieldDelegate { + + @IBOutlet weak var activationUsername: UITextField? + @IBOutlet weak var activationPassword: UITextField? + + @IBOutlet weak var accountDomain: UITextField? + @IBOutlet weak var accountUsername: UITextField? + @IBOutlet weak var accountPassword: UITextField? + + @IBOutlet weak var btnRegister: UIButton? + + override func viewDidLoad() { + super.viewDidLoad() + // Do any additional setup after loading the view. + + accountViewController = self + } + + func textFieldShouldReturn(_ textField: UITextField) -> Bool { + self.view.endEditing(true) + return false + } + + @objc + func changeRegisterButtonTitleTo(_ title: String) { + print("New (register) button title: '\(title)'") + btnRegister?.setTitle(title, for: .normal) + btnRegister?.setTitle(title, for: .highlighted) + btnRegister?.setTitle(title, for: .selected) + btnRegister?.setTitle(title, for: .disabled) + } + + @IBAction func activateTapped(_ sender: Any) { + guard activationUsername != nil else { + print("Activation user name text field is nil.") + return + } + + guard activationPassword != nil else { + print("Activation password text field is nil.") + return + } + + if activationUsername!.text!.count == 0 || activationPassword!.text!.count == 0 { + let alert = UIAlertController(title: "Error", message: "Empty user name and/or password.", preferredStyle: .alert) + let OKAction = UIAlertAction(title: "OK", style: .default) { (action) in + return + } + alert.addAction(OKAction) + self.present(alert, animated: true, completion: nil) + return + } + + let appDelegate = UIApplication.shared.delegate as! AppDelegate + appDelegate.contextManager.activateZDK(zdkVersion, withUserName: activationUsername!.text!, andPassword: activationPassword!.text!) + } + + @IBAction func registerTapped(_ sender: AnyObject) { + let appDelegate = UIApplication.shared.delegate as! AppDelegate + if !appDelegate.contextManager.context.activation.activated { + let alert = UIAlertController(title: "Error", message: "ZDK is not activated.", preferredStyle: .alert) + let OKAction = UIAlertAction(title: "OK", style: .default) { (action) in + return + } + alert.addAction(OKAction) + self.present(alert, animated: true, completion: nil) + return + } + + guard accountDomain != nil else { + print("Account domain text field is nil.") + return + } + + guard accountUsername != nil else { + print("Account user name text field is nil.") + return + } + + guard accountPassword != nil else { + print("Account password text field is nil.") + return + } + + if accountDomain!.text!.count == 0 || accountUsername!.text!.count == 0 || accountPassword!.text!.count == 0 { + let alert = UIAlertController(title: "Error", message: "Some fields are not filled in.", preferredStyle: .alert) + let OKAction = UIAlertAction(title: "OK", style: .default) { (action) in + return + } + alert.addAction(OKAction) + self.present(alert, animated: true, completion: nil) + return + } + + appDelegate.contextManager.registerAccountWithDomain(accountDomain!.text!, username: accountUsername!.text!, andPassword: accountPassword!.text!) + } +} + diff --git a/ZDKDemo/AppDelegate.swift b/ZDKDemo/AppDelegate.swift new file mode 100644 index 0000000..be5af70 --- /dev/null +++ b/ZDKDemo/AppDelegate.swift @@ -0,0 +1,47 @@ +// +// AppDelegate.swift +// ZDKDemo +// +// Copyright © 2019 Securax. All rights reserved. +// + +import UIKit + +let appLogger = AppLogger() + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + + var window: UIWindow? + let contextManager = ContextManager() + + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + appLogger.startLog() + + return true + } + + func applicationWillResignActive(_ application: UIApplication) { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. + } + + func applicationDidEnterBackground(_ application: UIApplication) { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. + } + + func applicationWillEnterForeground(_ application: UIApplication) { + // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. + } + + func applicationDidBecomeActive(_ application: UIApplication) { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. + } + + func applicationWillTerminate(_ application: UIApplication) { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. + } + +} diff --git a/ZDKDemo/AppLogger.swift b/ZDKDemo/AppLogger.swift new file mode 100644 index 0000000..6fee316 --- /dev/null +++ b/ZDKDemo/AppLogger.swift @@ -0,0 +1,155 @@ +// +// AppLogger.swift +// ZDKDemo +// +// Copyright © 2019 petyo. All rights reserved. +// + +import Foundation +import UIKit + +private struct FacilityKeys { + static let Unknown = "iOS:Unknown" + static let Library = "iOS:Library" + static let ZDK = "iOS:ZDK" + static let UI = "iOS:UI" + static let Network = "iOS:Network" + static let Provisioning = "iOS:Provisioning" + static let Softphone = "iOS:Softphone" + static let Audio = "iOS:Audio" + static let Configuration = "iOS:Configuration" + static let Contacts = "iOS:Contacts" + static let Utility = "iOS:Utility" + static let Persistence = "iOS:Persistence" +} + +extension ZDKLoggingFacility { + public var description: String { + get { + switch self { + case .lf_Library: + return FacilityKeys.Library + case .lf_ZDK: + return FacilityKeys.ZDK + case .lf_UI: + return FacilityKeys.UI + case .lf_Network: + return FacilityKeys.Network + case .lf_Provisioning: + return FacilityKeys.Provisioning + case .lf_Softphone: + return FacilityKeys.Softphone + case .lf_Audio: + return FacilityKeys.Audio + case .lf_Configuration: + return FacilityKeys.Configuration + case .lf_Contacts: + return FacilityKeys.Contacts + case .lf_Utility: + return FacilityKeys.Utility + case .lf_Persistence: + return FacilityKeys.Persistence + default: + return FacilityKeys.Unknown + } + } + } +} + +class AppLogger: NSObject { + private let logger: ZDKLog = HelperFactory.sharedInstance().log + private var fileIsOpen = false + private var maxLevel: ZDKLoggingLevel = .ll_Debug + + var outputToConsole: Bool = true + + private func serviceInfo() -> String { + + let versionNumber = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as! String + let buildNumber = Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") as! String + let iosVersion = UIDevice.current.systemVersion + var utsStruct = utsname() + let deviceVersion = uname(&utsStruct) == 0 ? String(cString: &utsStruct.machine.0, encoding: String.Encoding.utf8)! + : "Unknown" + + let appDelegate = UIApplication.shared.delegate as! AppDelegate + + var info = "\n\nZDKDemo \(versionNumber).\(buildNumber) for iOS\n" + info.append("Library revision: \(appDelegate.contextManager.context.libraryVersion), iOS version: \(iosVersion), Device: \(deviceVersion)\n\n") + + return info + } + + @discardableResult + func startLog(_ path: String = documentsDirPath, maxLevel: ZDKLoggingLevel = .ll_Debug) -> Int { + let path = path + "ZDKDemo-log.txt" + + let result = logger.logOpen(path, + oldFileName: nil, + maxLevel: maxLevel, + maxSizeBytes: 0) + + if result.code == .rc_Ok { + self.maxLevel = maxLevel + fileIsOpen = true + logDebug(.lf_UI, message: serviceInfo()) + } else { + print("Failed to start debug log, code: \(result.code.rawValue)") + } + + return Int(result.code.rawValue) + } + + func log(level: ZDKLoggingLevel, facility: ZDKLoggingFacility, message: String, sourceFileName: String = #file, sourceLine: Int = #line) { + guard level.rawValue <= maxLevel.rawValue else { + return + } + + if fileIsOpen { + logger.logMessage(level, + facility: facility, + facilityName: facility.description, + sourceFileName: sourceFileName, + sourceLine: Int32(sourceLine), + message: message) + } + + if outputToConsole && logger.shouldLogFacility(facility) { + print("\n\(facility): \(message)") + } + } +} + +extension AppLogger { + func logDebug(_ facility: ZDKLoggingFacility, message: String, sourceFileName: String = #file, sourceLine: Int = #line) { + log(level: .ll_Debug, + facility: facility, + message: message, + sourceFileName: sourceFileName, + sourceLine: sourceLine) + } + + func logWarning(_ facility: ZDKLoggingFacility, message: String, sourceFileName: String = #file, sourceLine: Int = #line) { + log(level: .ll_Warning, + facility: facility, + message: message, + sourceFileName: sourceFileName, + sourceLine: sourceLine) + } + + func logError(_ facility: ZDKLoggingFacility, message: String, sourceFileName: String = #file, sourceLine: Int = #line) { + log(level: .ll_Error, + facility: facility, + message: message, + sourceFileName: sourceFileName, + sourceLine: sourceLine) + } + + func logInfo(_ facility: ZDKLoggingFacility, message: String, sourceFileName: String = #file, sourceLine: Int = #line) { + log(level: .ll_Info, + facility: facility, + message: message, + sourceFileName: sourceFileName, + sourceLine: sourceLine) + } +} diff --git a/ZDKDemo/Assets.xcassets/AppIcon.appiconset/Contents.json b/ZDKDemo/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..d8db8d6 --- /dev/null +++ b/ZDKDemo/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,98 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + }, + { + "idiom" : "ios-marketing", + "size" : "1024x1024", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/ZDKDemo/Assets.xcassets/Contents.json b/ZDKDemo/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/ZDKDemo/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/ZDKDemo/Assets.xcassets/first.imageset/Contents.json b/ZDKDemo/Assets.xcassets/first.imageset/Contents.json new file mode 100644 index 0000000..33a7451 --- /dev/null +++ b/ZDKDemo/Assets.xcassets/first.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "first.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/ZDKDemo/Assets.xcassets/first.imageset/first.pdf b/ZDKDemo/Assets.xcassets/first.imageset/first.pdf new file mode 100644 index 0000000..47d911d Binary files /dev/null and b/ZDKDemo/Assets.xcassets/first.imageset/first.pdf differ diff --git a/ZDKDemo/Assets.xcassets/second.imageset/Contents.json b/ZDKDemo/Assets.xcassets/second.imageset/Contents.json new file mode 100644 index 0000000..03bd9c9 --- /dev/null +++ b/ZDKDemo/Assets.xcassets/second.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "second.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/ZDKDemo/Assets.xcassets/second.imageset/second.pdf b/ZDKDemo/Assets.xcassets/second.imageset/second.pdf new file mode 100644 index 0000000..401614e Binary files /dev/null and b/ZDKDemo/Assets.xcassets/second.imageset/second.pdf differ diff --git a/ZDKDemo/Base.lproj/LaunchScreen.storyboard b/ZDKDemo/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000..bfa3612 --- /dev/null +++ b/ZDKDemo/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ZDKDemo/Base.lproj/Main.storyboard b/ZDKDemo/Base.lproj/Main.storyboard new file mode 100644 index 0000000..4986267 --- /dev/null +++ b/ZDKDemo/Base.lproj/Main.storyboard @@ -0,0 +1,258 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ZDKDemo/CallViewController.swift b/ZDKDemo/CallViewController.swift new file mode 100644 index 0000000..ad0045c --- /dev/null +++ b/ZDKDemo/CallViewController.swift @@ -0,0 +1,64 @@ +// +// CallViewController.swift +// ZDKDemo +// +// Copyright © 2019 Securax. All rights reserved. +// + +import UIKit + +var callViewController : CallViewController? + +class CallViewController: UIViewController, UITextFieldDelegate { + + @IBOutlet weak var numberToDial: UITextField? + @IBOutlet weak var btnDial: UIButton? + + override func viewDidLoad() { + super.viewDidLoad() + // Do any additional setup after loading the view. + + callViewController = self + } + + func textFieldShouldReturn(_ textField: UITextField) -> Bool { + self.view.endEditing(true) + return false + } + + @IBAction func dialTapped(_ sender: Any) { + guard numberToDial != nil else { + print("Number to dial text field is nil.") + return + } + + let appDelegate = UIApplication.shared.delegate as! AppDelegate + if appDelegate.contextManager.isInCall() { + print("Hanging call up...") + appDelegate.contextManager.hangupCall() + return + } + + if numberToDial!.text!.count == 0 { + let alert = UIAlertController(title: "Error", message: "Cannot dial an empty number.", preferredStyle: .alert) + let OKAction = UIAlertAction(title: "OK", style: .default) { (action) in + return + } + alert.addAction(OKAction) + self.present(alert, animated: true, completion: nil) + return + } + + appDelegate.contextManager.makeCallTo(callee: numberToDial!.text!) + } + + @objc + func changeDialButtonTitleTo(_ title: String) { + print("New (dial) button title: '\(title)'") + btnDial?.setTitle(title, for: .normal) + btnDial?.setTitle(title, for: .highlighted) + btnDial?.setTitle(title, for: .selected) + btnDial?.setTitle(title, for: .disabled) + } +} + diff --git a/ZDKDemo/ContextManager.swift b/ZDKDemo/ContextManager.swift new file mode 100644 index 0000000..c4cf37b --- /dev/null +++ b/ZDKDemo/ContextManager.swift @@ -0,0 +1,374 @@ +// +// ContextManager.swift +// ZDKDemo +// +// Copyright © 2019 Securax. All rights reserved. +// + +import Foundation + +let zdkVersion = "ZDK for iOS 2.0" +let documentsDirPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).last!.path + "/" + +enum CodecId: Int { + case NA = -1 + case uLaw = 0 + case GSM = 1 + case aLaw = 6 + case g722 = 7 + case g729 = 16 + case speex = 24 + case speexWide = 25 + case speexUltra = 26 + case iLBC30 = 27 + case g726 = 29 + case h263Plus = 30 + case vp8 = 31 + case opusNarrow = 34 + case opusWide = 35 + case opusSuper = 36 + case opusFull = 37 +} + +class ContextManager: NSObject { + + private var zdkContext: ZDKContext + private let zdkAccountProvider: ZDKAccountProvider + private var zdkAccount: ZDKAccount? = nil + private var zdkCall : ZDKCall? = nil + + private let pollInterval: Int32 = 400 + private let reRegistrationTime: Int32 = 600 + private let accountName = "Demo SIP Account" + + var context: ZDKContext { + return zdkContext + } + + override init() { + zdkContext = HelperFactory.sharedInstance().context + zdkAccountProvider = HelperFactory.sharedInstance().context.accountProvider + + super.init() + + zdkContext.setStatusListener(self) + initContext() + } + + func initContext() { + zdkContext.configuration.sipPort = Int32.random(in: 32000..<65000) + repeat { + zdkContext.configuration.rtpPort = Int32.random(in: 32000..<65000) + } while (zdkContext.configuration.rtpPort != zdkContext.configuration.sipPort) + + zdkContext.audioControls.echoCancellation = .ect_Hardware + zdkContext.audioControls.automaticGainControl = .agct_Hardware + zdkContext.configuration.enableIPv6 = true + } + + func activateZDK(_ zdkVersion: String, withUserName username: String, andPassword password: String) { + let path = documentsDirPath + "private/" + if !FileManager.default.fileExists(atPath: path) { + do { + try FileManager.default.createDirectory(atPath: path, withIntermediateDirectories: true, attributes: nil) + } catch { + print(error.localizedDescription); + } + } + + let cacheFile = path + "activationFile" + let certPem = "-----BEGIN PUBLIC KEY-----\n" + + "MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAwX+jHbOCZkZxXBR0V5tq\n" + + "uo+tGD0uioUB3yXfWPJGkX3jxuGIj3TdIVOoe39CveojovF8imhOTmlFNZzyzsua\n" + + "Wi/mb03+xu2rBO/UznOptOtOblGG77jIywZZ4pSIXY+0A+7GcauyuR46XQNryy+v\n" + + "VtRJfuu+pbqrGkldNRhWcr8duhAV4PhezyrwJyz1cfJjXObS4ysENHVkbeilQdM9\n" + + "oaofjqM0wD9YyE7ICQJ9c7f+0amZHvQPqljFoQE9uwvf63yyI5rToiNBUI7BK6tZ\n" + + "qEn/wZnueOjLSlP8ZBEI8pWDV1DEq6Kk8zE+yNenH21dEf+6T8ZXWTqlYakE9NlT\n" + + "SrBTPYoRM8Gji0dFwuw6rfibNqqLc5Tgtuc6MsPzVtTxsh0+Cf13bSEpyXqEyLu5\n" + + "m/lMllvvBbz2wLbget6/b5XNym4xC9xOWNcFVNnA0tHMKNAWwqlWgeF++Ydi20YE\n" + + "fo6LHnCs9AR/aIWHX7FdqlsGNzK0aQQLgf97ZHuMoZOMw+m4Poy5naUo3PKN+87h\n" + + "lSTSz3dGesgv4L66Dnyldlf7zt0krhmN5KJNx9jMtOJI7EAyrJtipXms6x8y+bhB\n" + + "8Ao+qIT5OcgFAUFrZ6den9XMBNIYTSCyCYnEtD4vBiO/BrnYwmJ2RTNFRjWE60V0\n" + + "xU+U6NFcvqbNpGEF5O6yi90CAwEAAQ==\n" + + "-----END PUBLIC KEY-----\n" + + let result = zdkContext.activation.start(cacheFile, + moduleName: nil, + // 0x10 - E_ACTIVATION_FLAG_USE_V4_CERTIFICATE + // 0x2 - E_ACTIVATION_FLAG_SKIP_CHECKSUM_VERIFICATION + opFlags: 0x10 + 0x2, + username: username, + password: password, + version: zdkVersion, + certPem: certPem) + if result.code != .rc_Ok { + print("Failed to start activation: \(result.text) (code: \(result.code.rawValue))") + } else { + print("Activation started.") + } + } + + @discardableResult @objc + func startContext() -> ZDKResult { + let result = context.start() + if result.code == .rc_Ok { + print("ZDK context is started.") + } else { + print("ZDK context failed to start, code: \(result.code.rawValue).") + } + + return result + } + + private func createDefaultSTUNConfiguration() ->ZDKStunConfig { + let stunConfiguration = zdkAccountProvider.createStunConfiguration() + stunConfiguration.stunEnabled = false + + stunConfiguration.stunServer = "stun.zoiper.com" + stunConfiguration.stunPort = 3478 + stunConfiguration.stunRefresh = 30 + + return stunConfiguration + } + + private func createDefaultSIPConfiguration() -> ZDKSIPConfig { + let sipConfiguration = zdkAccountProvider.createSIPConfiguration() + + sipConfiguration.transport = .tt_TCP + + sipConfiguration.useOutboundProxy = false + sipConfiguration.outboundProxy = nil + sipConfiguration.authUsername = nil + + sipConfiguration.callerID = accountName + sipConfiguration.rPort = .rpt_Signaling + sipConfiguration.enableSRTP = false + sipConfiguration.dtmf = .dtmftsip_RFC_2833 + + sipConfiguration.enablePushNotifications = false + sipConfiguration.pushTransport = .tt_TCP + + sipConfiguration.stun = createDefaultSTUNConfiguration() + + return sipConfiguration + } + + @discardableResult + private func createAccountWithDomain(_ domain: String, username: String, andPassword password: String) -> ZDKAccount? { + zdkAccount = zdkAccountProvider.createUserAccount() + guard zdkAccount != nil else { + print( "Failed to create ZDK account." ) + return nil + } + + zdkAccount!.accountName = accountName + + let accountConfiguration = zdkAccount!.configuration + accountConfiguration.userName = username + accountConfiguration.password = password + accountConfiguration.type = .pt_SIP + + accountConfiguration.reregistrationTime = reRegistrationTime + + accountConfiguration.sip = createDefaultSIPConfiguration() + guard accountConfiguration.sip != nil else { + print("Failed to create SIP configuration.") + zdkAccount = nil + return nil + } + accountConfiguration.sip!.domain = domain + + zdkAccount!.configuration = accountConfiguration + zdkAccount!.mediaCodecs = [CodecId.uLaw.rawValue as NSNumber, + CodecId.aLaw.rawValue as NSNumber, + CodecId.GSM.rawValue as NSNumber, + CodecId.speex.rawValue as NSNumber, + CodecId.iLBC30.rawValue as NSNumber, + CodecId.g729.rawValue as NSNumber, + CodecId.vp8.rawValue as NSNumber] + + return zdkAccount + } + + func registerAccountWithDomain(_ domain: String, username: String, andPassword password: String) { + var result : ZDKResult + + guard context.contextRunning else { + print("Cannot register account- ZDK context is not started.") + return + } + + if zdkAccount == nil { + createAccountWithDomain(domain, username: username, andPassword: password) + + guard zdkAccount != nil else { + print("Cannot register account- ZDK Account is nil!") + return + } + zdkAccount!.removeUser() + result = zdkAccount!.createUser() + if result.code != .rc_Ok { + print("Failed to create ZDK account- \(result.text), code: \(result.code.rawValue).") + return; + } + + zdkAccount!.setStatusEventListener(self) + } + + context.accountProvider.setAsDefaultAccount(zdkAccount!) + + if zdkAccount!.registrationStatus == .as_Registered { + result = zdkAccount!.unRegister() + if result.code != .rc_Ok { + print("Failed to unregsiter ZDK account- \(result.text), code: \(result.code.rawValue).") + return; + } + print("Unregistering ZDK account...") + } else { + // Update account data + let config = zdkAccount!.configuration + config.sip!.domain = domain + config.userName = username + config.password = password + zdkAccount!.configuration = config + + result = zdkAccount!.register() + if result.code != .rc_Ok { + print("Failed to register ZDK account- \(result.text), code: \(result.code.rawValue).") + return; + } + print("Registering ZDK account...") + } + } + + func isInCall() -> Bool { + return zdkCall != nil + } + + func hangupCall() { + guard zdkCall != nil else { + print("Cannot hang-up non-existing call!") + return + } + + let result = zdkCall?.hangUp() + if result!.code != .rc_Ok { + print("Hang-up call, something went wrong- \(result!.description), code: \(result!.code.rawValue)") + } else { + print("Call hung up successfully.") + } + + zdkCall?.dropStatusListener(self) + zdkCall = nil + } + + func makeCallTo(callee:String) { + guard context.contextRunning else { + print("Cannot make a call- ZDK context is not started.") + return + } + + guard zdkAccount != nil else { + print("Cannot make a call- please create an account.") + return + } + + guard context.callsProvider.activeCall == nil else { + print("There is already an active call.") + return + } + + print("Dialling \(callee)...") + + zdkCall = zdkAccount?.createCall(callee, handlingVoipPhoneCallEvents: true, video: false) + guard zdkCall != nil else { + print("Something went wrong, failed to create a call!") + return + } + zdkCall?.setCallStatusListener(self) + } +} + +// MARK: - Context events handler + +extension ContextManager: ZDKContextEventsHandler { + func eventHandle() -> Int { + return 0 + } + + func handlesDescription() -> String { + return String() + } + + func onContext(_ context: ZDKContext, secureCerterror secureCert: ZDKSecureCertData) { + + } + + func onContext(_ context: ZDKContext, activationCompleted activationResult: ZDKActivationResult) { + var strStatus: String + + switch activationResult.status { + case .as_Failed: + strStatus = "Failed" + case .as_Success: + strStatus = "Success" + default: + strStatus = "Failed, code: " + String(describing: activationResult.status.rawValue) + } + + print("Activation completed- \"\(activationResult.reason), \(strStatus)\"") + + if activationResult.status == .as_Success { + self.performSelector(onMainThread: #selector(startContext), with: nil, waitUntilDone: false) + } + } +} + +// MARK: - Account events handler + +extension ContextManager: ZDKAccountEventsHandler { + func onAccount(_ account: ZDKAccount, status: ZDKAccountStatus, changed statusCode: Int32) { + if statusCode != 0 { + print("Account '\(String(describing: account.accountName!))' status change to \(status.rawValue) failed, code: \(statusCode).") + } else { + print("Successfully changed account '\(String(describing: account.accountName!))' status to \(status.rawValue).") + } + + let title : String + if status == .as_Registered { + title = "Unregister" + } else { + title = "Register" + } + + accountViewController?.performSelector(onMainThread: #selector(accountViewController?.changeRegisterButtonTitleTo), with: title, waitUntilDone: false) + } + + func onAccount(_ account: ZDKAccount, extendedError message: ZDKExtendedError) { + print("'\(String(describing: account.accountName!))' extended error: \(message.message), q931 Code: \(message.q931Code).") + } +} + +// MARK: - Call events handler + +extension ContextManager: ZDKCallEventsHandler { + func onCall(_ call: ZDKCall, statuschanged status: ZDKCallStatus) { + DispatchQueue.main.async { + print("Call status changed: \(status.description), code: \(status.lineStatus.rawValue)") + + if status.origin == .ot_Remote && status.lineStatus == .cls_Active { + print("The call is answered") + } + + if status.lineStatus == .cls_Terminated { + callViewController?.changeDialButtonTitleTo("Dial") + } else { + callViewController?.changeDialButtonTitleTo("Hangup") + } + } + } + + func onCall(_ call: ZDKCall, extendedError error: ZDKExtendedError) { + print("Call to '\(String(describing: call.calleeNumber))' extended error: \(error.message), q931 Code: \(error.q931Code).") + } +} diff --git a/ZDKDemo/Info.plist b/ZDKDemo/Info.plist new file mode 100644 index 0000000..909f96c --- /dev/null +++ b/ZDKDemo/Info.plist @@ -0,0 +1,59 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarTintParameters + + UINavigationBar + + Style + UIBarStyleDefault + Translucent + + + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + NSMicrophoneUsageDescription + The app uses the microphone for VoIP calls. + UIFileSharingEnabled + + +