2023-04-03 11:04:31 +08:00

370 lines
13 KiB
Objective-C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#import "TDDeviceInfo.h"
#import <UIKit/UIKit.h>
#import <CoreTelephony/CTCarrier.h>
#import <CoreTelephony/CTTelephonyNetworkInfo.h>
#import <sys/utsname.h>
#import "TDKeychainItemWrapper.h"
#import "TDPublicConfig.h"
#import "ThinkingAnalyticsSDKPrivate.h"
#import "TDFile.h"
#include <mach/mach.h>
#include <malloc/malloc.h>
#import <sys/sysctl.h>
#import "TDValidator.h"
#include <mach-o/arch.h>
#import "TDPMFPSMonitor.h"
#define TD_PM_UNIT_KB 1024.0
#define TD_PM_UNIT_MB (1024.0 * TD_PM_UNIT_KB)
#define TD_PM_UNIT_GB (1024.0 * TD_PM_UNIT_MB)
@interface TDDeviceInfo ()
@property (nonatomic, readwrite) BOOL isFirstOpen;
@property (nonatomic, strong) CTTelephonyNetworkInfo *telephonyInfo;
@property (nonatomic, strong) TDPMFPSMonitor *fpsMonitor;
@end
@implementation TDDeviceInfo
+ (TDDeviceInfo *)sharedManager {
static dispatch_once_t onceToken;
static TDDeviceInfo *manager;
dispatch_once(&onceToken, ^{
manager = [[TDDeviceInfo alloc] init];
});
return manager;
}
- (instancetype)init {
self = [super init];
if (self) {
self.libName = @"iOS";
self.libVersion = TDPublicConfig.version;
[self startCollectAPM];
NSDictionary *deviceInfo = [self getDeviceUniqueId];
_uniqueId = [deviceInfo objectForKey:@"uniqueId"];
_deviceId = [deviceInfo objectForKey:@"deviceId"];
_automaticData = [self collectAutomaticProperties];
_appVersion = [[NSBundle mainBundle] infoDictionary][@"CFBundleShortVersionString"];
}
return self;
}
+ (NSString *)libVersion {
return [self sharedManager].libVersion;
}
- (void)updateAutomaticData {
_automaticData = [self collectAutomaticProperties];
}
//-(NSDictionary *)getAutomaticData {
// if (_automaticData) {
// NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithDictionary:_automaticData];
// [self addAPMParams:dic];
// _automaticData = dic;
// }
// return _automaticData;
//}
- (NSDictionary *)collectAutomaticProperties {
NSMutableDictionary *p = [NSMutableDictionary dictionary];
UIDevice *device = [UIDevice currentDevice];
[p setValue:_deviceId forKey:@"#device_id"];
_telephonyInfo = [[CTTelephonyNetworkInfo alloc] init];
CTCarrier *carrier = nil;
#ifdef __IPHONE_12_1
if (@available(iOS 12.1, *)) {
carrier = _telephonyInfo.serviceSubscriberCellularProviders.allValues.firstObject;
}
#endif
if (!carrier) {
carrier = [_telephonyInfo subscriberCellularProvider];
}
[p setValue:carrier.carrierName forKey:@"#carrier"];
CGSize size = [UIScreen mainScreen].bounds.size;
[p addEntriesFromDictionary:@{
@"#lib": self.libName,
@"#lib_version": self.libVersion,
@"#manufacturer": @"Apple",
@"#device_model": [self iphoneType],
@"#os": @"iOS",
@"#os_version": [device systemVersion],
@"#screen_height": @((NSInteger)size.height),
@"#screen_width": @((NSInteger)size.width),
}];
NSString *preferredLanguages = [[NSLocale preferredLanguages] firstObject];
if (preferredLanguages && preferredLanguages.length > 0) {
p[@"#system_language"] = [[preferredLanguages componentsSeparatedByString:@"-"] firstObject];;
}
// p = [self addAPMParams:p];
return [p copy];
}
+ (NSString*)bundleId
{
return [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleIdentifier"];
}
//TODO
- (NSString *)iphoneType {
struct utsname systemInfo;
uname(&systemInfo);
NSString *platform = [NSString stringWithCString:systemInfo.machine encoding:NSASCIIStringEncoding];
if ([platform isEqualToString:@"iPhone1,1"]) return @"iPhone 2G";
if ([platform isEqualToString:@"iPhone1,2"]) return @"iPhone 3G";
if ([platform isEqualToString:@"iPhone2,1"]) return @"iPhone 3GS";
if ([platform isEqualToString:@"iPhone3,1"]) return @"iPhone 4";
if ([platform isEqualToString:@"iPhone3,2"]) return @"iPhone 4";
if ([platform isEqualToString:@"iPhone3,3"]) return @"iPhone 4";
if ([platform isEqualToString:@"iPhone4,1"]) return @"iPhone 4S";
if ([platform isEqualToString:@"iPhone5,1"]) return @"iPhone 5";
if ([platform isEqualToString:@"iPhone5,2"]) return @"iPhone 5";
if ([platform isEqualToString:@"iPhone5,3"]) return @"iPhone 5c";
if ([platform isEqualToString:@"iPhone5,4"]) return @"iPhone 5c";
if ([platform isEqualToString:@"iPhone6,1"]) return @"iPhone 5s";
if ([platform isEqualToString:@"iPhone6,2"]) return @"iPhone 5s";
if ([platform isEqualToString:@"iPhone7,1"]) return @"iPhone 6 Plus";
if ([platform isEqualToString:@"iPhone7,2"]) return @"iPhone 6";
if ([platform isEqualToString:@"iPhone8,1"]) return @"iPhone 6s";
if ([platform isEqualToString:@"iPhone8,2"]) return @"iPhone 6s Plus";
if ([platform isEqualToString:@"iPhone8,4"]) return @"iPhone SE";
if ([platform isEqualToString:@"iPhone9,1"]) return @"iPhone 7";
if ([platform isEqualToString:@"iPhone9,2"]) return @"iPhone 7 Plus";
if ([platform isEqualToString:@"iPod1,1"]) return @"iPod Touch 1G";
if ([platform isEqualToString:@"iPod2,1"]) return @"iPod Touch 2G";
if ([platform isEqualToString:@"iPod3,1"]) return @"iPod Touch 3G";
if ([platform isEqualToString:@"iPod4,1"]) return @"iPod Touch 4G";
if ([platform isEqualToString:@"iPod5,1"]) return @"iPod Touch 5G";
if ([platform isEqualToString:@"iPad1,1"]) return @"iPad 1G";
if ([platform isEqualToString:@"iPad2,1"]) return @"iPad 2";
if ([platform isEqualToString:@"iPad2,2"]) return @"iPad 2";
if ([platform isEqualToString:@"iPad2,3"]) return @"iPad 2";
if ([platform isEqualToString:@"iPad2,4"]) return @"iPad 2";
if ([platform isEqualToString:@"iPad2,5"]) return @"iPad Mini 1G";
if ([platform isEqualToString:@"iPad2,6"]) return @"iPad Mini 1G";
if ([platform isEqualToString:@"iPad2,7"]) return @"iPad Mini 1G";
if ([platform isEqualToString:@"iPad3,1"]) return @"iPad 3";
if ([platform isEqualToString:@"iPad3,2"]) return @"iPad 3";
if ([platform isEqualToString:@"iPad3,3"]) return @"iPad 3";
if ([platform isEqualToString:@"iPad3,4"]) return @"iPad 4";
if ([platform isEqualToString:@"iPad3,5"]) return @"iPad 4";
if ([platform isEqualToString:@"iPad3,6"]) return @"iPad 4";
if ([platform isEqualToString:@"iPad4,1"]) return @"iPad Air";
if ([platform isEqualToString:@"iPad4,2"]) return @"iPad Air";
if ([platform isEqualToString:@"iPad4,3"]) return @"iPad Air";
if ([platform isEqualToString:@"iPad4,4"]) return @"iPad Mini 2G";
if ([platform isEqualToString:@"iPad4,5"]) return @"iPad Mini 2G";
if ([platform isEqualToString:@"iPad4,6"]) return @"iPad Mini 2G";
if ([platform isEqualToString:@"i386"]) return @"iPhone Simulator";
if ([platform isEqualToString:@"x86_64"]) return @"iPhone Simulator";
return platform;
}
- (NSDictionary *)getDeviceUniqueId {
NSString *defaultDistinctId = [self getIdentifier];
NSString *deviceId;
NSString *uniqueId;
TDKeychainItemWrapper *wrapper = [[TDKeychainItemWrapper alloc] init];
NSString *deviceIdKeychain = [wrapper readDeviceId];
NSString *installTimesKeychain = [wrapper readInstallTimes];
BOOL isExistFirstRecord = [[[NSUserDefaults standardUserDefaults] objectForKey:@"thinking_isfirst"] boolValue];
if (!isExistFirstRecord) {
_isFirstOpen = YES;
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"thinking_isfirst"];
[[NSUserDefaults standardUserDefaults] synchronize];
} else {
_isFirstOpen = NO;
}
if (deviceIdKeychain.length == 0 || installTimesKeychain.length == 0) {
[wrapper readOldKeychain];
deviceIdKeychain = [wrapper getDeviceIdOld];
installTimesKeychain = [wrapper getInstallTimesOld];
}
TDFile *file = [[TDFile alloc] initWithAppid:[ThinkingAnalyticsSDK sharedInstance].appid];
if (deviceIdKeychain.length == 0 || installTimesKeychain.length == 0) {
deviceIdKeychain = [file unarchiveDeviceId];
installTimesKeychain = [file unarchiveInstallTimes];
}
if (deviceIdKeychain.length == 0 || installTimesKeychain.length == 0) {
deviceId = defaultDistinctId;
installTimesKeychain = @"1";
} else {
if (!isExistFirstRecord) {
int setup_int = [installTimesKeychain intValue];
setup_int++;
installTimesKeychain = [NSString stringWithFormat:@"%d",setup_int];
}
deviceId = deviceIdKeychain;
}
if ([installTimesKeychain isEqualToString:@"1"]) {
uniqueId = deviceId;
} else {
uniqueId = [NSString stringWithFormat:@"%@_%@",deviceId,installTimesKeychain];
}
[wrapper saveDeviceId:deviceId];
[wrapper saveInstallTimes:installTimesKeychain];
[file archiveDeviceId:deviceId];
[file archiveInstallTimes:installTimesKeychain];
return @{@"uniqueId":uniqueId, @"deviceId":deviceId};
}
- (NSString *)getIdentifier {
NSString *anonymityId = NULL;
if (NSClassFromString(@"UIDevice")) {
anonymityId = [[UIDevice currentDevice].identifierForVendor UUIDString];
}
if (!anonymityId) {
anonymityId = [[NSUUID UUID] UUIDString];
}
return anonymityId;
}
#pragma mark - memory
//返回memory空闲值单位为Byte
+ (int64_t)td_pm_func_getFreeMemory {
size_t length = 0;
int mib[6] = {0};
int pagesize = 0;
mib[0] = CTL_HW;
mib[1] = HW_PAGESIZE;
length = sizeof(pagesize);
if (sysctl(mib, 2, &pagesize, &length, NULL, 0) < 0){
return -1;
}
mach_msg_type_number_t count = HOST_VM_INFO_COUNT;
vm_statistics_data_t vmstat;
if (host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t)&vmstat, &count) != KERN_SUCCESS){
return -1;
}
int64_t freeMem = vmstat.free_count * pagesize;
int64_t inactiveMem = vmstat.inactive_count * pagesize;
return freeMem + inactiveMem;
}
//获取memory总大小单位Byte
+ (int64_t)td_pm_func_getRamSize{
int mib[2];
size_t length = 0;
mib[0] = CTL_HW;
mib[1] = HW_MEMSIZE;
long ram;
length = sizeof(ram);
if (sysctl(mib, 2, &ram, &length, NULL, 0) < 0) {
return -1;
}
return ram;
}
#pragma mark - disk
+ (NSDictionary *)td_pm_getFileAttributeDic {
NSError *error;
NSDictionary *directory = [[NSFileManager defaultManager] attributesOfFileSystemForPath:NSHomeDirectory() error:&error];
if (error) {
return nil;
}
return directory;
}
+ (long long)td_get_disk_free_size {
NSDictionary<NSFileAttributeKey, id> *directory = [self td_pm_getFileAttributeDic];
if (directory) {
return [[directory objectForKey:NSFileSystemFreeSize] unsignedLongLongValue];
}
return -1;
}
+ (long long)td_get_storage_size {
NSDictionary<NSFileAttributeKey, id> *directory = [self td_pm_getFileAttributeDic];
return directory ? ((NSNumber *)[directory objectForKey:NSFileSystemSize]).unsignedLongLongValue:-1;
}
#pragma mark - CPU
- (NSNumber *)is_simulator {
static dispatch_once_t onceToken;
static NSNumber *isSimulator;
dispatch_once(&onceToken, ^{
NSInteger cputype = NXGetLocalArchInfo()->cputype;
if ((cputype == CPU_TYPE_X86) || (cputype == CPU_TYPE_X86_64)) {
isSimulator = [NSNumber numberWithBool:YES];
} else {
isSimulator = [NSNumber numberWithBool:NO];
}
});
return isSimulator;
}
#pragma mark - 安装时间
+ (NSDate *)td_getInstallTime {
NSURL* urlToDocumentsFolder = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
__autoreleasing NSError *error;
NSDate *installDate = [[[NSFileManager defaultManager] attributesOfItemAtPath:urlToDocumentsFolder.path error:&error] objectForKey:NSFileCreationDate];
if (!error) {
return installDate;
}
return [NSDate date];
}
#pragma mark - APM
- (void)startCollectAPM {
// _fpsMonitor = [[TDPMFPSMonitor alloc] init];
// [_fpsMonitor setEnable:YES];
}
// 性能参数
- (NSDictionary *)addAPMParams:(NSDictionary *)p {
if (!p) return p;
if (![p isKindOfClass:[NSDictionary class]]) return p;
NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithDictionary:p];
NSString *ram = [NSString stringWithFormat:@"%.1f/%.1f", [TDDeviceInfo td_pm_func_getFreeMemory]/TD_PM_UNIT_GB, [TDDeviceInfo td_pm_func_getRamSize]/TD_PM_UNIT_GB];
if (ram && ram.length) {
[dic setObject:ram forKey:@"#ram"];
}
NSString *disk = [NSString stringWithFormat:@"%.1f/%.1f", [TDDeviceInfo td_get_disk_free_size]/TD_PM_UNIT_GB, [TDDeviceInfo td_get_storage_size]/TD_PM_UNIT_GB];
if (disk && disk.length) {
[dic setObject:disk forKey:@"#disk"];
}
[dic setObject:[self is_simulator] forKey:@"#simulator"];
[dic setObject:[_fpsMonitor getPFS] forKey:@"#fps"];
return dic;
}
@end