Flutter CallKit Incoming:应用终止时接听电话功能失效
Flutter CallKit 终止状态接听按钮无响应解决方案
核心原因
应用处于终止状态时,Flutter引擎未启动,flutter_callkit_incoming的Dart侧事件回调无法触发,必须通过原生端先唤醒应用,再将通话事件传递到Flutter层处理。
分平台处理方案
iOS端配置
- 扩展
AppDelegate实现CXProviderDelegate,处理CallKit的接听回调,通过MethodChannel传递事件到Flutter:
import Flutter import CallKit @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate, CXProviderDelegate { private var methodChannel: FlutterMethodChannel? override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { let controller = window?.rootViewController as! FlutterViewController methodChannel = FlutterMethodChannel(name: "callkit_event_channel", binaryMessenger: controller.binaryMessenger) // 初始化CallKit Provider let config = CXProviderConfiguration(localizedName: "你的通话应用") config.supportsVideo = true config.maximumCallGroups = 1 let provider = CXProvider(configuration: config) provider.setDelegate(self, queue: nil) GeneratedPluginRegistrant.register(with: self) return super.application(application, didFinishLaunchingWithOptions: launchOptions) } // 处理来电接听事件 func provider(_ provider: CXProvider, perform action: CXAnswerCallAction) { action.fulfill() // 传递通话ID到Flutter methodChannel?.invokeMethod("acceptCall", arguments: ["callId": action.callUUID.uuidString]) } }
- 在Xcode中开启Background Modes的
Voice over IP权限(项目配置 -> Signing & Capabilities -> 添加Background Modes)。
Android端配置
- 创建广播接收器处理接听事件,唤醒应用并传递通话参数:
import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import io.flutter.embedding.android.FlutterActivity class CallKitAcceptReceiver : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { val callId = intent?.getStringExtra("call_id") ?: return // 启动应用并携带通话ID val launchIntent = Intent(context, FlutterActivity::class.java).apply { putExtra("launch_from_call", true) putExtra("call_id", callId) addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP) } context?.startActivity(launchIntent) } }
- 在
AndroidManifest.xml中注册接收器:
<receiver android:name=".CallKitAcceptReceiver"> <intent-filter> <action android:name="com.your.package.ACCEPT_CALL" /> </intent-filter> </receiver>
- 配置CallKit通知的PendingIntent时,指定上述广播作为触发目标。
Flutter端处理
在应用启动时检查启动参数,判断是否是从终止状态被接听事件唤醒,直接跳转通话界面:
import 'package:flutter/services.dart'; import 'package:flutter/material.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); final initialData = await _getInitialCallData(); runApp(MyApp(initialCallData: initialData)); } Future<Map<String, dynamic>?> _getInitialCallData() async { const channel = MethodChannel('callkit_event_channel'); try { // 读取原生传递的启动参数 final args = await channel.invokeMethod('getInitialCallArgs'); if (args != null && args['callId'] != null) { return args; } } catch (e) { debugPrint('读取启动参数失败: $e'); } return null; } class MyApp extends StatelessWidget { final Map<String, dynamic>? initialCallData; const MyApp({super.key, this.initialCallData}); @override Widget build(BuildContext context) { return MaterialApp( initialRoute: initialCallData != null ? '/call_screen' : '/home', routes: { '/home': (context) => const HomeScreen(), '/call_screen': (context) => CallScreen(callId: initialCallData!['callId']), }, ); } }
注意事项
- 测试终止状态时,必须完全关闭应用(后台划掉),不能仅退到后台。
- Android需确保应用拥有
WAKE_LOCK权限,可在AndroidManifest.xml中添加:<uses-permission android:name="android.permission.WAKE_LOCK" /> - iOS需确保CallKit的配置与应用的权限申请一致,避免被系统拦截。
内容的提问来源于stack exchange,提问作者Kavita Patel
相关产品推荐
相关产品推荐

