Flutter来电界面集成插件waterbus_callkit_incoming的使用

Flutter来电界面集成插件waterbus_callkit_incoming的使用

A Flutter 插件用于在您的 Flutter 应用程序中显示来电界面(Android 自定义/Callkit 适用于 iOS)。

pub package pub points Build Status

Buy Me A Coffee

⭐ 特性

  • 显示来电
  • 开始通话
  • 自定义 Android/Callkit 适用于 iOS
  • 使用 Pushkit/VoIP 的示例

iOS: 仅在真机上工作,模拟器不支持(Callkit 框架在模拟器上不工作)

🚀 安装

1. 安装包

运行以下命令:

flutter pub add flutter_callkit_incoming

pubspec.yaml 中添加依赖项:

dependencies:
  flutter_callkit_incoming: any

2. 配置项目

Android

AndroidManifest.xml 中添加以下权限:

<manifest...>
    ...
    <!-- 
        使用以从互联网加载图像
    -->
    <uses-permission android:name="android.permission.INTERNET"/>
</manifest>

proguard-rules.pro 中添加以下规则以避免混淆密钥:

-keep class com.hiennv.flutter_callkit_incoming.** { *; }
iOS

Info.plist 中添加以下配置:

<key>UIBackgroundModes</key>
<array>
    <string>voip</string>
    <string>remote-notification</string>
    <string>processing</string> <!-- 如果需要可以添加此条目 -->
</array>

3. 使用

导入
import 'package:flutter_callkit_incoming/flutter_callkit_incoming.dart';
接收到来电
this._currentUuid = _uuid.v4();
CallKitParams callKitParams = CallKitParams(
  id: _currentUuid,
  nameCaller: 'Hien Nguyen',
  appName: 'Callkit',
  avatar: 'https://i.pravatar.cc/100',
  handle: '0123456789',
  type: 0,
  textAccept: 'Accept',
  textDecline: 'Decline',
  missedCallNotification: NotificationParams(
      showNotification: true,
      isShowCallback: true,
      subtitle: 'Missed call',
      callbackText: 'Call back',
  ),
  duration: 30000,
  extra: <String, dynamic>{'userId': '1a2b3c4d'},
  headers: <String, dynamic>{'apiKey': 'Abc@123!', 'platform': 'flutter'},
  android: const AndroidParams(
      isCustomNotification: true,
      isShowLogo: false,
      ringtonePath: 'system_ringtone_default',
      backgroundColor: '#0955fa',
      backgroundUrl: 'assets/test.png',
      actionColor: '#4CAF50',
      incomingCallNotificationChannelName: "Incoming Call",
      missedCallNotificationChannelName: "Missed Call"
  ),
  ios: IOSParams(
    iconName: 'CallKitLogo',
    handleType: 'generic',
    supportsVideo: true,
    maximumCallGroups: 2,
    maximumCallsPerCallGroup: 1,
    audioSessionMode: 'default',
    audioSessionActive: true,
    audioSessionPreferredSampleRate: 44100.0,
    audioSessionPreferredIOBufferDuration: 0.005,
    supportsDTMF: true,
    supportsHolding: true,
    supportsGrouping: false,
    supportsUngrouping: false,
    ringtonePath: 'system_ringtone_default',
  ),
);
await FlutterCallkitIncoming.showCallkitIncoming(callKitParams);

注意:对于 Firebase 消息,请使用 @pragma('vm:entry-point')

请求通知权限(Android 13+)

对于 Android 13 及以上版本,请在调用 showCallkitIncoming 之前请求通知权限:

await FlutterCallkitIncoming.requestNotificationPermission({
  "rationaleMessagePermission": "通知权限是必需的,以便显示通知。",
  "postNotificationMessageRequired": "通知权限是必需的,请从设置中允许通知权限。"
});
显示未接来电通知
this._currentUuid = _uuid.v4();
CallKitParams params = CallKitParams(
  id: _currentUuid,
  nameCaller: 'Hien Nguyen',
  handle: '0123456789',
  type: 1,
  textMissedCall: 'Missed call',
  textCallback: 'Call back',
  extra: <String, dynamic>{'userId': '1a2b3c4d'},
);
await FlutterCallkitIncoming.showMissCallNotification(params);
开始外呼
this._currentUuid = _uuid.v4();
CallKitParams params = CallKitParams(
  id: this._currentUuid,
  nameCaller: 'Hien Nguyen',
  handle: '0123456789',
  type: 1,
  extra: <String, dynamic>{'userId': '1a2b3c4d'},
  ios: IOSParams(handleType: 'generic')
);
await FlutterCallkitIncoming.startCall(params);
结束来电
await FlutterCallkitIncoming.endCall(this._currentUuid);
结束所有来电
await FlutterCallkitIncoming.endAllCalls();
获取活跃的通话
await FlutterCallkitIncoming.activeCalls();

输出:

[{"id": "8BAA2B26-47AD-42C1-9197-1D75F662DF78", ...}]
设置通话已连接状态(仅限 iOS)
await FlutterCallkitIncoming.setCallConnected(this._currentUuid);

在通话被接受或开始通话后调用此函数。通常在 WebRTC/P2P 建立时调用。

获取设备 VoIP 推送令牌
await FlutterCallkitIncoming.getDevicePushTokenVoIP();

输出:

d6a77ca80c5f09f87f353cdd328ec8d7d34e92eb108d046c91906f27f54949cd

确保在 AppDelegate.swift 中使用 SwiftFlutterCallkitIncomingPlugin.sharedInstance?.setDevicePushTokenVoIP(deviceToken)(示例:Example

func pushRegistry(_ registry: PKPushRegistry, didUpdate credentials: PKPushCredentials, for type: PKPushType) {
    print(credentials.token)
    let deviceToken = credentials.token.map { String(format: "%02x", $0) }.joined()
    // Save deviceToken to your server
    SwiftFlutterCallkitIncomingPlugin.sharedInstance?.setDevicePushTokenVoIP(deviceToken)
}
    
func pushRegistry(_ registry: PKPushRegistry, didInvalidatePushTokenFor type: PKPushType) {
    print("didInvalidatePushTokenFor")
    SwiftFlutterCallkitIncomingPlugin.sharedInstance?.setDevicePushTokenVoIP("")
}
监听事件
FlutterCallkitIncoming.onEvent.listen((CallEvent event) {
  switch (event!.event) {
    case Event.actionCallIncoming:
      // TODO: 收到来电
      break;
    case Event.actionCallStart:
      // TODO: 开始外呼
      // TODO: 在 Flutter 中显示呼叫屏幕
      break;
    case Event.actionCallAccept:
      // TODO: 接受来电
      // TODO: 在 Flutter 中显示呼叫屏幕
      break;
    case Event.actionCallDecline:
      // TODO: 拒绝来电
      break;
    case Event.actionCallEnded:
      // TODO: 结束来电
      break;
    case Event.actionCallTimeout:
      // TODO: 未接来电
      break;
    case Event.actionCallCallback:
      // TODO: 仅限 Android - 点击未接来电通知中的“回拨”
      break;
    case Event.actionCallToggleHold:
      // TODO: 仅限 iOS
      break;
    case Event.actionCallToggleMute:
      // TODO: 仅限 iOS
      break;
    case Event.actionCallToggleDmtf:
      // TODO: 仅限 iOS
      break;
    case Event.actionCallToggleGroup:
      // TODO: 仅限 iOS
      break;
    case Event.actionCallToggleAudioSession:
      // TODO: 仅限 iOS
      break;
    case Event.actionDidUpdateDevicePushTokenVoip:
      // TODO: 仅限 iOS
      break;
    case Event.actionCallCustom:
      // TODO: 自定义动作
      break;
  }
});
从原生代码调用(iOS/Android)
// Swift iOS
var info = [String: Any?]()
info["id"] = "44d915e1-5ff4-4bed-bf13-c423048ec97a"
info["nameCaller"] = "Hien Nguyen"
info["handle"] = "0123456789"
info["type"] = 1
//... 设置更多数据
SwiftFlutterCallkitIncomingPlugin.sharedInstance?.showCallkitIncoming(flutter_callkit_incoming.Data(args: info), fromPushKit: true)

// 请确保在 pushRegistry(......, completion: @escaping () -> Void) 调用 completion() 或
// DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) { completion() }
// 如果不在 pushRegistry(......, completion: @escaping () -> Void) 调用 completion(),则在接收 VoIP 时可能会导致系统崩溃
// Kotlin/Java Android
FlutterCallkitIncomingPlugin.getInstance().showIncomingNotification(...)
// 或者
let data = flutter_callkit_incoming.Data(id: "44d915e1-5ff4-4bed-bf13-c423048ec97a", nameCaller: "Hien Nguyen", handle: "0123456789", type: 0)
data.nameCaller = "Johnny"
data.extra = ["user": "abc@123", "platform": "ios"]
//... 设置更多数据
SwiftFlutterCallkitIncomingPlugin.sharedInstance?.showCallkitIncoming(data, fromPushKit: true)
// 发送自定义事件
SwiftFlutterCallkitIncomingPlugin.sharedInstance?.sendEventCustom(body: ["customKey": "customValue"])
// Kotlin/Java Android
FlutterCallkitIncomingPlugin.getInstance().sendEventCustom(body: Map<String, Any>)

更多关于Flutter来电界面集成插件waterbus_callkit_incoming的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter来电界面集成插件waterbus_callkit_incoming的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


waterbus_callkit_incoming 是一个用于在 Flutter 应用中集成来电界面的插件。它可以帮助你在应用中显示一个类似系统来电的界面,支持接听、挂断等操作。以下是使用 waterbus_callkit_incoming 插件的基本步骤。

1. 添加依赖

首先,在 pubspec.yaml 文件中添加 waterbus_callkit_incoming 插件的依赖:

dependencies:
  flutter:
    sdk: flutter
  waterbus_callkit_incoming: ^1.0.0  # 请使用最新版本

然后运行 flutter pub get 来获取依赖。

2. 初始化插件

在你的 Dart 代码中,首先需要初始化插件。通常可以在 main.dart 文件中进行初始化:

import 'package:waterbus_callkit_incoming/waterbus_callkit_incoming.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  
  // 初始化插件
  await WaterbusCallkitIncoming().initialize();

  runApp(MyApp());
}

3. 显示来电界面

当你需要显示来电界面时,可以调用 showCallkitIncoming 方法:

void showIncomingCall() {
  WaterbusCallkitIncoming().showCallkitIncoming(
    uuid: "123456",  // 唯一标识符
    nameCaller: "John Doe",  // 来电者姓名
    handle: "1234567890",  // 来电号码
    avatar: "https://example.com/avatar.png",  // 来电者头像
    type: 0,  // 0: 来电, 1: 去电
    duration: 30000,  // 来电持续时间(毫秒)
    acceptText: "接听",  // 接听按钮文本
    declineText: "挂断",  // 挂断按钮文本
    missedCallNotification: true,  // 是否显示未接来电通知
    extra: <String, dynamic>{"userId": "1"},  // 额外信息
  );
}

4. 监听事件

你可以监听来电的相关事件,例如接听、挂断等:

WaterbusCallkitIncoming().onEvent.listen((event) {
  switch (event!.name) {
    case EventType.actionCallAccept:
      // 用户接听电话
      break;
    case EventType.actionCallDecline:
      // 用户挂断电话
      break;
    case EventType.actionCallEnded:
      // 电话结束
      break;
    case EventType.actionCallTimeout:
      // 来电超时
      break;
    case EventType.actionCallCallback:
      // 用户点击了回调按钮
      break;
    case EventType.actionCallToggleHold:
      // 用户切换了保持状态
      break;
    case EventType.actionCallToggleMute:
      // 用户切换了静音状态
      break;
    case EventType.actionCallToggleDmtf:
      // 用户输入了DTMF
      break;
    case EventType.actionCallToggleGroup:
      // 用户切换了群组通话
      break;
    case EventType.actionCallToggleAudioSession:
      // 用户切换了音频会话
      break;
  }
});

5. 结束来电

当通话结束时,可以调用 endCall 方法来结束来电界面:

void endCall() {
  WaterbusCallkitIncoming().endCall("123456");  // 使用与来电相同的uuid
}

6. 处理未接来电

如果你启用了未接来电通知,可以在 onEvent 中处理未接来电事件,并在需要时显示通知。

7. 权限处理

在 Android 上,你可能需要处理一些权限,例如 READ_PHONE_STATECALL_PHONE。确保在 AndroidManifest.xml 中添加相应的权限声明:

<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.CALL_PHONE" />
回到顶部