Flutter语音通信插件twilio_voice_mimp的使用
Flutter语音通信插件twilio_voice_mimp的使用
提供了与Twilio的Programmable Voice SDK接口,允许将VoIP(Voice over Internet Protocol)通话集成到您的Flutter应用程序中。
此插件是从原始的flutter_twilio_voice分离出来的,因为它似乎不再被维护。此插件将继续维护。
特性
- 在iOS设备上接收和拨打电话,使用CallKit接收来电。
- 在Android设备上接收和拨打电话,使用自定义UI接收来电。
Android限制
由于iOS有CallKit(苹果提供的接听电话的UI),而安卓没有默认的UI来接收来电,因此为安卓制作了默认的UI。为了增加可定制性,UI将使用在res/drawable
文件夹注册的splash_icon.png
图标。如果找到一种定制颜色的方法,请提交一个Pull Request。
设置
请遵循Twilio的快速设置指南进行每个平台的设置。虽然不需要编写原生代码,但可以帮助您了解如何设置服务器、为iOS应用注册VOIP等基本功能。
iOS设置
要自定义CallKit调用时显示的图标,请打开XCode并添加一个名为callkit_icon
的png图标到您的assets.xassets
文件夹。
Android设置
在AndroidManifest.xml
中注册负责显示来电通知的服务:
<Application>
.....
<service
android:name="com.twilio.twilio_voice.fcm.VoiceFirebaseMessagingService"
android:stopWithTask="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
</Application>
使用
该插件分为两个类:TwilioVoice.instance
和 TwilioVoice.instance.call
。前者负责一般配置,后者负责管理通话。
注册iOS能力
- 添加音频和VoIP背景模式。
TwilioVoice.instance
设置令牌
当应用启动时,调用TwilioVoice.instance.setTokens
。
accessToken
:从服务器提供的访问令牌,您可以查看示例云函数这里。deviceToken
:iOS上自动处理,对于Android,您需要传递FCM令牌。
调用TwilioVoice.instance.unregister
以注销Twilio,如果没有访问令牌,则将使用在setTokens
中提供的同一会话中的令牌。
呼叫标识符
由于来电UI在后台显示,甚至在接收到呼叫时应用可以关闭,您可以将呼叫标识符(如firebaseAuth
用户ID)映射到真实名称。此操作必须在实际接收呼叫之前完成。因此,如果您有一个聊天应用,并且知道成员的名字,可以注册它们,以便当他们呼叫时,呼叫UI可以显示他们的名字而不是用户ID。
注册客户端
TwilioVoice.instance.registerClient(String clientId, String clientName);
取消注册客户端
TwilioVoice.instance.unregisterClient(String clientId);
默认来电者
您还可以设置一个默认来电者,例如“未知号码”或“聊天朋友”,以防来电来自未注册的客户端。
TwilioVoice.instance.setDefaultCallerName(String callerName);
呼叫事件
使用流TwilioVoice.instance.callEventsListener
接收来自TwilioSDK的事件,例如呼叫事件和日志。这是一个广播,因此可以在应用的不同部分监听它。当应用未启动时,可能会错过某些事件,请参阅示例项目以查找解决方法。
发送的事件包括:
- ringing(响铃)
- connected(已连接)
- callEnded(呼叫结束)
- unhold(取消保持)
- hold(保持)
- unmute(取消静音)
- mute(静音)
- speakerOn(扬声器开启)
- speakerOff(扬声器关闭)
- log(日志)
- answer(接听)
显示未接来电通知
默认情况下,在用户错过呼叫后,会向用户显示本地通知。点击通知将回拨用户。要移除此功能,请将showMissedCallNotifications
设置为false
。
呼叫
拨打呼叫
await TwilioVoice.instance.call.place(from: myId, to: clientId, extraOptions);
静音呼叫
TwilioVoice.instance.call.toggleMute(isMuted: true);
切换扬声器
TwilioVoice.instance.call.toggleSpeaker(speakerIsOn: true);
挂断
TwilioVoice.instance.call.hangUp();
发送数字
TwilioVoice.instance.call.sendDigits(String digits);
权限
麦克风
接收和拨打呼叫需要麦克风权限,在iOS的info.plist
中注册麦克风权限。
您可以使用TwilioVoice.instance.hasMicAccess
和TwilioVoice.instance.requestMicAccess
检查和请求权限。在接收到呼叫时也会自动请求权限。
后台呼叫(仅限Android某些设备)
小米设备等可能需要特殊权限才能接收后台呼叫。使用TwilioVoice.instance.requiresBackgroundPermissions
检查您的设备是否需要特殊权限,如果需要,请解释用户为什么需要此权限。最后调用TwilioVoice.instance.requestBackgroundPermissions
,这将引导用户到应用设置页面以启用权限。
本地化
由于一些UI是原生代码,因此您需要在项目中本地化这些字符串。您可以在示例项目中找到西班牙语的本地化,欢迎其他语言的PR。
Twilio设置/快速入门帮助
Twilio使用云函数生成访问令牌并将其发送到您的应用。此外,Twilio还使用自己的应用程序TwiML来处理呼叫功能等。
要设置Twilio,有两个主要组件:
- 云函数(生成访问令牌和处理呼叫请求的功能)
- 移动应用(接收/更新令牌并执行实际呼叫)
1) 云函数
云函数可以分开或组合在一起。主要的两个组件是:
- 生成访问令牌
make-call
端点以实际拨打电话
您可以将两者托管在Firebase,TwiML应用程序或混合使用。以下设置假设是混合方式,其中Firebase Functions托管access-token
以方便与Flutter集成,TwiML托管make-call
函数。
云函数步骤1:创建您的TwiML应用
这将允许您实际拨打电话。
先决条件
- 一个Twilio帐户。如果没有?免费注册!
应用程序设置
从GitHub获取这个项目,即示例TwiML应用。
cp .env.example .env
编辑.env
文件,使用上面收集的三个配置参数。
见配置环境下的详细信息
接下来,我们需要从npm安装依赖项:
npm install
为了简化您的工作,进入src/
文件夹,将server.js
文件重命名为make-call
。这假设每个函数都有自己的文件,这对于新项目来说是个不错的想法。
然后添加以下代码:
const AccessToken = require('twilio').jwt.AccessToken;
const VoiceGrant = AccessToken.VoiceGrant;
const VoiceResponse = require('twilio').twiml.VoiceResponse;
/**
* 创建一个端点,可以用作TwiML App的语音请求URL。
*
* 为了使用Twilio Voice SDK拨打电话,您需要在访问令牌中提供TwiML App SID。您可以运行您的服务器,使其公开可用,并将`/makeCall`端点作为TwiML App的语音请求URL。
*
* @returns {Object} - 用于响应出站呼叫的Response对象
* @param context
* @param event
* @param callback
*/
exports.handler = function(context, event, callback) {
// 调用的接收者,一个电话号码或客户端
console.log(event);
const from = event.From;
let to = event.to;
if(isEmptyOrNull(to)) {
to = event.To;
if(isEmptyOrNull(to)) {
console.error("无法找到要呼叫的人");
to = undefined;
}
}
const voiceResponse = new VoiceResponse();
if (!to) {
voiceResponse.say("欢迎,您刚刚打了第一个电话。");
} else if (isNumber(to)) {
const dial = voiceResponse.dial({callerId : callerNumber});
dial.number(to);
} else {
console.log(`正在呼叫 [${from}] -> [${to}]`);
const dial = voiceResponse.dial({callerId: to, timeout: 30, record: "record-from-answer-dual", trim: "trim-silence"});
dial.client(to);
}
callback(null, voiceResponse);
}
const isEmptyOrNull = (s) => {
return !s || s === '';
}
安装Twilio CLI
确保您已登录到twilio-cli
。首先,使用以下命令安装twilio-cli
:
npm i twilio-cli -g
之后,使用以下命令登录到Twilio(请提供Twilio账户SID和AuthToken):
twilio login
我们需要生成一个应用,这将给我们一个App SID,稍后在Firebase函数中使用(见此处了解更多详情)。
创建TwiML应用
我们需要创建一个TwiML应用,这将允许我们托管make-call
函数:
twilio api:core:applications:create \
--friendly-name=my-twiml-app \
--voice-method=POST \
--voice-url="https://my-quickstart-dev.twil.io/make-call"
这将为您提供一个格式为APxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
的应用程序SID,我们将稍后在Firebase配置和生成推送凭证密钥中使用它。
非常重要! 这里提供的URL https://my-quickstart-dev.twil.io/make-call
对您无效。一旦部署了您的TwiML应用(稍后),您将获得一个URL(首次部署时),您需要复制并粘贴为您的请求URL
。如果不这样做,呼叫将无法正常工作!
配置环境
确保您在项目的根目录下有一个.env
文件,与package.json
在同一目录下。
接下来,编辑.env
文件,格式如下:
ACCOUNT_SID=(插入您的账户SID)
APP_SID=(插入TwiML应用中的App SID,或上述APxxxxx密钥)
API_KEY
和API_KEY_SECRET
在这里不是必需的,因为我们不会使用它们。
获取推送凭证
我们将在稍后生成它们
您将获得一个格式为CRxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
的推送凭证SID,将其用于PUSH_CREDENTIAL_SID
。
部署
现在让我们部署。
请注意: 确保您已经配置好环境
导航到根目录,使用以下命令部署:
twilio serverless:deploy
非常重要! 一旦完成(如果尚未完成),请确保将make-call
端点添加到您的Twilio应用的请求URL
中。此URL将在部署文本中显示。如果不这样做,呼叫将无法正常工作!
云函数步骤2:设置Firebase和配置
Twilio的配置存储在.runtimeconfig.json
中,包含:
"auth_token": "",
"account_sid": "",
"app_sid": "",
"phone": "",
"api_key": "",
"api_key_secret": "",
"android_push_credential": "",
"apple_push_credential_debug": "",
"apple_push_credential_release": ""
注意: 这用于本地模拟器测试,但在您准备上线时,您需要将这些部署到您的Firebase函数应用中。如果不这样做,这将不起作用!
推送凭证是一次性创建的(针对iOS和Android),用于生成access-token
,这是所有Twilio应用用于其通信的回调函数。
以下是生成推送凭证所需的三个操作,这些推送凭证应添加到上述.runtimeconfig.json
中
Android
要生成Android推送凭证,请从Firebase FCM获取Cloud Messaging服务器密钥,并将其添加到以下内容:
twilio api:chat:v2:credentials:create \
--type=fcm \
--friendly-name="voice-push-credential-fcm" \
--secret=SERVER_KEY_VALUE
然后将其放入字段:android_push_credential
中
这将生成一个格式为CRxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
的推送凭证SID,必须用于生成Android设备的访问令牌。
iOS
类似于Android,但步骤更多,包括使用.p12证书。要获取这些证书,请登录到Apple开发者网站并转到证书页面。您需要生成一个VoIP服务证书,如下所示。
请注意: 有两种不同的模式:沙盒和生产。
- 沙盒模式
使用沙盒VoIP证书:
$ openssl pkcs12 -in PATH_TO_YOUR_SANDBOX_P12 -nokeys -out sandbox_cert.pem -nodes
$ openssl pkcs12 -in PATH_TO_YOUR_SANDBOX_P12 -nocerts -out sandbox_key.pem -nodes
$ openssl rsa -in sandbox_key.pem -out sandbox_key.pem
使用沙盒证书生成凭证:
twilio api:chat:v2:credentials:create \
--type=apn \
--sandbox \
--friendly-name="voice-push-credential (sandbox)" \
--certificate="$(cat PATH_TO_SANDBOX_CERT_PEM)" \
--private-key="$(cat PATH_TO_SANDBOX_KEY_PEM)"
然后将其放入字段apple_push_credential_debug
中
- 生产模式
使用生产VoIP证书:
$ openssl pkcs12 -in PATH_TO_YOUR_P12 -nokeys -out prod_cert.pem -nodes
$ openssl pkcs12 -in PATH_TO_YOUR_P12 -nocerts -out prod_key.pem -nodes
$ openssl rsa -in prod_key.pem -out prod_key.pem
使用生产证书生成凭证:
twilio api:chat:v2:credentials:create \
--type=apn \
--friendly-name="voice-push-credential (production)" \
--certificate="$(cat PATH_TO_PROD_CERT_PEM)" \
--private-key="$(cat PATH_TO_PROD_KEY_PEM)"
然后将其放入字段apple_push_credential_release
中
云函数步骤3:通过云函数生成访问令牌
GET api-voice-accessToken
要生成access-tokens
,将使用以下Firebase函数:
请注意,默认的有效期为1小时。
有关更多信息,请参阅:https://github.com/twilio/voice-quickstart-android/blob/master/Docs/access-token.md
Firebase Cloud Function: access-token
const { AccessToken } = require('twilio').jwt;
const functions = require('firebase-functions');
const { VoiceGrant } = AccessToken;
/**
* 使用您的Twilio凭据创建带有VoiceGrant的访问令牌。
*
* @param {Object} request - 提供呼叫接收者的POST或GET请求,一个电话号码或客户端
* @param {Object} response - HTTP请求的响应对象
* @returns {string} - 访问令牌字符串及其过期日期(毫秒)
*/
exports.accessToken = functions.https.onCall((payload, context) => {
// 检查用户是否已认证
if (typeof (context.auth) === 'undefined') {
throw new functions.https.HttpsError('unauthenticated', '该函数必须在认证后调用');
}
let userId = context.auth.uid;
console.log('为', userId, '创建访问令牌');
// 使用Firebase环境变量进行配置
const twilioConfig = functions.config().twilio;
const accountSid = twilioConfig.account_sid;
const apiKey = twilioConfig.api_key;
const apiSecret = twilioConfig.api_key_secret;
const outgoingApplicationSid = twilioConfig.app_sid;
// 专门用于创建语音令牌,我们需要为每个平台使用单独的推送凭证。
// iOS有不同的APNs环境,所以我们需要区分沙盒和生产,因为一个不能在另一个环境中工作。
let pushCredSid;
if (payload.isIOS === true) {
console.log('为iOS创建访问令牌');
pushCredSid = payload.production ? twilioConfig.apple_push_credential_release
: (twilioConfig.apple_push_credential_debug || twilioConfig.apple_push_credential_release);
} else if (payload.isAndroid === true) {
console.log('为Android创建访问令牌');
pushCredSid = twilioConfig.android_push_credential;
} else {
throw new functions.https.HttpsError('unknown_platform', '未指定平台');
}
// 生成有效期为24小时的令牌 - 最小3分钟,最大24小时,默认1小时
const dateTime = new Date();
dateTime.setDate(dateTime.getDate() + 1);
// 创建一个访问令牌,我们将对其进行签名并返回给客户端,
// 包含我们刚创建的授予
const voiceGrant = new VoiceGrant({
outgoingApplicationSid,
pushCredentialSid: pushCredSid,
});
// 创建一个访问令牌,我们将对其进行签名并返回给客户端,
// 包含我们刚创建的授予
const token = new AccessToken(accountSid, apiKey, apiSecret);
token.addGrant(voiceGrant);
// 使用Firebase ID作为身份
token.identity = userId;
console.log(`Token:${token.toJwt()}`);
// 返回JSON对象
return {
"jwt_token": token.toJwt(),
"expiry_date": dateTime.getTime()
};
});
将上述函数添加到您的Firebase Functions应用中,详见创建Firebase Functions项目的帮助文档。
完成后,部署您的.runtimeconfig.json
,详见环境配置的帮助文档。
完成以上所有操作后,使用以下命令部署您的Firebase函数:
firebase deploy --only functions
更多关于Flutter语音通信插件twilio_voice_mimp的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter语音通信插件twilio_voice_mimp的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何使用 twilio_voice_mimp
插件进行 Flutter 语音通信的基本代码示例。这个插件允许你在 Flutter 应用中实现 Twilio 的语音通信功能。请注意,这只是一个基本的实现示例,你可能需要根据实际需求进行进一步的配置和优化。
首先,你需要在你的 Flutter 项目中添加 twilio_voice_mimp
插件。你可以通过在你的 pubspec.yaml
文件中添加以下依赖项来完成这一步:
dependencies:
flutter:
sdk: flutter
twilio_voice_mimp: ^最新版本号 # 请替换为实际的最新版本号
然后,运行 flutter pub get
来获取依赖项。
接下来,在你的 Flutter 应用中实现 Twilio 语音通信。以下是一个基本的实现示例:
-
配置 Twilio 凭证:
你需要在你的 Flutter 应用中配置 Twilio 的 Account SID 和 Auth Token。这些信息通常是从你的 Twilio 控制台获取的。
import 'package:twilio_voice_mimp/twilio_voice_mimp.dart'; void configureTwilio() { TwilioVoiceMimp.configure( accountSid: '你的Account SID', // 替换为你的Twilio Account SID authToken: '你的Auth Token', // 替换为你的Twilio Auth Token ); }
-
初始化 Twilio 语音通信:
在你的应用启动时,调用
configureTwilio
方法来初始化 Twilio 语音通信。void main() { WidgetsFlutterBinding.ensureInitialized(); configureTwilio(); runApp(MyApp()); }
-
拨打电话:
你可以使用
TwilioVoiceMimp.call
方法来拨打电话。import 'package:flutter/material.dart'; void makeCall(String toPhoneNumber) { TwilioVoiceMimp.call( to: toPhoneNumber, // 替换为你要拨打的电话号码 from: '你的Twilio Phone Number', // 替换为你的Twilio 电话号码 ).then((callSid) { print('Call SID: $callSid'); }).catchError((error) { print('Error making call: $error'); }); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar( title: Text('Twilio Voice Example'), ), body: Center( child: ElevatedButton( onPressed: () { makeCall('+1234567890'); // 替换为实际的电话号码 }, child: Text('Make Call'), ), ), ), ); } }
-
接听电话(可选):
如果你想处理来电,你需要监听 Twilio 的来电事件。这通常涉及到在后台运行一个服务来监听 Twilio 的 Webhook 请求,并在收到来电时通知你的 Flutter 应用。这超出了这个基本示例的范围,但你可以参考 Twilio 的文档来实现这一功能。
-
处理通话状态(可选):
你还可以监听通话状态的变化,例如通话开始、通话结束等。这可以通过监听
TwilioVoiceMimp
提供的回调来完成。TwilioVoiceMimp.onCallStarted.listen((call) { print('Call started: ${call.callSid}'); }); TwilioVoiceMimp.onCallEnded.listen((call) { print('Call ended: ${call.callSid}'); });
请注意,这只是一个基本的实现示例,你可能需要根据你的具体需求进行进一步的配置和优化。此外,由于 Twilio 的 API 和插件可能会随时间更新,因此请确保你查阅最新的文档和插件版本。