패키지, 저장소 및 앱 카테고리 검색

패키지 상세v2.3.0

flutter_callkit_voximplant

iOS에서 Flutter 애플리케이션에 CallKit 통합을 위한 Flutter SDK

iOS
30일 다운로드
839
좋아요
28
Pub 점수
160

패키지 설치

flutter pub add flutter_callkit_voximplant

패키지 개요

공개 정보를 바탕으로 생성한 선택 가이드입니다.

iOS 애플리케이션용 CallKit 통합을 가능하게 하는 플러터 플러그인으로, 네이티브 iOS 전화 인터페이스를 사용하여 수신 및 발신 통화를 원활하게 처리할 수 있습니다. Voximplant에서 개발한 이 패키지는 Apple의 CallKit 프레임워크를 활용하여 VoIP 통화 경험을 향상시키며, 시스템 내장 다이얼러에 통화를 표시하고, 통화 중 UI를 지원하며, 발신자 ID, 방해 금지 모드, 백그라운드 통화 처리와 같은 기능과 통합됩니다. 이 패키지는 iOS 전용으로 설계되어 플러터 앱에 고품질 음성 및 비디오 통화 기능을 쉽게 통합하는 과정을 단순화합니다.

사용 사례

  • VoIP 앱에서 네이티브 전화 인터페이스 통합
  • 시스템 수준의 전화 알림 활성화
  • 백그라운드 통화 기능 지원
  • iOS CallKit를 활용한 통화 경험 향상
  • 네이티브 UI를 통해 수신/발신 통화 처리

주요 기능

  • iOS 전용 CallKit 통합
  • 네이티브 호출 인터페이스 렌더링
  • 백그라운드 통화 지원
  • 발신자 ID 표시
  • 시스템 전체 통화 관리

적합한 대상

  • iOS를 대상으로 한 VoIP 애플리케이션
  • 네이티브 호출 동작을 필요로 하는 Flutter 앱
  • Voximplant의 통신 서비스를 사용하는 개발자
  • CallKit 호환성이 필요한 앱

고려 사항

  • iOS 플랫폼에 한정
  • iOS 전용 구성이 필요합니다
  • Voximplant 백엔드 서비스에 의존합니다
  • 적절한 권한과 허가가 필요합니다
  • Android와 호환되지 않습니다

원본 README

연결된 소스 저장소의 README 원문 스냅샷입니다. 최신 내용은 저장소에서 확인하세요.

flutter_callkit_voximplant

Flutter SDK for CallKit integration to Flutter applications on iOS

Requirements

Minimum version
Flutter 3.24.0
Dart 3.5.0
iOS 12.0

We wrote an article about the plugin - "How we make Flutter work with CallKit Call Directory".

Available on English and Russian languages.

Install

  1. Add flutter_callkit_voximplant as a dependency in your pubspec.yaml file.
  2. Add the following entry to your Info.plist file, located in <project root>/ios/Runner/Info.plist:
<key>UIBackgroundModes</key>
<array>
  <string>voip</string>
</array>

This entry required for CallKit to work

Usage

API of the SDK is designed as close as possible to CallKit iOS Framework.

CallKit documentation can be found here

A few differences explained:

  • Use FlutterCallkitPlugin.sharedInstance.reportNewIncomingCallWithUUID: native iOS method to report new incoming call received via VoIP push notification
  • Use FlutterCallkitPlugin.sharedInstance.hasCallWithUUID: native iOS method to check if CallKit already has a call with the given UUID
  • Use FCXPlugin.didDisplayIncomingCall (dart) handle incoming call reported with reportNewIncomingCallWithUUID
  • Use FCXPlugin.logLevel (dart) to adjust logging
  • Use FCXPlugin.processPushCompletion (dart) to execute completion block received from push (iOS 11+ only)
  • FCXCallController and FCXProvider are only allowed in single instance (use it as a singletone)

Note that UUID's passed to FCXProvider will be uppercased by the CallKit.

Initialization
import 'package:flutter_callkit_voximplant/flutter_callkit_voximplant.dart';

// init main plugin class:
FCXPlugin _plugin = FCXPlugin();
// init main CallKit classes:
FCXProvider _provider = FCXProvider();
FCXCallController _callController = FCXCallController();
// at this point CallKit classes are not ready yet
// configure it to use:
try {
  await _callController.configure();
  await _provider.configure(FCXProviderConfiguration('ExampleLocalizedName'));
} catch (_) {
  // handle exception
}
Making outgoing calls

To make an outgoing call, an app requests a FCXStartCallAction object from its FCXCallController object. The action consists of a UUID to uniquely identify the call and a FCXHandle object to specify the recipient.

Future<void> makeCall(String contactName, String uuid) async {
  FCXHandle handle = FCXHandle(FCXHandleType.Generic, contactName);
  FCXStartCallAction action = FCXStartCallAction(uuid, handle);
  await _callController.requestTransactionWithAction(action);
}

After the call is connected, the system calls the provider's performStartCallAction method. In your implementation, this method is responsible for configuring an AVAudioSession and calling fulfill() on the action when finished.

_provider.performStartCallAction = (startCallAction) async {
  // configure audio session
  await startCallAction.fulfill();
};
Receiving an Incoming Call

Using the information provided by the external notification, the app creates a UUID and a CXCallUpdate object to uniquely identify the call and the caller, and passes them both to the provider using the reportNewIncomingCall() method.

Future<void> handleIncomingCall(String contactName, String uuid) async {
  FCXCallUpdate callUpdate = FCXCallUpdate(localizedCallerName: contactName);
  await _provider.reportNewIncomingCall(uuid, callUpdate);
}

After the recipient answers the call, the system calls the performAnswerCallAction method of the provider. In your implementation of that method, configure an AVAudioSession and call the fulfill() method on the action object when finished.

_provider.performAnswerCallAction = (answerCallAction) async {
  // configure audio session
  await answerCallAction.fulfill();
};
Handling push notifications

Note: This SDK is not related to PushKit

Push handling must be done through native iOS code due to iOS 13 PushKit VoIP restrictions.

Flutter CallKit SDK has built-in reportNewIncomingCallWithUUID:callUpdate:providerConfiguration:pushProcessingCompletion:) method (iOS) to correctly work with it

Swift
import Flutter
import flutter_callkit_voximplant
import PushKit
import CallKit

class AppDelegate: FlutterAppDelegate, PKPushRegistryDelegate {
    // 1. override PKPushRegistryDelegate methods
    func pushRegistry(_ registry: PKPushRegistry,
                      didReceiveIncomingPushWith payload: PKPushPayload,
                      for type: PKPushType
    ) {
        processPush(with: payload.dictionaryPayload, and: nil)
    }

    func pushRegistry(_ registry: PKPushRegistry,
                      didReceiveIncomingPushWith payload: PKPushPayload,
                      for type: PKPushType,
                      completion: @escaping () -> Void
    ) {
        processPush(with: payload.dictionaryPayload, and: completion)
    }

    // 2. process push
    private func processPush(with payload: Dictionary<AnyHashable, Any>,
                             and completion: (() -> Void)?
    ) {
        // 3. get uuid and other needed information from payload
        guard let uuidString = payload["UUID"] as? String,
            let uuid = UUID(uuidString: uuidString),
            let localizedName = payload["identifier"] as? String
            else {
                return
        }
        // 4. prepare call update
        let callUpdate = CXCallUpdate()
        callUpdate.localizedCallerName = localizedName
        // 5. prepare provider configuration
        let configuration = CXProviderConfiguration(localizedName: "ExampleLocalizedName")
        // 6. send it to the plugin
        FlutterCallkitPlugin.sharedInstance.reportNewIncomingCall(
            with: uuid,
            callUpdate: callUpdate,
            providerConfiguration: configuration,
            pushProcessingCompletion: completion
        )
    }
}
Objective-C
#import <Flutter/Flutter.h>
#import <FlutterCallkitPlugin.h>
#import <PushKit/PushKit.h>
#import <CallKit/CallKit.h>

@interface AppDelegate : FlutterAppDelegate<PKPushRegistryDelegate>

@end

@implementation AppDelegate

// 1. override PKPushRegistryDelegate methods
- (void)             pushRegistry:(PKPushRegistry *)registry
didReceiveIncomingPushWithPayload:(PKPushPayload *)payload
                          forType:(PKPushType)type {
    [self processPushWithPayload:payload.dictionaryPayload 
            andCompletionHandler:nil];
}

- (void)             pushRegistry:(PKPushRegistry *)registry
didReceiveIncomingPushWithPayload:(PKPushPayload *)payload
                          forType:(PKPushType)type
            withCompletionHandler:(void (^)(void))completion {
    [self processPushWithPayload:payload.dictionaryPayload
            andCompletionHandler:completion];
}

// 2. process push
-(void)processPushWithPayload:(NSDictionary *)payload
         andCompletionHandler:(dispatch_block_t)completion {
    // 3. get uuid and other needed information from payload
    NSUUID *UUID = [[NSUUID alloc] initWithUUIDString:payload[@"UUID"]];
    NSString *localizedName = payload[@"identifier"];
    // 4. prepare call update
    CXCallUpdate *callUpdate = [CXCallUpdate new];
    callUpdate.localizedCallerName = localizedName;
    // 5. prepare provider configuration
    CXProviderConfiguration *configuration =
        [[CXProviderConfiguration alloc]
              initWithLocalizedName:@"ExampleLocalizedName"];
    // 6. send it to plugin
    [FlutterCallkitPlugin.sharedInstance reportNewIncomingCallWithUUID:UUID
                                                            callUpdate:callUpdate
                                                 providerConfiguration:configuration
                                              pushProcessingCompletion:completion];
}
@end

At this point CallKit will be set up to handle incoming call and will present its UI.

didDisplayIncomingCall of FCXPlugin will be called in dart code.

Call processPushCompletion from dart code once call successfully connected.

Call Blocking and Identification

Apps can create a Call Directory app extension to identify and block incoming callers by their phone number.

When a phone number is blocked, the system telephony provider will disallow incoming calls from that phone number without displaying them to the user.

When a phone number has an identification entry, incoming calls from that phone number will display its associated label to the user.

To integrate CallDirectory App Extension functionality to an Flutter application, it is required:

  • add a CallDirectory Extenstion to the XCode project.
  • implement data storage for blocked and/or identifiable numders in the native iOS code and connect it with CallDirectory Extension.
  • assign FlutterCallkitPlugin CallDirectory related properties with functions that access numbers storage.

More on the CallDirectory App Extension

Example App with CallDirectory App Extension implemented

Reference

iOS CallKit Framework Documentation by Apple: https://developer.apple.com/documentation/callkit

카테고리

소스 저장소

이 패키지를 사용하는 프로젝트

아직 데이터가 없습니다.