// // IPhoneHertbeat.m // NotNil // // Created by mac on 2024/6/13. // #import "IPhoneHertbeat.h" #import #import "XSPhoneConfig.h" #import "XSPhoneInfo.h" #import "XSHelper.h" #import "XSHackIos.h" #import "XSHttpHelper.h" #import "MyAdServer.h" #import "MyAdTask2.h" #import "MyEventBus.h" @interface IPhoneHertbeat () { @private XSPhoneConfig *iphone; NSTimeInterval _lastCheckTaskTime; XSHttpHelper *http; NSDate *lastStop; dispatch_source_t _timer; // 替换 NSTimer dispatch_queue_t _workQueue; } @property (nonatomic, assign) NSTimeInterval lastTouchTime; @property (nonatomic, assign) BOOL isProcessingTouch; @property (nonatomic, assign) NSTimeInterval lastCheckTaskTime; @property (nonatomic, strong) dispatch_source_t touchTimer; @end @implementation IPhoneHertbeat +(instancetype)sharedInstance { static IPhoneHertbeat* _sharedInstance = nil; static dispatch_once_t oncePredicate; dispatch_once (&oncePredicate, ^{ _sharedInstance = [[IPhoneHertbeat alloc] init]; }); return _sharedInstance; } -(instancetype)init { if (self = [super init]) { self->iphone = [XSPhoneConfig sharedInstance]; // self.apps = [self getApps]; self->_lastCheckTaskTime = [XSHelper getCurTime]; self->http = [[XSHttpHelper alloc] init]; self.status = @"已停止"; self->lastStop = [NSDate date]; return self; } return nil; } - (void)stop { if (_timer) { dispatch_source_cancel(_timer); _timer = nil; } } - (void)dealloc { [self stop]; [self cancelCurrentTask]; } - (void) start { if (_timer) return; _workQueue = dispatch_queue_create("com.iphone.heartbeat.queue", DISPATCH_QUEUE_SERIAL); _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, _workQueue); dispatch_source_set_timer(_timer, dispatch_time(DISPATCH_TIME_NOW, 0), 5 * NSEC_PER_SEC, 0.1 * NSEC_PER_SEC); __weak typeof(self) weakSelf = self; dispatch_source_set_event_handler(_timer, ^{ @autoreleasepool { [weakSelf ping]; } }); dispatch_resume(_timer); } - (BOOL)isHeartbeatActive { // 检查心跳是否处于活动状态 return _timer != nil; } - (void)restartHeartbeat { // 重新启动心跳 [self stopHeartbeat]; [self start]; } - (void)stopHeartbeat { // 停止心跳 [self stop]; } - (void) checkxxx { NSDate *last = [[XSPhoneConfig sharedInstance] GetLastOverTime]; NSDate *date2 = [NSDate date]; // 获取相差的秒数 NSTimeInterval seconds = [date2 timeIntervalSinceDate:last]; if (seconds > 5 * 24 * 60 * 60) { NSDate *currentDate = [NSDate date]; NSDate *fiveDaysLater = [currentDate dateByAddingTimeInterval:-4 * 24 * 60 * 60 - 3600]; [[XSPhoneConfig sharedInstance] SetLastOverTime:fiveDaysLater]; // XSReboot(); } } - (void)ping { @try { if (!self->iphone || !self->http) return; NSString *server = self->iphone.MainServerURL; if (!server.length) { NSLog(@"Invalid server URL"); return; } NSString *url = [NSString stringWithFormat:@"%@/ios/top_selection/heartbeat", server]; if (!url) { NSLog(@"Invalid URL for heartbeat"); return; } dispatch_async(self->_workQueue, ^{ if ([self.status isEqualToString:@"运行中"]) { self->lastStop = [NSDate date]; } // 检查自动重启 NSDate *curRunTime = [NSDate date]; NSTimeInterval elapsed = [curRunTime timeIntervalSinceDate:self->lastStop]; if (elapsed > 60 * 10 && !myadTaskManualStop) { self->lastStop = [NSDate date]; dispatch_async(self->_workQueue, ^{ [[MyAdTask2Mangger sharedInstance] start]; }); } }); self.name = self->iphone.IPhoneName ?: @""; self.deviceId = self->iphone.DeviceId ?: @""; self.ip = [[XSPhoneInfo sharedInstance] IPAddress] ?: @""; self.remoteIp = [[XSPhoneInfo sharedInstance] remoteIp] ?: @""; self.diskSize = [[XSPhoneInfo sharedInstance] IPhoneStatus] ?: @""; self.message = @"251121-nt-newapi-05"; NSDictionary *heartbeatData = [self constructHeartbeatData]; if (!heartbeatData) { NSLog(@"Failed to construct heartbeat data"); return; } [self sendHeartbeat:heartbeatData toURL:url]; } @catch (NSException *exception) { NSLog(@"XS- app run man ping error: %@", exception); } @finally { NSLog(@"XS- ping end"); } } - (void)sendHeartbeat:(NSDictionary *)data toURL:(NSString *)url { [self->http doPOST:url json:[XSHelper dic2Json:data] withCallback:^(NSData *responseData) { if (responseData) { NSString *json = [XSHelper data2str:responseData]; NSLog(@"Heartbeat success: %@", json); NSDictionary *dic = [XSHelper json2Dictionary:json]; NSDictionary *json_data = dic[@"data"]; // [[MyEventBus sharedInstance] postEvent:@"UpdateInfo" withObject:json_data]; } else { NSLog(@"Empty heartbeat response"); } } withError:^(NSError *err) { NSLog(@"Heartbeat error: %@", err); }]; } - (NSDictionary *)constructHeartbeatData { @try { return @{ @"deviceId": self.deviceId ?: @"", @"ip": self.ip ?: @"", @"appId": self.appId ?: @"", @"apps": self.apps ?: @[], @"name": self.name ?: @"", @"message": self.message ?: @"", @"status": self.status ?: @"", @"disk": self.diskSize ?: @"", @"remoteIp": self.remoteIp ?: @"" }; } @catch (NSException *exception) { NSLog(@"Error constructing heartbeat data: %@", exception); return nil; } } - (void)checkAndPerformTasks { NSTimeInterval currentTime = [XSHelper getCurTime]; // 检查任务执行间隔 if (currentTime - self.lastCheckTaskTime <= 240) { return; } // 更新最后检查时间 self.lastCheckTaskTime = currentTime; __weak typeof(self) weakSelf = self; // 使用专门的触摸队列 dispatch_async(_workQueue, ^{ @try { [weakSelf safePerformTouchEvents]; } @catch (NSException *exception) { NSLog(@"Error performing touch events: %@", exception); } }); } - (void)safePerformTouchEvents { // 检查触摸状态 if (self.isProcessingTouch) { NSLog(@"Already processing touch events"); return; } // 获取前台应用 NSString *appId = XSFrontMostAppId(); if (!appId.length) { NSLog(@"No foreground app detected"); return; } } // 添加清理方法 - (void)cleanup { self.isProcessingTouch = NO; self.lastTouchTime = 0; } // 添加取消当前任务的方法 - (void)cancelCurrentTask { if (self.touchTimer) { dispatch_source_cancel(self.touchTimer); self.touchTimer = nil; } [self cleanup]; } // 添加重置方法 - (void)reset { [self cancelCurrentTask]; [self cleanup]; } @end