Flutter Voip24h-SDK Mobile

pub package

Mục lục

Tính năng

Chức năng Mô tả
CallKit • Đăng nhập/Đăng xuất/Refresh kết nối tài khoản SIP
• Gọi đi/Nhận cuộc gọi đến
• Chấp nhận cuộc gọi/Từ chối cuộc gọi đến/Ngắt máy
• Pause/Resume cuộc gọi
• Hold/Unhold cuộc gọi
• Bật/Tắt mic
• Lấy trạng thái mic
• Bật/Tắt loa
• Lấy trạng thái loa
• Transfer cuộc gọi
• Send DTMF
Graph • Lấy access token
• Request API từ: https://docs-sdk.voip24h.vn/

Yêu cầu

  • OS Platform:
    • Android -> minSdkVersion: 23
    • IOS -> iOS Deployment Target: 9.0
  • Permissions: khai báo và cấp quyền lúc runtime
    • Android: Trong file AndroidManifest.xml

      <uses-permission android:name="android.permission.INTERNET" />
      <uses-permission android:name="android.permission.RECORD_AUDIO"/>
      
    • IOS: Trong file Info.plist

      <key>NSAppTransportSecurity</key>
      <dict>
          <key>NSAllowsArbitraryLoads</key><true/>
      </dict>
      <key>NSMicrophoneUsageDescription</key>
      <string>{Your permission microphone description}</string>
      

Cài đặt

Sử dụng terminal:

flutter pub add voip24h_sdk_mobile

Linking module:

  • IOS:
    • Trong ios/Podfile:
      ...
      # Khai báo thư viện
      platform :ios, '9.0'
      source "https://gitlab.linphone.org/BC/public/podspec.git"
      
      target 'Your Project' do
          ...
          use_frameworks!
          use_modular_headers!
      
          flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
      
          # Khai báo thư viện 
          pod 'linphone-sdk-novideo' , '5.1.36'
      end
      
    • Trong folder ios mở terminal, nhập dòng lệnh:
      rm -rf Pods/
      pod install
      

Khai báo module

import 'package:voip24h_sdk_mobile/voip24h_sdk_mobile.dart';
import 'package:voip24h_sdk_mobile/callkit/utils/sip_event.dart';
import 'package:voip24h_sdk_mobile/callkit/utils/transport_type.dart';
import 'package:voip24h_sdk_mobile/graph/extensions/extensions.dart';
import 'package:voip24h_sdk_mobile/callkit/model/sip_configuration.dart';

// TODO: Using module

CallKit

  • Khai báo sipConfiguration:

    var sipConfiguration = SipConfigurationBuilder(extension: "extension", domain: "domain", password: "password")
                            .setKeepAlive(true/false) // optional (bool)
                            .setPort(port) // optional (int)
                            .setTransport(TransportType.Udp/TransportType.Tcp/TransportType.Tls) // optional (enum)
                            .build(); 
    
Chức năng
Phương thức và tham số
(Dùng cơ chế async/await hoặc then để lấy dữ liệu trả về)
Kết quả trả về và thuộc tính
Khởi tạo Voip24hSdkMobile.callModule.initSipModule(sipConfiguration) None
Lấy trạng thái đăng kí tài khoản SIP Voip24hSdkMobile.callModule.getSipRegistrationState() value: String
error: String
Logout tài khoản SIP Voip24hSdkMobile.callModule.unregisterSipAccount() value: bool
error: String
Refresh kết nối SIP Voip24hSdkMobile.callModule.refreshSipAccount() value: bool
error: String
Gọi đi Voip24hSdkMobile.callModule.call(phoneNumber) value: bool
error: String
Ngắt máy Voip24hSdkMobile.callModule.hangup() value: bool
error: String
Chấp nhận cuộc gọi đến Voip24hSdkMobile.callModule.answer() value: bool
error: String
Từ chối cuộc gọi đến Voip24hSdkMobile.callModule.reject() value: bool
error: String
Transfer cuộc gọi Voip24hSdkMobile.callModule.transfer("extension") value: bool
error: String
Lấy call id Voip24hSdkMobile.callModule.getCallId() value: String
error: String
Lấy số lượng cuộc gọi nhỡ Voip24hSdkMobile.callModule.getMissedCalls() value: int
error: String
Pause cuộc gọi Voip24hSdkMobile.callModule.pause() value: bool
error: String
Resume cuộc gọi Voip24hSdkMobile.callModule.resume() value: bool
error: String
Bật/Tắt mic Voip24hSdkMobile.callModule.toggleMic() value: bool
error: String
Trạng thái mic Voip24hSdkMobile.callModule.isMicEnabled() value: bool
error: String
Bật/Tắt loa Voip24hSdkMobile.callModule.toggleSpeaker() value: bool
error: String
Trạng thái loa Voip24hSdkMobile.callModule.isSpeakerEnabled() value: bool
error: String
Send DTMF Voip24hSdkMobile.callModule.sendDTMF("number#") value: bool
error: String
  • Event listener SIP:

    Voip24hSdkMobile.callModule.eventStreamController.stream.listen((event) {
        switch (event['event']) {
            case SipEvent.AccountRegistrationStateChanged: {
                var body = event['body'];
                // TODO
            } break;
            case SipEvent.Ring: {
                // TODO
            } break;
            case ...
              break;
        }
    });
    
    ...
    
    @override
    void dispose() {
        Voip24hSdkMobile.callModule.eventStreamController.close();
        super.dispose();
    }
    
Tên sự kiện
Kết quả trả về và thuộc tính
Đặc tả thuộc tính
SipEvent.AccountRegistrationStateChanged body = {
  registrationState: String,
  message: String
}
registrationState: trạng thái kết nối của sip (None/Progress/Ok/Cleared/Failed)
message: chuỗi mô tả trạng thái
SipEvent.Ring body = {
  extension: String,
  phoneNumber: String
  callType: String
}
extension: máy nhánh
phoneNumber: số điện thoại người (gọi/nhận)
callType: loại cuộc gọi(inbound/outbound)
SipEvent.Up body = {
  callId: String
}
callId: mã cuộc gọi
SipEvent.Hangup body = {
  duration: int
}
duration: thời gian đàm thoại (milliseconds)
SipEvent.Paused None
SipEvent.Resuming None
SipEvent.Missed body = {
  phoneNumber: String,
  totalMissed: int
}
phone: số điện thoại người gọi
totalMissed: tổng cuộc gọi nhỡ
SipEvent.Error body = {
  message: String
}
message: trạng thái lỗi

Push Notification

  • IOS: Chúng tôi sử dụng Apple Push Notification service (APNs) cho thông báo đẩy cuộc gọi đến khi app ở trạng thái background
    • Step 1: Tạo APNs Auth Key
      • Truy cập Apple Developer để tạo Certificates
        9
      • Chọn chứng nhận VoIP Services Certificate 7
      • Chọn ID ứng dụng của bạn. Mỗi ứng dụng bạn muốn sử dụng với dịch vụ VoIP đều yêu cầu chứng chỉ dịch vụ VoIP riêng. Chứng chỉ dịch vụ VoIP dành riêng cho ID ứng dụng cho phép máy chủ thông báo (Voip24h) kết nối với dịch vụ VoIP để gửi thông báo đẩy về ứng dụng của bạn.
        8
      • Download file chứng chỉ và mở bằng Keychain Access
        11
      • Export chứng chỉ sang định dạng .p12
        12
      • Convert file chứng chỉ .p12 sang định dạng .pem và submit cho Voip24h cấu hình
        openssl pkcs12 -in path_your_certificate.p12 -out path_your_certificate.pem -nodes
        
  • Step 2: Cấu hình project app của bạn để nhận thông báo đẩy cuộc gọi đến -> Từ IOS 10 trở lên, sử dụng CallKit + PushKit

    • Callkit cho phép hiển thị giao diện cuộc gọi hệ thống cho các dịch vụ VoIP trong ứng dụng của bạn và điều phối dịch vụ gọi điện của bạn với các ứng dụng và hệ thống khác.
    • PushKit hỗ trợ các thông báo chuyên biệt để nhận các cuộc gọi Thoại qua IP (VoIP) đến.
    • Để sử dụng CallKit Framework + PushKit FrameWork, chúng tôi khuyến khích sử dụng thư viện callkeep, trong pubspec.yaml:
    dependencies:
        ....
        callkeep:
        git:
          url: https://github.com/Voip24h-Corp/callkeep
          ref: master
    

    Chạy lệnh:

    flutter pub get
    cd ios
    pod install
    
    • Tại project của bạn thêm Push Notifications và tích chọn Voice over IP, Background fetch, Remote notifications, Background processing (Background Modes) trong Capabilities. 5 6
    • Khi khởi động ứng dụng callkeep sẽ tạo mã thông báo đăng kí cho ứng dụng khách. Sử dụng mã này để đăng kí lên server Voip24h
    import 'package:callkeep/callkeep.dart';
    ...
    callKeep.on<CallKeepPushKitToken>((value) => {
      tokenPushIOS = value.token ?? ""
    });
    callKeep.setup(context, <String, dynamic>{
      'ios': {
        'appName': 'Example',
      }
    });
    
    // tokenGraph: access token được generate từ API Graph
    // token: token device pushkit
    // sipConfiguration: thông số sip khi đăng kí máy nhánh
    // isIOS: mặc định là false
    // appId: bundle id của app ios
    // isProduction: true(production) / false(dev)
    // deviceMac: device mac của thiết bị
    
    Voip24hSdkMobile.pushNotificationModule.registerPushNotification(
          tokenGraph: tokenGraph,
          token: tokenPushIOS,
          sipConfiguration: sipConfiguration,
          isIOS: true,
          appId: packageInfo.packageName,
          isProduction: false,
          deviceMac: iosDeviceInfo.identifierForVendor
      ).then((value) => {
        print(value)
      }, onError: (error) => {
        print(error)
      });
    

    Phải cấp quyền thông báo trên ios trước khi sử dụng tính năng Push Notification

    • Đăng kí nhận thông báo đẩy từ Voip24h Server

    • Important Note: Sau khi nhận thông báo đẩy từ Voip24h Server, như đã đề cập cơ chế Callkit, PushKit ở trên thì phải hiển thị màn hình cuộc gọi của hệ thống (cuộc gọi giả) trước, thực thi Login lại máy nhánh ngay sau đó để nhận tín hiệu cuộc gọi thật từ Voip24h thông qua bản tin event Ring, lúc này mọi action call như answer/reject mới hoạt động.

    callKeep.on<CallKeepReceivedPushNotification>((value) => {
      callId = value.callId ?? "",
      testCallKit()
    });
    callKeep.on<CallKeepPerformAnswerCallAction>((value) => {
      answer()
    });
    callKeep.on<CallKeepPerformEndCallAction>((value) => {
      reject()
    });
    
    • Để huỷ đăng kí nhận Push Notification
    Voip24hSdkMobile.pushNotificationModule.unregisterPushNotification(
        sipConfiguration: sipConfiguration,
        isIOS: true,
        appId: packageInfo.packageName
    ).then((value) => {
      print(value)
    }, onError: (error) => {
      print(error)
    });
    
  • Android: Chúng tôi sử dụng Firebase Cloud Messaging (FCM) cho thông báo đẩy cuộc gọi đến khi app ở trạng thái background
    • Step 1: Tạo API Token
      • Tạo dự án trong bảng điều khiển Firebase
        1
      • Đăng kí app Android
        2
        • Download file google-services.json và thêm Firebase SDK vào project app của bạn
          3
      • Trong Project settings Firebase, tạo token Cloud Messaging API (Legacy) và submit token này cho Voip24h cấu hình
        4
    • Step 2: Cấu hình project app của bạn để nhận thông báo đẩy cuộc gọi đến -> chúng tôi khuyến khích bạn sử dụng thư viện Firebase Messaging
      • Flutter packages:
      flutter pub add firebase_core
      flutter pub add firebase_messaging
      

      Theo dõi docs Firebase Messaging để cấu hình project app của bạn

      • Khi khởi động ứng dụng Firebase Messaging sẽ tạo mã thông báo đăng kí cho ứng dụng khách. Sử dụng mã này để đăng kí lên server Voip24h
        String? token = await messaging.getToken();
          ....
        if(token != null) {
            // tokenGraph: access token được generate từ API Graph
        // token: token device push firebase
        // sipConfiguration: thông số sip khi đăng kí máy nhánh
        // isAndroid: mặc định là false
        // appId: package id của app android
        // isProduction: true(production) / false(dev)
        // deviceMac: device mac của thiết bị
           
        Voip24hSdkMobile.pushNotificationModule.registerPushNotification(
        tokenGraph: tokenGraph,
        token: token,
        sipConfiguration: sipConfiguration,
        isAndroid: true,
        appId: packageInfo.packageName,
        isProduction: false,
        deviceMac: androidDeviceInfo.androidId
        ).then((value) => {
          print(value)
        }, onError: (error) => {
          print(error)
        });
        }	
        
        • Phiên bản từ Android 13 (SDK 32) trở đi sẽ yêu cầu quyền thông báo để nhận Push Notification https://developer.android.com/develop/ui/views/notifications/notification-permission. Vui lòng cấp quyền runtime POST_NOTIFICATIONS trước khi sử dụng
          • Cấu hình nhận thông báo đẩy. Khi nhận thông báo đẩy, vui lòng đăng kí lại máy nhánh để nhận tín hiệu cuộc gọi đến
            @pragma('vm:entry-point')
            Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
            if(Platform.isAndroid) {
            print("Handling a background message: ${message.data}");
            await Firebase.initializeApp().whenComplete(() => {
              localNotificationService.initialNotification().then((value) => {
            // register sip account here
              })
            });
            }
            }
            
          • Huỷ đăng kí nhận Push Notification
          Voip24hSdkMobile.pushNotificationModule.unregisterPushNotification(
              sipConfiguration: sipConfiguration,
              isAndroid: true,
              appId: packageInfo.packageName
          ).then((value) => {
            print(value)
          }, onError: (error) => {
            print(error)
          });
          

Graph

• key và security certificate(secert) do Voip24h cung cấp
• request api: phương thức, endpoint. data body tham khảo từ docs https://docs-sdk.voip24h.vn/

Chức năng
Phương thức
Đặc tả tham số
Kết quả trả về
Đặc tả thuộc tính
Lấy access token Voip24hSdkMobile.graphModule.getAccessToken(apiKey: API_KEY, apiSecert: API_SECERT) • apiKey: String,
• secert: String
value: Oauth
error: String
• Oauth: gồm các thuộc tính (token, createAt, expired, isLongAlive)
• error: thông báo lỗi
Request API Voip24hSdkMobile.graphModule.sendRequest(token: token, endpoint: endpoint, body: body) • method: MethodRequest(MethodRequest.POST, MethodRequest.GET,...)
• endpoint: chuỗi cuối của URL request: "call/find", "call/findone",...
• token: access token
• params: data body dạng object như { "offset": "0", "limit": "25" }
value: Map<String, dynamic>
error: String
• value: kết quả response dạng key - value
• error: mã lỗi
Lấy data object value.getData()
(Dạng extension function)
None object: Object object gồm các thuộc tính được mô tả ở dữ liệu trả về trong docs https://docs-sdk.voip24h.vn/
Lấy danh sách data object value.getDataList()
(Dạng extension function)
List<Object> mỗi object gồm các thuộc tính được mô tả ở dữ liệu trả về trong docs https://docs-sdk.voip24h.vn/
Lấy status code value.statusCode()
(Dạng extension function)
int mã trạng thái
Lấy message value.message()
(Dạng extension function)
String chuỗi mô tả trạng thái
Lấy limit value.limit()
(Dạng extension function)
int giới hạn dữ liệu của dữ liệu tìm được
Lấy offset value.offset()
(Dạng extension function)
int vị trí bắt đầu của dữ liệu tìm được
Lấy total value.total()
(Dạng extension function)
int tổng số lượng dữ liệu
Lấy kiểu sắp xếp value.isSort()
(Dạng extension function)
String kiểu sắp xếp dữ liệu