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

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

配置插件

首先,我们需要配置 flutter_callkit_incoming_yoer 插件。以下是需要修改的地方:

AndroidManifest.xml

<activity
    android:name=".MainActivity"
    android:exported="false"
    ...

build.gradle

确保 compileOptionskotlinOptions 设置为相同的版本:

compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
}

kotlinOptions {
    jvmTarget = '1.8'
}

完整示例代码

以下是一个完整的示例代码,展示了如何使用 flutter_callkit_incoming_yoer 插件来实现一个简单的来电界面。

main.dart

import 'dart:async';

import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/material.dart';
import 'package:flutter_callkit_incoming_yoer/entities/entities.dart';
import 'package:flutter_callkit_incoming_yoer/flutter_callkit_incoming.dart';
import 'package:flutter_callkit_incoming_example/app_router.dart';
import 'package:flutter_callkit_incoming_example/navigation_service.dart';
import 'package:uuid/uuid.dart';

Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
  print("Handling a background message: ${message.messageId}");
  await Firebase.initializeApp(); // 确保 Firebase 已初始化
  showCallkitIncoming(const Uuid().v4());
}

Future<void> showCallkitIncoming(String uuid) async {
  final params = CallKitParams(
    id: uuid,
    nameCaller: 'Hien Nguyen',
    appName: 'Callkit',
    avatar: 'https://i.pravatar.cc/100',
    handle: '0123456789',
    type: 0,
    duration: 30000,
    textAccept: 'Accept',
    textDecline: 'Decline',
    missedCallNotification: const NotificationParams(
      showNotification: true,
      isShowCallback: true,
      subtitle: 'Missed call',
      callbackText: 'Call back',
    ),
    extra: {'userId': '1a2b3c4d'},
    headers: {'apiKey': 'Abc@123!', 'platform': 'flutter'},
    android: const AndroidParams(
      isCustomNotification: true,
      isShowLogo: false,
      ringtonePath: 'system_ringtone_default',
      backgroundColor: '#0955fa',
      backgroundUrl: 'assets/test.png',
      actionColor: '#4CAF50',
      textColor: '#ffffff',
    ),
    ios: const IOSParams(
      iconName: 'CallKitLogo',
      handleType: '',
      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(params);
}

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  [@override](/user/override)
  MyAppState createState() => MyAppState();
}

class MyAppState extends State<MyApp> with WidgetsBindingObserver {
  late final Uuid _uuid;
  String? _currentUuid;

  late final FirebaseMessaging _firebaseMessaging;

  [@override](/user/override)
  void initState() {
    super.initState();
    _uuid = const Uuid();
    initFirebase();
    WidgetsBinding.instance.addObserver(this);
    // 检查打开应用时是否有正在进行的通话
    checkAndNavigationCallingPage();
  }

  Future<dynamic> getCurrentCall() async {
    // 检查当前通话(如果有)
    var calls = await FlutterCallkitIncoming.activeCalls();
    if (calls is List) {
      if (calls.isNotEmpty) {
        print('DATA: $calls');
        _currentUuid = calls[0]['id'];
        return calls[0];
      } else {
        _currentUuid = "";
        return null;
      }
    }
  }

  Future<void> checkAndNavigationCallingPage() async {
    var currentCall = await getCurrentCall();
    if (currentCall != null) {
      NavigationService.instance.pushNamedIfNotCurrent(AppRoute.callingPage, args: currentCall);
    }
  }

  [@override](/user/override)
  Future<void> didChangeAppLifecycleState(AppLifecycleState state) async {
    print(state);
    if (state == AppLifecycleState.resumed) {
      // 检查从后台唤醒应用时是否有正在进行的通话
      checkAndNavigationCallingPage();
    }
  }

  [@override](/user/override)
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  Future<void> initFirebase() async {
    await Firebase.initializeApp();
    _firebaseMessaging = FirebaseMessaging.instance;
    FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
    FirebaseMessaging.onMessage.listen((RemoteMessage message) async {
      print('Message title: ${message.notification?.title}, body: ${message.notification?.body}, data: ${message.data}');
      _currentUuid = _uuid.v4();
      showCallkitIncoming(_currentUuid!);
    });
    _firebaseMessaging.getToken().then((token) {
      print('Device Token FCM: $token');
    });
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.light(),
      onGenerateRoute: AppRoute.generateRoute,
      initialRoute: AppRoute.homePage,
      navigatorKey: NavigationService.instance.navigationKey,
      navigatorObservers: [NavigationService.instance.routeObserver],
    );
  }

  Future<void> getDevicePushTokenVoIP() async {
    var devicePushTokenVoIP = await FlutterCallkitIncoming.getDevicePushTokenVoIP();
    print(devicePushTokenVoIP);
  }
}

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

1 回复

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


flutter_callkit_incoming 是一个用于在 Flutter 应用中集成来电界面的插件,特别是在 VoIP 应用中非常有用。它提供了与 iOS 的 CallKit 和 Android 的自定义来电界面的集成。

以下是使用 flutter_callkit_incoming 插件的基本步骤:

1. 添加依赖

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

dependencies:
  flutter:
    sdk: flutter
  flutter_callkit_incoming: ^1.4.0

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

2. 导入插件

在需要使用插件的 Dart 文件中导入插件:

import 'package:flutter_callkit_incoming/flutter_callkit_incoming.dart';

3. 初始化插件

在应用启动时初始化插件,通常可以在 main() 函数中完成:

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

  runApp(MyApp());
}

4. 配置来电界面

你可以使用 FlutterCallkitIncoming.showCallkitIncoming() 方法来显示来电界面。以下是一个简单的示例:

void showIncomingCall(String uuid, String callerName, String callerNumber) async {
  var params = <String, dynamic>{
    'id': uuid,
    'nameCaller': callerName,
    'appName': 'MyApp',
    'avatar': 'https://example.com/avatar.png', // 可选,来电者头像
    'handle': callerNumber,
    'type': 0, // 0 for voice call, 1 for video call
    'duration': 30000, // 通话时长(毫秒)
    'textAccept': 'Accept', // 接听按钮文本
    'textDecline': 'Decline', // 拒绝按钮文本
    'textMissedCall': 'Missed Call', // 未接来电文本
    'textCallback': 'Callback', // 回拨按钮文本
    'extra': <String, dynamic>{'userId': '1a2b3c4d'}, // 自定义数据
  };

  await FlutterCallkitIncoming.showCallkitIncoming(params);
}

5. 处理来电事件

你可以监听来电事件,例如用户接听、拒绝或未接来电。以下是一个示例:

void listenCallkitEvents() {
  FlutterCallkitIncoming.onEvent.listen((event) async {
    switch (event!.event) {
      case Event.actionCallAccept:
        // 用户接听来电
        print('Call accepted');
        break;
      case Event.actionCallDecline:
        // 用户拒绝来电
        print('Call declined');
        break;
      case Event.actionCallEnded:
        // 通话结束
        print('Call ended');
        break;
      case Event.actionCallTimeout:
        // 未接来电
        print('Missed call');
        break;
      case Event.actionCallCallback:
        // 用户点击回拨
        print('Callback clicked');
        break;
      case Event.actionCallToggleHold:
        // 用户切换保持状态
        print('Call hold toggled');
        break;
      case Event.actionCallToggleMute:
        // 用户切换静音状态
        print('Call muted toggled');
        break;
      case Event.actionCallToggleDmtf:
        // 用户发送双音多频信号
        print('DTMF sent');
        break;
      case Event.actionCallToggleGroup:
        // 用户切换群组通话
        print('Call group toggled');
        break;
      case Event.actionCallToggleAudioSession:
        // 用户切换音频会话
        print('Audio session toggled');
        break;
    }
  });
}

6. 结束通话

你可以使用 FlutterCallkitIncoming.endCall() 方法来结束通话:

void endCall(String uuid) async {
  await FlutterCallkitIncoming.endCall(uuid);
}

7. 启动应用时恢复通话状态

如果应用在后台时收到来电,你可以在应用启动时恢复通话状态:

void restoreCallkitCalls() async {
  var calls = await FlutterCallkitIncoming.activeCalls();
  if (calls.isNotEmpty) {
    // 处理恢复通话的逻辑
    print('Active calls: $calls');
  }
}

8. 后台模式(iOS)

在 iOS 上,你需要在 Info.plist 文件中添加以下配置来支持后台模式:

<key>UIBackgroundModes</key>
<array>
  <string>audio</string>
  <string>voip</string>
</array>

9. 权限(Android)

在 Android 上,你需要在 AndroidManifest.xml 文件中添加以下权限:

<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />

10. 启动应用时处理未接来电

你可以在应用启动时检查是否有未接来电,并显示通知或执行其他操作:

void checkMissedCalls() async {
  var missedCalls = await FlutterCallkitIncoming.getMissedCalls();
  if (missedCalls.isNotEmpty) {
    // 处理未接来电的逻辑
    print('Missed calls: $missedCalls');
  }
}
回到顶部