#import #import #import #import #import #import #import // 为了 getpid() #import #import #import "server/MySimpleServer.h" #import "server/FloatingWindow.h" #import "XSLog.h" __attribute__((constructor)) static void SetupXSLog() { XSLogSetupLogWithFilePath(@"/var/mobile/Documents/AppRunMain.log", 50 * 1024 * 1024); XSLogRedirectNSLog(); } // 一次性服务器启动封装 static void startServerOnce(void) { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ NSLog(@"[AppRunMan] start app server (pid=%d)", getpid()); startSimpleServer(); }); } @interface UIWindow (FloatingWindow) @end @implementation UIWindow (FloatingWindow) - (void)addFloatingWindow { // Check if already exists if (objc_getAssociatedObject(self, @selector(addFloatingWindow))) { return; } // Create floating window UIWindow *floatingWindow = [[FloatingWindow alloc] initWithFrame]; floatingWindow.windowLevel = UIWindowLevelAlert + 1; floatingWindow.layer.masksToBounds = YES; // Show window floatingWindow.hidden = NO; // Associate object to prevent multiple windows objc_setAssociatedObject(self, @selector(addFloatingWindow), floatingWindow, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } @end %group all %hook SpringBoard - (void)applicationDidFinishLaunching:(id)arg1 { %orig; // 延迟启动服务器,让系统UI完全加载 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ // 改为一次性启动 startServerOnce(); }); @autoreleasepool { // 延迟添加悬浮窗,给系统UI足够的启动时间 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ // 添加保护机制 @try { if (@available(iOS 13.0, *)) { // iOS 13+ 使用 UIWindowScene for (UIScene *scene in [UIApplication sharedApplication].connectedScenes) { if ([scene isKindOfClass:[UIWindowScene class]]) { UIWindowScene *windowScene = (UIWindowScene *)scene; UIWindow *window = windowScene.windows.firstObject; if (window) { [window addFloatingWindow]; } } } } else { // iOS 12 及以下使用 keyWindow 或 windows UIWindow *window = [UIApplication sharedApplication].keyWindow; if (!window) { // 如果 keyWindow 为 nil,尝试从 windows 数组获取 window = [UIApplication sharedApplication].windows.firstObject; } if (window) { [window addFloatingWindow]; } } } @catch (NSException *exception) { NSLog(@"Add floating window error: %@", exception); } }); } } // 添加生命周期方法以便清理 - (void)applicationWillTerminate:(id)arg1 { %orig; // 清理服务器资源 // 清理悬浮窗 } %end /* // 注入网络权限 %hook NSBundle - (NSDictionary *)infoDictionary { NSMutableDictionary *dict = [[%orig mutableCopy] copy]; [dict setObject:@YES forKey:@"NSLocalNetworkUsageDescription"]; [dict setObject:@YES forKey:@"NSAllowsLocalNetworking"]; return dict; } %end */ %end %ctor { // 使用一次性保护,避免 dylib 被重复装载时重复执行 static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ NSLog(@"[AppRunMan] %ctor init (pid=%d)", getpid()); %init(all); }); }