278 lines
7.3 KiB
Objective-C
Executable File
278 lines
7.3 KiB
Objective-C
Executable File
//
|
|
// IPhoneHertbeat.m
|
|
// NotNil
|
|
//
|
|
// Created by mac on 2024/6/13.
|
|
//
|
|
#import "IPhoneHertbeat.h"
|
|
|
|
#import <Foundation/Foundation.h>
|
|
|
|
#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 = @"251202-nt-02";
|
|
|
|
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
|
|
|
|
|