Skip to main content

PitelVoIP Integration Guide

Version: 2.1.0
Platform: iOS 14.0+
Language: Swift 5.5+

📋 Table of Contents

  1. Overview
  2. Prerequisites
  3. Step-by-Step Integration
  4. API Reference
  5. Customize CallScreen UI
  6. Essential Tips
  7. Troubleshooting

Overview

PitelVoIP Framework is a comprehensive VoIP solution for iOS applications, built on top of PJSIP with CallKit integration and push notification support.

✨ Key Features

  • One-Line Integration - Add full VoIP capabilities in minutes.
  • CallKit Native UI - Seamless system call experience.
  • VoIP Push & Auto-Login - Reliable background call receiving.
  • SwiftUI Ready - Modern ViewModels and Modifiers included.
  • Call Controls - Complete feature set (Mute, Hold, Transfer, DTMF).

Prerequisites

System Requirements

  • iOS: 14.0 or later
  • Xcode: 13.0 or later
  • Swift: 5.5 or later
  • Firebase SDK: for FCM integration

Xcode Configuration

1. Enable Required Capabilities

Go to Target → Signing & Capabilities and add:

Background Modes:

  • ✅ Voice over IP
  • ✅ Background fetch
  • ✅ Remote notifications

Push Notifications:

  • ✅ Enable push notifications

2. Configure Info.plist

Add the following keys to your Info.plist:

<!-- Background Modes -->
<key>UIBackgroundModes</key>
<array>
<string>voip</string>
<string>fetch</string>
<string>remote-notification</string>
</array>

<!-- Permissions -->
<key>NSMicrophoneUsageDescription</key>
<string>We need access to your microphone to make VoIP calls.</string>

3. VoIP Push Certificate

  1. Go to Apple Developer Portal
  2. Create a VoIP Services Certificate
  3. Download and install the certificate
  4. Export as .p12 file for your push server

Step-by-Step Integration

Step 1: Add Framework to Your Project

Manual Installation

  1. Download or clone the PitelVoIP framework
  2. Drag IOSPitelVoIPFramework into your Xcode project
  3. Add the framework to Frameworks, Libraries, and Embedded Content
  4. Set to Embed & Sign

Step 2: Create AppDelegate

Create an AppDelegate class that inherits from PitelVoIPDelegate:

import UIKit
import PitelVoIPFramework
import Firebase
import FirebaseMessaging

class AppDelegate: PitelVoIPDelegate, MessagingDelegate {
static let shared = AppDelegate()

override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
// ✅ Parent class automatically configures PJSIP
_ = super.application(application, didFinishLaunchingWithOptions: launchOptions)

// Initialize Firebase
FirebaseApp.configure()
Messaging.messaging().delegate = self

// Setup incoming call handler
self.onIncomingCall = { [weak self] name, callerId, uuid in
self?.handleIncomingCall(name: name, callerId: callerId, uuid: uuid)
}

return true
}

// Override to integrate FCM
override func onAPNsTokenReceived(_ deviceToken: Data) {
Messaging.messaging().apnsToken = deviceToken
}

// Firebase Messaging delegate
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
if let token = fcmToken {
onFCMTokenReceived(token)
}
}

// Handle incoming call
func handleIncomingCall(name: String, callerId: String, uuid: UUID) {
print("📞 Incoming call from \(name)")
}
}

Step 3: Setup App with Lifecycle Modifier

In your main app file:

import SwiftUI
import PitelVoIPFramework

@main
struct YourApp: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate

var body: some Scene {
WindowGroup {
ContentView()
.pitelVoIPLifecycle()
}
}
}

That's it! ✅ Your app is now ready to make and receive VoIP calls.


API Reference

1. Login with Builder Pattern

import SwiftUI
import PitelVoIPFramework

struct ContentView: View {
@StateObject var viewModel = AccountViewModel()

var body: some View {
VStack {
Button("Login") {
PitelVoIP.login(
accountViewModel: viewModel
) { builder in
builder
.setExtension("YOUR_EXTENSION")
.setPassword("YOUR_PASSWORD")
.setDomain("YOUR_DOMAIN") // e.g., sip.pitel.vn
.setProxy("YOUR_PROXY") // Optional
.setPort("YOUR_PORT") // e.g., 50061
.setDisplayName("Your Name")
.setTeamId("YOUR_TEAM_ID")
.setAppId("com.yourcompany.app")
.setAppMode("dev") // or "production"
}
}
}
}
}

2. Making Calls

// Simple call
PitelVoIP.makeCall(to: "sip:101@sip.pitel.vn:50061")

// Call with display name
PitelVoIP.makeCall(
to: "sip:101@sip.pitel.vn:50061",
callerName: "Agent 101"
)

3. Handle Incoming Call UI

Add navigation to your call view:

@ObservedObject private var callManager = globalCallStatusManager

var body: some View {
NavigationLink(
destination: CallView(),
isActive: $callManager.isActiveCallPresented
) {
EmptyView()
}
}

4. Call Controls

PitelVoIP.mute()                                              // Toggle mute
PitelVoIP.unmute()
PitelVoIP.hold() // Toggle hold
PitelVoIP.unhold()
PitelVoIP.hangup() // End call
PitelVoIP.sendDTMF("1") // Send DTMF
PitelVoIP.transferCall(to: "sip:102@sip.pitel.vn:50061") // Transfer call

5. Logout

PitelVoIP.logout(
accountViewModel: viewModel,
sipInfo: sipInfo
)

Customize CallScreen UI

PitelCallView is a complete, pre-built VoIP call screen that supports all essential features: Mute, Speaker, Hold, Transfer, Keypad, and End Call.

1. Basic Usage

Use the default configuration (Light Mode):

PitelCallView()

Use the Dark Mode configuration:

PitelCallView(config: .defaultDark)

2. Customization

You can fully customize the UI using PitelCallConfig.

let config = PitelCallConfig(
colors: .init(background: .blue), // Change background color
texts: .init(endCall: "Hang Up") // Change button text
)
PitelCallView(config: config)

3. Properties Reference

Colors (config.colors)

PropertyTypeDescriptionDefault
backgroundColorMain screen background colorSoft White / Charcoal
cardBackgroundColorBackground color of the bottom action cardWhite / Dark Gray
textPrimaryColorCaller name colorDark Gray / White
textSecondaryColorTimer and secondary text colorGray
textStatusColorCall status (Incoming/Outgoing) colorGray
buttonIconActiveColorIcon color when button is ACTIVEOrange
buttonIconInactiveColorIcon color when button is INACTIVEGray
buttonBackgroundActiveColorButton background when ACTIVELight Orange
buttonBackgroundInactiveColorButton background when INACTIVESoft Gray
hangupButtonBackgroundColorBackground color of the End Call buttonSoft Red
dialPadNumberColorColor of numbers on the keypadDark Gray
dialPadButtonBackgroundColorBackground color of keypad buttonsWhite

Texts (config.texts)

PropertyDescriptionDefault
outgoingOutgoing call status text"Starting call..."
incomingIncoming call status text"Incoming..."
unknownCallerDisplay name when CallerID is missing"Unknown Caller"
mute / unmuteMute button label"Mute" / "Unmute"
speakerSpeaker button label"Speaker"
hold / unholdHold button label"Hold" / "Unhold"
transferTransfer button label"Transfer"
keypadKeypad button label"Keypad"
endCallEnd Call button label"End Call"
enterNumberPlaceholder for transfer number input"Enter number"

Fonts (config.fonts)

PropertyDescription
callerNameFont for the caller's name
statusFont for call status (Incoming...)
timerFont for the call timer
actionButtonLabelFont for labels below action buttons
dialPadNumberFont for numbers on the keypad

Icons (config.icons)

Uses system SF Symbols names.

PropertyDefault
mute / unmute"mic.slash" / "mic"
speakerOn / speakerOff"speaker.wave.2" / "speaker"
hold / unhold"pause" / "play"
hangup"phone.down.fill"
transfer"arrowshape.turn.up.right"

💡 Essential Tips

1. Store Credentials Securely

The framework automatically handles secure storage via ExtInfoStorage. Just call PitelVoIP.login().

2. Handle App Lifecycle

Always add .pitelVoIPLifecycle() to your root view. This ensures auto-login works when the app resumes or wakes up from VoIP push.

3. Use Global State

Observe call status easily anywhere in your app:

@ObservedObject var callManager = globalCallStatusManager

❓ Troubleshooting

IssueSolution
No VoIP PushCheck .p12 certificate & enable Background Modes (VoIP, Remote Notif).
Registration FailEnsure internet connection & verify SIP credentials. Check logs.
Audio Key MissingAdd NSMicrophoneUsageDescription to Info.plist.
Build ErrorSet Framework to Embed & Sign in Target settings.

📚 Resources


Made with ❤️ by the Pitel Team