243 lines
9.1 KiB
Mathematica
243 lines
9.1 KiB
Mathematica
|
|
#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"
|
|||
|
|
#import "LKS_MultiplatformAdapter.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"];
|
|||
|
|
self.serverReadableVersion = [aDecoder decodeObjectForKey:@"serverReadableVersion"];
|
|||
|
|
self.swiftEnabledInLookinServer = [aDecoder decodeIntForKey:@"swiftEnabledInLookinServer"];
|
|||
|
|
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"];
|
|||
|
|
[aCoder encodeObject:self.serverReadableVersion forKey:@"serverReadableVersion"];
|
|||
|
|
[aCoder encodeInt:self.swiftEnabledInLookinServer forKey:@"swiftEnabledInLookinServer"];
|
|||
|
|
|
|||
|
|
#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<NSNumber *> *)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.serverReadableVersion = LOOKIN_SERVER_READABLE_VERSION;
|
|||
|
|
#ifdef LOOKIN_SERVER_SWIFT_ENABLED
|
|||
|
|
info.swiftEnabledInLookinServer = 1;
|
|||
|
|
#else
|
|||
|
|
info.swiftEnabledInLookinServer = -1;
|
|||
|
|
#endif
|
|||
|
|
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 ([LKS_MultiplatformAdapter isiPad]) {
|
|||
|
|
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 = [LKS_MultiplatformAdapter mainScreenBounds].size;
|
|||
|
|
info.screenWidth = screenSize.width;
|
|||
|
|
info.screenHeight = screenSize.height;
|
|||
|
|
info.screenScale = [LKS_MultiplatformAdapter mainScreenScale];
|
|||
|
|
|
|||
|
|
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 = [LKS_MultiplatformAdapter keyWindow];
|
|||
|
|
if (!window) {
|
|||
|
|
return nil;
|
|||
|
|
}
|
|||
|
|
CGSize size = window.bounds.size;
|
|||
|
|
if (size.width <= 0 || size.height <= 0) {
|
|||
|
|
// *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'UIGraphicsBeginImageContext() failed to allocate CGBitampContext: size={0, 0}, scale=3.000000, bitmapInfo=0x2002. Use UIGraphicsImageRenderer to avoid this assert.'
|
|||
|
|
|
|||
|
|
// https://github.com/hughkli/Lookin/issues/21
|
|||
|
|
return nil;
|
|||
|
|
}
|
|||
|
|
UIGraphicsBeginImageContextWithOptions(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 */
|