app-starlock/ios/Runner/AppDelegate.m

297 lines
12 KiB
Objective-C
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#import "AppDelegate.h"
#import "GeneratedPluginRegistrant.h"
#import "CommonDefine.h"
#import "XSFlutterManager.h"
#import "Runner-Swift.h"
#import <UserNotifications/UserNotifications.h>
#import <PushKit/PushKit.h>
#import <CallKit/CallKit.h>
// #import <UMCommon/UMCommon.h>
@interface AppDelegate()<PKPushRegistryDelegate, CXProviderDelegate>
@property (nonatomic, strong) FlutterMethodChannel *methodChannel;
@property (nonatomic, strong) CXProvider *callKitProvider;
@property (nonatomic, copy) NSString *pendingCallKitEvent; // 缓存未处理的CallKit事件
@property (nonatomic, strong) NSUUID *lastCallUUID;
@property (nonatomic, copy) NSString *voipTokenString; // + 新增缓存VoIP Token
@end
@implementation AppDelegate {
}
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// [UMConfigure initWithAppkey:@"671244ae80464b33f6df9646" channel:@"Product"];
//Required
//notice: 3.0.0 及以后版本注册可以这样写,也可以继续用之前的注册方式
JPUSHRegisterEntity * entity = [[JPUSHRegisterEntity alloc] init];
entity.types = JPAuthorizationOptionAlert|JPAuthorizationOptionBadge|JPAuthorizationOptionSound|JPAuthorizationOptionProvidesAppNotificationSettings;
if ([[UIDevice currentDevice].systemVersion floatValue] >= 8.0) {
// 可以添加自定义 categories
// NSSet<UNNotificationCategory *> *categories for iOS10 or later
// NSSet<UIUserNotificationCategory *> *categories for iOS8 and iOS9
}
[JPUSHService registerForRemoteNotificationConfig:entity delegate:self];
// 注册VoIP推送
PKPushRegistry *voipRegistry = [[PKPushRegistry alloc] initWithQueue:dispatch_get_main_queue()];
voipRegistry.delegate = self;
voipRegistry.desiredPushTypes = [NSSet setWithObject:PKPushTypeVoIP];
XSFlutterManager *VC = [[XSFlutterManager alloc] init];
self.window.rootViewController = VC;
[self.window makeKeyAndVisible];
// 初始化FlutterMethodChannel
FlutterViewController *controller = (FlutterViewController *)self.window.rootViewController;
self.methodChannel = [FlutterMethodChannel methodChannelWithName:@"com.starlock/callkit" binaryMessenger:controller.binaryMessenger];
// 注册拉取pending事件方法
__weak typeof(self) weakSelf = self;
[self.methodChannel setMethodCallHandler:^(FlutterMethodCall *call, FlutterResult result) {
if ([call.method isEqualToString:@"get_pending_event"]) {
if (weakSelf.pendingCallKitEvent) {
result(weakSelf.pendingCallKitEvent);
weakSelf.pendingCallKitEvent = nil;
} else {
result(nil);
}
} else if ([call.method isEqualToString:@"end_call"]) {
NSLog(@"[CallKit] 收到Flutter端结束通话请求");
// 结束CallKit通话
// 这里只能结束最近一次来电需保存UUID
if (weakSelf.lastCallUUID) {
CXCallEndedReason reason = CXCallEndedReasonRemoteEnded;
[weakSelf.callKitProvider reportCallWithUUID:weakSelf.lastCallUUID endedAtDate:[NSDate date] reason:reason];
weakSelf.lastCallUUID = nil;
result(@"ok");
} else {
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);
}
}];
// 初始化CallKit Provider仅国外包
#if USE_CALLKIT
CXProviderConfiguration *providerConfiguration = [[CXProviderConfiguration alloc] initWithLocalizedName:@"来电"];
providerConfiguration.supportsVideo = NO;
providerConfiguration.maximumCallsPerCallGroup = 1;
self.callKitProvider = [[CXProvider alloc] initWithConfiguration:providerConfiguration];
[self.callKitProvider setDelegate:self queue:nil];
#endif
return YES;
}
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
// 判断是否是你的应用程序的 URL Scheme
if ([url.scheme isEqualToString:@"skysmartlock"]) {
// 处理被唤起的逻辑,可以根据 URL 中的其他信息来执行相应的操作
return YES;
}
return NO;
}
/**
* 注册苹果推送获取deviceToken用于推送
*
* @param application
*/
- (void)registerAPNS:(UIApplication *)application {
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0) {
// iOS 8 Notifications
[application registerUserNotificationSettings:
[UIUserNotificationSettings settingsForTypes:
(UIUserNotificationTypeSound | UIUserNotificationTypeAlert)
categories:nil]];
[application registerForRemoteNotifications];
}
else {
// iOS < 8 Notifications
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:
(UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound)];
}
}
/*
* 苹果推送注册成功回调将苹果返回的deviceToken上传到CloudPush服务器
*/
//- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
// NSString *tokenString = [self hexStringFromData:deviceToken];
// NSLog(@"starlock didRegisterForRemoteNotificationsWithDeviceToken token: %@", tokenString);
// /// Required - 注册 DeviceToken
// [JPUSHService registerDeviceToken:deviceToken];
//
//}
- (NSString *)hexStringFromData:(NSData *)data {
const unsigned char *dataBuffer = (const unsigned char *)[data bytes];
NSMutableString *hexString = [NSMutableString stringWithCapacity:data.length * 2];
for (NSInteger i = 0; i < data.length; i++) {
[hexString appendFormat:@"%02x", dataBuffer[i]];
}
return [hexString copy];
}
/*
* 苹果推送注册失败回调
*/
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
//Optional
NSLog(@"did Fail To Register For Remote Notifications With Error: %@", error);
}
/**
* 注册推送消息到来监听
*/
- (void)registerMessageReceive {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(onMessageReceived:)
name:@"CCPDidReceiveMessageNotification"
object:nil];
}
/**
* 处理到来推送消息
*
* @param notification
*/
- (void)onMessageReceived:(NSNotification *)notification {
CCPSysMessage *message = [notification object];
NSString *title = [[NSString alloc] initWithData:message.title encoding:NSUTF8StringEncoding];
NSString *body = [[NSString alloc] initWithData:message.body encoding:NSUTF8StringEncoding];
NSLog(@"Receive message title: %@, content: %@.", title, body);
}
# pragma mark- JPUSHRegisterDelegate
// iOS 12 Support
- (void)jpushNotificationCenter:(UNUserNotificationCenter *)center openSettingsForNotification:(UNNotification *)notification{
if (notification && [notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
//从通知界面直接进入应用
}else{
//从通知设置界面进入应用
}
}
// iOS 10 Support
- (void)jpushNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(NSInteger))completionHandler {
// Required
NSDictionary * userInfo = notification.request.content.userInfo;
if([notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
[JPUSHService handleRemoteNotification:userInfo];
}
completionHandler(UNNotificationPresentationOptionAlert); // 需要执行这个方法,选择是否提醒用户,有 Badge、Sound、Alert 三种类型可以选择设置
}
// iOS 10 Support
- (void)jpushNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler {
// Required
NSDictionary * userInfo = response.notification.request.content.userInfo;
if([response.notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
[JPUSHService handleRemoteNotification:userInfo];
}
completionHandler(); // 系统要求执行这个方法
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
// Required, iOS 7 Support
[JPUSHService handleRemoteNotification:userInfo];
completionHandler(UIBackgroundFetchResultNewData);
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
// Required, For systems with less than or equal to iOS 6
[JPUSHService handleRemoteNotification:userInfo];
}
#pragma mark - PKPushRegistryDelegate
// 获取VoIP Token
- (void)pushRegistry:(PKPushRegistry *)registry didUpdatePushCredentials:(PKPushCredentials *)credentials forType:(PKPushType)type {
if ([type isEqualToString:PKPushTypeVoIP]) {
const unsigned char *tokenBytes = credentials.token.bytes;
NSMutableString *tokenString = [NSMutableString string];
for (NSInteger i = 0; i < credentials.token.length; i++) {
[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未readyFlutter端可通过get_voip_token拉取
}
}
// 收到VoIP推送
- (void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(PKPushType)type withCompletionHandler:(void (^)(void))completion {
if ([type isEqualToString:PKPushTypeVoIP]) {
NSLog(@"[VoIP] didReceiveIncomingPushWithPayload: %@", payload.dictionaryPayload);
#if USE_CALLKIT
// 国外环境直接用CallKit弹窗
NSString *callerName = @"来电"; // 可根据payload内容自定义
// 复用已初始化的provider
CXCallUpdate *update = [[CXCallUpdate alloc] init];
update.remoteHandle = [[CXHandle alloc] initWithType:CXHandleTypeGeneric value:callerName];
update.hasVideo = NO;
NSUUID *callUUID = [NSUUID UUID];
self.lastCallUUID = callUUID;
[self.callKitProvider reportNewIncomingCallWithUUID:callUUID update:update completion:^(NSError * _Nullable error) {
if (error) {
NSLog(@"CallKit error: %@", error);
}
}];
#else
// 国内环境使用LiveCommunicationKit弹窗
UIViewController *rootVC = [UIApplication sharedApplication].delegate.window.rootViewController;
NSString *callerName = @"来电"; // 可根据payload内容自定义
[LCKBridge presentCallInterfaceFromRootVC:rootVC callerName:callerName];
#endif
}
if (completion) {
completion();
}
}
#pragma mark - CXProviderDelegate
// 用户点击"接听"
- (void)provider:(CXProvider *)provider performAnswerCallAction:(CXAnswerCallAction *)action {
NSLog(@"[CallKit] 用户接听来电");
if (self.methodChannel) {
[self.methodChannel invokeMethod:@"callkit_answered" arguments:nil];
} else {
self.pendingCallKitEvent = @"callkit_answered";
}
[action fulfill];
}
// 用户点击"拒绝"或挂断
- (void)provider:(CXProvider *)provider performEndCallAction:(CXEndCallAction *)action {
NSLog(@"[CallKit] 用户拒绝/挂断来电");
if (self.methodChannel) {
[self.methodChannel invokeMethod:@"callkit_declined" arguments:nil];
} else {
self.pendingCallKitEvent = @"callkit_declined";
}
[action fulfill];
}
@end