// // Tools.m // jiaPei // // Created by apple on 16/3/12. // Copyright © 2016年 JCZ. All rights reserved. // #import "Tools.h" #import "SDSoundPlayer.h" #import "sys/utsname.h" //广告标识 #import #import #import //获取IP地址 #import #import @implementation Tools #pragma mark - 绑定imei判断 +(BOOL)confirmImeiWithLogType:(NSString *)logType successBlock:(void(^)(void))successBlock{ if (defUser.userDict[@"outId"] && [defUser.userDict[@"outId"] length] > 0) { //存在outID(==“学员”身份证登录 or 已绑定“学员证件号”的手机/qq/wx登录) //判断是否绑定 NSString *IMEI = defUser.userDict[@"imei"]; if (IMEI && IMEI.length > 0) { //是否开启iMEi验证 NSInteger isNeed = 1; for (NSDictionary * dic in defUser.userDict[@"params"]) { if ([dic[@"KEY"] isEqualToString:@"SP_VERIFY_IMEI"]) { isNeed = [dic[@"VALUE"] integerValue]; } } if (isNeed == 1) { //判断是否是当前手机 if ([Tools getIDFAWithType:GetIDFAType_Default]) { if ([IMEI isEqualToString:[Tools getIDFAWithType:GetIDFAType_Default]]) { if (successBlock) { successBlock(); return YES; } }else{ UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"温馨提示" message:@"您的账号已与其它手机绑定,请使用已绑定该账号的手机继续此操作。如果您中途更换过手机,或使用过手机系统设置里的还原功能,请联系驾校工作人员重新绑定" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil]; [alert show]; } } }else{ [Tools saveNotBindImeiLogWithType:logType block:^(BOOL isSuccess) { }]; if (successBlock) { successBlock(); return YES; } } }else{ UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"温馨提示" message:@"您的账号暂未与该手机绑定,不能进行此操作,请通过“考试界面左上角点击头像-弹出左边侧栏-绑定账号”进行绑定" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil]; [alert show]; } }else{ //不存在outID NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; NSDictionary *udDic = [ud objectForKey:@"jiaPeiLoginTest"]; if ([udDic[@"loginType"] isEqualToString:@"1"]){ UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"温馨提示" message:@"您的账号暂未在计时系统受理,无法计时!" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil]; [alert show]; }else{ UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"温馨提示" message:@"您的账号暂未与该手机绑定,不能进行此操作,请通过“考试界面左上角点击头像-弹出左边侧栏-绑定账号”进行绑定" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil]; [alert show]; } } return NO; } #pragma mark - 保存非绑定IMEI操作日志 +(void)saveNotBindImeiLogWithType:(NSString *)type block:(void (^)(BOOL isSuccess))block{ NSMutableArray *arr=[NSMutableArray array]; [arr addPro:@"dqbh" Value:defUser.userDict[@"city"]]; [arr addPro:@"idcard" Value:defUser.sfzmhm]; [arr addPro:@"cx" Value:defUser.userDict[@"carType"]]; [arr addPro:@"type" Value:type];//操作类型(1理论设备扫码,2远程计时,3模拟终端,4大车)
 [arr addPro:@"bindImei" Value:defUser.userDict[@"imei"]]; [arr addPro:@"kind" Value:@"2"]; /// @RQ-MARK 1.0.6: 判断imei 和 bindImei 是否相同 不同则保存新的imei if ([Tools getIDFAWithType:GetIDFAType_Default]) { block(true); if ([[Tools getIDFAWithType:GetIDFAType_Default] isEqualToString:defUser.userDict[@"imei"]]) { return; } else { [arr addPro:@"imei" Value:[Tools getIDFAWithType:GetIDFAType_Default]]; } } else { block(false); NSLog(@"IDFA未授权"); return; } NSString* method = @"saveNotBindImeiLog"; [jiaPeiManager requestAnythingWithURL:method array:arr data:nil completion:^(NSDictionary * root) { }]; } #pragma mark - iphoneX验证 + (BOOL)isIPhoneX { struct utsname systemInfo; uname(&systemInfo); NSString *platform = [NSString stringWithCString:systemInfo.machine encoding:NSASCIIStringEncoding]; if ([platform isEqualToString:@"i386"] || [platform isEqualToString:@"x86_64"]) { // 模拟器下采用屏幕的高度来判断 return [UIScreen mainScreen].bounds.size.height == 812; } // iPhone10,6是美版iPhoneX 感谢hegelsu指出:https://github.com/banchichen/TZImagePickerController/issues/635 BOOL isIPhoneX = [platform isEqualToString:@"iPhone10,3"] || [platform isEqualToString:@"iPhone10,6"]; return isIPhoneX; } + (NSString *)getPathWithFileName:(NSString *)fileName { NSString *document = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]; NSString *filePath = [document stringByAppendingPathComponent:fileName]; return filePath; } + (NSString *)isWan:(NSString *)string { NSString *newString = string; if (string.length > 4) { newString = [NSString stringWithFormat:@"%@.%@万",[string substringToIndex:string.length - 4],[string substringWithRange:NSMakeRange(string.length - 4, 1)]]; } return newString; } //播报声音 +(void)playAudioWithString:(NSString *)string { SDSoundPlayer *player = [SDSoundPlayer SDSoundPlayerInit]; [player setDefaultWithVolume:-1.0 rate:0.5 pitchMultiplier:1.2]; [player play:string]; } //验证是否是电话号码 + (BOOL)isMobileNumber:(NSString *)mobileNum { // 电信号段:133/153/180/181/189/177 // 联通号段:130/131/132/155/156/185/186/145/176 // 移动号段:134/135/136/137/138/139/150/151/152/157/158/159/182/183/184/187/188/147/178 // 虚拟运营商:170 NSString *MOBILE = @"^1(3[0-9]|4[57]|5[0-35-9]|8[0-9]|7[06-8])\\d{8}$"; NSPredicate *regextestmobile = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", MOBILE]; return [regextestmobile evaluateWithObject:mobileNum]; } //汉字转拼音 + (NSString *)pinYinFromChinese:(NSString *)chinese { if (chinese.length < 1) { return @""; } return [ChineseToPinyin pinyinFromChiniseString:chinese]; } //根据图片二进制流获取图片格式 + (NSString *)typeForImageData:(NSData *)data { uint8_t c; [data getBytes:&c length:1]; switch (c) { case 0xFF: return @"jpeg"; case 0x89: return @"png"; case 0x47: return @"gif"; case 0x49: case 0x4D: return @"tiff"; } return @"jpg"; } //烦烦烦 每次返回的都不一样 这里给个方法 解决图片的问题 优先显示photo + (NSString *)imageStringWithPhotoString:(NSString *)firstString HeadImgString:(NSString *)secondString Type:(NSInteger)type { NSString *imgString = @""; if (type == 1) { imgString = firstString; if (imgString && imgString.length > 0) { NSString *photoString = @"http://fj.jppt.com.cn"; if (imgString && ![imgString hasPrefix:@"http"]){ imgString = [photoString stringByAppendingString:imgString]; } }else{ imgString = secondString; if (imgString && ![imgString hasPrefix:@"http"]){ imgString = [imgPreFix stringByAppendingString:imgString]; } } }else{ imgString = secondString; if (imgString && imgString.length > 0) { if (imgString && ![imgString hasPrefix:@"http"]){ imgString = [imgPreFix stringByAppendingString:imgString]; } }else{ imgString = firstString; NSString *photoString = @"http://fj.jppt.com.cn"; if (imgString && ![imgString hasPrefix:@"http"]){ imgString = [photoString stringByAppendingString:imgString]; } } } if (!imgString) { imgString = @""; } return imgString; } + (UIImage *)watermarkImage:(UIImage *)img withDic:(NSDictionary *)dic { NSString *mark = @""; int w = img.size.width; int h = img.size.height; UIGraphicsBeginImageContext(img.size); [img drawInRect:CGRectMake(0, 0, w, h)]; NSDictionary *attr = @{ NSFontAttributeName: [UIFont boldSystemFontOfSize:16], //设置字体 NSForegroundColorAttributeName : [UIColor redColor] //设置字体颜色 }; mark = dic[@"up1"]; [mark drawInRect:CGRectMake(10, 10, 200, 20) withAttributes:attr]; //上一 mark = dic[@"up2"]; [mark drawInRect:CGRectMake(10, 35, 200, 20) withAttributes:attr]; //上二 mark = dic[@"down1"]; [mark drawInRect:CGRectMake(w - 170, h - 80 , 170, 20) withAttributes:attr]; //下一 mark = dic[@"down2"]; [mark drawInRect:CGRectMake(w - 170, h - 55 , 170, 20) withAttributes:attr]; //下二 mark = dic[@"down3"]; [mark drawInRect:CGRectMake(w - 170, h - 30 , 170, 20) withAttributes:attr]; //下三 UIImage *aimg = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return aimg; } //获取ip地址 + (NSString *)getIpAddresses { NSString *address = @"error"; struct ifaddrs *interfaces = NULL; struct ifaddrs *temp_addr = NULL; int success = 0; // retrieve the current interfaces - returns 0 on success success = getifaddrs(&interfaces); if (success == 0) { // Loop through linked list of interfaces temp_addr = interfaces; while(temp_addr != NULL) { if(temp_addr->ifa_addr->sa_family == AF_INET) { // Check if interface is en0 which is the wifi connection on the iPhone if([[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:@"en0"]) { // Get NSString from C String address = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)]; } } temp_addr = temp_addr->ifa_next; } } // Free memory freeifaddrs(interfaces); return address; } //获取IDFV + (NSString *)getIDFAWithType:(GetIDFAType)type { //这里复制的时候忘记改一个独立于其它app的key了 暂时未有什么影响。 中途要改的话 得考虑以前的用户 NSString * const KEY_USERNAME_PASSWORD = @"com.danson.jiaPeiCo.usernamepassword"; NSString * const KEY_PASSWORD = @"com.danson.jiaPeiCo.password"; //测试用 清除keychain中的内容 // [Tools delete:KEY_USERNAME_PASSWORD]; NSMutableDictionary *readUserPwd = (NSMutableDictionary *)[Tools load:KEY_USERNAME_PASSWORD]; //NSLog(@"keychain------><>%@",readUserPwd); if (!readUserPwd) { //如果为空 说明是第一次安装 做存储操作 /* 仅在第一次装app的时候获取。并存储下来。 */ //IDFV // NSString *identifierStr = [[[UIDevice currentDevice] identifierForVendor] UUIDString]; // NSMutableDictionary *usernamepasswordKVPairs = [NSMutableDictionary dictionaryWithObject:identifierStr forKey:KEY_PASSWORD]; // [Tools save:KEY_USERNAME_PASSWORD data:usernamepasswordKVPairs]; // return identifierStr; //IDFA NSString *adId = [XYUUID uuidForDevice]; // if (@available(iOS 14, *)) { // [ATTrackingManager requestTrackingAuthorizationWithCompletionHandler:^(ATTrackingManagerAuthorizationStatus status) { // if (status == ATTrackingManagerAuthorizationStatusAuthorized) { // adId = [[ASIdentifierManager sharedManager] advertisingIdentifier].UUIDString; // } // }]; // } else { // // 使用原方式访问 IDFA // adId = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString]; // } if (!adId) { return nil; } else { if ([adId isEqualToString:@"00000000-0000-0000-0000-000000000000"] || [adId isEqualToString:@"00000000000000000000000000000000"]) { [RQ_SHARE_FUNCTION showAlertWithTitle:@"温馨提示" message:@"获取广告标识失败,请在“设置-隐私-广告”中,关闭“限制广告跟踪”" alertControllerStyle:UIAlertControllerStyleAlert cancelButtonTitle:@"确定" otherButtonTitles:nil otherButtonStyles:nil completion:nil]; return nil; } else { NSMutableDictionary *usernamepasswordKVPairs = [NSMutableDictionary dictionaryWithObject:adId forKey:KEY_PASSWORD]; [Tools save:KEY_USERNAME_PASSWORD data:usernamepasswordKVPairs]; return adId; } } }else{ NSString *theIdfv = [readUserPwd objectForKey:KEY_PASSWORD]; return theIdfv; } } //存 + (void)save:(NSString *)service data:(id)data { //Get search dictionary NSMutableDictionary *keychainQuery = [self getKeychainQuery:service]; //Delete old item before add new item SecItemDelete((__bridge CFDictionaryRef)keychainQuery); //Add new object to search dictionary(Attention:the data format) [keychainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:data] forKey:(__bridge id)kSecValueData]; //Add item to keychain with the search dictionary SecItemAdd((__bridge CFDictionaryRef)keychainQuery, NULL); } + (NSMutableDictionary *)getKeychainQuery:(NSString *)service { return [NSMutableDictionary dictionaryWithObjectsAndKeys: (__bridge id)kSecClassGenericPassword,(__bridge id)kSecClass, service, (__bridge id)kSecAttrService, service, (__bridge id)kSecAttrAccount, (__bridge id)kSecAttrAccessibleAfterFirstUnlock,(__bridge id)kSecAttrAccessible, nil]; } //取 + (id)load:(NSString *)service { id ret = nil; NSMutableDictionary *keychainQuery = [self getKeychainQuery:service]; //Configure the search setting //Since in our simple case we are expecting only a single attribute to be returned (the password) we can set the attribute kSecReturnData to kCFBooleanTrue [keychainQuery setObject:(__bridge id)kCFBooleanTrue forKey:(__bridge id)kSecReturnData]; [keychainQuery setObject:(__bridge id)kSecMatchLimitOne forKey:(__bridge id)kSecMatchLimit]; CFDataRef keyData = NULL; if (SecItemCopyMatching((__bridge CFDictionaryRef)keychainQuery, (CFTypeRef *)&keyData) == noErr) { @try { ret = [NSKeyedUnarchiver unarchiveObjectWithData:(__bridge NSData *)keyData]; } @catch (NSException *e) { NSLog(@"Unarchive of %@ failed: %@", service, e); } @finally { } } if (keyData) CFRelease(keyData); return ret; } //删除 + (void)delete:(NSString *)service { NSMutableDictionary *keychainQuery = [self getKeychainQuery:service]; SecItemDelete((__bridge CFDictionaryRef)keychainQuery); } #pragma mark 16进制与NSData之间的转化 及验证算法计算 //data转换为16进制 + (NSString *)convertDataToHexStr:(NSData *)data { if (!data || [data length] == 0) { return @""; } NSMutableString *string = [[NSMutableString alloc] initWithCapacity:[data length]]; [data enumerateByteRangesUsingBlock:^(const void *bytes, NSRange byteRange, BOOL *stop) { unsigned char *dataBytes = (unsigned char*)bytes; for (NSInteger i = 0; i < byteRange.length; i++) { NSString *hexStr = [NSString stringWithFormat:@"%x", (dataBytes[i]) & 0xff]; if ([hexStr length] == 2) { [string appendString:hexStr]; } else { [string appendFormat:@"0%@", hexStr]; } } }]; return string; } //16进制转换为data + (NSData *)convertHexStrToData:(NSString *)str { if (!str || [str length] == 0) { return nil; } NSMutableData *hexData = [[NSMutableData alloc] initWithCapacity:8]; NSRange range; if ([str length] % 2 == 0) { range = NSMakeRange(0, 2); } else { range = NSMakeRange(0, 1); } for (NSInteger i = range.location; i < [str length]; i += 2) { unsigned int anInt; NSString *hexCharStr = [str substringWithRange:range]; NSScanner *scanner = [[NSScanner alloc] initWithString:hexCharStr]; [scanner scanHexInt:&anInt]; NSData *entity = [[NSData alloc] initWithBytes:&anInt length:1]; [hexData appendData:entity]; range.location += range.length; range.length = 2; } return hexData; } /** 将原本是16进制数字的字符串转换成计算机可以识别的int型10进制数据 */ + (int)getHexNumWithString:(NSString *)string { int number = 0; for (int i = 0; i < string.length; i ++) { NSString *letterOrNumber = [string substringWithRange:NSMakeRange(string.length - i - 1, 1)]; int a = 0; if ([letterOrNumber isEqualToString:@"a"] || [letterOrNumber isEqualToString:@"A"]) { a = 10; }else if ([letterOrNumber isEqualToString:@"b"] || [letterOrNumber isEqualToString:@"B"]){ a = 11; }else if ([letterOrNumber isEqualToString:@"c"] || [letterOrNumber isEqualToString:@"C"]){ a = 12; }else if ([letterOrNumber isEqualToString:@"d"] || [letterOrNumber isEqualToString:@"D"]){ a = 13; }else if ([letterOrNumber isEqualToString:@"e"] || [letterOrNumber isEqualToString:@"E"]){ a = 14; }else if ([letterOrNumber isEqualToString:@"f"] || [letterOrNumber isEqualToString:@"F"]){ a = 15; }else { a = [letterOrNumber intValue]; } a = a * pow(16, i); number += a; } return number; } //将十六进制的字符串转换成NSString则可使用如下方式 + (NSString *)convertHexStrToString:(NSString *)str { if (!str || [str length] == 0) { return nil; } NSMutableData *hexData = [[NSMutableData alloc] initWithCapacity:8]; NSRange range; if ([str length] % 2 == 0) { range = NSMakeRange(0, 2); } else { range = NSMakeRange(0, 1); } for (NSInteger i = range.location; i < [str length]; i += 2) { unsigned int anInt; NSString *hexCharStr = [str substringWithRange:range]; NSScanner *scanner = [[NSScanner alloc] initWithString:hexCharStr]; [scanner scanHexInt:&anInt]; NSData *entity = [[NSData alloc] initWithBytes:&anInt length:1]; [hexData appendData:entity]; range.location += range.length; range.length = 2; } NSString *string = [[NSString alloc]initWithData:hexData encoding:NSUTF8StringEncoding]; return string; } //将NSString转换成十六进制的字符串则可使用如下方式 + (NSString *)convertStringToHexStr:(NSString *)str { if (!str || [str length] == 0) { return @""; } NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding]; NSMutableString *string = [[NSMutableString alloc] initWithCapacity:[data length]]; [data enumerateByteRangesUsingBlock:^(const void *bytes, NSRange byteRange, BOOL *stop) { unsigned char *dataBytes = (unsigned char*)bytes; for (NSInteger i = 0; i < byteRange.length; i++) { NSString *hexStr = [NSString stringWithFormat:@"%x", (dataBytes[i]) & 0xff]; if ([hexStr length] == 2) { [string appendString:hexStr]; } else { [string appendFormat:@"0%@", hexStr]; } } }]; return string; } @end