Flutter VoIP通信插件voip24h_sdk_mobile的使用

Flutter VoIP通信插件voip24h_sdk_mobile的使用


Flutter Voip24h-SDK Mobile #

pub package

目录 #

功能 #

功能 描述
CallKit • 登录/登出/刷新SIP账户连接
• 拨打电话/接听来电
• 接受/拒绝/挂断来电
• 暂停/恢复通话
• 保持/取消保持通话
• 开启/关闭麦克风
• 获取麦克风状态
• 开启/关闭扬声器
• 获取扬声器状态
• 转接通话
• 发送DTMF音
Graph • 获取访问令牌
• 请求API(参考https://docs-sdk.voip24h.vn/)

要求 #

  • 操作系统平台:
    • Android -> minSdkVersion: 23
    • IOS -> iOS Deployment Target: 9.0
  • 权限:在运行时声明和授权
    • Android: 在文件 AndroidManifest.xml

      <uses-permission android:name="android.permission.INTERNET" />
      <uses-permission android:name="android.permission.RECORD_AUDIO"/>
      
    • IOS: 在文件 Info.plist

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

安装 #

使用终端:

flutter pub add voip24h_sdk_mobile

关联模块:

  • IOS:
    • 在 ios/Podfile 文件中:
      ...
      # 声明库
      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__))
      
      # 声明库 
      pod 'linphone-sdk-novideo' , '5.1.36'
      

      end

    • 在 ios 文件夹打开终端,输入以下命令:
      rm -rf Pods/
      pod install
      

模块声明 #

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: 使用模块

CallKit #

  • 声明 sipConfiguration: #

    var sipConfiguration = SipConfigurationBuilder(extension: "extension", domain: "domain", password: "password")
                            .setKeepAlive(true/false) // 可选参数(布尔值)
                            .setPort(port) // 可选参数(整数)
                            .setTransport(TransportType.Udp/TransportType.Tcp/TransportType.Tls) // 可选参数(枚举类型)
                            .build(); 
    
功能
方法和参数
(使用异步/等待或.then来获取返回数据)
返回结果及属性
初始化 Voip24hSdkMobile.callModule.initSipModule(sipConfiguration) 无
获取SIP账户注册状态 Voip24hSdkMobile.callModule.getSipRegistrationState() value: String
error: String
注销SIP账户 Voip24hSdkMobile.callModule.unregisterSipAccount() value: bool
error: String
刷新SIP账户 Voip24hSdkMobile.callModule.refreshSipAccount() value: bool
error: String
拨打电话 Voip24hSdkMobile.callModule.call(phoneNumber) value: bool
error: String
挂断电话 Voip24hSdkMobile.callModule.hangup() value: bool
error: String
接听来电 Voip24hSdkMobile.callModule.answer() value: bool
error: String
拒绝来电 Voip24hSdkMobile.callModule.reject() value: bool
error: String
转接通话 Voip24hSdkMobile.callModule.transfer("extension") value: bool
error: String
获取通话ID Voip24hSdkMobile.callModule.getCallId() value: String
error: String
获取未接来电数量 Voip24hSdkMobile.callModule.getMissedCalls() value: int
error: String
暂停通话 Voip24hSdkMobile.callModule.pause() value: bool
error: String
恢复通话 Voip24hSdkMobile.callModule.resume() value: bool
error: String
开启/关闭麦克风 Voip24hSdkMobile.callModule.toggleMic() value: bool
error: String
获取麦克风状态 Voip24hSdkMobile.callModule.isMicEnabled() value: bool
error: String
开启/关闭扬声器 Voip24hSdkMobile.callModule.toggleSpeaker() value: bool
error: String
获取扬声器状态 Voip24hSdkMobile.callModule.isSpeakerEnabled() value: bool
error: String
发送DTMF音 Voip24hSdkMobile.callModule.sendDTMF("number#") value: bool
error: String
  • 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(); }

事件名称
返回结果及属性
属性特性
SipEvent.AccountRegistrationStateChanged body = {
  registrationState: String,
  message: String
}
registrationState: SIP连接状态 (None/Progress/Ok/Cleared/Failed)
message: 描述状态的字符串
SipEvent.Ring body = {
  extension: String,
  phoneNumber: String
  callType: String
}
extension: 分机号
phoneNumber: 来电号码
callType: 通话类型(inbound/outbound)
SipEvent.Up body = {
  callId: String
}
callId: 通话ID
SipEvent.Hangup body = {
  duration: int
}
duration: 通话时长(毫秒)
SipEvent.Paused 无
SipEvent.Resuming 无
SipEvent.Missed body = {
  phoneNumber: String,
  totalMissed: int
}
phoneNumber: 来电号码
totalMissed: 总未接来电数
SipEvent.Error body = {
  message: String
}
message: 错误信息

推送通知 #

  • IOS: 我们使用Apple Push Notification service (APNs) 进行后台状态下的来电推送通知
    • 步骤1: 创建APNs Auth Key
      • 访问Apple Developer创建证书
        9
      • 选择VoIP Services Certificate 7
      • 选择你的应用ID。每个想使用VoIP服务的应用都需要单独的VoIP服务证书。VoIP服务证书绑定到应用ID上,允许服务器通知(Voip24h)连接到VoIP服务以向你的应用发送推送通知。
        8
      • 下载证书并用Keychain Access打开
        11
      • 将证书导出为.p12格式
        12
      • 将.p12格式的证书转换为.pem格式并提交给Voip24h配置
        openssl pkcs12 -in path_your_certificate.p12 -out path_your_certificate.pem -nodes
        
  • 步骤2: 配置你的项目以接收来电推送通知 -> 从iOS 10开始,使用CallKit + PushKit

    • Callkit 允许你在你的应用中显示系统级别的通话界面,并协调你的呼叫服务与其它应用和系统。
    • PushKit 支持专门的通知类型以接收VoIP来电。
    • 为了使用CallKit框架+PushKit框架,我们推荐使用库callkeep,在pubspec.yaml中添加:
      dependencies:
          ....
          callkeep:
          git:
            url: https://github.com/Voip24h-Corp/callkeep
            ref: master
      

      然后运行命令:

      flutter pub get
      cd ios
      pod install
      
      • 在你的项目中添加Push Notifications,并选择Voice over IP,Background fetch,Remote notifications,Background processing(Background Modes)。 5 6
      • 当启动应用时,callkeep会为应用客户生成注册令牌。使用该令牌注册到服务器Voip24h。
      import 'package:callkeep/callkeep.dart';
      ...
      callKeep.on<CallKeepPushKitToken>((value) => {
        tokenPushIOS = value.token ?? ""
      });
      callKeep.setup(context, <String, dynamic>{
        'ios': {
          'appName': 'Example',
        }
      });
      

      // tokenGraph: 通过API Graph生成的访问令牌 // token: 通过pushkit生成的设备令牌 // sipConfiguration: SIP注册时的参数 // isIOS: 默认为false // appId: iOS应用的Bundle ID // isProduction: true(生产环境) / false(开发环境) // deviceMac: 设备MAC地址

      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) });

      必须在使用推送通知功能前在iOS上授予通知权限。

      • 注册接收来自Voip24h服务器的推送通知

      • 重要提示: 接收到来自Voip24h服务器的推送通知后,根据上述的Callkit和PushKit机制,你必须首先显示系统的通话界面(假的通话),然后立即重新登录分机以接收来自Voip24h的真实通话信号,此时所有如接听/拒绝等通话操作才能正常工作。

      callKeep.on<CallKeepReceivedPushNotification>((value) => {
        callId = value.callId ?? "",
        testCallKit()
      });
      callKeep.on<CallKeepPerformAnswerCallAction>((value) => {
        answer()
      });
      callKeep.on<CallKeepPerformEndCallAction>((value) => {
        reject()
      });
      
      • 取消注册接收推送通知
      Voip24hSdkMobile.pushNotificationModule.unregisterPushNotification(
          sipConfiguration: sipConfiguration,
          isIOS: true,
          appId: packageInfo.packageName
      ).then((value) => {
        print(value)
      }, onError: (error) => {
        print(error)
      });
      
    • Android: 我们使用Firebase Cloud Messaging (FCM) 进行后台状态下的来电推送通知
      • 步骤1: 创建API Token
        • 在Firebase控制台创建一个项目
          1
        • 注册Android应用
          2
          • 下载google-services.json文件并将其添加到你的应用项目中
            3
        • 在Firebase项目设置中创建Cloud Messaging API (Legacy) Token,并将此Token提交给Voip24h进行配置
          4
      • 步骤2: 配置你的项目以接收来电推送通知 -> 我们建议你使用库Firebase Messaging
        • Flutter包:
        flutter pub add firebase_core
        flutter pub add firebase_messaging
        

        根据Firebase Messaging文档配置你的项目

        • 当启动应用时,Firebase Messaging会为应用客户生成注册令牌。使用该令牌注册到服务器Voip24h
          String? token = await messaging.getToken();
            ....
          if(token != null) {
              // tokenGraph: 通过API Graph生成的访问令牌
          // token: 通过Firebase生成的设备令牌
          // sipConfiguration: SIP注册时的参数
          // isAndroid: 默认为false
          // appId: Android应用的包名
          // isProduction: true(生产环境) / false(开发环境)
          // deviceMac: 设备MAC地址
          

          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) }); }

          • 从Android 13 (SDK 32) 开始,接收推送通知需要请求通知权限 https://developer.android.com/develop/ui/views/notifications/notification-permission。请确保在使用前请求POST_NOTIFICATIONS权限。
            • 配置接收推送通知。当收到推送通知时,请重新注册分机以接收来电信号
              [@pragma](/user/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
                })
              });
              }
              }
              
            • 取消注册接收推送通知
            Voip24hSdkMobile.pushNotificationModule.unregisterPushNotification(
                sipConfiguration: sipConfiguration,
                isAndroid: true,
                appId: packageInfo.packageName
            ).then((value) => {
              print(value)
            }, onError: (error) => {
              print(error)
            });
            

      Graph #

      • key和security certificate由Voip24h提供
      • 请求API: 方法,端点。数据主体可参考https://docs-sdk.voip24h.vn/文档

      功能
      方法
      参数说明
      返回结果
      返回结果属性
      获取访问令牌 Voip24hSdkMobile.graphModule.getAccessToken(apiKey: API_KEY, apiSecert: API_SECERT) • apiKey: String,
      • secert: String
      value: Oauth
      error: String
      • Oauth: 包含的属性 (token, createAt, expired, isLongAlive)
      • error: 错误信息
      请求API Voip24hSdkMobile.graphModule.sendRequest(token: token, endpoint: endpoint, body: body) • method: MethodRequest(MethodRequest.POST, MethodRequest.GET,...)
      • endpoint: 请求URL的末尾部分:"call/find", "call/findone",...
      • token: 访问令牌
      • params: 数据主体对象如 { "offset": "0", "limit": "25" }
      value: Map<String, dynamic>
      error: String
      • value: 返回结果的形式为键值对
      • error: 错误码
      获取数据对象 value.getData()
      (扩展函数形式)
      无 object: Object object包含的数据属性可参考https://docs-sdk.voip24h.vn/文档中的返回结果描述
      获取数据对象列表 value.getDataList()
      (扩展函数形式)
      无 List<Object> 每个object包含的数据属性可参考https://docs-sdk.voip24h.vn/文档中的返回结果描述
      获取状态码 value.statusCode()
      (扩展函数形式)
      无 int 状态码
      获取消息 value.message()
      (扩展函数形式)
      无 String 描述状态的字符串
      获取限制 value.limit()
      (扩展函数形式)
      无 int 找到数据的数量限制
      获取偏移量 value.offset()
      (扩展函数形式)
      无 int 找到数据的起始位置
      获取总数 value.total()
      (扩展函数形式)
      无 int 数据的总数量
      获取排序方式 value.isSort()
      (扩展函数形式)
      无 String 数据的排序方式


更多关于Flutter VoIP通信插件voip24h_sdk_mobile的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter VoIP通信插件voip24h_sdk_mobile的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何在Flutter项目中使用voip24h_sdk_mobile插件进行VoIP通信的示例代码。请注意,这只是一个基本的示例,具体实现可能需要根据您的实际需求进行调整。同时,确保您已经按照插件的官方文档完成了必要的配置和权限申请。

首先,您需要在pubspec.yaml文件中添加voip24h_sdk_mobile插件的依赖:

dependencies:
  flutter:
    sdk: flutter
  voip24h_sdk_mobile: ^最新版本号  # 请替换为插件的实际最新版本号

然后,运行flutter pub get来安装依赖。

接下来,我们需要在Flutter项目中初始化VoIP SDK,并进行基本的通话操作。以下是一个示例代码:

import 'package:flutter/material.dart';
import 'package:voip24h_sdk_mobile/voip24h_sdk_mobile.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: VoIPPage(),
    );
  }
}

class VoIPPage extends StatefulWidget {
  @override
  _VoIPPageState createState() => _VoIPPageState();
}

class _VoIPPageState extends State<VoIPPage> {
  VoIP24hSdk? voipSdk;

  @override
  void initState() {
    super.initState();
    // 初始化VoIP SDK
    initVoIPSdk();
  }

  void initVoIPSdk() async {
    // 替换为您的API Key和Secret
    String apiKey = "YOUR_API_KEY";
    String apiSecret = "YOUR_API_SECRET";

    voipSdk = VoIP24hSdk(apiKey: apiKey, apiSecret: apiSecret);

    // 注册VoIP回调(例如来电、挂断等)
    voipSdk?.setCallEventListener((callEvent) {
      if (callEvent.type == CallEventType.Incoming) {
        // 处理来电
        showDialog(
          context: context,
          builder: (context) => AlertDialog(
            title: Text("来电"),
            content: Text("来自: ${callEvent.callerId}"),
            actions: [
              TextButton(
                onPressed: () {
                  // 拒绝来电
                  voipSdk?.rejectCall(callEvent.callId);
                  Navigator.of(context).pop();
                },
                child: Text("拒绝"),
              ),
              TextButton(
                onPressed: () {
                  // 接听来电
                  voipSdk?.acceptCall(callEvent.callId);
                  Navigator.of(context).pop();
                },
                child: Text("接听"),
              ),
            ],
          ),
        );
      } else if (callEvent.type == CallEventType.Ended) {
        // 处理通话结束
        print("通话结束: ${callEvent.callId}");
      }
    });

    // 注册VoIP服务(确保在后台运行时也能接收来电)
    await voipSdk?.registerVoIPService();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("VoIP通信示例"),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            TextButton(
              onPressed: () async {
                // 发起通话(替换为实际的被叫号码)
                String calleeId = "callee_id";
                await voipSdk?.makeCall(calleeId);
              },
              child: Text("发起通话"),
            ),
          ],
        ),
      ),
    );
  }

  @override
  void dispose() {
    // 注销VoIP服务并释放资源
    voipSdk?.unregisterVoIPService();
    voipSdk = null;
    super.dispose();
  }
}

在这个示例中,我们完成了以下操作:

  1. 在pubspec.yaml中添加了voip24h_sdk_mobile插件的依赖。
  2. 在VoIPPage中初始化了VoIP SDK,并设置了来电回调。
  3. 提供了发起通话和接听/拒绝来电的基本功能。
  4. 在dispose方法中注销了VoIP服务并释放了资源。

请注意,这只是一个基本的示例。在实际应用中,您可能还需要处理更多的细节,如音频管理、UI优化、错误处理等。同时,确保您已经阅读并理解了voip24h_sdk_mobile插件的官方文档,以便更好地集成和使用该插件。

回到顶部