Flutter使用Agora实现应用关闭时呼起视频通话界面方案咨询
实现方案(Android+iOS通用逻辑)
核心前提
- 首先要申请系统*悬浮窗(出现在其他应用上层)*权限,这是在应用外显示通话界面的基础
- 集成Agora RTM(实时消息)组件做呼叫信令监听,即使主应用进程被回收,也要通过保活的后台服务/推送通道唤醒信令监听
- 音视频流的初始化可以放到独立的Service组件中,不和主应用页面生命周期绑定
Android端实现代码
首先在AndroidManifest.xml中添加必要权限:
<!-- 悬浮窗权限 --> <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> <!-- 前台服务权限 --> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE_CAMERA" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE_MICROPHONE" />
编写后台监听呼叫信令的前台服务代码:
public class CallMonitorService extends Service { private RtmClient mRtmClient; private final String APP_ID = "替换为你的Agora App ID"; @Override public void onCreate() { super.onCreate(); // 初始化RTM客户端监听呼叫信令 try { mRtmClient = RtmClient.createInstance(this, APP_ID, new RtmClientListener() { @Override public void onMessageReceived(RtmMessage rtmMessage, String peerId) { // 匹配自定义呼叫信令,收到后唤起通话界面 if ("invite_call".equals(rtmMessage.getText())) { showCallNotification(peerId); launchFloatingCallActivity(peerId); } } }); } catch (Exception e) { e.printStackTrace(); } } // 启动前台服务保活,避免被系统回收 @Override public int onStartCommand(Intent intent, int flags, int startId) { Notification notification = buildForegroundNotification(); startForeground(1001, notification); return START_STICKY; } // 唤起悬浮窗通话页面 private void launchFloatingCallActivity(String callerId) { Intent intent = new Intent(this, FloatingCallActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); intent.putExtra("caller_id", callerId); startActivity(intent); } }
给悬浮窗通话页面添加特殊配置,在AndroidManifest.xml中声明对应属性:
<activity android:name=".FloatingCallActivity" android:exported="true" android:showOnLockScreen="true" android:turnScreenOn="true" android:theme="@style/Theme.Transparent.Floating" />
iOS端实现代码
首先在Info.plist中添加必要权限和后台模式:
<key>NSMicrophoneUsageDescription</key> <string>需要麦克风权限进行语音通话</string> <key>NSCameraUsageDescription</key> <string>需要摄像头权限进行视频通话</string> <key>UIBackgroundModes</key> <array> <string>audio</string> <string>voip</string> </array>
基于PushKit实现后台呼叫唤醒逻辑:
import PushKit import AgoraRtmKit class CallHandler: NSObject, PKPushRegistryDelegate { let rtmKit: AgoraRtmKit? = AgoraRtmKit(appId: "替换为你的Agora App ID", delegate: nil) func registerVoIPPush() { let pushRegistry = PKPushRegistry(queue: DispatchQueue.main) pushRegistry.delegate = self pushRegistry.desiredPushTypes = [.voIP] } func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType, completion: @escaping () -> Void) { guard type == .voIP else { completion() return } // 收到VoIP推送后唤起通话界面 let callVC = FloatingCallViewController() callVC.callerId = payload.dictionaryPayload["caller_id"] as? String // 获取当前顶层窗口展示通话页面 if let keyWindow = UIApplication.shared.windows.first(where: { $0.isKeyWindow }) { keyWindow.rootViewController?.present(callVC, animated: true) } completion() } }
注意事项
- 不同Android厂商的后台权限限制不同,需要额外引导用户开启应用的自启动、后台活动权限,否则服务被杀死后无法监听呼叫
- iOS端必须使用VoIP推送来唤醒应用,普通推送无法直接唤起通话界面,且需要符合苹果的VoIP推送规范,否则会被拒审
- Agora的音视频引擎不需要和主进程绑定,放到独立的服务/模块中即可保证通话流程不被主应用生命周期影响
内容的提问来源于stack exchange,提问作者Hasnain Saeed
相关产品推荐
相关产品推荐

