diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 9a9985d9..81dbbce1 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -1215,6 +1215,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = NAQ5PL2DYC; + GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = USE_CALLKIT; INFOPLIST_FILE = Runner/info_sky.plist; IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = ( diff --git a/ios/Runner/AppDelegate.m b/ios/Runner/AppDelegate.m index 555cd8c2..f750d38a 100755 --- a/ios/Runner/AppDelegate.m +++ b/ios/Runner/AppDelegate.m @@ -16,6 +16,7 @@ @property (nonatomic, strong) CXProvider *callKitProvider; @property (nonatomic, copy) NSString *pendingCallKitEvent; // 缓存未处理的CallKit事件 @property (nonatomic, strong) NSUUID *lastCallUUID; +@property (nonatomic, copy) NSString *voipTokenString; // + 新增:缓存VoIP Token @end @@ -75,6 +76,12 @@ NSLog(@"[CallKit] 无有效UUID,无法结束通话"); result(@"no_call"); } + } else if ([call.method isEqualToString:@"get_voip_token"]) { // + 新增 + if (weakSelf.voipTokenString) { + result(weakSelf.voipTokenString); + } else { + result(nil); + } } else { result(FlutterMethodNotImplemented); } @@ -227,6 +234,11 @@ [tokenString appendFormat:@"%02x", tokenBytes[i]]; } NSLog(@"[VoIP] didUpdatePushCredentials, token: %@", tokenString); + self.voipTokenString = tokenString; // + 缓存token + if (self.methodChannel) { + [self.methodChannel invokeMethod:@"voip_token" arguments:tokenString]; + } + // 若Flutter未ready,Flutter端可通过get_voip_token拉取 } } // 收到VoIP推送 diff --git a/ios/fastlane/Fastfile b/ios/fastlane/Fastfile index 2ab2fc24..0e4dd2b0 100644 --- a/ios/fastlane/Fastfile +++ b/ios/fastlane/Fastfile @@ -96,6 +96,7 @@ platform :ios do output_directory: $path_ipa_output_dir, output_name: ipa_default_filename, export_method: "ad-hoc", + xcargs: "GCC_PREPROCESSOR_DEFINITIONS='USE_CALLKIT=1 $(inherited)'", export_options: { provisioningProfiles: { "com.skychip.lock.dev" => "Adhoc_com.skychip.lock.dev.mobileprovision", diff --git a/lib/main.dart b/lib/main.dart index ca70354c..e49ab97e 100755 --- a/lib/main.dart +++ b/lib/main.dart @@ -67,6 +67,8 @@ FutureOr main() async { // ChangeNotifierProvider(create: (_) => DebugInfoModel()), // ], child: MyApp(isLogin: isLogin))); CallKitHandler.setupListener(); + String? token = await CallKitHandler.getVoipToken(); + print('获取到的VoIP Token: $token'); runApp(MyApp(isLogin: isLogin)); }, onException: (FlutterErrorDetails details) async { debugPrint('FlutterErrorDetails ${details.exceptionAsString()}'); diff --git a/lib/tools/callkit_handler.dart b/lib/tools/callkit_handler.dart index 06d360f5..f24e335a 100644 --- a/lib/tools/callkit_handler.dart +++ b/lib/tools/callkit_handler.dart @@ -2,6 +2,7 @@ import 'package:flutter/services.dart'; import 'package:get/get.dart'; import 'package:star_lock/appRouters.dart'; import 'package:star_lock/app_settings/app_settings.dart'; +import 'package:star_lock/tools/storage.dart'; class CallKitHandler { static const MethodChannel _channel = MethodChannel('com.starlock/callkit'); @@ -41,6 +42,11 @@ class CallKitHandler { } } else if (call.method == 'callkit_declined') { print('返回主页面'); + } else if (call.method == 'voip_token') { + print('收到VoIP Token: ${call.arguments}'); + if (call.arguments != null) { + await Storage.setString(voipToken, call.arguments); + } } else { print('收到未知事件: ${call.method}'); } @@ -53,4 +59,21 @@ class CallKitHandler { print('CallKitHandler.endCall 通知原生端结束通话'); await _channel.invokeMethod('end_call'); } + + /// 主动获取iOS VoIP Token + static Future getVoipToken() async { + try { + final String? token = + await _channel.invokeMethod('get_voip_token'); + print('CallKitHandler.getVoipToken 拉取到token: $token'); + if (token != null) { + await Storage.setString(voipToken, token); + } + + return token; + } catch (e) { + print('CallKitHandler.getVoipToken 异常: $e'); + return null; + } + } } diff --git a/lib/tools/push/xs_jPhush.dart b/lib/tools/push/xs_jPhush.dart index 7ab5edb3..0563de44 100755 --- a/lib/tools/push/xs_jPhush.dart +++ b/lib/tools/push/xs_jPhush.dart @@ -7,9 +7,11 @@ import 'package:flutter/foundation.dart'; import 'package:get/get.dart'; import 'package:jpush_flutter/jpush_flutter.dart'; import 'package:star_lock/flavors.dart'; +import 'package:star_lock/login/register/entity/checkIP_entity.dart'; import 'package:star_lock/mine/minePersonInfo/minePersonInfoEditAccount/minePersonInfoEditAccount/mineUnbindPhoneOrEmail_entity.dart'; import 'package:star_lock/network/api_repository.dart'; import 'package:star_lock/tools/baseGetXController.dart'; +import 'package:star_lock/tools/callkit_handler.dart'; import 'package:star_lock/tools/debounce_throttle_tool.dart'; import 'package:star_lock/tools/push/message_management.dart'; import 'package:star_lock/tools/push/notification_service.dart'; @@ -169,6 +171,28 @@ class XSJPushProvider { 'channelToken': entry.value }) .toList(); + if (Platform.isIOS) { + final CheckIPEntity entity = + await ApiRepository.to.checkIpAction(ip: ''); + debugPrint('entity: ${jsonEncode(entity)}'); + if (entity.errorCode!.codeIsSuccessful) { + if ('中国' != entity.data!.name) { + String? token = await CallKitHandler.getVoipToken(); + if (token != null && token.isNotEmpty) { + channels.add({ + 'channel': 'voipToken', + 'channelToken': token, + }); + } else { + debugPrint( + 'iOS VoIP Token is null or empty, not adding to channels'); + } + } else { + debugPrint('国内用户不上报VOIP Token'); + } + } + } + debugPrint("BindPushChannels ${channels}"); final String? deviceID = await Storage.getString(appDeviceID); final MineUnbindPhoneOrEmailEntity entity = diff --git a/lib/tools/storage.dart b/lib/tools/storage.dart index 85477417..8f20526a 100755 --- a/lib/tools/storage.dart +++ b/lib/tools/storage.dart @@ -39,6 +39,7 @@ const String relayInfo = 'relayInfo'; //星图中继服务器信息 const String lockNetWorkInfo = 'lockNetWorkInfo'; //锁板配网信息 const String appVersionHistoryUrl = 'appVersionHistoryUrl'; //是否同意隐私协议弹窗 +const String voipToken = 'voipToken'; //是否同意隐私协议弹窗 class Storage { factory Storage() => _instance;