fix(mobile-next): 清理悬浮窗、语音文案与位置发送

按 B-273 / B-269 收口 Android 客户端:去掉悬浮窗申请与旧浮窗服务,通话入口统一为语音通话,删除位置发送与定位权限,保留历史位置只读展示。

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
编码工程师
2026-08-21 10:04:39 +08:00
co-authored by Cursor multica-agent
parent 092039bc1a
commit 694891c393
20 changed files with 662 additions and 726 deletions
@@ -1,6 +1,5 @@
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:collection/collection.dart';
import 'package:flutter/services.dart';
@@ -88,7 +87,8 @@ mixin OpenIMLive {
});
}
Stream<CallEvent> get _stream => signalingSubject.stream /*.where((event) => LiveClient.dispatchSignaling(event))*/;
Stream<CallEvent> get _stream => signalingSubject
.stream /*.where((event) => LiveClient.dispatchSignaling(event))*/;
_signalingListener() => _stream.listen(
(event) async {
@@ -97,15 +97,13 @@ mixin OpenIMLive {
_playSound(vibrate: true);
final mediaType = event.data.invitation!.mediaType;
final sessionType = event.data.invitation!.sessionType;
final callType = mediaType == 'audio' ? CallType.audio : CallType.video;
final callObj = sessionType == ConversationType.single ? CallObj.single : CallObj.group;
final callType =
mediaType == 'audio' ? CallType.audio : CallType.video;
final callObj = sessionType == ConversationType.single
? CallObj.single
: CallObj.group;
if (Platform.isAndroid && _isRunningBackground) {
_beCalledEvent = event;
if (await Permissions.checkSystemAlertWindow()) {
return;
}
}
// 不再申请/依赖悬浮窗:后台来电也走应用内通话页,切回前台可继续。
_beCalledEvent = null;
OpenIMLiveClient().start(
Get.overlayContext!,
@@ -151,7 +149,8 @@ mixin OpenIMLive {
_stopSound();
} else if (event.state == CallState.beAccepted) {
_stopSound();
} else if (event.state == CallState.otherReject || event.state == CallState.otherAccepted) {
} else if (event.state == CallState.otherReject ||
event.state == CallState.otherAccepted) {
_stopSound();
} else if (event.state == CallState.timeout) {
insertSignalingMessageSubject.add(event);
@@ -257,15 +256,19 @@ mixin OpenIMLive {
onRoomDisconnected(SignalingInfo signalingInfo) {}
Future<SignalingCertificate> onDialSingle(SignalingInfo signaling) async {
final data = {'customType': CustomMessageType.callingInvite, 'data': signaling.invitation!.toJson()};
final message = await OpenIM.iMManager.messageManager
.createCustomMessage(data: jsonEncode(data), extension: '', description: '');
final data = {
'customType': CustomMessageType.callingInvite,
'data': signaling.invitation!.toJson()
};
final message = await OpenIM.iMManager.messageManager.createCustomMessage(
data: jsonEncode(data), extension: '', description: '');
OpenIM.iMManager.messageManager.sendMessage(
message: message,
offlinePushInfo: OfflinePushInfo(),
userID: signaling.invitation!.inviteeUserIDList!.first,
isOnlineOnly: true);
final certificate = await getRtcCertificate(signaling.invitation!.roomID!, OpenIM.iMManager.userID);
final certificate = await getRtcCertificate(
signaling.invitation!.roomID!, OpenIM.iMManager.userID);
return certificate;
}
@@ -283,15 +286,19 @@ mixin OpenIMLive {
_beCalledEvent = null; // ios bug
_autoPickup = false;
_stopSound();
final data = {'customType': CustomMessageType.callingAccept, 'data': signaling.invitation!.toJson()};
final message = await OpenIM.iMManager.messageManager
.createCustomMessage(data: jsonEncode(data), extension: '', description: '');
final data = {
'customType': CustomMessageType.callingAccept,
'data': signaling.invitation!.toJson()
};
final message = await OpenIM.iMManager.messageManager.createCustomMessage(
data: jsonEncode(data), extension: '', description: '');
OpenIM.iMManager.messageManager.sendMessage(
message: message,
offlinePushInfo: OfflinePushInfo(),
userID: signaling.invitation!.inviterUserID,
isOnlineOnly: true);
final certificate = await getRtcCertificate(signaling.invitation!.roomID!, OpenIM.iMManager.userID);
final certificate = await getRtcCertificate(
signaling.invitation!.roomID!, OpenIM.iMManager.userID);
return certificate;
}
@@ -300,35 +307,52 @@ mixin OpenIMLive {
_stopSound();
insertSignalingMessageSubject.add(CallEvent(CallState.reject, signaling));
final data = {'customType': CustomMessageType.callingReject, 'data': signaling.invitation!.toJson()};
final message = await OpenIM.iMManager.messageManager
.createCustomMessage(data: jsonEncode(data), extension: '', description: '');
final recvUserID = signaling.invitation!.inviterUserID == OpenIM.iMManager.userID
? signaling.invitation!.inviteeUserIDList!.first
: signaling.invitation!.inviterUserID;
return OpenIM.iMManager.messageManager
.sendMessage(message: message, offlinePushInfo: OfflinePushInfo(), userID: recvUserID, isOnlineOnly: true);
final data = {
'customType': CustomMessageType.callingReject,
'data': signaling.invitation!.toJson()
};
final message = await OpenIM.iMManager.messageManager.createCustomMessage(
data: jsonEncode(data), extension: '', description: '');
final recvUserID =
signaling.invitation!.inviterUserID == OpenIM.iMManager.userID
? signaling.invitation!.inviteeUserIDList!.first
: signaling.invitation!.inviterUserID;
return OpenIM.iMManager.messageManager.sendMessage(
message: message,
offlinePushInfo: OfflinePushInfo(),
userID: recvUserID,
isOnlineOnly: true);
}
onTapCancel(SignalingInfo signaling) async {
_stopSound();
insertSignalingMessageSubject.add(CallEvent(CallState.cancel, signaling));
final data = {'customType': CustomMessageType.callingCancel, 'data': signaling.invitation!.toJson()};
final message = await OpenIM.iMManager.messageManager
.createCustomMessage(data: jsonEncode(data), extension: '', description: '');
final recvUserID = signaling.invitation!.inviterUserID == OpenIM.iMManager.userID
? signaling.invitation!.inviteeUserIDList!.first
: signaling.invitation!.inviterUserID;
OpenIM.iMManager.messageManager
.sendMessage(message: message, offlinePushInfo: OfflinePushInfo(), userID: recvUserID, isOnlineOnly: true);
final data = {
'customType': CustomMessageType.callingCancel,
'data': signaling.invitation!.toJson()
};
final message = await OpenIM.iMManager.messageManager.createCustomMessage(
data: jsonEncode(data), extension: '', description: '');
final recvUserID =
signaling.invitation!.inviterUserID == OpenIM.iMManager.userID
? signaling.invitation!.inviteeUserIDList!.first
: signaling.invitation!.inviterUserID;
OpenIM.iMManager.messageManager.sendMessage(
message: message,
offlinePushInfo: OfflinePushInfo(),
userID: recvUserID,
isOnlineOnly: true);
return true;
}
onTimeoutCancelled(SignalingInfo signaling) async {
final data = {'customType': CustomMessageType.callingCancel, 'data': signaling.invitation!.toJson()};
final message = await OpenIM.iMManager.messageManager
.createCustomMessage(data: jsonEncode(data), extension: '', description: '');
final data = {
'customType': CustomMessageType.callingCancel,
'data': signaling.invitation!.toJson()
};
final message = await OpenIM.iMManager.messageManager.createCustomMessage(
data: jsonEncode(data), extension: '', description: '');
OpenIM.iMManager.messageManager.sendMessage(
message: message,
@@ -349,14 +373,21 @@ mixin OpenIMLive {
onTapHangup(SignalingInfo signaling, int duration, bool isPositive) async {
if (isPositive) {
final data = {'customType': CustomMessageType.callingHungup, 'data': signaling.invitation!.toJson()};
final message = await OpenIM.iMManager.messageManager
.createCustomMessage(data: jsonEncode(data), extension: '', description: '');
final recvUserID = signaling.invitation!.inviterUserID == OpenIM.iMManager.userID
? signaling.invitation!.inviteeUserIDList!.first
: signaling.invitation!.inviterUserID;
OpenIM.iMManager.messageManager
.sendMessage(message: message, offlinePushInfo: OfflinePushInfo(), userID: recvUserID, isOnlineOnly: true);
final data = {
'customType': CustomMessageType.callingHungup,
'data': signaling.invitation!.toJson()
};
final message = await OpenIM.iMManager.messageManager.createCustomMessage(
data: jsonEncode(data), extension: '', description: '');
final recvUserID =
signaling.invitation!.inviterUserID == OpenIM.iMManager.userID
? signaling.invitation!.inviteeUserIDList!.first
: signaling.invitation!.inviterUserID;
OpenIM.iMManager.messageManager.sendMessage(
message: message,
offlinePushInfo: OfflinePushInfo(),
userID: recvUserID,
isOnlineOnly: true);
}
_stopSound();
@@ -389,7 +420,8 @@ mixin OpenIMLive {
return list.firstOrNull;
}
Future<List<GroupMembersInfo>> onSyncGroupMemberInfo(groupID, userIDList) async {
Future<List<GroupMembersInfo>> onSyncGroupMemberInfo(
groupID, userIDList) async {
var list = await OpenIM.iMManager.groupManager.getGroupMembersInfo(
groupID: groupID,
userIDList: userIDList,
@@ -412,7 +444,8 @@ mixin OpenIMLive {
void _startIncomingVibrate() {
_stopIncomingVibrate();
_pulseVibrate();
_incomingVibrateTimer = Timer.periodic(Styles.callVibrate, (_) => _pulseVibrate());
_incomingVibrateTimer =
Timer.periodic(Styles.callVibrate, (_) => _pulseVibrate());
}
void _stopIncomingVibrate() {
@@ -467,7 +500,8 @@ mixin OpenIMLive {
receiverID = inviteeUserID;
}
var msg = await OpenIM.iMManager.messageManager.insertSingleMessageToLocalStorage(
var msg = await OpenIM.iMManager.messageManager
.insertSingleMessageToLocalStorage(
receiverID: inviteeUserID,
senderID: inviterUserID,
message: message
@@ -495,7 +529,9 @@ class SignalingMessageEvent {
bool get isSingleChat => sessionType == ConversationType.single;
bool get isGroupChat => sessionType == ConversationType.group || sessionType == ConversationType.superGroup;
bool get isGroupChat =>
sessionType == ConversationType.group ||
sessionType == ConversationType.superGroup;
}
extension MessageMangerExt on MessageManager {