#ifdef SHOULD_COMPILE_LOOKIN_SERVER // // LookinAppInfo.m // qmuidemo // // Created by Li Kai on 2018/11/3. // Copyright © 2018 QMUI Team. All rights reserved. // #import "LookinAppInfo.h" static NSString * const CodingKey_AppIcon = @"1"; static NSString * const CodingKey_Screenshot = @"2"; static NSString * const CodingKey_DeviceDescription = @"3"; static NSString * const CodingKey_OsDescription = @"4"; static NSString * const CodingKey_AppName = @"5"; static NSString * const CodingKey_ScreenWidth = @"6"; static NSString * const CodingKey_ScreenHeight = @"7"; static NSString * const CodingKey_DeviceType = @"8"; @implementation LookinAppInfo - (id)copyWithZone:(NSZone *)zone { LookinAppInfo *newAppInfo = [[LookinAppInfo allocWithZone:zone] init]; newAppInfo.appIcon = self.appIcon; newAppInfo.appName = self.appName; newAppInfo.deviceDescription = self.deviceDescription; newAppInfo.osDescription = self.osDescription; newAppInfo.osMainVersion = self.osMainVersion; newAppInfo.deviceType = self.deviceType; newAppInfo.screenWidth = self.screenWidth; newAppInfo.screenHeight = self.screenHeight; newAppInfo.screenScale = self.screenScale; newAppInfo.appInfoIdentifier = self.appInfoIdentifier; return newAppInfo; } - (instancetype)initWithCoder:(NSCoder *)aDecoder { if (self = [super init]) { self.serverVersion = [aDecoder decodeIntForKey:@"serverVersion"]; NSData *screenshotData = [aDecoder decodeObjectForKey:CodingKey_Screenshot]; self.screenshot = [[LookinImage alloc] initWithData:screenshotData]; NSData *appIconData = [aDecoder decodeObjectForKey:CodingKey_AppIcon]; self.appIcon = [[LookinImage alloc] initWithData:appIconData]; self.appName = [aDecoder decodeObjectForKey:CodingKey_AppName]; self.appBundleIdentifier = [aDecoder decodeObjectForKey:@"appBundleIdentifier"]; self.deviceDescription = [aDecoder decodeObjectForKey:CodingKey_DeviceDescription]; self.osDescription = [aDecoder decodeObjectForKey:CodingKey_OsDescription]; self.osMainVersion = [aDecoder decodeIntegerForKey:@"osMainVersion"]; self.deviceType = [aDecoder decodeIntegerForKey:CodingKey_DeviceType]; self.screenWidth = [aDecoder decodeDoubleForKey:CodingKey_ScreenWidth]; self.screenHeight = [aDecoder decodeDoubleForKey:CodingKey_ScreenHeight]; self.screenScale = [aDecoder decodeDoubleForKey:@"screenScale"]; self.appInfoIdentifier = [aDecoder decodeIntegerForKey:@"appInfoIdentifier"]; self.shouldUseCache = [aDecoder decodeBoolForKey:@"shouldUseCache"]; } return self; } - (void)encodeWithCoder:(NSCoder *)aCoder { [aCoder encodeInt:self.serverVersion forKey:@"serverVersion"]; #if TARGET_OS_IPHONE NSData *screenshotData = UIImagePNGRepresentation(self.screenshot); [aCoder encodeObject:screenshotData forKey:CodingKey_Screenshot]; NSData *appIconData = UIImagePNGRepresentation(self.appIcon); [aCoder encodeObject:appIconData forKey:CodingKey_AppIcon]; #elif TARGET_OS_MAC NSData *screenshotData = [self.screenshot TIFFRepresentation]; [aCoder encodeObject:screenshotData forKey:CodingKey_Screenshot]; NSData *appIconData = [self.appIcon TIFFRepresentation]; [aCoder encodeObject:appIconData forKey:CodingKey_AppIcon]; #endif [aCoder encodeObject:self.appName forKey:CodingKey_AppName]; [aCoder encodeObject:self.appBundleIdentifier forKey:@"appBundleIdentifier"]; [aCoder encodeObject:self.deviceDescription forKey:CodingKey_DeviceDescription]; [aCoder encodeObject:self.osDescription forKey:CodingKey_OsDescription]; [aCoder encodeInteger:self.osMainVersion forKey:@"osMainVersion"]; [aCoder encodeInteger:self.deviceType forKey:CodingKey_DeviceType]; [aCoder encodeDouble:self.screenWidth forKey:CodingKey_ScreenWidth]; [aCoder encodeDouble:self.screenHeight forKey:CodingKey_ScreenHeight]; [aCoder encodeDouble:self.screenScale forKey:@"screenScale"]; [aCoder encodeInteger:self.appInfoIdentifier forKey:@"appInfoIdentifier"]; [aCoder encodeBool:self.shouldUseCache forKey:@"shouldUseCache"]; } + (BOOL)supportsSecureCoding { return YES; } - (BOOL)isEqual:(id)object { if (self == object) { return YES; } if (![object isKindOfClass:[LookinAppInfo class]]) { return NO; } if ([self isEqualToAppInfo:object]) { return YES; } return NO; } - (NSUInteger)hash { return self.appName.hash ^ self.deviceDescription.hash ^ self.osDescription.hash ^ self.deviceType; } - (BOOL)isEqualToAppInfo:(LookinAppInfo *)info { if (!info) { return NO; } if ([self.appName isEqualToString:info.appName] && [self.deviceDescription isEqualToString:info.deviceDescription] && [self.osDescription isEqualToString:info.osDescription] && self.deviceType == info.deviceType) { return YES; } return NO; } #if TARGET_OS_IPHONE + (LookinAppInfo *)currentInfoWithScreenshot:(BOOL)hasScreenshot icon:(BOOL)hasIcon localIdentifiers:(NSArray *)localIdentifiers { NSInteger selfIdentifier = [self getAppInfoIdentifier]; if ([localIdentifiers containsObject:@(selfIdentifier)]) { LookinAppInfo *info = [LookinAppInfo new]; info.appInfoIdentifier = selfIdentifier; info.shouldUseCache = YES; return info; } LookinAppInfo *info = [[LookinAppInfo alloc] init]; info.appInfoIdentifier = selfIdentifier; info.appName = [self appName]; info.deviceDescription = [UIDevice currentDevice].name; info.appBundleIdentifier = [[NSBundle mainBundle] bundleIdentifier]; if ([self isSimulator]) { info.deviceType = LookinAppInfoDeviceSimulator; } else if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { info.deviceType = LookinAppInfoDeviceIPad; } else { info.deviceType = LookinAppInfoDeviceOthers; } info.osDescription = [UIDevice currentDevice].systemVersion; NSString *mainVersionStr = [[[UIDevice currentDevice] systemVersion] componentsSeparatedByString:@"."].firstObject; info.osMainVersion = [mainVersionStr integerValue]; CGSize screenSize = [UIScreen mainScreen].bounds.size; info.screenWidth = screenSize.width; info.screenHeight = screenSize.height; info.screenScale = [UIScreen mainScreen].scale; if (hasScreenshot) { info.screenshot = [self screenshotImage]; } if (hasIcon) { info.appIcon = [self appIcon]; } return info; } + (NSString *)appName { NSDictionary *info = [[NSBundle mainBundle] infoDictionary]; NSString *displayName = [info objectForKey:@"CFBundleDisplayName"]; NSString *name = [info objectForKey:@"CFBundleName"]; return displayName.length ? displayName : name; } + (UIImage *)appIcon { #if TARGET_OS_TV return nil; #else NSString *imageName = [[[[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleIcons"] objectForKey:@"CFBundlePrimaryIcon"] objectForKey:@"CFBundleIconFiles"] lastObject]; if (!imageName.length) { // 正常情况下拿到的 name 可能比如 “AppIcon60x60”。但某些情况可能为 nil,此时直接 return 否则 [UIImage imageNamed:nil] 可能导致 console 报 "CUICatalog: Invalid asset name supplied: '(null)'" 的错误信息 return nil; } return [UIImage imageNamed:imageName]; #endif } + (UIImage *)screenshotImage { UIWindow *window = [UIApplication sharedApplication].keyWindow; if (!window) { return nil; } UIGraphicsBeginImageContextWithOptions(window.bounds.size, YES, 0.4); [window drawViewHierarchyInRect:window.bounds afterScreenUpdates:YES]; UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return image; } + (BOOL)isSimulator { if (TARGET_OS_SIMULATOR) { return YES; } return NO; } #endif + (NSInteger)getAppInfoIdentifier { static dispatch_once_t onceToken; static NSInteger identifier = 0; dispatch_once(&onceToken,^{ identifier = [[NSDate date] timeIntervalSince1970]; }); return identifier; } @end #endif /* SHOULD_COMPILE_LOOKIN_SERVER */