Flutter VoIP通信插件siprix_voip_sdk的使用
Flutter VoIP通信插件siprix_voip_sdk的使用
Siprix VoIP SDK 是一个用于在 Flutter 应用中嵌入基于 SIP/RTP 协议的语音和视频通话的插件。它支持多个平台,包括 Android、iOS、MacOS、Windows 和 Linux,并提供了一个统一的 API。
使用方法
1. 在 pubspec.yaml
中添加依赖
dependencies:
siprix_voip_sdk: ^1.0.3
provider: ^6.1.1
2. 添加导入
import 'package:provider/provider.dart';
import 'package:siprix_voip_sdk/accounts_model.dart';
import 'package:siprix_voip_sdk/network_model.dart';
import 'package:siprix_voip_sdk/calls_model.dart';
import 'package:siprix_voip_sdk/cdrs_model.dart';
import 'package:siprix_voip_sdk/devices_model.dart';
import 'package:siprix_voip_sdk/logs_model.dart';
import 'package:siprix_voip_sdk/siprix_voip_sdk.dart';
3. 准备模型
void main() async {
AccountsModel accountsModel = AccountsModel();
CallsModel callsModel = CallsModel(accountsModel);
runApp(
MultiProvider(providers:[
ChangeNotifierProvider(create: (context) => accountsModel),
ChangeNotifierProvider(create: (context) => callsModel),
],
child: const MyApp(),
));
}
4. 初始化 SDK
class _MyAppState extends State<MyApp> {
[@override](/user/override)
void initState() {
super.initState();
_initializeSiprix();
}
void _initializeSiprix([LogsModel? logsModel]) async {
InitData iniData = InitData();
iniData.license = "...license-credentials..."; // 替换为实际的许可证信息
iniData.logLevelFile = LogLevel.info;
//iniData.enableCallKit = true; <- 如果需要的话取消注释
SiprixVoipSdk().initialize(iniData, logsModel);
}
5. 构建 UI,添加账户/通话
Widget buildBody() {
final accounts = context.watch<AccountsModel>();
final calls = context.watch<CallsModel>();
return Column(children: [
ListView.separated(shrinkWrap: true,
itemCount: accounts.length,
separatorBuilder: (BuildContext context, int index) => const Divider(height: 1),
itemBuilder: (BuildContext context, int index) {
AccountModel acc = accounts[index];
return
ListTile(title: Text(acc.uri, style: Theme.of(context).textTheme.titleSmall),
subtitle: Text(acc.regText),
tileColor: Colors.blue
);
},
),
ElevatedButton(onPressed: _addAccount, child: const Icon(Icons.add_card)),
ElevatedButton(onPressed: _addCall, child: const Icon(Icons.add_call)),
// 其他UI组件
]);
}
void _addAccount() {
AccountModel account = AccountModel();
account.sipServer = "192.168.0.122";
account.sipExtension = "1016";
account.sipPassword = "12345";
account.expireTime = 300;
context.read<AccountsModel>().addAccount(account)
.catchError(showSnackBar);
}
void _addCall() {
final accounts = context.read<AccountsModel>();
if(accounts.selAccountId==null) return;
CallDestination dest = CallDestination("1012", accounts.selAccountId!, false);
context.read<CallsModel>().invite(dest)
.catchError(showSnackBar);
}
void showSnackBar(dynamic err) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(err)));
}
示例 Demo
以下是完整的示例代码,包含初始化、添加账户和发起通话的功能:
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:siprix_voip_sdk/accounts_model.dart';
import 'package:siprix_voip_sdk/network_model.dart';
import 'package:siprix_voip_sdk/calls_model.dart';
import 'package:siprix_voip_sdk/cdrs_model.dart';
import 'package:siprix_voip_sdk/devices_model.dart';
import 'package:siprix_voip_sdk/logs_model.dart';
import 'package:siprix_voip_sdk/subscriptions_model.dart';
import 'package:siprix_voip_sdk/siprix_voip_sdk.dart';
void main() async {
LogsModel logsModel = LogsModel(true); // 设置为false时不会在UI上渲染日志
CdrsModel cdrsModel = CdrsModel(); // 最近通话记录列表
DevicesModel devicesModel = DevicesModel(logsModel); // 设备列表
NetworkModel networkModel = NetworkModel(logsModel); // 网络状态详情
AccountsModel accountsModel = AccountsModel(logsModel); // 账户列表
CallsModel callsModel = CallsModel(accountsModel, logsModel, cdrsModel); // 通话列表
SubscriptionsModel subscrModel = SubscriptionsModel<BlfSubscrModel>(accountsModel, BlfSubscrModel.fromJson, logsModel); // 订阅列表
// 运行应用
runApp(
MultiProvider(providers:[
ChangeNotifierProvider(create: (context) => accountsModel),
ChangeNotifierProvider(create: (context) => networkModel),
ChangeNotifierProvider(create: (context) => devicesModel),
ChangeNotifierProvider(create: (context) => subscrModel),
ChangeNotifierProvider(create: (context) => callsModel),
ChangeNotifierProvider(create: (context) => cdrsModel),
ChangeNotifierProvider(create: (context) => logsModel),
],
child: const MyApp(),
));
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
static String _ringtonePath="";
[@override](/user/override)
State<MyApp> createState() => _MyAppState();
/// 返回设备上保存的铃声路径
static String getRingtonePath() => _ringtonePath;
/// 将资产文件写入设备
void writeRingtoneAsset() async {
_ringtonePath = await writeAssetAndGetFilePath("ringtone.mp3");
}
/// 将资产文件写入设备并返回其路径
static Future<String> writeAssetAndGetFilePath(String assetsFileName) async {
var homeFolder = await SiprixVoipSdk().homeFolder();
var filePath = '$homeFolder$assetsFileName';
var file = File(filePath);
var exists = file.existsSync();
debugPrint("writeAsset: '$filePath' exists:$exists");
if (exists) return filePath;
final byteData = await rootBundle.load('assets/$assetsFileName');
await file.create(recursive: true);
file.writeAsBytes(byteData.buffer.asUint8List(), flush: true);
return filePath;
}
/// 返回应用程序存储录制文件的文件夹路径
static Future<String> getRecFilePath(String recFileName) async {
var homeFolder = await SiprixVoipSdk().homeFolder();
var filePath = '$homeFolder$recFileName';
return filePath;
}
}
class _MyAppState extends State<MyApp> {
[@override](/user/override)
void initState() {
super.initState();
_initializeSiprix(context.read<LogsModel>());
widget.writeRingtoneAsset(); // 在初始化Siprix之后调用,因为它使用了'homeFolder'
_readSavedState();
}
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
routes: <String, WidgetBuilder>{
// 定义路由
},
home: const HomePage(),
title: 'Siprix VoIP app',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.indigo),
visualDensity: VisualDensity.adaptivePlatformDensity,
useMaterial3: true,
),
);
}
void _initializeSiprix(LogsModel? logsModel) async {
InitData iniData = InitData();
iniData.license = "...license-credentials..."; // 替换为实际的许可证信息
iniData.logLevelFile = LogLevel.debug;
iniData.logLevelIde = LogLevel.info;
//- 取消注释如果需要 -//
//iniData.listenTelState = true;
//iniData.singleCallMode = false;
//iniData.tlsVerifyServer = false;
//iniData.enableCallKit = true;
SiprixVoipSdk().initialize(iniData, logsModel);
// 设置视频参数(如果需要)
//VideoData vdoData = VideoData();
//vdoData.noCameraImgPath = await MyApp.writeAssetAndGetFilePath("noCamera.jpg");
//vdoData.bitrateKbps = 800;
//SiprixVoipSdk().setVideoParams(vdoData);
}
void _readSavedState() {
SharedPreferences.getInstance().then((prefs) {
String accJsonStr = prefs.getString('accounts') ?? '';
String subsJsonStr = prefs.getString('subscriptions') ?? '';
String cdrsJsonStr = prefs.getString('cdrs') ?? '';
_loadModels(accJsonStr, cdrsJsonStr, subsJsonStr);
});
}
void _loadModels(String accJsonStr, String cdrsJsonStr, String subsJsonStr) {
// 账户
AccountsModel accsModel = context.read<AccountsModel>();
accsModel.onSaveChanges = _saveAccountChanges;
// 订阅
SubscriptionsModel subsModel = context.read<SubscriptionsModel>();
subsModel.onSaveChanges = _saveSubscriptionChanges;
// 呼叫详情记录
CdrsModel cdrs = context.read<CdrsModel>();
cdrs.onSaveChanges = _saveCdrsChanges;
// 加载账户,然后加载其他模型
accsModel.loadFromJson(accJsonStr).then((val) {
subsModel.loadFromJson(subsJsonStr);
cdrs.loadFromJson(cdrsJsonStr);
});
// 分配联系人名称解析器
context.read<CallsModel>().onResolveContactName = _resolveContactName;
// 加载设备
context.read<DevicesModel>().load();
}
void _saveCdrsChanges(String cdrsJsonStr) {
SharedPreferences.getInstance().then((prefs) {
prefs.setString('cdrs', cdrsJsonStr);
});
}
void _saveAccountChanges(String accountsJsonStr) {
SharedPreferences.getInstance().then((prefs) {
prefs.setString('accounts', accountsJsonStr);
});
}
void _saveSubscriptionChanges(String subscrJsonStr) {
SharedPreferences.getInstance().then((prefs) {
prefs.setString('subscriptions', subscrJsonStr);
});
}
String _resolveContactName(String phoneNumber) {
return ""; //TODO 添加自己的实现
//if(phoneNumber=="100") { return "MyFriend100"; } else
//if(phoneNumber=="101") { return "MyFriend101"; }
//else { return ""; }
}
}
更多关于Flutter VoIP通信插件siprix_voip_sdk的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter VoIP通信插件siprix_voip_sdk的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是一个关于如何在Flutter项目中使用siprix_voip_sdk
插件进行VoIP通信的代码示例。这个插件允许你通过SIP协议进行音频和视频通话。请注意,在实际应用中,你需要确保你的Flutter环境和相关依赖已经正确配置。
1. 添加依赖
首先,你需要在你的pubspec.yaml
文件中添加siprix_voip_sdk
依赖:
dependencies:
flutter:
sdk: flutter
siprix_voip_sdk: ^最新版本号 # 请替换为实际可用的最新版本号
然后运行flutter pub get
来安装依赖。
2. 配置Android权限
在android/app/src/main/AndroidManifest.xml
中添加必要的权限:
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
3. 初始化SDK
在你的Flutter项目的lib/main.dart
文件中,初始化并配置siprix_voip_sdk
:
import 'package:flutter/material.dart';
import 'package:siprix_voip_sdk/siprix_voip_sdk.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
SiprixVoipSdk? siprixVoipSdk;
@override
void initState() {
super.initState();
initSiprixVoipSdk();
}
void initSiprixVoipSdk() async {
siprixVoipSdk = SiprixVoipSdk();
// 配置SIP账户
await siprixVoipSdk?.configureSipAccount(
sipUsername: 'your_sip_username',
sipPassword: 'your_sip_password',
sipDomain: 'your_sip_domain',
sipPort: 5060, // 默认SIP端口
transportType: SipTransportType.udp, // 或tcp, ws, wss等
);
// 注册SIP账户
siprixVoipSdk?.registerSipAccount()?.then((registrationResult) {
if (registrationResult) {
print('SIP Account Registered Successfully');
} else {
print('SIP Account Registration Failed');
}
});
// 监听来电事件
siprixVoipSdk?.onIncomingCall?.listen((callInfo) {
print('Incoming Call: ${callInfo.callerId}');
// 处理来电逻辑,如显示来电界面等
});
// 监听挂断事件
siprixVoipSdk?.onCallEnded?.listen((callInfo) {
print('Call Ended: ${callInfo.callId}');
// 处理挂断逻辑,如更新UI等
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Flutter VoIP Demo'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ElevatedButton(
onPressed: () async {
// 发起呼叫
await siprixVoipSdk?.makeCall('callee_sip_address');
},
child: Text('Make Call'),
),
ElevatedButton(
onPressed: () {
// 挂断当前呼叫
siprixVoipSdk?.endCall();
},
child: Text('End Call'),
),
],
),
),
),
);
}
}
4. 处理权限请求
在实际应用中,你还需要处理Android和iOS上的权限请求。这通常涉及在运行时检查并请求权限。由于篇幅限制,这里不展开详细说明,但你可以使用permission_handler
等Flutter插件来处理权限请求。
注意事项
- SIP服务器配置:确保你的SIP服务器地址、用户名和密码等信息正确无误。
- 网络配置:检查设备的网络连接,确保能够访问SIP服务器。
- 错误处理:在实际应用中,你应该添加更多的错误处理逻辑,以确保用户体验。
以上代码是一个基本的示例,展示了如何使用siprix_voip_sdk
进行VoIP通信。根据你的具体需求,你可能需要添加更多的功能和逻辑。