├── .gitignore ├── README.md ├── TencentYoutuYun ├── Auth.h ├── Auth.m ├── Conf.h ├── Conf.m ├── TXQcloudFrSDK.h ├── TXQcloudFrSDK.m └── vendor │ ├── NSData+Base64.h │ └── NSData+Base64.m ├── YoutuYunDemo.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── xcuserdata │ └── patyang.xcuserdatad │ └── xcschemes │ └── xcschememanagement.plist ├── YoutuYunDemo ├── Base.lproj │ └── LaunchScreen.xib ├── DemoAppDelegate.h ├── DemoAppDelegate.m ├── Images.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Info.plist ├── Resource │ ├── beginbtn_nor@2x.png │ ├── beginbtn_selected@2x.png │ ├── bt_blue@2x.png │ ├── face.jpg │ ├── id.jpg │ ├── id_back@2x.png │ ├── id_back_back@2x.png │ ├── id_back_front@2x.png │ ├── idcard_back@2x.png │ ├── idcard_first@2x.png │ ├── idcard_second@2x.png │ ├── indicator_correct@2x.png │ ├── indicator_nor@2x.png │ ├── indicator_wrong@2x.png │ ├── namecard.jpg │ ├── nav_back64@2x.png │ ├── nav_back@2x.png │ ├── person_face@2x.png │ ├── video.mp4 │ └── video_begin@2x.png ├── UI │ ├── CardResultViewController.h │ ├── CardResultViewController.m │ ├── CardResultViewController.xib │ ├── CardVideoViewController.h │ ├── CardVideoViewController.m │ ├── CardVideoViewController.xib │ ├── DemoViewController.h │ ├── DemoViewController.m │ ├── DemoViewController.xib │ ├── VideoViewController.h │ ├── VideoViewController.m │ ├── VideoViewController.xib │ ├── WBBaseViewController.h │ └── WBBaseViewController.m ├── common │ ├── CaptureService │ │ ├── WBCaptureService.h │ │ ├── WBCaptureService.m │ │ ├── WBVideoRecorder.h │ │ └── WBVideoRecorder.m │ ├── GTMNSString+HTML.h │ ├── GTMNSString+HTML.m │ ├── JSONKit │ │ ├── JSONKit.h │ │ └── JSONKit.m │ ├── MBProgressHUD │ │ ├── MBProgressHUD.h │ │ └── MBProgressHUD.m │ ├── Server │ │ ├── ServerAPI.h │ │ ├── ServerAPI.m │ │ ├── YTServerAPI.h │ │ └── YTServerAPI.m │ ├── WBObjectExtension.h │ └── WBObjectExtension.m └── main.m └── YoutuYunDemoTests ├── Info.plist └── YoutuYunDemoTests.m /.gitignore: -------------------------------------------------------------------------------- 1 | YoutuYunDemo.xcodeproj/project.xcworkspace/xcuserdata 2 | YoutuYunDemo.xcodeproj/xcuserdata 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ios_sdk 2 | 3 | iOS SDK宗旨:展示如何在iOS平台上使用优图开放平台开放的图像服务, 不能作为sdk使用。 4 | 5 | iOS SDK包含: 6 | 1. 如何进行鉴权 7 | 2. 如何对参数进行封装 8 | 3. 如何使用iOS API来发送GET或POST请求 9 | 4. 如何把服务器返回的结果转换为NSDictionary 10 | 11 | demo展示如何调用优图开放平台API接口,网络请求返回的数据以log形式展示,请开发者用XCode查看,是根据 http://open.youtu.qq.com/welcome/developer#/api-summary 实现的。 12 | 13 | 请开发者根据自己的需求,按照SDK中实现方式,封装http://open.youtu.qq.com/welcome/developer#/api-summary 列出的API 14 | 15 | 16 | 如果遇到问题,请按以下步骤解决: 17 | 1. 阅读iOS SDK源码 18 | 2. 在http://open.youtu.qq.com/welcome/developer#/api-summary 阅读发送参数、返回结果含义 19 | 3. 请联系我们 20 | 21 | ## 注意: 22 | 23 | 人脸核身相关接口,需要申请权限接入,具体参考http://open.youtu.qq.com/welcome/service#/solution-facecheck 24 | 人脸核身接口包括: 25 | - (void)idcardOcrFaceIn:(id)image cardType:(NSInteger)cardType successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 26 | - (void)idcardNameFaceIn:(NSString*)id_num cardName:(NSString*)id_name successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 27 | - (void)faceCompareFaceIn:(id)imageA imageB:(id)imageB successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 28 | - (void)idcardfacecompare:(NSString*)idCardNumber withName:(NSString*)idCardName image:(id)image successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 29 | - (void)livegetfour:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 30 | - (void)livedetectfour:(NSData*)video image:(id)image validateId:(NSString*) validateData isCompare:(BOOL)isCompare successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 31 | - (void)idcardlivedetectfour:(NSData*)video withId:(NSString*)idCardNumber withName:(NSString*)idCardName validateId:(NSString*) validateData successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 32 | 33 | 34 | ## 名词: 35 | 36 | - AppId 平台添加应用后分配的AppId 37 | - SecretId 平台添加应用后分配的SecretId 38 | - SecretKey 平台添加应用后分配的SecretKey 39 | - 签名 接口鉴权凭证,由AppId、SecretId、SecretKey等生成,详见 http://open.youtu.qq.com/welcome/new-authentication 40 | 41 | 42 | ## 使用示例 43 | 44 | ##### 设置APP 鉴权信息 45 | Conf.m里设置自己申请的 APP_ID, SECRET_ID, SECRET_KEY 46 | -(instancetype)init{ 47 | self = [super init]; 48 | _appId = @"your appid"; // 替换APP_ID 49 | _secretId = @"your secretId"; // 替换SECRET_ID 50 | _secretKey = @"your secretkey"; // 替换SECRET_KEY 51 | _API_END_POINT = API_END_POINT; 52 | _API_VIP_END_POINT = API_VIP_END_POINT; 53 | return self; 54 | } 55 | 56 | ##### 根据你使用的平台选择一种初始化方式 57 | 优图开放平台初始化 58 | NSString *auth = [Auth appSign:1000000 userId:nil]; 59 | TXQcloudFrSDK *sdk = [[TXQcloudFrSDK alloc] initWithName:[Conf instance].appId authorization:auth endPoint:[Conf instance].API_END_POINT]; 60 | 61 | 优图开放平台核身服务初始化(**核身服务目前仅支持核身专有接口,需要联系商务开通**) 62 | NSString *auth = [Auth appSign:1000000 userId:nil]; 63 | TXQcloudFrSDK *sdk = [[TXQcloudFrSDK alloc] initWithName:[Conf instance].appId authorization:auth endPoint:[Conf instance].API_VIP_END_POINT]; 64 | 65 | ##### 调用示例 66 | UIImage *local = [UIImage imageNamed:@"id.jpg"]; 67 | id image = local; 68 | [sdk detectFace:image successBlock:^(id responseObject) { 69 | NSLog(@"responseObject: %@", responseObject); 70 | } failureBlock:^(NSError *error) { 71 | NSLog(@"error"); 72 | }]; 73 | 74 | 75 | ## 接口说明: 76 | 77 | #### 接口分为开放平台免费接口和人脸核身接口,人脸核身接口访问权限需要联系商务开通;开放平台接口访问域名为https://api.youtu.qq.com/, 人脸核身接口访问域名为https://vip-api.youtu.qq.com/ 78 | 79 | 80 | 构造方法 81 | - (id)initWithName:(NSString *)_appid authorization:(NSString *)_authorization endPoint:(NSString *)endpoint; 82 | 参数: 83 | appid 授权appid 84 | secret_id 授权secret_id 85 | secret_key 授权secret_key 86 | end_point 域名(开放平台接口访问域名为:https://api.youtu.qq.com/,人脸核身接口访问域名为:https://vip-api.youtu.qq.com/) 87 | 88 | ### 开放平台免费接口说明 89 | 90 | 人脸检测,检测给定图片(Image)中的所有人脸(Face)的位置和相应的面部属性。位置包括(x, y, w, h), 面部属性包括性别(gender), 年龄(age), 表情(expression), 眼镜(glass)和姿态(pitch,roll,yaw). 91 | - (void)detectFace:(id)image successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 92 | 参数: 93 | image 人脸图片 94 | 95 | 五官定位 96 | - (void)faceShape:(id)image successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 97 | 参数: 98 | image 人脸图片 99 | 100 | 人脸对比, 计算两个Face的相似性以及五官相似度。 101 | - (void)faceCompare:(id)imageA imageB:(id)imageB successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 102 | 参数: 103 | imageA 第一张人脸图片 104 | imageB 第二张人脸图片 105 | 106 | 107 | 人脸识别,对于一个待识别的人脸图片,在一个Group中识别出最相似的Top5 Person作为其身份返回,返回的Top5中按照相似度从大到小排列。 108 | - (void)faceIdentify:(id)image groupId:(NSString *)groupId successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 109 | 参数: 110 | image 需要识别的人脸图片 111 | groupId 人脸face组 112 | 113 | 创建一个Person,并将Person放置到group_ids指定的组当中 114 | - (void)newPerson:(id)image personId:(NSString *)personId groupIds:(NSArray *) groupIds personName:(NSString*) personName successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 115 | 参数: 116 | image 需要新建的人脸图片 117 | personId 指定创建的人脸 118 | groupIds 加入的group列表 119 | personName 名字 120 | 121 | 创建一个Person,并将Person放置到group_ids指定的组当中 122 | - (void)newPerson:(id)image personId:(NSString *)personId groupIds:(NSArray *) groupIds successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 123 | 参数: 124 | image 需要新建的人脸图片 125 | personId 指定创建的人脸 126 | groupIds 加入的group列表 127 | 128 | 增加一个人脸Face.将一组Face加入到一个Person中。注意,一个Face只能被加入到一个Person中。一个Person最多允许包含100个Face。 129 | - (void)addFace:(NSString *)personId imageArray:(NSArray *)imageArray successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 130 | 参数: 131 | personId 人脸Face的person id 132 | imageArray 人脸图片UIImage列表 133 | 134 | 删除一个person下的face,包括特征,属性和face_id. 135 | - (void)delFace:(NSString *)personId faceIdArray:(NSArray *)faceIdArray successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 136 | 参数: 137 | personId 待删除人脸的person ID 138 | faceIdArray 删除人脸id的列表 139 | 140 | 设置Person的name. 141 | - (void)setInfo:(NSString *)personName personId:(NSString *)personId successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 142 | 参数: 143 | personName新的name 144 | personId 要设置的person id 145 | 146 | 获取一个Person的信息, 包括name, id, tag, 相关的face, 以及groups等信息。 147 | - (void)getInfo:(NSString *)personId successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 148 | 参数: 149 | personId 待查询个体的ID 150 | 151 | 获取一个AppId下所有group列表 152 | - (void)getGroupIdsWithsuccessBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 153 | 154 | - (void)getPersonIds:(NSString *)groupId successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 155 | 参数: 156 | groupId 待查询的组id 157 | 158 | 获取一个组person中所有face列表 159 | - (void)getFaceIds:(NSString *)personId successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 160 | 参数: 161 | personId 待查询的个体id 162 | 163 | 获取一个face的相关特征信息 164 | - (void)getFaceInfo:(NSString *)face_id successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 165 | 参数: 166 | faceId 带查询的人脸ID 167 | 168 | 删除一个Person 169 | - (void)delPerson:(NSString *)personId successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 170 | 参数: 171 | personId 要删除的person ID 172 | 173 | 创建一个Person,并将Person放置到group_ids指定的组当中 174 | - (void)newPerson:(id)image personId:(NSString *)personId groupIds:(NSArray *)groupIds personName:(NSString *) personName personTag:(NSString *) personTag successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 175 | 参数: 176 | image 需要新建的人脸图片 177 | personId 指定创建的人脸 178 | groupIds 加入的group列表 179 | personName 名字 180 | personTag 备注 181 | 182 | 身份证OCR识别 183 | - (void)idcardOcr:(UIImage *)image cardType:(NSInteger)cardType sessionId:(NSString *)sessionId successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 184 | 参数: 185 | image 输入图片 186 | cardType 身份证图片类型,0-正面,1-反面 187 | sessionId 请求序列号,用于流水查询 188 | 189 | 名片OCR识别 190 | - (void)namecardOcr:(UIImage *)image sessionId:(NSString *)sessionId successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 191 | 参数: 192 | image 输入图片 193 | sessionId 请求序列号,用于流水查询 194 | 195 | 196 | 判断一个图像的模糊程度 197 | - (void)fuzzyDetect:(id)image cookie:(NSString *)cookie seq:(NSString *)seq successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 198 | 参数: 199 | image 输入图片 200 | cookie 下载url时需要的cookie 信息 201 | seq 请求序列号,用于流水查询 202 | 203 | 204 | 识别一个图像是否为美食图像 205 | - (void)foodDetect:(id)image cookie:(NSString *)cookie seq:(NSString *)seq successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 206 | 参数: 207 | image 输入图片 208 | cookie 当imagePath为url时,需要的cookie信息 209 | seq 请求序列号,用于流水查询 210 | 211 | 识别一个图像的标签信息,对图像分类。 212 | - (void)imageTag:(id)image cookie:(NSString *)cookie seq:(NSString *)seq successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 213 | 参数: 214 | image 输入图片 215 | cookie 当imagePath为url时,需要的cookie信息 216 | seq 请求序列号,用于流水查询 217 | 218 | 识别一个图像是否为色情图像 219 | - (void)imagePorn:(id)image cookie:(NSString *)cookie seq:(NSString *)seq successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 220 | 参数: 221 | image 输入图片 222 | cookie 当imagePath为url时,需要的cookie信息 223 | seq 请求序列号,用于流水查询 224 | 225 | 226 | 227 | ### 人脸核身接口说明 228 | 229 | #### 人脸核身接口访问域名为:https://vip-api.youtu.qq.com/,需要联系商务开通权限。 230 | 231 | 身份证OCR识别 232 | - (void)idcardOcrFaceIn:(id)image cardType:(NSInteger)cardType successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 233 | 参数: 234 | image 输入图片 235 | cardType 身份证图片类型,0-正面,1-反面 236 | 237 | 身份证实名认证 238 | - (void)idcardNameFaceIn:(NSString*)id_num cardName:(NSString*)id_name successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 239 | 参数: 240 | id_num 用户身份证号码 241 | id_name 用户身份证姓名 242 | 243 | 人脸比对 244 | - (void)faceCompareFaceIn:(id)imageA imageB:(id)imageB successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 245 | 参数: 246 | imageA 输入图片A 247 | imageB 输入图片B 248 | 249 | 人脸比对:使用优图数据源比对 250 | - (void)idcardfacecompare:(NSString*)idCardNumber withName:(NSString*)idCardName image:(id)image successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 251 | 参数: 252 | idCardNumber 用户身份证号码 253 | idCardName 用户身份证姓名 254 | image 输入图片 255 | 256 | 唇语获取 257 | - (void)livegetfour:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 258 | 259 | 视频人脸核身:用户自带数据源核身 260 | - (void)livedetectfour:(NSData*)video image:(id)image validateId:(NSString*) validateData isCompare:(BOOL)isCompare successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 261 | 参数: 262 | video 需要检测的视频base64编码 263 | validateData livegetfour得到的唇语验证数据 264 | image 输入图片 265 | isCompare video中的照片和card是否做对比,True做对比,False不做对比 266 | 267 | 视频人脸核身:使用优图数据源核身 268 | - (void)idcardlivedetectfour:(NSData*)video withId:(NSString*)idCardNumber withName:(NSString*)idCardName validateId:(NSString*) validateData successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 269 | 参数: 270 | video 需要检测的视频base64编码 271 | idCardNumber 用户身份证号码 272 | idCardName 用户身份证姓名 273 | validateData livegetfour得到的唇语验证数据 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | -------------------------------------------------------------------------------- /TencentYoutuYun/Auth.h: -------------------------------------------------------------------------------- 1 | // 2 | // Auth.h 3 | // YoutuYunDemo 4 | // 5 | // Created by Patrick Yang on 15/9/15. 6 | // Copyright (c) 2015年 Tencent. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface Auth : NSObject 12 | 13 | + (NSString *)appSign:(unsigned int)expired userId:(NSString *)userId; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /TencentYoutuYun/Auth.m: -------------------------------------------------------------------------------- 1 | // 2 | // Auth.m 3 | // YoutuYunDemo 4 | // 5 | // Created by Patrick Yang on 15/9/15. 6 | // Copyright (c) 2015年 Tencent. All rights reserved. 7 | // 8 | 9 | #import "Auth.h" 10 | #import "Conf.h" 11 | #import "NSData+Base64.h" 12 | #import 13 | #import 14 | 15 | #define USER_ID_MAX_LEN 64 16 | #define URL_MAX_LEN 1024 17 | #define PLAIN_TEXT_MAX_LEN 4096 18 | #define CIPER_TEXT_MAX_LEN 1024 19 | 20 | @implementation Auth 21 | 22 | + (NSString *)appSign:(unsigned int)expired userId:(NSString *)userId 23 | { 24 | if ([Conf instance].secretId.length <= 0 || [Conf instance].secretKey.length <= 0) { 25 | NSLog(@"ERROR: secretId & secretKey empty!"); 26 | return nil; 27 | } 28 | if ([Conf instance].userId.length > USER_ID_MAX_LEN) { 29 | NSLog(@"ERROR: userId exceed the length limitation!"); 30 | return nil; 31 | } 32 | unsigned int now = (int)[[NSDate date] timeIntervalSince1970]; 33 | unsigned int rdm = (int)random() % 1000000000; 34 | NSString *origin = [NSString stringWithFormat:@"a=%@&k=%@&e=%u&t=%u&r=%d&u=%zd&f=%@", [Conf instance].appId, [Conf instance].secretId, expired + now, now, rdm, [[Conf instance].userId integerValue], @""]; 35 | NSData *data = [self hmacsha1:origin secret:[Conf instance].secretKey]; 36 | NSLog(@"s: %@", [data base64String]); 37 | NSMutableData *all = [NSMutableData dataWithData:data]; 38 | [all appendBytes:origin.UTF8String length:origin.length]; 39 | NSString *base64 = [all base64String]; 40 | return base64; 41 | } 42 | 43 | + (NSData *)hmacsha1:(NSString *)data secret:(NSString *)key 44 | { 45 | const char *cKey = [key cStringUsingEncoding:NSASCIIStringEncoding]; 46 | const char *cData = [data cStringUsingEncoding:NSASCIIStringEncoding]; 47 | 48 | unsigned char cHMAC[CC_SHA1_DIGEST_LENGTH]; 49 | 50 | CCHmac(kCCHmacAlgSHA1, cKey, strlen(cKey), cData, strlen(cData), cHMAC); 51 | 52 | NSData *HMAC = [[NSData alloc] initWithBytes:cHMAC length:sizeof(cHMAC)]; 53 | 54 | return HMAC; 55 | } 56 | 57 | @end 58 | -------------------------------------------------------------------------------- /TencentYoutuYun/Conf.h: -------------------------------------------------------------------------------- 1 | // 2 | // Conf.h 3 | // YoutuYunDemo 4 | // 5 | // Created by Patrick Yang on 15/9/15. 6 | // Copyright (c) 2015年 Tencent. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface Conf : NSObject 12 | 13 | @property (nonatomic, copy) NSString *appId; 14 | @property (nonatomic, copy) NSString *secretId; 15 | @property (nonatomic, copy) NSString *secretKey; 16 | @property (nonatomic, copy) NSString *userId; 17 | @property (nonatomic, copy) NSString *API_END_POINT; 18 | @property (nonatomic, copy) NSString *API_VIP_END_POINT; 19 | 20 | + (Conf *)instance; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /TencentYoutuYun/Conf.m: -------------------------------------------------------------------------------- 1 | // 2 | // Conf.m 3 | // YoutuYunDemo 4 | // 5 | // Created by Patrick Yang on 15/9/15. 6 | // Copyright (c) 2015年 Tencent. All rights reserved. 7 | // 8 | 9 | #import "Conf.h" 10 | 11 | #define API_END_POINT @"http://api.youtu.qq.com/youtu" 12 | #define API_VIP_END_POINT @"https://vip-api.youtu.qq.com/youtu" 13 | 14 | @implementation Conf 15 | 16 | + (Conf *)instance 17 | { 18 | static Conf *singleton = nil; 19 | if (singleton) { 20 | return singleton; 21 | } 22 | singleton = [[Conf alloc] init]; 23 | return singleton; 24 | } 25 | 26 | -(instancetype)init{ 27 | self = [super init]; 28 | _appId = @"123456"; // 替换APP_ID 29 | _secretId = @"aaaaa"; // 替换SECRET_ID 30 | _secretKey = @"bbbbb"; // 替换SECRET_KEY 31 | _API_END_POINT = API_END_POINT; 32 | _API_VIP_END_POINT = API_VIP_END_POINT; 33 | return self; 34 | } 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /TencentYoutuYun/TXQcloudFrSDK.h: -------------------------------------------------------------------------------- 1 | // 2 | // TXQcloudFrSDK.h 3 | // SimpleURLConnections 4 | // 5 | // Created by kenxjgao on 15/9/9. 6 | // 7 | // 8 | 9 | #import 10 | 11 | typedef void(^HttpRequestSuccessBlock)(id responseObject); 12 | typedef void(^HttpRequestFailBlock)(NSError *error); 13 | 14 | @interface TXQcloudFrSDK: NSObject 15 | 16 | @property (nonatomic, copy, readwrite) NSString *API_END_POINT; 17 | @property (nonatomic, copy, readwrite) NSString *appid; 18 | @property (nonatomic, copy, readwrite) NSString *authorization; 19 | 20 | /*! 21 | * 构造方法 22 | * 23 | * @input appid 24 | * 授权appid 25 | * @input authorization 26 | * 通过appid secretId和secretKey生成的鉴权密钥 27 | */ 28 | - (id)initWithName:(NSString *)appId authorization:(NSString *)_authCode endPoint:(NSString *)endpoint; 29 | /*! 30 | * 人脸属性分析 检测给定图片(Image)中的所有人脸(Face)的位置和相应的面部属性。位置包括(x, y, w, h), 31 | * 面部属性包括性别(gender), 年龄(age), 表情(expression), 眼镜(glass)和姿态(pitch,roll,yaw). 32 | * 33 | * @input image 34 | * 人脸图片 35 | * @return 请求json结果 36 | */ 37 | - (void)detectFace:(id)image successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 38 | /*! 39 | * 五官定位 40 | * 41 | * @input image 42 | * 人脸图片 43 | */ 44 | - (void)faceShape:(id)image successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 45 | /*! 46 | * 人脸对比, 计算两个Face的相似性以及五官相似度。 47 | * 48 | * @input imageA 49 | * 第一张人脸图片 50 | * @input imageB 51 | * 第二张人脸图片 52 | */ 53 | - (void)faceCompare:(id)imageA imageB:(id)imageB successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 54 | /*! 55 | * 人脸验证,给定一个Face和一个Person,返回是否是同一个人的判断以及置信度。 56 | * 57 | * @input image 58 | * 需要验证的人脸图片 59 | * @input personId 60 | * 验证的目标person 61 | */ 62 | - (void)faceVerify:(id)image personId:(NSString *)personId successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 63 | /*! 64 | * 人脸识别,对于一个待识别的人脸图片,在一个Group中识别出最相似的Top5 Person作为其身份返回,返回的Top5中按照相似度从大到小排列。 65 | * 66 | * @input image 67 | * 需要识别的人脸图片 68 | * @input groupId 69 | * 人脸face组 70 | */ 71 | - (void)faceIdentify:(id)image groupId:(NSString *)groupId successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 72 | /*! 73 | * 创建一个Person,并将Person放置到group_ids指定的组当中 74 | * 75 | * @input image 76 | * 需要新建的人脸图片 77 | * @input personId 78 | * 指定创建的人脸 79 | * @input groupIds 80 | * 加入的group列表 81 | * @input personName 82 | * 名字 83 | */ 84 | - (void)newPerson:(id)image personId:(NSString *)personId groupIds:(NSArray *) groupIds personName:(NSString*) personName successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 85 | /*! 86 | * 创建一个Person,并将Person放置到group_ids指定的组当中 87 | * 88 | * @input image 89 | * 需要新建的人脸图片 90 | * @input personId 91 | * 指定创建的人脸 92 | * @input groupIds 93 | * 加入的group列表 94 | */ 95 | - (void)newPerson:(id)image personId:(NSString *)personId groupIds:(NSArray *) groupIds successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 96 | /*! 97 | * 增加一个人脸Face.将一组Face加入到一个Person中。注意,一个Face只能被加入到一个Person中。 98 | * 一个Person最多允许包含100个Face。 99 | * 100 | * @input personId 101 | * 人脸Face的person id 102 | * @input imageArray 103 | * 人脸图片UIImage列表 104 | */ 105 | - (void)addFace:(NSString *)personId imageArray:(NSArray *)imageArray successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 106 | /*! 107 | * 删除一个person下的face,包括特征,属性和face_id. 108 | * 109 | * @input personId 110 | * 待删除人脸的person ID 111 | * @input faceIdArray 112 | * 删除人脸id的列表 113 | */ 114 | - (void)delFace:(NSString *)personId faceIdArray:(NSArray *)faceIdArray successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 115 | /*! 116 | * 设置Person的name. 117 | * 118 | * @input personName 119 | * 新的name 120 | * @input personId 121 | * 要设置的person id 122 | */ 123 | - (void)setInfo:(NSString *)personName personId:(NSString *)personId successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 124 | /*! 125 | * 获取一个Person的信息, 包括name, id, tag, 相关的face, 以及groups等信息。 126 | * 127 | * @input personId 128 | * 待查询个体的ID 129 | */ 130 | - (void)getInfo:(NSString *)personId successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 131 | /*! 132 | * 获取一个AppId下所有group列表 133 | * 134 | * @input 请求json结果 135 | */ 136 | - (void)getGroupIdsWithsuccessBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 137 | /*! 138 | * 获取一个组Group中所有person列表 139 | * 140 | * @input groupId 141 | * 待查询的组id 142 | */ 143 | - (void)getPersonIds:(NSString *)groupId successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 144 | /*! 145 | * 获取一个组person中所有face列表 146 | * 147 | * @input personId 148 | * 待查询的个体id 149 | */ 150 | - (void)getFaceIds:(NSString *)personId successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 151 | /*! 152 | * 获取一个face的相关特征信息 153 | * 154 | * @input faceId 155 | * 带查询的人脸ID 156 | */ 157 | - (void)getFaceInfo:(NSString *)face_id successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 158 | /*! 159 | * 删除一个Person 160 | * 161 | * @input personId 162 | * 要删除的person ID 163 | */ 164 | - (void)delPerson:(NSString *)personId successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 165 | /*! 166 | * 创建一个Person,并将Person放置到group_ids指定的组当中 167 | * 168 | * @input image 169 | * 需要新建的人脸图片 170 | * @input personId 171 | * 指定创建的人脸 172 | * @input groupIds 173 | * 加入的group列表 174 | * @input personName 175 | * 名字 176 | * @input personTag 177 | * 备注 178 | */ 179 | - (void)newPerson:(id)image personId:(NSString *)personId groupIds:(NSArray *)groupIds personName:(NSString *) personName personTag:(NSString *) personTag successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 180 | #pragma mark - ID OCR 181 | /*! 182 | * 身份证OCR识别 183 | * 184 | * @input image 185 | * 输入图片 186 | * @input cardType 187 | * 身份证图片类型,0-正面,1-反面 188 | * @input sessionId 189 | * 请求序列号,用于流水查询 190 | */ 191 | - (void)idcardOcr:(UIImage *)image cardType:(NSInteger)cardType sessionId:(NSString *)sessionId successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 192 | /*! 193 | * 名片OCR识别 194 | * 195 | * @input image 196 | * 输入图片 197 | * @input sessionId 198 | * 请求序列号,用于流水查询 199 | */ 200 | - (void)namecardOcr:(UIImage *)image sessionId:(NSString *)sessionId successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 201 | 202 | #pragma mark - FaceIn人脸核身相关接口 203 | /*! 204 | * 身份证OCR识别-----人脸核身相关接口 205 | * 206 | * @input image 207 | * 输入图片 208 | * @input cardType 209 | * 身份证图片类型,0-正面,1-反面 210 | */ 211 | - (void)idcardOcrFaceIn:(id)image cardType:(NSInteger)cardType successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 212 | 213 | /*! 214 | * 身份证实名认证-----人脸核身相关接口 215 | * 216 | * @input id_num 217 | * 用户身份证号码 218 | * @input id_name 219 | * 用户身份证姓名 220 | */ 221 | - (void)idcardNameFaceIn:(NSString*)id_num cardName:(NSString*)id_name successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 222 | /*! 223 | * 人脸比对-----人脸核身相关接口 224 | * 225 | * @input imageA 226 | * 输入图片A 227 | * @input imageB 228 | * 输入图片B 229 | */ 230 | - (void)faceCompareFaceIn:(id)imageA imageB:(id)imageB successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 231 | 232 | /*! 233 | * 人脸比对:使用优图数据源比对-----人脸核身相关接口 234 | * 235 | * @input idCardNumber 236 | * 用户身份证号码 237 | * @input idCardName 238 | * 用户身份证姓名 239 | @input image 240 | * 输入图片 241 | */ 242 | -(void)idcardfacecompare:(NSString*)idCardNumber withName:(NSString*)idCardName image:(id)image successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 243 | /*! 244 | * 唇语获取-----人脸核身相关接口 245 | * 246 | */ 247 | - (void)livegetfour:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 248 | 249 | /*! 250 | * 视频人脸核身:用户自带数据源核身-----人脸核身相关接口 251 | * 252 | * @input video 253 | * 需要检测的视频base64编码 254 | * @input validateData 255 | * livegetfour得到的唇语验证数据 256 | @input image 257 | * 输入图片 258 | @input imisCompare 259 | * video中的照片和card是否做对比,True做对比,False不做对比 260 | */ 261 | - (void)livedetectfour:(NSData*)video image:(id)image validateId:(NSString*) validateData isCompare:(BOOL)isCompare successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 262 | 263 | /*! 264 | * 视频人脸核身:使用优图数据源核身-----人脸核身相关接口 265 | * 266 | * @input video 267 | * 需要检测的视频base64编码 268 | * @input idCardNumber 269 | * 用户身份证号码 270 | * @input idCardName 271 | * 用户身份证姓名 272 | * @input validateData 273 | * livegetfour得到的唇语验证数据 274 | */ 275 | -(void)idcardlivedetectfour:(NSData*)video withId:(NSString*)idCardNumber withName:(NSString*)idCardName validateId:(NSString*) validateData successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 276 | 277 | 278 | #pragma mark - Image Recognition 279 | /*! 280 | * 判断一个图像的模糊程度 281 | * 282 | * @input image 283 | * 输入图片 284 | * @input cookie 285 | * 下载url时需要的cookie 信息 286 | * @input seq 287 | * 请求序列号,用于流水查询 288 | */ 289 | - (void)fuzzyDetect:(id)image cookie:(NSString *)cookie seq:(NSString *)seq successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 290 | /*! 291 | * 识别一个图像是否为美食图像 292 | * 293 | * @input image 294 | * 输入图片 295 | * @input cookie 296 | * 当imagePath为url时,需要的cookie信息 297 | * @input seq 298 | * 请求序列号,用于流水查询 299 | */ 300 | - (void)foodDetect:(id)image cookie:(NSString *)cookie seq:(NSString *)seq successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 301 | /*! 302 | * 识别一个图像的标签信息,对图像分类。 303 | * 304 | * @input imagePath 305 | * 输入图片 306 | * @input cookie 307 | * 当imagePath为url时,需要的cookie信息 308 | * @input seq 309 | * 请求序列号,用于流水查询 310 | */ 311 | - (void)imageTag:(id)image cookie:(NSString *)cookie seq:(NSString *)seq successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 312 | /*! 313 | * 识别一个图像是否为色情图像 314 | * 315 | * @input imagePath 316 | * 输入图片 317 | * @input cookie 318 | * 当imagePath为url时,需要的cookie信息 319 | * @input seq 320 | * 请求序列号,用于流水查询 321 | */ 322 | - (void)imagePorn:(id)image cookie:(NSString *)cookie seq:(NSString *)seq successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 323 | 324 | 325 | 326 | 327 | 328 | @end 329 | -------------------------------------------------------------------------------- /TencentYoutuYun/vendor/NSData+Base64.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSData+Base64.h 3 | // MeetingCheck 4 | // 5 | // Created by Patrick Yang on 15/7/16. 6 | // Copyright (c) 2015年 Tencent. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSData (Base64) 12 | 13 | - (NSString *)base64String; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /TencentYoutuYun/vendor/NSData+Base64.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSData+Base64.m 3 | // MeetingCheck 4 | // 5 | // Created by Patrick Yang on 15/7/16. 6 | // Copyright (c) 2015年 Tencent. All rights reserved. 7 | // 8 | 9 | #import "NSData+Base64.h" 10 | 11 | @implementation NSData (Base64) 12 | 13 | - (NSString *)base64String; 14 | { 15 | if ([[[UIDevice currentDevice] systemVersion] floatValue] < 7.0) { 16 | const uint8_t* input = (const uint8_t*)[self bytes]; 17 | NSInteger length = [self length]; 18 | 19 | static char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; 20 | 21 | NSMutableData* data = [NSMutableData dataWithLength:((length + 2) / 3) * 4]; 22 | uint8_t* output = (uint8_t*)data.mutableBytes; 23 | 24 | NSInteger i; 25 | for (i=0; i < length; i += 3) { 26 | NSInteger value = 0; 27 | NSInteger j; 28 | for (j = i; j < (i + 3); j++) { 29 | value <<= 8; 30 | 31 | if (j < length) { 32 | value |= (0xFF & input[j]); 33 | } 34 | } 35 | 36 | NSInteger theIndex = (i / 3) * 4; 37 | output[theIndex + 0] = table[(value >> 18) & 0x3F]; 38 | output[theIndex + 1] = table[(value >> 12) & 0x3F]; 39 | output[theIndex + 2] = (i + 1) < length ? table[(value >> 6) & 0x3F] : '='; 40 | output[theIndex + 3] = (i + 2) < length ? table[(value >> 0) & 0x3F] : '='; 41 | } 42 | 43 | return [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding] ; 44 | } else { 45 | return [self base64EncodedStringWithOptions:0]; 46 | } 47 | } 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /YoutuYunDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /YoutuYunDemo.xcodeproj/xcuserdata/patyang.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | YoutuYunDemo.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | D456A5B51BA7F635008A0CF0 16 | 17 | primary 18 | 19 | 20 | D456A5CE1BA7F635008A0CF0 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /YoutuYunDemo/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 20 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /YoutuYunDemo/DemoAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // YoutuYunDemo 4 | // 5 | // Created by Patrick Yang on 15/9/15. 6 | // Copyright (c) 2015年 Tencent. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface DemoAppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /YoutuYunDemo/DemoAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // YoutuYunDemo 4 | // 5 | // Created by Patrick Yang on 15/9/15. 6 | // Copyright (c) 2015年 Tencent. All rights reserved. 7 | // 8 | 9 | #import "DemoAppDelegate.h" 10 | #import "DemoViewController.h" 11 | 12 | @interface DemoAppDelegate () 13 | 14 | @end 15 | 16 | @implementation DemoAppDelegate 17 | 18 | 19 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 20 | UIWindow *window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; 21 | self.window = window; 22 | 23 | DemoViewController *rootController = [[DemoViewController alloc] init]; 24 | 25 | UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:rootController]; 26 | navigationController.navigationBarHidden = YES; 27 | self.window.rootViewController = navigationController; 28 | 29 | [self.window makeKeyAndVisible]; 30 | return YES; 31 | } 32 | 33 | - (void)applicationWillResignActive:(UIApplication *)application { 34 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 35 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 36 | } 37 | 38 | - (void)applicationDidEnterBackground:(UIApplication *)application { 39 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 40 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 41 | } 42 | 43 | - (void)applicationWillEnterForeground:(UIApplication *)application { 44 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 45 | } 46 | 47 | - (void)applicationDidBecomeActive:(UIApplication *)application { 48 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 49 | } 50 | 51 | - (void)applicationWillTerminate:(UIApplication *)application { 52 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 53 | } 54 | 55 | @end 56 | -------------------------------------------------------------------------------- /YoutuYunDemo/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /YoutuYunDemo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.tencent.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | NSAppTransportSecurity 26 | 27 | NSAllowsArbitraryLoads 28 | 29 | 30 | UIFileSharingEnabled 31 | 32 | UILaunchStoryboardName 33 | LaunchScreen 34 | UIRequiredDeviceCapabilities 35 | 36 | armv7 37 | 38 | UISupportedInterfaceOrientations 39 | 40 | UIInterfaceOrientationPortrait 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | UISupportedInterfaceOrientations~ipad 45 | 46 | UIInterfaceOrientationPortrait 47 | UIInterfaceOrientationPortraitUpsideDown 48 | UIInterfaceOrientationLandscapeLeft 49 | UIInterfaceOrientationLandscapeRight 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /YoutuYunDemo/Resource/beginbtn_nor@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tencent-YouTu/ios_sdk/fd56235294b8882786dbea80ca928d3564132ffc/YoutuYunDemo/Resource/beginbtn_nor@2x.png -------------------------------------------------------------------------------- /YoutuYunDemo/Resource/beginbtn_selected@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tencent-YouTu/ios_sdk/fd56235294b8882786dbea80ca928d3564132ffc/YoutuYunDemo/Resource/beginbtn_selected@2x.png -------------------------------------------------------------------------------- /YoutuYunDemo/Resource/bt_blue@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tencent-YouTu/ios_sdk/fd56235294b8882786dbea80ca928d3564132ffc/YoutuYunDemo/Resource/bt_blue@2x.png -------------------------------------------------------------------------------- /YoutuYunDemo/Resource/face.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tencent-YouTu/ios_sdk/fd56235294b8882786dbea80ca928d3564132ffc/YoutuYunDemo/Resource/face.jpg -------------------------------------------------------------------------------- /YoutuYunDemo/Resource/id.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tencent-YouTu/ios_sdk/fd56235294b8882786dbea80ca928d3564132ffc/YoutuYunDemo/Resource/id.jpg -------------------------------------------------------------------------------- /YoutuYunDemo/Resource/id_back@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tencent-YouTu/ios_sdk/fd56235294b8882786dbea80ca928d3564132ffc/YoutuYunDemo/Resource/id_back@2x.png -------------------------------------------------------------------------------- /YoutuYunDemo/Resource/id_back_back@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tencent-YouTu/ios_sdk/fd56235294b8882786dbea80ca928d3564132ffc/YoutuYunDemo/Resource/id_back_back@2x.png -------------------------------------------------------------------------------- /YoutuYunDemo/Resource/id_back_front@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tencent-YouTu/ios_sdk/fd56235294b8882786dbea80ca928d3564132ffc/YoutuYunDemo/Resource/id_back_front@2x.png -------------------------------------------------------------------------------- /YoutuYunDemo/Resource/idcard_back@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tencent-YouTu/ios_sdk/fd56235294b8882786dbea80ca928d3564132ffc/YoutuYunDemo/Resource/idcard_back@2x.png -------------------------------------------------------------------------------- /YoutuYunDemo/Resource/idcard_first@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tencent-YouTu/ios_sdk/fd56235294b8882786dbea80ca928d3564132ffc/YoutuYunDemo/Resource/idcard_first@2x.png -------------------------------------------------------------------------------- /YoutuYunDemo/Resource/idcard_second@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tencent-YouTu/ios_sdk/fd56235294b8882786dbea80ca928d3564132ffc/YoutuYunDemo/Resource/idcard_second@2x.png -------------------------------------------------------------------------------- /YoutuYunDemo/Resource/indicator_correct@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tencent-YouTu/ios_sdk/fd56235294b8882786dbea80ca928d3564132ffc/YoutuYunDemo/Resource/indicator_correct@2x.png -------------------------------------------------------------------------------- /YoutuYunDemo/Resource/indicator_nor@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tencent-YouTu/ios_sdk/fd56235294b8882786dbea80ca928d3564132ffc/YoutuYunDemo/Resource/indicator_nor@2x.png -------------------------------------------------------------------------------- /YoutuYunDemo/Resource/indicator_wrong@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tencent-YouTu/ios_sdk/fd56235294b8882786dbea80ca928d3564132ffc/YoutuYunDemo/Resource/indicator_wrong@2x.png -------------------------------------------------------------------------------- /YoutuYunDemo/Resource/namecard.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tencent-YouTu/ios_sdk/fd56235294b8882786dbea80ca928d3564132ffc/YoutuYunDemo/Resource/namecard.jpg -------------------------------------------------------------------------------- /YoutuYunDemo/Resource/nav_back64@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tencent-YouTu/ios_sdk/fd56235294b8882786dbea80ca928d3564132ffc/YoutuYunDemo/Resource/nav_back64@2x.png -------------------------------------------------------------------------------- /YoutuYunDemo/Resource/nav_back@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tencent-YouTu/ios_sdk/fd56235294b8882786dbea80ca928d3564132ffc/YoutuYunDemo/Resource/nav_back@2x.png -------------------------------------------------------------------------------- /YoutuYunDemo/Resource/person_face@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tencent-YouTu/ios_sdk/fd56235294b8882786dbea80ca928d3564132ffc/YoutuYunDemo/Resource/person_face@2x.png -------------------------------------------------------------------------------- /YoutuYunDemo/Resource/video.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tencent-YouTu/ios_sdk/fd56235294b8882786dbea80ca928d3564132ffc/YoutuYunDemo/Resource/video.mp4 -------------------------------------------------------------------------------- /YoutuYunDemo/Resource/video_begin@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tencent-YouTu/ios_sdk/fd56235294b8882786dbea80ca928d3564132ffc/YoutuYunDemo/Resource/video_begin@2x.png -------------------------------------------------------------------------------- /YoutuYunDemo/UI/CardResultViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // YoutuYunDemo 4 | // 5 | // Created by Patrick Yang on 15/9/15. 6 | // Copyright (c) 2015年 Tencent. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "WBBaseViewController.h" 11 | 12 | @interface CardResultViewController : WBBaseViewController 13 | 14 | 15 | @end 16 | 17 | -------------------------------------------------------------------------------- /YoutuYunDemo/UI/CardResultViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // YoutuYunDemo 4 | // 5 | // Created by Patrick Yang on 15/9/15. 6 | // Copyright (c) 2015年 Tencent. All rights reserved. 7 | // 8 | 9 | #import "CardResultViewController.h" 10 | #import "VideoViewController.h" 11 | #import "YTServerAPI.h" 12 | #import "DemoViewController.h" 13 | 14 | 15 | @interface CardResultViewController () 16 | @property (strong, nonatomic) IBOutlet UILabel *nameLabel; 17 | @property (strong, nonatomic) IBOutlet UILabel *idCardLabel; 18 | @property (strong, nonatomic) IBOutlet UIButton *confirmButton; 19 | 20 | @property (strong, nonatomic) NSString *name; 21 | @property (strong, nonatomic) NSString *id; 22 | 23 | @end 24 | 25 | @implementation CardResultViewController 26 | - (instancetype) init{ 27 | NSString *nibName = @"CardResultViewController"; 28 | self = [super initWithNibName:nibName bundle:nil]; 29 | return self; 30 | } 31 | 32 | - (void)viewDidLoad 33 | { 34 | [super viewDidLoad]; 35 | 36 | UIBarButtonItem *barButton = [[UIBarButtonItem alloc] init]; 37 | barButton.title = @"返回"; 38 | self.navigationController.navigationBar.topItem.backBarButtonItem = barButton; 39 | 40 | [self.navigationController setNavigationBarHidden:NO animated:NO]; 41 | [self.navigationItem setTitle:@"确认信息"]; 42 | [self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:@"nav_back64.png"] forBarMetrics:UIBarMetricsDefault]; 43 | self.navigationController.navigationBar.tintColor = [UIColor whiteColor]; 44 | [self.navigationController.navigationBar 45 | setTitleTextAttributes:@{NSForegroundColorAttributeName : [UIColor whiteColor]}]; 46 | 47 | UIImage *buttongBgImg = [[UIImage imageNamed:@"bt_blue"] resizableImageWithCapInsets:UIEdgeInsetsMake(6, 6, 6, 6)]; 48 | [self.confirmButton setBackgroundImage:buttongBgImg forState:UIControlStateNormal]; 49 | 50 | NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults]; 51 | self.name = [userDefault stringForKey:@"idCardName"]; 52 | self.id = [userDefault stringForKey:@"idCardNo"]; 53 | 54 | self.nameLabel.text = self.name; 55 | self.idCardLabel.text = self.id; 56 | 57 | } 58 | - (IBAction)clickConfirm:(id)sender { 59 | [self showLoading:@""]; 60 | [[YTServerAPI instance] getLivefour:^(NSInteger error, NSString *number){ 61 | [self hideLoading]; 62 | if (error == 0) { 63 | VideoViewController *controller = [[VideoViewController alloc]init]; 64 | [controller setReadLips:number]; 65 | [controller setCardId:self.id]; 66 | [controller setCardName:self.name]; 67 | [self.navigationController pushViewController:controller animated:YES]; 68 | } 69 | }]; 70 | } 71 | - (IBAction)clickBack:(id)sender { 72 | DemoViewController* controller = [[DemoViewController alloc]init]; 73 | [self.navigationController pushViewController:controller animated:YES]; 74 | } 75 | 76 | - (void)didReceiveMemoryWarning 77 | { 78 | [super didReceiveMemoryWarning]; 79 | } 80 | 81 | 82 | @end 83 | -------------------------------------------------------------------------------- /YoutuYunDemo/UI/CardResultViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 32 | 39 | 40 | 41 | 42 | 43 | 50 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 71 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /YoutuYunDemo/UI/CardVideoViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // CardVideoViewController.h 3 | // WeBank 4 | // 5 | // Created by doufeifei on 15/1/21. 6 | // 7 | // 8 | 9 | #import 10 | #import "WBBaseViewController.h" 11 | @interface CardVideoViewController : WBBaseViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /YoutuYunDemo/UI/CardVideoViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // CardVideoViewController.m 3 | // WeBank 4 | // 5 | // Created by doufeifei on 15/1/21. 6 | // 7 | // 8 | 9 | #import "CardVideoViewController.h" 10 | 11 | #import "YTServerAPI.h" 12 | #import "WBCaptureService.h" 13 | #import "JSONKit.h" 14 | #import "WBObjectExtension.h" 15 | #import "Auth.h" 16 | #import "Conf.h" 17 | #import "CardResultViewController.h" 18 | 19 | #define FrontCardVideoTag 0 20 | #define BackCardVideoTag 1 21 | 22 | #define kVideoWidth 720 23 | #define kVideoHeight 1280 24 | 25 | @interface CardVideoViewController () 26 | { 27 | NSInteger currentType;//1正 28 | 29 | NSInteger terminaTime; 30 | NSTimer *timer; 31 | UIBackgroundTaskIdentifier backgroundRecordingID; 32 | BOOL isRecording; 33 | BOOL addedObservers; 34 | BOOL allowedToUseGPU; 35 | 36 | BOOL isVertical; 37 | float scale; 38 | float x; 39 | float y; 40 | float w; 41 | float h; 42 | CGRect idPosHintRect; 43 | CGRect idPosRealRect; 44 | 45 | NSString *weBankSession; 46 | NSString *encryptKey; 47 | BOOL needsUpload; 48 | } 49 | @property (weak, nonatomic) IBOutlet UIImageView *backGround; 50 | 51 | @property(nonatomic, strong) AVCaptureVideoPreviewLayer *previewView; 52 | @property(nonatomic, strong) WBCaptureService *captureService; 53 | @property (weak, nonatomic) IBOutlet UIView *preView; 54 | 55 | @property (weak, nonatomic) IBOutlet UILabel *tipsLabel; 56 | @property (weak, nonatomic) IBOutlet UILabel *errMsgLabel; 57 | @property (weak, nonatomic) IBOutlet UIButton *beginBtn; 58 | @property (weak, nonatomic) IBOutlet UIImageView *indicatorLeft; 59 | @property (weak, nonatomic) IBOutlet UIImageView *indicatorRight; 60 | @property (weak, nonatomic) IBOutlet UIImageView *idcardFirst; 61 | @property (weak, nonatomic) IBOutlet UIImageView *idcardSecode; 62 | @property (nonatomic, assign) NSString * cardId; 63 | @property (nonatomic, assign) NSString * cardName; 64 | 65 | 66 | @end 67 | 68 | @implementation CardVideoViewController 69 | 70 | - (instancetype) init{ 71 | NSString *nibName = @"CardVideoViewController"; 72 | self = [super initWithNibName:nibName bundle:nil]; 73 | return self; 74 | } 75 | 76 | - (void)viewWillAppear:(BOOL)animated 77 | { 78 | [super viewWillAppear:animated]; 79 | 80 | UIBarButtonItem *barButton = [[UIBarButtonItem alloc] init]; 81 | barButton.title = @"返回"; 82 | self.navigationController.navigationBar.topItem.backBarButtonItem = barButton; 83 | 84 | [self.navigationController setNavigationBarHidden:NO animated:NO]; 85 | [self.navigationItem setTitle:@"身份证识别"]; 86 | [self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:@"nav_back64.png"] forBarMetrics:UIBarMetricsDefault]; 87 | self.navigationController.navigationBar.tintColor = [UIColor whiteColor]; 88 | [self.navigationController.navigationBar 89 | setTitleTextAttributes:@{NSForegroundColorAttributeName : [UIColor whiteColor]}]; 90 | 91 | [self.captureService startRunning]; 92 | [self setupPreviewView]; 93 | needsUpload = YES; 94 | [self initUI]; 95 | } 96 | 97 | - (void)viewDidLoad { 98 | [super viewDidLoad]; 99 | 100 | self.preView.frame = self.view.frame; 101 | 102 | [self initVideoCapture]; 103 | 104 | x = 16; 105 | y = 150; 106 | w = 300; 107 | h = 192; 108 | // TODO: idPosHintRect的值应该根据view去获取 109 | idPosHintRect = CGRectMake(16, 151, 288, 183); 110 | idPosRealRect = CGRectNull; 111 | currentType = 1; 112 | 113 | // Do any additional setup after loading the view. 114 | } 115 | 116 | - (void)viewDidDisappear:(BOOL)animated 117 | { 118 | if (self.captureService) { 119 | [self.captureService stopRunning]; 120 | } 121 | // [[WBNetMethods sharedInstance] cleanRequest]; 122 | [super viewDidDisappear:animated]; 123 | } 124 | 125 | - (void)initUI 126 | { 127 | 128 | } 129 | - (void)dealloc 130 | { 131 | [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidEnterBackgroundNotification object:nil]; 132 | [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillEnterForegroundNotification object:nil]; 133 | [[NSNotificationCenter defaultCenter] removeObserver:self name:UIDeviceOrientationDidChangeNotification object:nil]; 134 | } 135 | - (void)initVideoCapture 136 | { 137 | self.captureService = [[WBCaptureService alloc] init]; 138 | [self.captureService setDelegate:self callbackQueue:dispatch_get_main_queue()]; 139 | 140 | [[NSNotificationCenter defaultCenter] addObserver:self 141 | selector:@selector(applicationDidEnterBackground) 142 | name:UIApplicationDidEnterBackgroundNotification 143 | object:[UIApplication sharedApplication]]; 144 | [[NSNotificationCenter defaultCenter] addObserver:self 145 | selector:@selector(applicationWillEnterForeground) 146 | name:UIApplicationWillEnterForegroundNotification 147 | object:[UIApplication sharedApplication]]; 148 | [[NSNotificationCenter defaultCenter] addObserver:self 149 | selector:@selector(deviceOrientationDidChange) 150 | name:UIDeviceOrientationDidChangeNotification 151 | object:[UIDevice currentDevice]]; 152 | 153 | // Keep track of changes to the device orientation so we can update the capture Service 154 | [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications]; 155 | 156 | // the willEnterForeground and didEnterBackground notifications are subsequently used to update _allowedToUseGPU 157 | allowedToUseGPU = ( [UIApplication sharedApplication].applicationState != UIApplicationStateBackground ); 158 | self.captureService.renderingEnabled = allowedToUseGPU; 159 | self.captureService.shouldSaveToAlbum = NO; 160 | self.captureService.shouldRecordAudio = NO; 161 | self.captureService.preferedDevicePosition = AVCaptureDevicePositionBack; 162 | self.captureService.captureType = WBCaptureType_Image; 163 | } 164 | - (void)setupPreviewView 165 | { 166 | AVCaptureVideoPreviewLayer *previewLayer = self.captureService.previewLayer; 167 | [previewLayer setFrame:[self.preView bounds]]; 168 | 169 | CALayer *rootLayer = [self.preView layer]; 170 | [rootLayer setBackgroundColor:[[UIColor blackColor] CGColor]]; 171 | [rootLayer addSublayer:previewLayer]; 172 | } 173 | 174 | - (void)didReceiveMemoryWarning { 175 | [super didReceiveMemoryWarning]; 176 | // Dispose of any resources that can be recreated. 177 | } 178 | 179 | - (IBAction)ClickBeginCamera:(id)sender { 180 | //拍摄照片 181 | self.errMsgLabel.hidden = YES; 182 | 183 | if (self.captureService) { 184 | [self.captureService takeOneShotPicture:^(int result, UIImage *image) { 185 | if (result == 0 && image) { 186 | [self uploadImage:image]; 187 | } else { 188 | dispatch_async(dispatch_get_main_queue(), ^{ 189 | }); 190 | } 191 | }]; 192 | } 193 | } 194 | 195 | - (void)uploadImage:(UIImage *)image 196 | { 197 | if (image) { 198 | NSInteger requestTag = currentType == 1 ? FrontCardVideoTag: BackCardVideoTag; 199 | 200 | [self showLoading:@"身份证识别中"]; 201 | self.beginBtn.enabled = NO; 202 | // YTServerAPI *api = [YTServerAPI instance]; 203 | [[YTServerAPI instance] idcardOCR:image withCardType:requestTag callback:^(NSInteger error, NSDictionary *dic){ 204 | [self hideLoading]; 205 | self.beginBtn.enabled = YES; 206 | if(requestTag == FrontCardVideoTag) { 207 | if (error == 0) { 208 | [self frontSucc:dic]; 209 | }else{ 210 | NSString *message = @"OCR识别失败, 请重试"; 211 | [self frontFail:message]; 212 | } 213 | }else if(requestTag == BackCardVideoTag) { 214 | if (error == 0) { 215 | [self backSucc]; 216 | }else{ 217 | NSString *message = @"OCR识别失败, 请重试"; 218 | [self backFail:message]; 219 | } 220 | } 221 | 222 | }]; 223 | 224 | } 225 | } 226 | 227 | - (void)frontSucc:(NSDictionary *)dict 228 | { 229 | currentType = 2; 230 | [self.tipsLabel setText:@"请翻转到身份证另一面"]; 231 | 232 | [[NSUserDefaults standardUserDefaults] setValue:[dict stringValueForKey:@"name" defaultValue:@" " operation:NSStringOperationTypeNone] forKey:@"idCardName"]; 233 | [[NSUserDefaults standardUserDefaults] setValue:[dict stringValueForKey:@"id" defaultValue:@" " operation:NSStringOperationTypeNone] forKey:@"idCardNo"]; 234 | [[NSUserDefaults standardUserDefaults] synchronize]; 235 | 236 | [self.indicatorLeft setImage:[UIImage imageNamed:@"indicator_correct.png"]]; 237 | 238 | __weak CardVideoViewController *weakSelf = self; 239 | 240 | [UIView animateWithDuration:1.5f delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{ 241 | weakSelf.idcardFirst.transform = CGAffineTransformMakeScale(0.001, 1); 242 | } completion:^(BOOL finished) { 243 | weakSelf.idcardFirst.hidden = YES; 244 | weakSelf.idcardSecode.hidden = NO; 245 | [UIView animateWithDuration:1.5f delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^{ 246 | CGAffineTransform t3 = CGAffineTransformMakeTranslation(0, 0); 247 | CGAffineTransform t_Scale = CGAffineTransformMakeScale(284, 1); 248 | CGAffineTransform t1 = CGAffineTransformConcat(t_Scale, t3); 249 | weakSelf.idcardSecode.transform = t1; 250 | } completion:^(BOOL finished) { 251 | [weakSelf.tipsLabel setText:@"请拍摄身份证国徽面"]; 252 | }]; 253 | }]; 254 | } 255 | 256 | - (void)frontFail:(NSString *)message 257 | { 258 | [self.indicatorLeft setImage:[UIImage imageNamed:@"indicator_wrong.png"]]; 259 | [self.errMsgLabel setText:message]; 260 | self.errMsgLabel.hidden = NO; 261 | } 262 | - (void)backFail:(NSString *)message 263 | { 264 | [self.indicatorRight setImage:[UIImage imageNamed:@"indicator_wrong.png"]]; 265 | [self.errMsgLabel setText:message]; 266 | self.errMsgLabel.hidden = NO; 267 | } 268 | - (void)backSucc 269 | { 270 | currentType = 1; 271 | 272 | [self.indicatorRight setImage:[UIImage imageNamed:@"indicator_correct.png"]]; 273 | 274 | CATransition* transition = [CATransition animation]; 275 | transition.duration = 0.375; 276 | transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]; 277 | transition.type = kCATransitionPush; //kCATransitionMoveIn; //, kCATransitionPush, kCATransitionReveal, kCATransitionFade 278 | 279 | transition.subtype = kCATransitionFromRight; //kCATransitionFromLeft, kCATransitionFromRight, kCATransitionFromTop, kCATransitionFromBottom 280 | [self.navigationController.view.layer addAnimation:transition forKey:nil]; 281 | [[self navigationController] popViewControllerAnimated:NO]; 282 | 283 | [[NSNotificationCenter defaultCenter] postNotificationName:@"nativeViewCallBack" object:@"id_card_verify_success"]; 284 | 285 | // CardResultViewController *controller = [[CardResultViewController alloc]init]; 286 | // [self.navigationController pushViewController:controller animated:YES]; 287 | } 288 | - (void)sessionError:(NSString *)message 289 | { 290 | UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"获取session失败" message:message delegate:self cancelButtonTitle:nil otherButtonTitles:@"确定", nil]; 291 | alertView.tag = 9528; 292 | [alertView show]; 293 | } 294 | 295 | #pragma mark - Notifcation 296 | 297 | - (void)applicationDidEnterBackground 298 | { 299 | // Avoid using the GPU in the background 300 | allowedToUseGPU = NO; 301 | self.captureService.renderingEnabled = NO; 302 | 303 | } 304 | - (void)applicationWillEnterForeground 305 | { 306 | allowedToUseGPU = YES; 307 | self.captureService.renderingEnabled = YES; 308 | 309 | NSString *string = currentType == 1 ? @"身份证正面放入框内" : @"请翻转到身份证反面"; 310 | [self.tipsLabel setText:string]; 311 | // [self.beginBtn setTitle:@"开始" forState:UIControlStateNormal]; 312 | needsUpload = YES; 313 | } 314 | 315 | - (void)deviceOrientationDidChange 316 | { 317 | UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation; 318 | 319 | // Update recording orientation if device changes to portrait or landscape orientation (but not face up/down) 320 | if ( UIDeviceOrientationIsPortrait( deviceOrientation ) || UIDeviceOrientationIsLandscape( deviceOrientation ) ) { 321 | [self.captureService setRecordingOrientation:(AVCaptureVideoOrientation)deviceOrientation]; 322 | } 323 | } 324 | 325 | #pragma mark - WBCaptureServiceDelegate 326 | 327 | - (void)captureService:(WBCaptureService *)captureService didStopRunningWithError:(NSError *)error 328 | { 329 | } 330 | 331 | // Preview 332 | - (void)captureService:(WBCaptureService *)captureService previewPixelBufferReadyForDisplay:(CVPixelBufferRef)previewPixelBuffer 333 | { 334 | } 335 | 336 | - (void)captureServiceDidRunOutOfPreviewBuffers:(WBCaptureService *)captureService 337 | { 338 | } 339 | 340 | // Recording 341 | - (void)captureServiceRecordingDidStart:(WBCaptureService *)captureService 342 | { 343 | 344 | } 345 | 346 | - (void)captureServiceRecordingWillStop:(WBCaptureService *)captureService 347 | { 348 | // Disable record button until we are ready to start another recording 349 | } 350 | 351 | - (void)captureServiceRecordingDidStop:(WBCaptureService *)captureService 352 | { 353 | 354 | } 355 | - (void)captureService:(WBCaptureService *)captureService recordingDidFailWithError:(NSError *)error 356 | { 357 | NSLog(@"error == %@", [error description]); 358 | 359 | } 360 | - (void)getScale 361 | { 362 | CGSize size = [UIScreen mainScreen].bounds.size; 363 | float rate = [[UIScreen mainScreen] scale]; 364 | float width = size.width * rate; 365 | float height = size.height * rate; 366 | 367 | if (height/width > kVideoHeight/kVideoWidth) { 368 | isVertical = YES; 369 | scale = kVideoWidth/width; 370 | w =ceilf(w * scale * rate); 371 | x = floorf(x * scale * rate); 372 | y = y * rate; 373 | h = h * rate; 374 | }else{ 375 | isVertical = NO; 376 | scale = kVideoHeight/height; 377 | y = floorf(y * scale * rate); 378 | h = ceilf(h * scale * rate); 379 | x = x * rate; 380 | w = w * rate; 381 | } 382 | } 383 | @end 384 | -------------------------------------------------------------------------------- /YoutuYunDemo/UI/CardVideoViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 60 | 67 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /YoutuYunDemo/UI/DemoViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // YoutuYunDemo 4 | // 5 | // Created by Patrick Yang on 15/9/15. 6 | // Copyright (c) 2015年 Tencent. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface DemoViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /YoutuYunDemo/UI/DemoViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // YoutuYunDemo 4 | // 5 | // Created by Patrick Yang on 15/9/15. 6 | // Copyright (c) 2015年 Tencent. All rights reserved. 7 | // 8 | // 9 | // 10 | //请在Conf.m里设置自己申请的 APP_ID, SECRET_ID, SECRET_KEY,否则网络请求签名验证会出错。 11 | // 12 | //人脸核身相关接口,需要申请权限接入,具体参考http://open.youtu.qq.com/welcome/service#/solution-facecheck 13 | //人脸核身接口包括: 14 | //- (void)idcardOcrFaceIn:(id)image cardType:(NSInteger)cardType successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 15 | //- (void)idcardNameFaceIn:(NSString*)id_num cardName:(NSString*)id_name successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 16 | //- (void)faceCompareFaceIn:(id)imageA imageB:(id)imageB successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 17 | //- (void)idcardfacecompare:(NSString*)idCardNumber withName:(NSString*)idCardName image:(id)image successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 18 | //- (void)livegetfour:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 19 | //- (void)livedetectfour:(NSData*)video image:(id)image validateId:(NSString*) validateData isCompare:(BOOL)isCompare successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 20 | //- (void)idcardlivedetectfour:(NSData*)video withId:(NSString*)idCardNumber withName:(NSString*)idCardName validateId:(NSString*) validateData successBlock:(HttpRequestSuccessBlock)successBlock failureBlock:(HttpRequestFailBlock)failureBlock; 21 | // 22 | // 23 | 24 | #import "DemoViewController.h" 25 | #import "Conf.h" 26 | #import "Auth.h" 27 | #import "TXQcloudFrSDK.h" 28 | #import "CardVideoViewController.h" 29 | #import "CardResultViewController.h" 30 | 31 | 32 | @interface DemoViewController () 33 | @property (strong, nonatomic) IBOutlet UIButton *faceInEnterButton; 34 | 35 | @end 36 | 37 | @implementation DemoViewController 38 | - (instancetype) init{ 39 | NSString *nibName = @"DemoViewController"; 40 | self = [super initWithNibName:nibName bundle:nil]; 41 | return self; 42 | } 43 | 44 | - (void)viewDidLoad 45 | { 46 | [super viewDidLoad]; 47 | UIImage *buttongBgImg = [[UIImage imageNamed:@"bt_blue"] resizableImageWithCapInsets:UIEdgeInsetsMake(6, 6, 6, 6)]; 48 | [self.faceInEnterButton setBackgroundImage:buttongBgImg forState:UIControlStateNormal]; 49 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(processCallBack:) name:@"nativeViewCallBack" object:nil]; 50 | 51 | self.title = @"优图"; 52 | 53 | [self testFacein]; 54 | 55 | NSString *auth = [Auth appSign:1000000 userId:nil]; 56 | TXQcloudFrSDK *sdk = [[TXQcloudFrSDK alloc] initWithName:[Conf instance].appId authorization:auth endPoint:[Conf instance].API_END_POINT]; 57 | 58 | // UIImage *local = [UIImage imageNamed:@"id.jpg"]; 59 | UIImage *local = [UIImage imageNamed:@"id3.jpg"]; 60 | NSString *remote = @"http://a.hiphotos.baidu.com/image/pic/item/42166d224f4a20a4be2c49a992529822720ed0aa.jpg"; 61 | id image = local; 62 | 63 | // [sdk detectFace:image successBlock:^(id responseObject) { 64 | // NSLog(@"responseObject: %@", responseObject); 65 | // } failureBlock:^(NSError *error) { 66 | // NSLog(@"error"); 67 | // }]; 68 | 69 | // [sdk idcardOcr:image cardType:0 sessionId:nil successBlock:^(id responseObject) { 70 | // NSLog(@"idcardOcr: %@", responseObject); 71 | // } failureBlock:^(NSError *error) { 72 | // 73 | // }]; 74 | 75 | // [sdk namecardOcr:image sessionId:nil successBlock:^(id responseObject) { 76 | // NSLog(@"namecardOcr: %@", responseObject); 77 | // } failureBlock:^(NSError *error) { 78 | // 79 | // }]; 80 | // [sdk imageTag:image cookie:nil seq:nil successBlock:^(id responseObject) { 81 | // NSLog(@"responseObject: %@", responseObject); 82 | // } failureBlock:^(NSError *error) { 83 | // 84 | // }]; 85 | // 86 | // [sdk imagePorn:image cookie:nil seq:nil successBlock:^(id responseObject) { 87 | // NSLog(@"responseObject: %@", responseObject); 88 | // } failureBlock:^(NSError *error) { 89 | // 90 | // }]; 91 | // 92 | // [sdk foodDetect:image cookie:nil seq:nil successBlock:^(id responseObject) { 93 | // NSLog(@"responseObject: %@", responseObject); 94 | // } failureBlock:^(NSError *error) { 95 | // 96 | // }]; 97 | // [sdk fuzzyDetect:image cookie:nil seq:nil successBlock:^(id responseObject) { 98 | // NSLog(@"responseObject: %@", responseObject); 99 | // } failureBlock:^(NSError *error) { 100 | // 101 | // }]; 102 | } 103 | 104 | //人脸核身相关接口调用 105 | - (void)testFacein{ 106 | NSString *auth = [Auth appSign:1000000 userId:nil]; 107 | TXQcloudFrSDK *sdk = [[TXQcloudFrSDK alloc] initWithName:[Conf instance].appId authorization:auth endPoint:[Conf instance].API_VIP_END_POINT]; 108 | 109 | 110 | // UIImage *local = [UIImage imageNamed:@"id.jpg"]; 111 | UIImage *local = [UIImage imageNamed:@"id.jpg"]; 112 | NSString *remote = @"http://a.hiphotos.baidu.com/image/pic/item/42166d224f4a20a4be2c49a992529822720ed0aa.jpg"; 113 | id image = local; 114 | 115 | [sdk idcardOcrFaceIn:image cardType:0 successBlock:^(id responseObject) { 116 | NSLog(@"idcardOcrFaceIn: %@", responseObject); 117 | }failureBlock:^(NSError *error) { 118 | NSLog(@"error"); 119 | }]; 120 | 121 | NSString *idNumber = @"12345678901234567"; 122 | NSString *idName = @"李磊"; 123 | [sdk idcardNameFaceIn:idNumber cardName:idName successBlock:^(id responseObject) { 124 | NSLog(@"idcardNameFaceIn: %@", responseObject); 125 | } failureBlock:^(NSError *error) { 126 | NSLog(@"error"); 127 | }]; 128 | 129 | 130 | 131 | // 132 | // [sdk faceCompareFaceIn:image imageB:remote successBlock:^(id responseObject) { 133 | // NSLog(@"faceCompareFaceIn: %@", responseObject); 134 | // }failureBlock:^(NSError *error) { 135 | // NSLog(@"error"); 136 | // }]; 137 | // 138 | // [sdk idcardfacecompare: @"1123456789987654321" withName:@"王小明" image:image successBlock:^(id responseObject){ 139 | // NSLog(@"idcardfacecompare: %@", responseObject); 140 | // }failureBlock:^(NSError *error) { 141 | // NSLog(@"error"); 142 | // }]; 143 | 144 | 145 | // [sdk livegetfour:^(id responseObject){ 146 | // NSLog(@"livegetfour: %@", responseObject); 147 | // }failureBlock:^(NSError *error) { 148 | // NSLog(@"error"); 149 | // }]; 150 | 151 | // NSString *filePath = [[NSBundle mainBundle] pathForResource:@"video" ofType:@"mp4"]; 152 | // NSData *video = [NSData dataWithContentsOfFile:filePath]; 153 | // [sdk livedetectfour:video image:image validateId:@"3388" isCompare:YES successBlock: ^(id responseObject){ 154 | // NSLog(@"livedetectfour: %@", responseObject); 155 | // }failureBlock:^(NSError *error) { 156 | // NSLog(@"error"); 157 | // }]; 158 | 159 | // [sdk idcardlivedetectfour:video withId:@"1123456789987654321" withName:@"王小明" validateId:@"3388" successBlock: ^(id responseObject){ 160 | // NSLog(@"idcardlivedetectfour: %@", responseObject); 161 | // }failureBlock:^(NSError *error) { 162 | // NSLog(@"error"); 163 | // }]; 164 | } 165 | - (void)didReceiveMemoryWarning 166 | { 167 | [super didReceiveMemoryWarning]; 168 | } 169 | 170 | - (IBAction)clickFacein:(id)sender { 171 | CardVideoViewController *controller = [[CardVideoViewController alloc] init]; 172 | [self.navigationController pushViewController:controller animated:YES]; 173 | 174 | // CardResultViewController *controller = [[CardResultViewController alloc]init]; 175 | // [self.navigationController pushViewController:controller animated:YES]; 176 | } 177 | 178 | - (void)processCallBack:(NSNotification *)notify 179 | { 180 | NSString *message = (NSString *)notify.object; 181 | 182 | NSString *callbackString = nil; 183 | if ([message isEqualToString:@"id_card_verify_success"]) { 184 | // NSString *name = [[NSUserDefaults standardUserDefaults] objectForKey:@"idCardName"]; 185 | // NSString *number = [[NSUserDefaults standardUserDefaults] objectForKey:@"idCardNo"]; 186 | // 187 | // [[NSUserDefaults standardUserDefaults] setValue:nil forKey:@"idCardName"]; 188 | // [[NSUserDefaults standardUserDefaults] setValue:nil forKey:@"idCardNo"]; 189 | // [[NSUserDefaults standardUserDefaults] synchronize]; 190 | 191 | CardResultViewController *controller = [[CardResultViewController alloc]init]; 192 | [self.navigationController pushViewController:controller animated:YES]; 193 | 194 | } 195 | 196 | } 197 | @end 198 | -------------------------------------------------------------------------------- /YoutuYunDemo/UI/DemoViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 31 | 38 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /YoutuYunDemo/UI/VideoViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // VideoViewController.h 3 | // WeBank 4 | // 5 | // Created by doufeifei on 14/12/23. 6 | // 7 | // 8 | 9 | #import 10 | #import "WBBaseViewController.h" 11 | 12 | @interface VideoViewController : WBBaseViewController 13 | 14 | -(void)setReadLips:(NSString *)r; 15 | -(void)setValidateId:(UInt32)i; 16 | 17 | -(void)setCardId:(NSString *)c; 18 | -(void)setCardName:(NSString *)c; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /YoutuYunDemo/UI/VideoViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // VideoViewController.m 3 | // WeBank 4 | // 5 | // Created by doufeifei on 14/12/23. 6 | // 7 | // 8 | 9 | #import "VideoViewController.h" 10 | #import "WBCaptureService.h" 11 | #import "JSONKit.h" 12 | #import "WBObjectExtension.h" 13 | #import "YTServerAPI.h" 14 | 15 | 16 | #define VideoLength 4 17 | 18 | #define kalaOkLength 4 19 | #define kwordSize 24 20 | 21 | #define VideoUploadTag 3131 22 | #define VideoSecretTag 3133 23 | @interface VideoViewController () 24 | { 25 | NSInteger terminaTime; 26 | NSTimer *timer; 27 | 28 | BOOL addedObservers; 29 | BOOL allowedToUseGPU; 30 | BOOL isRecording; 31 | UIBackgroundTaskIdentifier backgroundRecordingID; 32 | 33 | NSString *meadiaId; 34 | NSString *weBankSession; 35 | NSString *readLips; 36 | NSString *encryptKey; 37 | 38 | NSString *cardId; 39 | NSString *cardName; 40 | 41 | UInt32 validateId; 42 | 43 | BOOL needsUpload; 44 | 45 | UIView *redBgView; 46 | } 47 | @property (weak, nonatomic) IBOutlet UILabel *wordLabel; 48 | @property (weak, nonatomic) IBOutlet UIButton *beginBtn; 49 | 50 | @property(nonatomic, strong) AVCaptureVideoPreviewLayer *previewView; 51 | @property(nonatomic, strong) WBCaptureService *captureService; 52 | 53 | @property (weak, nonatomic) IBOutlet UIView *preView; 54 | 55 | @property (weak, nonatomic) IBOutlet UILabel *redLabel; 56 | 57 | @property (nonatomic, strong) UIImageView *guideView; 58 | 59 | - (IBAction)beginClicked:(id)sender; 60 | @end 61 | 62 | @implementation VideoViewController 63 | 64 | - (instancetype) init{ 65 | NSString *nibName = @"VideoViewController"; 66 | self = [super initWithNibName:nibName bundle:nil]; 67 | return self; 68 | } 69 | 70 | -(void)setCardId:(NSString *)c 71 | { 72 | cardId = c; 73 | } 74 | -(void)setCardName:(NSString *)c 75 | { 76 | cardName = c; 77 | } 78 | 79 | - (void)viewDidLoad { 80 | [super viewDidLoad]; 81 | 82 | [self initVideoCapture]; 83 | isRecording = NO; 84 | 85 | NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:@"0",@"needActive", nil]; 86 | // [[WBNetMethods sharedInstance] getSecretKeyWithString:WBGetSecretKey value:dict delegate:self tag:VideoSecretTag]; 87 | // [self addGuideView]; 88 | } 89 | //- (void)addGuideView 90 | //{ 91 | // self.guideView = [[UIImageView alloc] initWithFrame:self.view.frame]; 92 | // [self.guideView setImage:[UIImage imageNamed:@"face_guide.png"]]; 93 | // [self.view addSubview:self.guideView]; 94 | // UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(guideViewTaped:)]; 95 | // self.guideView.userInteractionEnabled = YES; 96 | // [self.guideView addGestureRecognizer:tap]; 97 | // [self.view bringSubviewToFront:self.guideView]; 98 | //} 99 | - (void)guideViewTaped:(UITapGestureRecognizer *)guesture 100 | { 101 | self.guideView.hidden = YES; 102 | [self.guideView removeFromSuperview]; 103 | 104 | [self beginClicked:nil]; 105 | } 106 | - (void)cleanCurrentStats 107 | { 108 | allowedToUseGPU = NO; 109 | self.captureService.renderingEnabled = NO; 110 | 111 | // [self.captureService stopRecording]; // no-op if we aren't recording 112 | [self abortVideo]; 113 | [self stopKalaOk]; 114 | 115 | 116 | if (self.captureService) { 117 | [self.captureService stopRunning]; 118 | } 119 | } 120 | - (void)viewWillDisappear:(BOOL)animated 121 | { 122 | 123 | [super viewWillDisappear:animated]; 124 | } 125 | - (void)viewDidDisappear:(BOOL)animated 126 | { 127 | [self cleanCurrentStats]; 128 | // [[WBNetMethods sharedInstance] cleanRequest]; 129 | [super viewDidDisappear:animated]; 130 | } 131 | 132 | -(void)setReadLips:(NSString *)r 133 | { 134 | readLips = r; 135 | } 136 | 137 | -(void)setValidateId:(UInt32)i 138 | { 139 | validateId = i; 140 | } 141 | 142 | - (void)viewWillAppear:(BOOL)animated 143 | { 144 | [super viewWillAppear:animated]; 145 | 146 | UIBarButtonItem *barButton = [[UIBarButtonItem alloc] init]; 147 | barButton.title = @"返回"; 148 | self.navigationController.navigationBar.topItem.backBarButtonItem = barButton; 149 | 150 | [self.navigationController setNavigationBarHidden:NO animated:NO]; 151 | [self.navigationItem setTitle:@"人脸识别"]; 152 | [self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:@"nav_back64.png"] forBarMetrics:UIBarMetricsDefault]; 153 | self.navigationController.navigationBar.tintColor = [UIColor whiteColor]; 154 | [self.navigationController.navigationBar 155 | setTitleTextAttributes:@{NSForegroundColorAttributeName : [UIColor whiteColor]}]; 156 | 157 | [self adjustWordSize:readLips]; 158 | 159 | [self.captureService startRunning]; 160 | [self setupPreviewView]; 161 | 162 | } 163 | - (void)dealloc 164 | { 165 | [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidEnterBackgroundNotification object:nil]; 166 | [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillEnterForegroundNotification object:nil]; 167 | [[NSNotificationCenter defaultCenter] removeObserver:self name:UIDeviceOrientationDidChangeNotification object:nil]; 168 | } 169 | - (void)initVideoCapture 170 | { 171 | self.captureService = [[WBCaptureService alloc] init]; 172 | [self.captureService setDelegate:self callbackQueue:dispatch_get_main_queue()]; 173 | 174 | [[NSNotificationCenter defaultCenter] addObserver:self 175 | selector:@selector(applicationDidEnterBackground) 176 | name:UIApplicationDidEnterBackgroundNotification 177 | object:[UIApplication sharedApplication]]; 178 | [[NSNotificationCenter defaultCenter] addObserver:self 179 | selector:@selector(applicationWillEnterForeground) 180 | name:UIApplicationWillEnterForegroundNotification 181 | object:[UIApplication sharedApplication]]; 182 | [[NSNotificationCenter defaultCenter] addObserver:self 183 | selector:@selector(deviceOrientationDidChange) 184 | name:UIDeviceOrientationDidChangeNotification 185 | object:[UIDevice currentDevice]]; 186 | 187 | // Keep track of changes to the device orientation so we can update the capture Service 188 | [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications]; 189 | 190 | // the willEnterForeground and didEnterBackground notifications are subsequently used to update _allowedToUseGPU 191 | allowedToUseGPU = ( [UIApplication sharedApplication].applicationState != UIApplicationStateBackground ); 192 | self.captureService.renderingEnabled = allowedToUseGPU; 193 | self.captureService.shouldSaveToAlbum = NO; 194 | self.captureService.shouldRecordAudio = YES; 195 | // self.captureService.videoFrameRate = 1; 196 | } 197 | 198 | - (void)setupPreviewView 199 | { 200 | AVCaptureVideoPreviewLayer *previewLayer = self.captureService.previewLayer; 201 | [previewLayer setFrame:[self.preView bounds]]; 202 | 203 | CALayer *rootLayer = [self.preView layer]; 204 | [rootLayer setBackgroundColor:[[UIColor blackColor] CGColor]]; 205 | [rootLayer addSublayer:previewLayer]; 206 | } 207 | 208 | - (void)didReceiveMemoryWarning { 209 | [super didReceiveMemoryWarning]; 210 | // Dispose of any resources that can be recreated. 211 | } 212 | - (void)startTimer 213 | { 214 | if (nil == timer) { 215 | timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updageState) userInfo:nil repeats:YES]; 216 | } 217 | } 218 | - (void)stopTimer 219 | { 220 | if (nil != timer) { 221 | [timer invalidate]; 222 | timer = nil; 223 | } 224 | } 225 | - (void)updageState 226 | { 227 | if (terminaTime > 3) { 228 | NSString *string = [NSString stringWithFormat:@"%zd", terminaTime]; 229 | [self.beginBtn setTitle:string forState:UIControlStateNormal]; 230 | // [self.beginBtn setTitleColor:[UIColor colorWithHexString:@"959595"] forState:UIControlStateNormal]; 231 | }else if (terminaTime > 0){ 232 | NSString *string = [NSString stringWithFormat:@"%zd", terminaTime]; 233 | [self.beginBtn setTitle:string forState:UIControlStateNormal]; 234 | // [self.beginBtn setTitleColor:[UIColor colorWithHexString:@"ff0000"] forState:UIControlStateNormal]; 235 | }else{ 236 | [self stopRecording]; 237 | [self.beginBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; 238 | return; 239 | } 240 | // [WBComMediaMethods btnClickedVoice]; 241 | terminaTime --; 242 | 243 | } 244 | - (IBAction)beginClicked:(id)sender { 245 | // hadPreview = YES; 246 | if (!isRecording) { 247 | [self beginCaptureVideo]; 248 | }else{ 249 | [self stopRecording];; 250 | } 251 | } 252 | 253 | 254 | - (void)nextClicked{ 255 | // [[NSNotificationCenter defaultCenter] postNotificationName:@"nativeViewCallBack" object:@"face_verify_success"]; 256 | // 257 | // CATransition* transition = [CATransition animation]; 258 | // transition.duration = 0.375; 259 | // transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]; 260 | // transition.type = kCATransitionPush; //kCATransitionMoveIn; //, kCATransitionPush, kCATransitionReveal, kCATransitionFade 261 | // 262 | // transition.subtype = kCATransitionFromRight; //kCATransitionFromLeft, kCATransitionFromRight, kCATransitionFromTop, kCATransitionFromBottom 263 | // [self.navigationController.view.layer addAnimation:transition forKey:nil]; 264 | //[[self navigationController] popToRootViewControllerAnimated:YES]; 265 | 266 | [[self navigationController] popViewControllerAnimated:YES]; 267 | } 268 | - (void)abortVideo 269 | { 270 | needsUpload = NO; 271 | isRecording = NO; 272 | self.beginBtn.enabled = YES; 273 | 274 | [self stopTimer]; 275 | [self.captureService stopRecording]; 276 | } 277 | - (void)beginCaptureVideo 278 | { 279 | self.captureService.videoFrameRate = 30; 280 | terminaTime = VideoLength; 281 | [self startKalaOk]; 282 | [self startTimer]; 283 | [UIApplication sharedApplication].idleTimerDisabled = YES; 284 | 285 | if ( [[UIDevice currentDevice] isMultitaskingSupported] ) { 286 | backgroundRecordingID = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{}]; 287 | } 288 | 289 | [self.captureService startRecording]; 290 | 291 | isRecording = YES; 292 | self.beginBtn.enabled = NO; 293 | needsUpload = YES; 294 | } 295 | - (void)stopRecording 296 | { 297 | [self.captureService stopRecording]; 298 | [self stopTimer]; 299 | } 300 | - (void)uploadVideo 301 | { 302 | [self showLoading:@"视频上传中"]; 303 | NSLog(@"!!!!!!!!!!!!!!!!!!!!!!!!!!!url = %@", [self.captureService.recordingURL absoluteString]); 304 | NSData *data = [NSData dataWithContentsOfURL:self.captureService.recordingURL]; 305 | // data = @"aaa"; 306 | 307 | [[YTServerAPI instance] idcardLivedetectFour:data withCardId:cardId withCardName:cardName withValidateId:readLips callback:^(NSInteger error, NSInteger liveStatus, NSInteger compareStatus, NSInteger sim){ 308 | [self hideLoading]; 309 | UIAlertView *resultAlert=nil; 310 | if (error == 0) { 311 | NSString *message = @""; 312 | NSString *copmareResult = @""; 313 | NSString *liveDetectStatus = @""; 314 | if(compareStatus == 0)//face comparison succeeded 315 | { 316 | copmareResult = @"通过"; 317 | // [self finishRecordingVideo:YES]; 318 | }else{ 319 | copmareResult = @"不通过"; 320 | 321 | } 322 | message = [message stringByAppendingFormat:@"人脸识别:%@%@%ld%@", liveDetectStatus, @"(", (long)sim, @")"]; 323 | 324 | liveDetectStatus = [NSString stringWithFormat:@"通过"]; 325 | switch (liveStatus) { 326 | case -5001: 327 | liveDetectStatus = [NSString stringWithFormat:@"视频文件异常,请重新录制。"]; 328 | break; 329 | case -5002: 330 | liveDetectStatus = [NSString stringWithFormat:@"活体检测失败,请重新录制。"]; 331 | break; 332 | case -5007: 333 | liveDetectStatus = [NSString stringWithFormat:@"视频文件异常,请重新录制。"]; 334 | break; 335 | case -5008: 336 | liveDetectStatus = [NSString stringWithFormat:@"活体检测失败,请重新录制。"]; 337 | break; 338 | case -5009: 339 | liveDetectStatus = [NSString stringWithFormat:@"活体检测失败,请重新录制。"]; 340 | break; 341 | case -5010: 342 | liveDetectStatus = [NSString stringWithFormat:@"活体检测失败,请重新录制。"]; 343 | break; 344 | case -5011: 345 | liveDetectStatus = [NSString stringWithFormat:@"活体检测失败,请重新录制。"]; 346 | break; 347 | case -5012: 348 | liveDetectStatus = [NSString stringWithFormat:@"活体检测失败,请选择安静的环境朗读。"]; 349 | break; 350 | case -5013: 351 | liveDetectStatus = [NSString stringWithFormat:@"活体检测失败,请选择安静的环境朗读。"]; 352 | break; 353 | 354 | 355 | default: 356 | break; 357 | } 358 | 359 | message = [message stringByAppendingFormat:@"\n"]; 360 | message = [message stringByAppendingFormat:@"活体检测:%@", liveDetectStatus]; 361 | 362 | resultAlert = [[UIAlertView alloc] initWithTitle:@"对比结果" message:message delegate:self cancelButtonTitle:@"确定" otherButtonTitles:nil, nil]; 363 | resultAlert.tag = 9999; 364 | [resultAlert show]; 365 | 366 | } 367 | else{ 368 | 369 | resultAlert = [[UIAlertView alloc] initWithTitle:@"对比结果" message:@"活体检测失败,请重新录制。" delegate:self cancelButtonTitle:@"确定" otherButtonTitles:nil, nil]; 370 | resultAlert.tag = 9999; 371 | [resultAlert show]; 372 | 373 | } 374 | 375 | }]; 376 | } 377 | - (void)finishRecordingVideo:(BOOL)success 378 | { 379 | NSString *btnString = @"重试"; 380 | [self stopKalaOk]; 381 | if (success) { 382 | // [self adjustWordSize:@"识别成功"]; 383 | btnString = @"开始"; 384 | } 385 | [self.beginBtn setTitle:btnString forState:UIControlStateNormal]; 386 | self.beginBtn.hidden = NO; 387 | self.beginBtn.enabled = YES; 388 | isRecording = NO; 389 | [UIApplication sharedApplication].idleTimerDisabled = NO; 390 | 391 | [[UIApplication sharedApplication] endBackgroundTask:backgroundRecordingID]; 392 | backgroundRecordingID = UIBackgroundTaskInvalid; 393 | 394 | } 395 | - (void)prepareRetryVideo 396 | { 397 | 398 | } 399 | - (void)removeVideo:(NSString *)filePath 400 | { 401 | NSLog(@"!!!!!!!!!!!!!!!!!!!!!!!!filePath = %@", filePath); 402 | if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) { 403 | dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){ 404 | NSError *error; 405 | [[NSFileManager defaultManager] removeItemAtPath:filePath error:&error]; 406 | if (nil != error) { 407 | NSLog(@"%@", error); 408 | error = nil; 409 | } 410 | }); 411 | } 412 | } 413 | #pragma mark - Notifcation 414 | 415 | - (void)applicationDidEnterBackground 416 | { 417 | // Avoid using the GPU in the background 418 | allowedToUseGPU = NO; 419 | self.captureService.renderingEnabled = NO; 420 | 421 | // [self.captureService stopRecording]; // no-op if we aren't recording 422 | [self abortVideo]; 423 | [self stopKalaOk]; 424 | } 425 | 426 | - (void)applicationWillEnterForeground 427 | { 428 | allowedToUseGPU = YES; 429 | self.captureService.renderingEnabled = YES; 430 | [self.beginBtn setTitle:@"开始" forState:UIControlStateNormal]; 431 | } 432 | 433 | - (void)deviceOrientationDidChange 434 | { 435 | UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation; 436 | 437 | // Update recording orientation if device changes to portrait or landscape orientation (but not face up/down) 438 | if ( UIDeviceOrientationIsPortrait( deviceOrientation ) || UIDeviceOrientationIsLandscape( deviceOrientation ) ) { 439 | [self.captureService setRecordingOrientation:(AVCaptureVideoOrientation)deviceOrientation]; 440 | } 441 | } 442 | 443 | #pragma mark - WBCaptureServiceDelegate 444 | 445 | - (void)captureService:(WBCaptureService *)captureService didStopRunningWithError:(NSError *)error 446 | { 447 | } 448 | 449 | // Preview 450 | - (void)captureService:(WBCaptureService *)captureService previewPixelBufferReadyForDisplay:(CVPixelBufferRef)previewPixelBuffer 451 | { 452 | } 453 | 454 | - (void)captureServiceDidRunOutOfPreviewBuffers:(WBCaptureService *)captureService 455 | { 456 | } 457 | 458 | // Recording 459 | - (void)captureServiceRecordingDidStart:(WBCaptureService *)captureService 460 | { 461 | 462 | } 463 | 464 | - (void)captureServiceRecordingWillStop:(WBCaptureService *)captureService 465 | { 466 | // Disable record button until we are ready to start another recording 467 | } 468 | 469 | - (void)captureServiceRecordingDidStop:(WBCaptureService *)captureService 470 | { 471 | if (needsUpload) { 472 | self.beginBtn.hidden = YES; 473 | [self uploadVideo]; 474 | } 475 | } 476 | - (void)captureService:(WBCaptureService *)captureService recordingDidFailWithError:(NSError *)error 477 | { 478 | NSLog(@"error == %@", [error description]); 479 | } 480 | 481 | 482 | - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex 483 | { 484 | if (9999 == alertView.tag) { 485 | [self nextClicked]; 486 | return; 487 | } 488 | isRecording = NO; 489 | self.beginBtn.enabled = YES; 490 | [self.beginBtn setTitle:@"开始" forState:UIControlStateNormal]; 491 | self.beginBtn.hidden = NO; 492 | 493 | self.captureService.videoFrameRate = 30; 494 | [self.captureService startRunning]; 495 | [self setupPreviewView]; 496 | } 497 | 498 | - (void)startKalaOk 499 | { 500 | self.wordLabel.hidden = NO; 501 | [self.wordLabel setTextColor:[UIColor whiteColor]]; 502 | 503 | NSString *string = self.wordLabel.text; 504 | [self.redLabel setText:self.wordLabel.text]; 505 | string = self.redLabel.text; 506 | 507 | CGRect frame = self.wordLabel.frame; 508 | frame.size.width = 0.f; 509 | self.redLabel.frame = frame; 510 | self.redLabel.hidden = NO; 511 | self.redLabel.clipsToBounds = YES; 512 | self.redLabel.transform = CGAffineTransformIdentity; 513 | 514 | VideoViewController *weakSelf = self; 515 | [UIView animateWithDuration:kalaOkLength animations:^{ 516 | weakSelf.redLabel.frame = weakSelf.wordLabel.frame; 517 | } completion:^(BOOL finished) { 518 | // self.redLabel.frame = self.wordLabel.frame; 519 | }]; 520 | } 521 | - (void)stopKalaOk 522 | { 523 | self.redLabel.hidden = YES; 524 | [self.redLabel.layer removeAllAnimations]; 525 | } 526 | - (void)adjustWordSize:(NSString *)string 527 | { 528 | CGPoint center = self.wordLabel.center; 529 | [self.wordLabel setText:string]; 530 | [self.wordLabel sizeToFit]; 531 | self.wordLabel.center = center; 532 | } 533 | @end 534 | -------------------------------------------------------------------------------- /YoutuYunDemo/UI/VideoViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 39 | 46 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /YoutuYunDemo/UI/WBBaseViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // WBBaseViewController.h 3 | // WeBank 4 | // 5 | // Created by doufeifei on 14/12/11. 6 | // 7 | // 8 | 9 | #import 10 | 11 | @interface WBBaseViewController : UIViewController 12 | 13 | - (void)showLoading:(NSString *)text; 14 | - (void)showLoading:(NSString *)text toView:(UIView *)view; 15 | - (void)hideLoading; 16 | 17 | - (void)showAlert:(NSString *)title message:(NSString *)text; 18 | 19 | - (void)configNavigationBar; 20 | @end 21 | -------------------------------------------------------------------------------- /YoutuYunDemo/UI/WBBaseViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // WBBaseViewController.m 3 | // WeBank 4 | // 5 | // Created by doufeifei on 14/12/11. 6 | // 7 | // 8 | 9 | #import "WBBaseViewController.h" 10 | #import "MBProgressHUD.h" 11 | @interface WBBaseViewController () 12 | { 13 | MBProgressHUD *_hudLoading; 14 | } 15 | @end 16 | 17 | @implementation WBBaseViewController 18 | 19 | - (void)viewDidLoad { 20 | [super viewDidLoad]; 21 | // Do any additional setup after loading the view. 22 | self.view.backgroundColor = [UIColor whiteColor]; 23 | [self configNavigationBar]; 24 | } 25 | 26 | - (void)didReceiveMemoryWarning { 27 | [super didReceiveMemoryWarning]; 28 | // Dispose of any resources that can be recreated. 29 | } 30 | 31 | - (void)dealloc 32 | { 33 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 34 | } 35 | 36 | - (void)showLoading:(NSString *)text 37 | { 38 | [self showLoading:text toView:self.view]; 39 | } 40 | 41 | - (void)showLoading:(NSString *)text toView:(UIView *)view 42 | { 43 | _hudLoading = [MBProgressHUD showHUDAddedTo:view animated:YES]; 44 | _hudLoading.mode = MBProgressHUDModeIndeterminate; 45 | _hudLoading.labelText = text; 46 | _hudLoading.labelColor = [UIColor whiteColor]; 47 | } 48 | 49 | - (void)hideLoading 50 | { 51 | _hudLoading.progress = 1.00f; 52 | [_hudLoading hide:YES]; 53 | } 54 | - (void)showAlert:(NSString *)title message:(NSString *)text 55 | { 56 | UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title message:text delegate:nil cancelButtonTitle:@"确定"otherButtonTitles:nil, nil]; 57 | [alert show]; 58 | } 59 | 60 | - (void)configNavigationBar 61 | { 62 | [self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:@"nav_back64.png"] forBarMetrics:UIBarMetricsDefault]; 63 | self.navigationController.navigationBar.tintColor = [UIColor whiteColor]; 64 | [self.navigationController.navigationBar 65 | setTitleTextAttributes:@{NSForegroundColorAttributeName : [UIColor whiteColor]}]; 66 | [self.navigationController setNavigationBarHidden:NO animated:NO]; 67 | } 68 | 69 | @end 70 | -------------------------------------------------------------------------------- /YoutuYunDemo/common/CaptureService/WBCaptureService.h: -------------------------------------------------------------------------------- 1 | // 2 | // WBCaptureService.h 3 | // CaptrueServiceDemo 4 | // 5 | // Created by Sampanweng on 14/12/24. 6 | // Copyright (c) 2014年 webank. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import 12 | #import 13 | 14 | typedef void (^WBOneShotCallback)(int result, UIImage *image); //result 0 means successed, otherwise we got an error. 15 | 16 | typedef NS_ENUM(NSUInteger, WBCaptureType) { 17 | WBCaptureType_Video, 18 | WBCaptureType_Image, 19 | WBCaptureType_Count, 20 | }; 21 | 22 | @protocol WBCaptureServiceDelegate; 23 | 24 | @interface WBCaptureService : NSObject 25 | 26 | /** 27 | * @brief Set the callback delegate and callback queue. 28 | * 29 | * @param delegate delegate is weak referenced 30 | * @param delegateCallbackQueue callback queue 31 | * 32 | */ 33 | - (void)setDelegate:(id)delegate callbackQueue:(dispatch_queue_t)delegateCallbackQueue; 34 | 35 | 36 | /** 37 | * @brief Start capture session. Call this method first when you need a preview or recording. 38 | * These methods are synchronous. 39 | * 40 | */ 41 | - (void)startRunning; 42 | 43 | /** 44 | * @brief Stop capture session. These methods are synchronous. 45 | * 46 | */ 47 | - (void)stopRunning; 48 | 49 | /** 50 | * @brief Starting record. 51 | * Must be running before starting recording. 52 | * These methods are asynchronous, see the recording delegate callbacks. 53 | * 54 | */ 55 | - (void)startRecording; 56 | 57 | /** 58 | * @brief Stop recording. 59 | * These methods are asynchronous, see the recording delegate callbacks. 60 | * 61 | */ 62 | - (void)stopRecording; 63 | 64 | /** 65 | * @brief only valid after startRunning has been called 66 | * 67 | * @param orientation New video orientation for video. 68 | * @param mirroring Should mirror 69 | * 70 | * @return CGAffineTransform for view or layer. 71 | */ 72 | - (CGAffineTransform)transformFromVideoBufferOrientationToOrientation:(AVCaptureVideoOrientation)orientation withAutoMirroring:(BOOL)mirroring; 73 | 74 | /** 75 | * @brief Take picture from current preview session. 76 | * 77 | * @param callback Callback when take picture done. 78 | */ 79 | - (void)takeOneShotPicture:(WBOneShotCallback)callback; 80 | 81 | /** 82 | * @brief Cut origin image to desired frame. 83 | * 84 | * @param image The origin image. 85 | */ 86 | + (UIImage*)imageWithImage:(UIImage *)image cutToFrame:(CGRect)newFrame; 87 | 88 | 89 | /** 90 | * @brief Regiter a oneshot image callback. 91 | * If successed, result will be set 0 while jpeg from preview pixel buffer. 92 | */ 93 | //- (void)registerOneShotCallback:(WBOneShotCallback)oneShotCallback; 94 | 95 | /** 96 | * @brief When set to false the GPU will not be used after the setRenderingEnabled: call returns. 97 | */ 98 | @property (atomic, assign) BOOL renderingEnabled; 99 | 100 | /** 101 | * @brief Client can set the orientation for the recorded movie 102 | */ 103 | @property (nonatomic, readwrite) AVCaptureVideoOrientation recordingOrientation; 104 | 105 | // Stats 106 | /** 107 | * @brief Set and get FPS(frame rate per seconds). Default 30fps. 108 | */ 109 | @property (nonatomic, assign) float videoFrameRate; 110 | 111 | /** 112 | * @brief Get current video dimensions. Default is 640X480. 113 | */ 114 | @property (nonatomic, readonly) CMVideoDimensions videoDimensions; 115 | 116 | /** 117 | * @brief Get preview layer after capture session has started. 118 | */ 119 | @property (nonatomic, readonly) AVCaptureVideoPreviewLayer *previewLayer; 120 | 121 | /** 122 | * @brief Get the temporary video file path. 123 | */ 124 | @property (nonatomic, strong) NSURL *recordingURL; 125 | 126 | /** 127 | * @brief AssetURL of saved video in photo album. 128 | */ 129 | @property (nonatomic, readonly) NSURL *assetURL; 130 | 131 | /** 132 | * @brief Set the prefered camera device position. Default is AVCaptureDevicePositionFront. 133 | */ 134 | @property (nonatomic, assign) AVCaptureDevicePosition preferedDevicePosition; 135 | 136 | /** 137 | * @brief Should record audio. Default is NO. 138 | */ 139 | @property (nonatomic, assign) BOOL shouldRecordAudio; 140 | 141 | /** 142 | * @brief Should save video to local album. Default is NO. 143 | */ 144 | @property (nonatomic, assign) BOOL shouldSaveToAlbum; 145 | 146 | /** 147 | * @brief Capture type. Default is WBCaptureType_Video. 148 | */ 149 | @property (nonatomic, assign) WBCaptureType captureType; 150 | 151 | /** 152 | * @brief AVCaptureSessionPresent. 153 | */ 154 | @property (nonatomic, strong) NSString *sessionPresent; 155 | 156 | @end 157 | 158 | @protocol WBCaptureServiceDelegate 159 | @optional 160 | 161 | - (void)captureService:(WBCaptureService *)captureService didStopRunningWithError:(NSError *)error; 162 | 163 | // Preview 164 | - (void)captureService:(WBCaptureService *)captureService previewPixelBufferReadyForDisplay:(CVPixelBufferRef)previewPixelBuffer; 165 | - (void)captureServiceDidRunOutOfPreviewBuffers:(WBCaptureService *)captureService; 166 | 167 | // Recording 168 | - (void)captureServiceRecordingDidStart:(WBCaptureService *)captureService; 169 | - (void)captureService:(WBCaptureService *)captureService recordingDidFailWithError:(NSError *)error; // Can happen at any point after a startRecording call, for example: startRecording->didFail (without a didStart), willStop->didFail (without a didStop) 170 | - (void)captureServiceRecordingWillStop:(WBCaptureService *)captureService; 171 | - (void)captureServiceRecordingDidStop:(WBCaptureService *)captureService; 172 | 173 | @end 174 | -------------------------------------------------------------------------------- /YoutuYunDemo/common/CaptureService/WBVideoRecorder.h: -------------------------------------------------------------------------------- 1 | // 2 | // WBVideoRecorder.h 3 | // CaptrueServiceDemo 4 | // 5 | // Created by Sampanweng on 14/12/25. 6 | // Copyright (c) 2014年 webank. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import 12 | 13 | @protocol WBVideoRecorderDelegate; 14 | 15 | @interface WBVideoRecorder : NSObject 16 | 17 | - (instancetype)initWithURL:(NSURL *)URL; 18 | 19 | // Only one audio and video track each are allowed. 20 | - (void)addVideoTrackWithSourceFormatDescription:(CMFormatDescriptionRef)formatDescription transform:(CGAffineTransform)transform settings:(NSDictionary *)videoSettings; // see AVVideoSettings.h for settings keys/values 21 | - (void)addAudioTrackWithSourceFormatDescription:(CMFormatDescriptionRef)formatDescription settings:(NSDictionary *)audioSettings; // see AVAudioSettings.h for settings keys/values 22 | 23 | - (void)setDelegate:(id)delegate callbackQueue:(dispatch_queue_t)delegateCallbackQueue; // delegate is weak referenced 24 | 25 | - (void)prepareToRecord; // Asynchronous, might take several hundred milliseconds. When finished the delegate's recorderDidFinishPreparing: or recorder:didFailWithError: method will be called. 26 | 27 | - (void)appendVideoSampleBuffer:(CMSampleBufferRef)sampleBuffer; 28 | - (void)appendVideoPixelBuffer:(CVPixelBufferRef)pixelBuffer withPresentationTime:(CMTime)presentationTime; 29 | - (void)appendAudioSampleBuffer:(CMSampleBufferRef)sampleBuffer; 30 | 31 | - (void)finishRecording; // Asynchronous, might take several hundred milliseconds. When finished the delegate's recorderDidFinishRecording: or recorder:didFailWithError: method will be called. 32 | 33 | @end 34 | 35 | @protocol WBVideoRecorderDelegate 36 | 37 | @required 38 | - (void)recorderDidFinishPreparing:(WBVideoRecorder *)recorder; 39 | - (void)recorder:(WBVideoRecorder *)recorder didFailWithError:(NSError *)error; 40 | - (void)recorderDidFinishRecording:(WBVideoRecorder *)recorder; 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /YoutuYunDemo/common/GTMNSString+HTML.h: -------------------------------------------------------------------------------- 1 | // 2 | // GTMNSString+HTML.h 3 | // Dealing with NSStrings that contain HTML 4 | // 5 | // Copyright 2006-2008 Google Inc. 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 8 | // use this file except in compliance with the License. You may obtain a copy 9 | // of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 16 | // License for the specific language governing permissions and limitations under 17 | // the License. 18 | // 19 | 20 | #import 21 | 22 | /// Utilities for NSStrings containing HTML 23 | @interface NSString (GTMNSStringHTMLAdditions) 24 | 25 | /// Get a string where internal characters that need escaping for HTML are escaped 26 | // 27 | /// For example, '&' become '&'. This will only cover characters from table 28 | /// A.2.2 of http://www.w3.org/TR/xhtml1/dtds.html#a_dtd_Special_characters 29 | /// which is what you want for a unicode encoded webpage. If you have a ascii 30 | /// or non-encoded webpage, please use stringByEscapingAsciiHTML which will 31 | /// encode all characters. 32 | /// 33 | /// For obvious reasons this call is only safe once. 34 | // 35 | // Returns: 36 | // Autoreleased NSString 37 | // 38 | - (NSString *)gtm_stringByEscapingForHTML; 39 | 40 | /// Get a string where internal characters that need escaping for HTML are escaped 41 | // 42 | /// For example, '&' become '&' 43 | /// All non-mapped characters (unicode that don't have a &keyword; mapping) 44 | /// will be converted to the appropriate &#xxx; value. If your webpage is 45 | /// unicode encoded (UTF16 or UTF8) use stringByEscapingHTML instead as it is 46 | /// faster, and produces less bloated and more readable HTML (as long as you 47 | /// are using a unicode compliant HTML reader). 48 | /// 49 | /// For obvious reasons this call is only safe once. 50 | // 51 | // Returns: 52 | // Autoreleased NSString 53 | // 54 | - (NSString *)gtm_stringByEscapingForAsciiHTML; 55 | 56 | /// Get a string where internal characters that are escaped for HTML are unescaped 57 | // 58 | /// For example, '&' becomes '&' 59 | /// Handles and 2 cases as well 60 | /// 61 | // Returns: 62 | // Autoreleased NSString 63 | // 64 | - (NSString *)gtm_stringByUnescapingFromHTML; 65 | 66 | @end -------------------------------------------------------------------------------- /YoutuYunDemo/common/GTMNSString+HTML.m: -------------------------------------------------------------------------------- 1 | // 2 | // GTMNSString+HTML.m 3 | // Dealing with NSStrings that contain HTML 4 | // 5 | // Copyright 2006-2008 Google Inc. 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 8 | // use this file except in compliance with the License. You may obtain a copy 9 | // of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 16 | // License for the specific language governing permissions and limitations under 17 | // the License. 18 | // 19 | 20 | //#import "GTMDefines.h" 21 | #import "GTMNSString+HTML.h" 22 | 23 | typedef struct { 24 | __unsafe_unretained NSString *escapeSequence; 25 | unichar uchar; 26 | } HTMLEscapeMap; 27 | 28 | // Taken from http://www.w3.org/TR/xhtml1/dtds.html#a_dtd_Special_characters 29 | // Ordered by uchar lowest to highest for bsearching 30 | static HTMLEscapeMap gAsciiHTMLEscapeMap[] = { 31 | // A.2.2. Special characters 32 | { @""", 34 }, 33 | { @"&", 38 }, 34 | { @"'", 39 }, 35 | { @"<", 60 }, 36 | { @">", 62 }, 37 | 38 | // A.2.1. Latin-1 characters 39 | { @" ", 160 }, 40 | { @"¡", 161 }, 41 | { @"¢", 162 }, 42 | { @"£", 163 }, 43 | { @"¤", 164 }, 44 | { @"¥", 165 }, 45 | { @"¦", 166 }, 46 | { @"§", 167 }, 47 | { @"¨", 168 }, 48 | { @"©", 169 }, 49 | { @"ª", 170 }, 50 | { @"«", 171 }, 51 | { @"¬", 172 }, 52 | { @"­", 173 }, 53 | { @"®", 174 }, 54 | { @"¯", 175 }, 55 | { @"°", 176 }, 56 | { @"±", 177 }, 57 | { @"²", 178 }, 58 | { @"³", 179 }, 59 | { @"´", 180 }, 60 | { @"µ", 181 }, 61 | { @"¶", 182 }, 62 | { @"·", 183 }, 63 | { @"¸", 184 }, 64 | { @"¹", 185 }, 65 | { @"º", 186 }, 66 | { @"»", 187 }, 67 | { @"¼", 188 }, 68 | { @"½", 189 }, 69 | { @"¾", 190 }, 70 | { @"¿", 191 }, 71 | { @"À", 192 }, 72 | { @"Á", 193 }, 73 | { @"Â", 194 }, 74 | { @"Ã", 195 }, 75 | { @"Ä", 196 }, 76 | { @"Å", 197 }, 77 | { @"Æ", 198 }, 78 | { @"Ç", 199 }, 79 | { @"È", 200 }, 80 | { @"É", 201 }, 81 | { @"Ê", 202 }, 82 | { @"Ë", 203 }, 83 | { @"Ì", 204 }, 84 | { @"Í", 205 }, 85 | { @"Î", 206 }, 86 | { @"Ï", 207 }, 87 | { @"Ð", 208 }, 88 | { @"Ñ", 209 }, 89 | { @"Ò", 210 }, 90 | { @"Ó", 211 }, 91 | { @"Ô", 212 }, 92 | { @"Õ", 213 }, 93 | { @"Ö", 214 }, 94 | { @"×", 215 }, 95 | { @"Ø", 216 }, 96 | { @"Ù", 217 }, 97 | { @"Ú", 218 }, 98 | { @"Û", 219 }, 99 | { @"Ü", 220 }, 100 | { @"Ý", 221 }, 101 | { @"Þ", 222 }, 102 | { @"ß", 223 }, 103 | { @"à", 224 }, 104 | { @"á", 225 }, 105 | { @"â", 226 }, 106 | { @"ã", 227 }, 107 | { @"ä", 228 }, 108 | { @"å", 229 }, 109 | { @"æ", 230 }, 110 | { @"ç", 231 }, 111 | { @"è", 232 }, 112 | { @"é", 233 }, 113 | { @"ê", 234 }, 114 | { @"ë", 235 }, 115 | { @"ì", 236 }, 116 | { @"í", 237 }, 117 | { @"î", 238 }, 118 | { @"ï", 239 }, 119 | { @"ð", 240 }, 120 | { @"ñ", 241 }, 121 | { @"ò", 242 }, 122 | { @"ó", 243 }, 123 | { @"ô", 244 }, 124 | { @"õ", 245 }, 125 | { @"ö", 246 }, 126 | { @"÷", 247 }, 127 | { @"ø", 248 }, 128 | { @"ù", 249 }, 129 | { @"ú", 250 }, 130 | { @"û", 251 }, 131 | { @"ü", 252 }, 132 | { @"ý", 253 }, 133 | { @"þ", 254 }, 134 | { @"ÿ", 255 }, 135 | 136 | // A.2.2. Special characters cont'd 137 | { @"Œ", 338 }, 138 | { @"œ", 339 }, 139 | { @"Š", 352 }, 140 | { @"š", 353 }, 141 | { @"Ÿ", 376 }, 142 | 143 | // A.2.3. Symbols 144 | { @"ƒ", 402 }, 145 | 146 | // A.2.2. Special characters cont'd 147 | { @"ˆ", 710 }, 148 | { @"˜", 732 }, 149 | 150 | // A.2.3. Symbols cont'd 151 | { @"Α", 913 }, 152 | { @"Β", 914 }, 153 | { @"Γ", 915 }, 154 | { @"Δ", 916 }, 155 | { @"Ε", 917 }, 156 | { @"Ζ", 918 }, 157 | { @"Η", 919 }, 158 | { @"Θ", 920 }, 159 | { @"Ι", 921 }, 160 | { @"Κ", 922 }, 161 | { @"Λ", 923 }, 162 | { @"Μ", 924 }, 163 | { @"Ν", 925 }, 164 | { @"Ξ", 926 }, 165 | { @"Ο", 927 }, 166 | { @"Π", 928 }, 167 | { @"Ρ", 929 }, 168 | { @"Σ", 931 }, 169 | { @"Τ", 932 }, 170 | { @"Υ", 933 }, 171 | { @"Φ", 934 }, 172 | { @"Χ", 935 }, 173 | { @"Ψ", 936 }, 174 | { @"Ω", 937 }, 175 | { @"α", 945 }, 176 | { @"β", 946 }, 177 | { @"γ", 947 }, 178 | { @"δ", 948 }, 179 | { @"ε", 949 }, 180 | { @"ζ", 950 }, 181 | { @"η", 951 }, 182 | { @"θ", 952 }, 183 | { @"ι", 953 }, 184 | { @"κ", 954 }, 185 | { @"λ", 955 }, 186 | { @"μ", 956 }, 187 | { @"ν", 957 }, 188 | { @"ξ", 958 }, 189 | { @"ο", 959 }, 190 | { @"π", 960 }, 191 | { @"ρ", 961 }, 192 | { @"ς", 962 }, 193 | { @"σ", 963 }, 194 | { @"τ", 964 }, 195 | { @"υ", 965 }, 196 | { @"φ", 966 }, 197 | { @"χ", 967 }, 198 | { @"ψ", 968 }, 199 | { @"ω", 969 }, 200 | { @"ϑ", 977 }, 201 | { @"ϒ", 978 }, 202 | { @"ϖ", 982 }, 203 | 204 | // A.2.2. Special characters cont'd 205 | { @" ", 8194 }, 206 | { @" ", 8195 }, 207 | { @" ", 8201 }, 208 | { @"‌", 8204 }, 209 | { @"‍", 8205 }, 210 | { @"‎", 8206 }, 211 | { @"‏", 8207 }, 212 | { @"–", 8211 }, 213 | { @"—", 8212 }, 214 | { @"‘", 8216 }, 215 | { @"’", 8217 }, 216 | { @"‚", 8218 }, 217 | { @"“", 8220 }, 218 | { @"”", 8221 }, 219 | { @"„", 8222 }, 220 | { @"†", 8224 }, 221 | { @"‡", 8225 }, 222 | // A.2.3. Symbols cont'd 223 | { @"•", 8226 }, 224 | { @"…", 8230 }, 225 | 226 | // A.2.2. Special characters cont'd 227 | { @"‰", 8240 }, 228 | 229 | // A.2.3. Symbols cont'd 230 | { @"′", 8242 }, 231 | { @"″", 8243 }, 232 | 233 | // A.2.2. Special characters cont'd 234 | { @"‹", 8249 }, 235 | { @"›", 8250 }, 236 | 237 | // A.2.3. Symbols cont'd 238 | { @"‾", 8254 }, 239 | { @"⁄", 8260 }, 240 | 241 | // A.2.2. Special characters cont'd 242 | { @"€", 8364 }, 243 | 244 | // A.2.3. Symbols cont'd 245 | { @"ℑ", 8465 }, 246 | { @"℘", 8472 }, 247 | { @"ℜ", 8476 }, 248 | { @"™", 8482 }, 249 | { @"ℵ", 8501 }, 250 | { @"←", 8592 }, 251 | { @"↑", 8593 }, 252 | { @"→", 8594 }, 253 | { @"↓", 8595 }, 254 | { @"↔", 8596 }, 255 | { @"↵", 8629 }, 256 | { @"⇐", 8656 }, 257 | { @"⇑", 8657 }, 258 | { @"⇒", 8658 }, 259 | { @"⇓", 8659 }, 260 | { @"⇔", 8660 }, 261 | { @"∀", 8704 }, 262 | { @"∂", 8706 }, 263 | { @"∃", 8707 }, 264 | { @"∅", 8709 }, 265 | { @"∇", 8711 }, 266 | { @"∈", 8712 }, 267 | { @"∉", 8713 }, 268 | { @"∋", 8715 }, 269 | { @"∏", 8719 }, 270 | { @"∑", 8721 }, 271 | { @"−", 8722 }, 272 | { @"∗", 8727 }, 273 | { @"√", 8730 }, 274 | { @"∝", 8733 }, 275 | { @"∞", 8734 }, 276 | { @"∠", 8736 }, 277 | { @"∧", 8743 }, 278 | { @"∨", 8744 }, 279 | { @"∩", 8745 }, 280 | { @"∪", 8746 }, 281 | { @"∫", 8747 }, 282 | { @"∴", 8756 }, 283 | { @"∼", 8764 }, 284 | { @"≅", 8773 }, 285 | { @"≈", 8776 }, 286 | { @"≠", 8800 }, 287 | { @"≡", 8801 }, 288 | { @"≤", 8804 }, 289 | { @"≥", 8805 }, 290 | { @"⊂", 8834 }, 291 | { @"⊃", 8835 }, 292 | { @"⊄", 8836 }, 293 | { @"⊆", 8838 }, 294 | { @"⊇", 8839 }, 295 | { @"⊕", 8853 }, 296 | { @"⊗", 8855 }, 297 | { @"⊥", 8869 }, 298 | { @"⋅", 8901 }, 299 | { @"⌈", 8968 }, 300 | { @"⌉", 8969 }, 301 | { @"⌊", 8970 }, 302 | { @"⌋", 8971 }, 303 | { @"⟨", 9001 }, 304 | { @"⟩", 9002 }, 305 | { @"◊", 9674 }, 306 | { @"♠", 9824 }, 307 | { @"♣", 9827 }, 308 | { @"♥", 9829 }, 309 | { @"♦", 9830 } 310 | }; 311 | 312 | // Taken from http://www.w3.org/TR/xhtml1/dtds.html#a_dtd_Special_characters 313 | // This is table A.2.2 Special Characters 314 | static HTMLEscapeMap gUnicodeHTMLEscapeMap[] = { 315 | // C0 Controls and Basic Latin 316 | { @""", 34 }, 317 | { @"&", 38 }, 318 | { @"'", 39 }, 319 | { @"<", 60 }, 320 | { @">", 62 }, 321 | 322 | // Latin Extended-A 323 | { @"Œ", 338 }, 324 | { @"œ", 339 }, 325 | { @"Š", 352 }, 326 | { @"š", 353 }, 327 | { @"Ÿ", 376 }, 328 | 329 | // Spacing Modifier Letters 330 | { @"ˆ", 710 }, 331 | { @"˜", 732 }, 332 | 333 | // General Punctuation 334 | { @" ", 8194 }, 335 | { @" ", 8195 }, 336 | { @" ", 8201 }, 337 | { @"‌", 8204 }, 338 | { @"‍", 8205 }, 339 | { @"‎", 8206 }, 340 | { @"‏", 8207 }, 341 | { @"–", 8211 }, 342 | { @"—", 8212 }, 343 | { @"‘", 8216 }, 344 | { @"’", 8217 }, 345 | { @"‚", 8218 }, 346 | { @"“", 8220 }, 347 | { @"”", 8221 }, 348 | { @"„", 8222 }, 349 | { @"†", 8224 }, 350 | { @"‡", 8225 }, 351 | { @"‰", 8240 }, 352 | { @"‹", 8249 }, 353 | { @"›", 8250 }, 354 | { @"€", 8364 }, 355 | }; 356 | 357 | 358 | // Utility function for Bsearching table above 359 | static int EscapeMapCompare(const void *ucharVoid, const void *mapVoid) { 360 | const unichar *uchar = (const unichar*)ucharVoid; 361 | const HTMLEscapeMap *map = (const HTMLEscapeMap*)mapVoid; 362 | int val; 363 | if (*uchar > map->uchar) { 364 | val = 1; 365 | } else if (*uchar < map->uchar) { 366 | val = -1; 367 | } else { 368 | val = 0; 369 | } 370 | return val; 371 | } 372 | 373 | @implementation NSString (GTMNSStringHTMLAdditions) 374 | 375 | - (NSString *)gtm_stringByEscapingHTMLUsingTable:(HTMLEscapeMap*)table 376 | ofSize:(NSUInteger)size 377 | escapingUnicode:(BOOL)escapeUnicode { 378 | NSUInteger length = [self length]; 379 | if (!length) { 380 | return self; 381 | } 382 | 383 | NSMutableString *finalString = [NSMutableString string]; 384 | NSMutableData *data2 = [NSMutableData dataWithCapacity:sizeof(unichar) * length]; 385 | 386 | // this block is common between GTMNSString+HTML and GTMNSString+XML but 387 | // it's so short that it isn't really worth trying to share. 388 | const unichar *buffer = CFStringGetCharactersPtr((CFStringRef)self); 389 | if (!buffer) { 390 | // We want this buffer to be autoreleased. 391 | NSMutableData *data = [NSMutableData dataWithLength:length * sizeof(UniChar)]; 392 | if (!data) { 393 | // COV_NF_START - Memory fail case 394 | // _GTMDevLog(@"couldn't alloc buffer"); 395 | return nil; 396 | // COV_NF_END 397 | } 398 | [self getCharacters:[data mutableBytes]]; 399 | buffer = [data bytes]; 400 | } 401 | 402 | if (!buffer || !data2) { 403 | // COV_NF_START 404 | // _GTMDevLog(@"Unable to allocate buffer or data2"); 405 | return nil; 406 | // COV_NF_END 407 | } 408 | 409 | unichar *buffer2 = (unichar *)[data2 mutableBytes]; 410 | 411 | NSUInteger buffer2Length = 0; 412 | 413 | for (NSUInteger i = 0; i < length; ++i) { 414 | HTMLEscapeMap *val = bsearch(&buffer[i], table, 415 | size / sizeof(HTMLEscapeMap), 416 | sizeof(HTMLEscapeMap), EscapeMapCompare); 417 | if (val || (escapeUnicode && buffer[i] > 127)) { 418 | if (buffer2Length) { 419 | CFStringAppendCharacters((CFMutableStringRef)finalString, 420 | buffer2, 421 | buffer2Length); 422 | buffer2Length = 0; 423 | } 424 | if (val) { 425 | [finalString appendString:val->escapeSequence]; 426 | } 427 | else { 428 | // _GTMDevAssert(escapeUnicode && buffer[i] > 127, @"Illegal Character"); 429 | [finalString appendFormat:@"&#%d;", buffer[i]]; 430 | } 431 | } else { 432 | buffer2[buffer2Length] = buffer[i]; 433 | buffer2Length += 1; 434 | } 435 | } 436 | if (buffer2Length) { 437 | CFStringAppendCharacters((CFMutableStringRef)finalString, 438 | buffer2, 439 | buffer2Length); 440 | } 441 | return finalString; 442 | } 443 | 444 | - (NSString *)gtm_stringByEscapingForHTML { 445 | return [self gtm_stringByEscapingHTMLUsingTable:gUnicodeHTMLEscapeMap 446 | ofSize:sizeof(gUnicodeHTMLEscapeMap) 447 | escapingUnicode:NO]; 448 | } // gtm_stringByEscapingHTML 449 | 450 | - (NSString *)gtm_stringByEscapingForAsciiHTML { 451 | return [self gtm_stringByEscapingHTMLUsingTable:gAsciiHTMLEscapeMap 452 | ofSize:sizeof(gAsciiHTMLEscapeMap) 453 | escapingUnicode:YES]; 454 | } // gtm_stringByEscapingAsciiHTML 455 | 456 | - (NSString *)gtm_stringByUnescapingFromHTML { 457 | NSRange range = NSMakeRange(0, [self length]); 458 | NSRange subrange = [self rangeOfString:@"&" options:NSBackwardsSearch range:range]; 459 | 460 | // if no ampersands, we've got a quick way out 461 | if (subrange.length == 0) return self; 462 | NSMutableString *finalString = [NSMutableString stringWithString:self]; 463 | do { 464 | NSRange semiColonRange = NSMakeRange(subrange.location, NSMaxRange(range) - subrange.location); 465 | semiColonRange = [self rangeOfString:@";" options:0 range:semiColonRange]; 466 | range = NSMakeRange(0, subrange.location); 467 | // if we don't find a semicolon in the range, we don't have a sequence 468 | if (semiColonRange.location == NSNotFound) { 469 | continue; 470 | } 471 | NSRange escapeRange = NSMakeRange(subrange.location, semiColonRange.location - subrange.location + 1); 472 | NSString *escapeString = [self substringWithRange:escapeRange]; 473 | NSUInteger length = [escapeString length]; 474 | // a squence must be longer than 3 (<) and less than 11 (ϑ) 475 | if (length > 3 && length < 11) { 476 | if ([escapeString characterAtIndex:1] == '#') { 477 | unichar char2 = [escapeString characterAtIndex:2]; 478 | if (char2 == 'x' || char2 == 'X') { 479 | // Hex escape squences £ 480 | NSString *hexSequence = [escapeString substringWithRange:NSMakeRange(3, length - 4)]; 481 | NSScanner *scanner = [NSScanner scannerWithString:hexSequence]; 482 | unsigned value; 483 | if ([scanner scanHexInt:&value] && 484 | value < USHRT_MAX && 485 | value > 0 486 | && [scanner scanLocation] == length - 4) { 487 | unichar uchar = value; 488 | NSString *charString = [NSString stringWithCharacters:&uchar length:1]; 489 | [finalString replaceCharactersInRange:escapeRange withString:charString]; 490 | } 491 | 492 | } else { 493 | // Decimal Sequences { 494 | NSString *numberSequence = [escapeString substringWithRange:NSMakeRange(2, length - 3)]; 495 | NSScanner *scanner = [NSScanner scannerWithString:numberSequence]; 496 | int value; 497 | if ([scanner scanInt:&value] && 498 | value < USHRT_MAX && 499 | value > 0 500 | && [scanner scanLocation] == length - 3) { 501 | unichar uchar = value; 502 | NSString *charString = [NSString stringWithCharacters:&uchar length:1]; 503 | [finalString replaceCharactersInRange:escapeRange withString:charString]; 504 | } 505 | } 506 | } else { 507 | // "standard" sequences 508 | for (unsigned i = 0; i < sizeof(gAsciiHTMLEscapeMap) / sizeof(HTMLEscapeMap); ++i) { 509 | if ([escapeString isEqualToString:gAsciiHTMLEscapeMap[i].escapeSequence]) { 510 | [finalString replaceCharactersInRange:escapeRange withString:[NSString stringWithCharacters:&gAsciiHTMLEscapeMap[i].uchar length:1]]; 511 | break; 512 | } 513 | } 514 | } 515 | } 516 | } while ((subrange = [self rangeOfString:@"&" options:NSBackwardsSearch range:range]).length != 0); 517 | return finalString; 518 | } // gtm_stringByUnescapingHTML 519 | 520 | 521 | 522 | @end -------------------------------------------------------------------------------- /YoutuYunDemo/common/JSONKit/JSONKit.h: -------------------------------------------------------------------------------- 1 | // 2 | // JSONKit.h 3 | // http://github.com/johnezang/JSONKit 4 | // Dual licensed under either the terms of the BSD License, or alternatively 5 | // under the terms of the Apache License, Version 2.0, as specified below. 6 | // 7 | 8 | /* 9 | Copyright (c) 2011, John Engelhart 10 | 11 | All rights reserved. 12 | 13 | Redistribution and use in source and binary forms, with or without 14 | modification, are permitted provided that the following conditions are met: 15 | 16 | * Redistributions of source code must retain the above copyright 17 | notice, this list of conditions and the following disclaimer. 18 | 19 | * Redistributions in binary form must reproduce the above copyright 20 | notice, this list of conditions and the following disclaimer in the 21 | documentation and/or other materials provided with the distribution. 22 | 23 | * Neither the name of the Zang Industries nor the names of its 24 | contributors may be used to endorse or promote products derived from 25 | this software without specific prior written permission. 26 | 27 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 28 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 29 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 30 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 31 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 32 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 33 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 34 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 35 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 36 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 37 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 38 | */ 39 | 40 | /* 41 | Copyright 2011 John Engelhart 42 | 43 | Licensed under the Apache License, Version 2.0 (the "License"); 44 | you may not use this file except in compliance with the License. 45 | You may obtain a copy of the License at 46 | 47 | http://www.apache.org/licenses/LICENSE-2.0 48 | 49 | Unless required by applicable law or agreed to in writing, software 50 | distributed under the License is distributed on an "AS IS" BASIS, 51 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 52 | See the License for the specific language governing permissions and 53 | limitations under the License. 54 | */ 55 | 56 | #include 57 | #include 58 | #include 59 | #include 60 | #include 61 | 62 | #ifdef __OBJC__ 63 | #import 64 | #import 65 | #import 66 | #import 67 | #import 68 | #import 69 | #endif // __OBJC__ 70 | 71 | #ifdef __cplusplus 72 | extern "C" { 73 | #endif 74 | 75 | 76 | // For Mac OS X < 10.5. 77 | #ifndef NSINTEGER_DEFINED 78 | #define NSINTEGER_DEFINED 79 | #if defined(__LP64__) || defined(NS_BUILD_32_LIKE_64) 80 | typedef long NSInteger; 81 | typedef unsigned long NSUInteger; 82 | #define NSIntegerMin LONG_MIN 83 | #define NSIntegerMax LONG_MAX 84 | #define NSUIntegerMax ULONG_MAX 85 | #else // defined(__LP64__) || defined(NS_BUILD_32_LIKE_64) 86 | typedef int NSInteger; 87 | typedef unsigned int NSUInteger; 88 | #define NSIntegerMin INT_MIN 89 | #define NSIntegerMax INT_MAX 90 | #define NSUIntegerMax UINT_MAX 91 | #endif // defined(__LP64__) || defined(NS_BUILD_32_LIKE_64) 92 | #endif // NSINTEGER_DEFINED 93 | 94 | 95 | #ifndef _JSONKIT_H_ 96 | #define _JSONKIT_H_ 97 | 98 | #if defined(__GNUC__) && (__GNUC__ >= 4) && defined(__APPLE_CC__) && (__APPLE_CC__ >= 5465) 99 | #define JK_DEPRECATED_ATTRIBUTE __attribute__((deprecated)) 100 | #else 101 | #define JK_DEPRECATED_ATTRIBUTE 102 | #endif 103 | 104 | #define JSONKIT_VERSION_MAJOR 1 105 | #define JSONKIT_VERSION_MINOR 4 106 | 107 | typedef NSUInteger JKFlags; 108 | 109 | /* 110 | JKParseOptionComments : Allow C style // and /_* ... *_/ (without a _, obviously) comments in JSON. 111 | JKParseOptionUnicodeNewlines : Allow Unicode recommended (?:\r\n|[\n\v\f\r\x85\p{Zl}\p{Zp}]) newlines. 112 | JKParseOptionLooseUnicode : Normally the decoder will stop with an error at any malformed Unicode. 113 | This option allows JSON with malformed Unicode to be parsed without reporting an error. 114 | Any malformed Unicode is replaced with \uFFFD, or "REPLACEMENT CHARACTER". 115 | */ 116 | 117 | enum { 118 | JKParseOptionNone = 0, 119 | JKParseOptionStrict = 0, 120 | JKParseOptionComments = (1 << 0), 121 | JKParseOptionUnicodeNewlines = (1 << 1), 122 | JKParseOptionLooseUnicode = (1 << 2), 123 | JKParseOptionPermitTextAfterValidJSON = (1 << 3), 124 | JKParseOptionValidFlags = (JKParseOptionComments | JKParseOptionUnicodeNewlines | JKParseOptionLooseUnicode | JKParseOptionPermitTextAfterValidJSON), 125 | }; 126 | typedef JKFlags JKParseOptionFlags; 127 | 128 | enum { 129 | JKSerializeOptionNone = 0, 130 | JKSerializeOptionPretty = (1 << 0), 131 | JKSerializeOptionEscapeUnicode = (1 << 1), 132 | JKSerializeOptionEscapeForwardSlashes = (1 << 4), 133 | JKSerializeOptionValidFlags = (JKSerializeOptionPretty | JKSerializeOptionEscapeUnicode | JKSerializeOptionEscapeForwardSlashes), 134 | }; 135 | typedef JKFlags JKSerializeOptionFlags; 136 | 137 | #ifdef __OBJC__ 138 | 139 | typedef struct JKParseState JKParseState; // Opaque internal, private type. 140 | 141 | // As a general rule of thumb, if you use a method that doesn't accept a JKParseOptionFlags argument, it defaults to JKParseOptionStrict 142 | 143 | @interface JSONDecoder : NSObject { 144 | JKParseState *parseState; 145 | } 146 | + (id)decoder; 147 | + (id)decoderWithParseOptions:(JKParseOptionFlags)parseOptionFlags; 148 | - (id)initWithParseOptions:(JKParseOptionFlags)parseOptionFlags; 149 | - (void)clearCache; 150 | 151 | // The parse... methods were deprecated in v1.4 in favor of the v1.4 objectWith... methods. 152 | - (id)parseUTF8String:(const unsigned char *)string length:(size_t)length JK_DEPRECATED_ATTRIBUTE; // Deprecated in JSONKit v1.4. Use objectWithUTF8String:length: instead. 153 | - (id)parseUTF8String:(const unsigned char *)string length:(size_t)length error:(NSError **)error JK_DEPRECATED_ATTRIBUTE; // Deprecated in JSONKit v1.4. Use objectWithUTF8String:length:error: instead. 154 | // The NSData MUST be UTF8 encoded JSON. 155 | - (id)parseJSONData:(NSData *)jsonData JK_DEPRECATED_ATTRIBUTE; // Deprecated in JSONKit v1.4. Use objectWithData: instead. 156 | - (id)parseJSONData:(NSData *)jsonData error:(NSError **)error JK_DEPRECATED_ATTRIBUTE; // Deprecated in JSONKit v1.4. Use objectWithData:error: instead. 157 | 158 | // Methods that return immutable collection objects. 159 | - (id)objectWithUTF8String:(const unsigned char *)string length:(NSUInteger)length; 160 | - (id)objectWithUTF8String:(const unsigned char *)string length:(NSUInteger)length error:(NSError **)error; 161 | // The NSData MUST be UTF8 encoded JSON. 162 | - (id)objectWithData:(NSData *)jsonData; 163 | - (id)objectWithData:(NSData *)jsonData error:(NSError **)error; 164 | 165 | // Methods that return mutable collection objects. 166 | - (id)mutableObjectWithUTF8String:(const unsigned char *)string length:(NSUInteger)length; 167 | - (id)mutableObjectWithUTF8String:(const unsigned char *)string length:(NSUInteger)length error:(NSError **)error; 168 | // The NSData MUST be UTF8 encoded JSON. 169 | - (id)mutableObjectWithData:(NSData *)jsonData; 170 | - (id)mutableObjectWithData:(NSData *)jsonData error:(NSError **)error; 171 | 172 | @end 173 | 174 | //////////// 175 | #pragma mark Deserializing methods 176 | //////////// 177 | 178 | @interface NSString (JSONKitDeserializing) 179 | - (id)objectFromJSONString; 180 | - (id)objectFromJSONStringWithParseOptions:(JKParseOptionFlags)parseOptionFlags; 181 | - (id)objectFromJSONStringWithParseOptions:(JKParseOptionFlags)parseOptionFlags error:(NSError **)error; 182 | - (id)mutableObjectFromJSONString; 183 | - (id)mutableObjectFromJSONStringWithParseOptions:(JKParseOptionFlags)parseOptionFlags; 184 | - (id)mutableObjectFromJSONStringWithParseOptions:(JKParseOptionFlags)parseOptionFlags error:(NSError **)error; 185 | @end 186 | 187 | @interface NSData (JSONKitDeserializing) 188 | // The NSData MUST be UTF8 encoded JSON. 189 | - (id)objectFromJSONData; 190 | - (id)objectFromJSONDataWithParseOptions:(JKParseOptionFlags)parseOptionFlags; 191 | - (id)objectFromJSONDataWithParseOptions:(JKParseOptionFlags)parseOptionFlags error:(NSError **)error; 192 | - (id)mutableObjectFromJSONData; 193 | - (id)mutableObjectFromJSONDataWithParseOptions:(JKParseOptionFlags)parseOptionFlags; 194 | - (id)mutableObjectFromJSONDataWithParseOptions:(JKParseOptionFlags)parseOptionFlags error:(NSError **)error; 195 | @end 196 | 197 | //////////// 198 | #pragma mark Serializing methods 199 | //////////// 200 | 201 | @interface NSString (JSONKitSerializing) 202 | // Convenience methods for those that need to serialize the receiving NSString (i.e., instead of having to serialize a NSArray with a single NSString, you can "serialize to JSON" just the NSString). 203 | // Normally, a string that is serialized to JSON has quotation marks surrounding it, which you may or may not want when serializing a single string, and can be controlled with includeQuotes: 204 | // includeQuotes:YES `a "test"...` -> `"a \"test\"..."` 205 | // includeQuotes:NO `a "test"...` -> `a \"test\"...` 206 | - (NSData *)JSONData; // Invokes JSONDataWithOptions:JKSerializeOptionNone includeQuotes:YES 207 | - (NSData *)JSONDataWithOptions:(JKSerializeOptionFlags)serializeOptions includeQuotes:(BOOL)includeQuotes error:(NSError **)error; 208 | - (NSString *)JSONString; // Invokes JSONStringWithOptions:JKSerializeOptionNone includeQuotes:YES 209 | - (NSString *)JSONStringWithOptions:(JKSerializeOptionFlags)serializeOptions includeQuotes:(BOOL)includeQuotes error:(NSError **)error; 210 | @end 211 | 212 | @interface NSArray (JSONKitSerializing) 213 | - (NSData *)JSONData; 214 | - (NSData *)JSONDataWithOptions:(JKSerializeOptionFlags)serializeOptions error:(NSError **)error; 215 | - (NSData *)JSONDataWithOptions:(JKSerializeOptionFlags)serializeOptions serializeUnsupportedClassesUsingDelegate:(id)delegate selector:(SEL)selector error:(NSError **)error; 216 | - (NSString *)JSONString; 217 | - (NSString *)JSONStringWithOptions:(JKSerializeOptionFlags)serializeOptions error:(NSError **)error; 218 | - (NSString *)JSONStringWithOptions:(JKSerializeOptionFlags)serializeOptions serializeUnsupportedClassesUsingDelegate:(id)delegate selector:(SEL)selector error:(NSError **)error; 219 | @end 220 | 221 | @interface NSDictionary (JSONKitSerializing) 222 | - (NSData *)JSONData; 223 | - (NSData *)JSONDataWithOptions:(JKSerializeOptionFlags)serializeOptions error:(NSError **)error; 224 | - (NSData *)JSONDataWithOptions:(JKSerializeOptionFlags)serializeOptions serializeUnsupportedClassesUsingDelegate:(id)delegate selector:(SEL)selector error:(NSError **)error; 225 | - (NSString *)JSONString; 226 | - (NSString *)JSONStringWithOptions:(JKSerializeOptionFlags)serializeOptions error:(NSError **)error; 227 | - (NSString *)JSONStringWithOptions:(JKSerializeOptionFlags)serializeOptions serializeUnsupportedClassesUsingDelegate:(id)delegate selector:(SEL)selector error:(NSError **)error; 228 | @end 229 | 230 | #ifdef __BLOCKS__ 231 | 232 | @interface NSArray (JSONKitSerializingBlockAdditions) 233 | - (NSData *)JSONDataWithOptions:(JKSerializeOptionFlags)serializeOptions serializeUnsupportedClassesUsingBlock:(id(^)(id object))block error:(NSError **)error; 234 | - (NSString *)JSONStringWithOptions:(JKSerializeOptionFlags)serializeOptions serializeUnsupportedClassesUsingBlock:(id(^)(id object))block error:(NSError **)error; 235 | @end 236 | 237 | @interface NSDictionary (JSONKitSerializingBlockAdditions) 238 | - (NSData *)JSONDataWithOptions:(JKSerializeOptionFlags)serializeOptions serializeUnsupportedClassesUsingBlock:(id(^)(id object))block error:(NSError **)error; 239 | - (NSString *)JSONStringWithOptions:(JKSerializeOptionFlags)serializeOptions serializeUnsupportedClassesUsingBlock:(id(^)(id object))block error:(NSError **)error; 240 | @end 241 | 242 | #endif 243 | 244 | 245 | #endif // __OBJC__ 246 | 247 | #endif // _JSONKIT_H_ 248 | 249 | #ifdef __cplusplus 250 | } // extern "C" 251 | #endif 252 | -------------------------------------------------------------------------------- /YoutuYunDemo/common/MBProgressHUD/MBProgressHUD.h: -------------------------------------------------------------------------------- 1 | // 2 | // MBProgressHUD.h 3 | // Version 0.9 4 | // Created by Matej Bukovinski on 2.4.09. 5 | // 6 | 7 | // This code is distributed under the terms and conditions of the MIT license. 8 | 9 | // Copyright (c) 2013 Matej Bukovinski 10 | // 11 | // Permission is hereby granted, free of charge, to any person obtaining a copy 12 | // of this software and associated documentation files (the "Software"), to deal 13 | // in the Software without restriction, including without limitation the rights 14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | // copies of the Software, and to permit persons to whom the Software is 16 | // furnished to do so, subject to the following conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be included in 19 | // all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | // THE SOFTWARE. 28 | 29 | #import 30 | #import 31 | #import 32 | 33 | @protocol MBProgressHUDDelegate; 34 | 35 | 36 | typedef enum { 37 | /** Progress is shown using an UIActivityIndicatorView. This is the default. */ 38 | MBProgressHUDModeIndeterminate, 39 | /** Progress is shown using a round, pie-chart like, progress view. */ 40 | MBProgressHUDModeDeterminate, 41 | /** Progress is shown using a horizontal progress bar */ 42 | MBProgressHUDModeDeterminateHorizontalBar, 43 | /** Progress is shown using a ring-shaped progress view. */ 44 | MBProgressHUDModeAnnularDeterminate, 45 | /** Shows a custom view */ 46 | MBProgressHUDModeCustomView, 47 | /** Shows only labels */ 48 | MBProgressHUDModeText 49 | } MBProgressHUDMode; 50 | 51 | typedef enum { 52 | /** Opacity animation */ 53 | MBProgressHUDAnimationFade, 54 | /** Opacity + scale animation */ 55 | MBProgressHUDAnimationZoom, 56 | MBProgressHUDAnimationZoomOut = MBProgressHUDAnimationZoom, 57 | MBProgressHUDAnimationZoomIn 58 | } MBProgressHUDAnimation; 59 | 60 | 61 | #ifndef MB_INSTANCETYPE 62 | #if __has_feature(objc_instancetype) 63 | #define MB_INSTANCETYPE instancetype 64 | #else 65 | #define MB_INSTANCETYPE id 66 | #endif 67 | #endif 68 | 69 | #ifndef MB_STRONG 70 | #if __has_feature(objc_arc) 71 | #define MB_STRONG strong 72 | #else 73 | #define MB_STRONG retain 74 | #endif 75 | #endif 76 | 77 | #ifndef MB_WEAK 78 | #if __has_feature(objc_arc_weak) 79 | #define MB_WEAK weak 80 | #elif __has_feature(objc_arc) 81 | #define MB_WEAK unsafe_unretained 82 | #else 83 | #define MB_WEAK assign 84 | #endif 85 | #endif 86 | 87 | #if NS_BLOCKS_AVAILABLE 88 | typedef void (^MBProgressHUDCompletionBlock)(); 89 | #endif 90 | 91 | 92 | /** 93 | * Displays a simple HUD window containing a progress indicator and two optional labels for short messages. 94 | * 95 | * This is a simple drop-in class for displaying a progress HUD view similar to Apple's private UIProgressHUD class. 96 | * The MBProgressHUD window spans over the entire space given to it by the initWithFrame constructor and catches all 97 | * user input on this region, thereby preventing the user operations on components below the view. The HUD itself is 98 | * drawn centered as a rounded semi-transparent view which resizes depending on the user specified content. 99 | * 100 | * This view supports four modes of operation: 101 | * - MBProgressHUDModeIndeterminate - shows a UIActivityIndicatorView 102 | * - MBProgressHUDModeDeterminate - shows a custom round progress indicator 103 | * - MBProgressHUDModeAnnularDeterminate - shows a custom annular progress indicator 104 | * - MBProgressHUDModeCustomView - shows an arbitrary, user specified view (@see customView) 105 | * 106 | * All three modes can have optional labels assigned: 107 | * - If the labelText property is set and non-empty then a label containing the provided content is placed below the 108 | * indicator view. 109 | * - If also the detailsLabelText property is set then another label is placed below the first label. 110 | */ 111 | @interface MBProgressHUD : UIView 112 | 113 | /** 114 | * Creates a new HUD, adds it to provided view and shows it. The counterpart to this method is hideHUDForView:animated:. 115 | * 116 | * @param view The view that the HUD will be added to 117 | * @param animated If set to YES the HUD will appear using the current animationType. If set to NO the HUD will not use 118 | * animations while appearing. 119 | * @return A reference to the created HUD. 120 | * 121 | * @see hideHUDForView:animated: 122 | * @see animationType 123 | */ 124 | + (MB_INSTANCETYPE)showHUDAddedTo:(UIView *)view animated:(BOOL)animated; 125 | 126 | /** 127 | * Finds the top-most HUD subview and hides it. The counterpart to this method is showHUDAddedTo:animated:. 128 | * 129 | * @param view The view that is going to be searched for a HUD subview. 130 | * @param animated If set to YES the HUD will disappear using the current animationType. If set to NO the HUD will not use 131 | * animations while disappearing. 132 | * @return YES if a HUD was found and removed, NO otherwise. 133 | * 134 | * @see showHUDAddedTo:animated: 135 | * @see animationType 136 | */ 137 | + (BOOL)hideHUDForView:(UIView *)view animated:(BOOL)animated; 138 | 139 | /** 140 | * Finds all the HUD subviews and hides them. 141 | * 142 | * @param view The view that is going to be searched for HUD subviews. 143 | * @param animated If set to YES the HUDs will disappear using the current animationType. If set to NO the HUDs will not use 144 | * animations while disappearing. 145 | * @return the number of HUDs found and removed. 146 | * 147 | * @see hideHUDForView:animated: 148 | * @see animationType 149 | */ 150 | + (NSUInteger)hideAllHUDsForView:(UIView *)view animated:(BOOL)animated; 151 | 152 | /** 153 | * Finds the top-most HUD subview and returns it. 154 | * 155 | * @param view The view that is going to be searched. 156 | * @return A reference to the last HUD subview discovered. 157 | */ 158 | + (MB_INSTANCETYPE)HUDForView:(UIView *)view; 159 | 160 | /** 161 | * Finds all HUD subviews and returns them. 162 | * 163 | * @param view The view that is going to be searched. 164 | * @return All found HUD views (array of MBProgressHUD objects). 165 | */ 166 | + (NSArray *)allHUDsForView:(UIView *)view; 167 | 168 | /** 169 | * A convenience constructor that initializes the HUD with the window's bounds. Calls the designated constructor with 170 | * window.bounds as the parameter. 171 | * 172 | * @param window The window instance that will provide the bounds for the HUD. Should be the same instance as 173 | * the HUD's superview (i.e., the window that the HUD will be added to). 174 | */ 175 | - (id)initWithWindow:(UIWindow *)window; 176 | 177 | /** 178 | * A convenience constructor that initializes the HUD with the view's bounds. Calls the designated constructor with 179 | * view.bounds as the parameter 180 | * 181 | * @param view The view instance that will provide the bounds for the HUD. Should be the same instance as 182 | * the HUD's superview (i.e., the view that the HUD will be added to). 183 | */ 184 | - (id)initWithView:(UIView *)view; 185 | 186 | /** 187 | * Display the HUD. You need to make sure that the main thread completes its run loop soon after this method call so 188 | * the user interface can be updated. Call this method when your task is already set-up to be executed in a new thread 189 | * (e.g., when using something like NSOperation or calling an asynchronous call like NSURLRequest). 190 | * 191 | * @param animated If set to YES the HUD will appear using the current animationType. If set to NO the HUD will not use 192 | * animations while appearing. 193 | * 194 | * @see animationType 195 | */ 196 | - (void)show:(BOOL)animated; 197 | 198 | /** 199 | * Hide the HUD. This still calls the hudWasHidden: delegate. This is the counterpart of the show: method. Use it to 200 | * hide the HUD when your task completes. 201 | * 202 | * @param animated If set to YES the HUD will disappear using the current animationType. If set to NO the HUD will not use 203 | * animations while disappearing. 204 | * 205 | * @see animationType 206 | */ 207 | - (void)hide:(BOOL)animated; 208 | 209 | /** 210 | * Hide the HUD after a delay. This still calls the hudWasHidden: delegate. This is the counterpart of the show: method. Use it to 211 | * hide the HUD when your task completes. 212 | * 213 | * @param animated If set to YES the HUD will disappear using the current animationType. If set to NO the HUD will not use 214 | * animations while disappearing. 215 | * @param delay Delay in seconds until the HUD is hidden. 216 | * 217 | * @see animationType 218 | */ 219 | - (void)hide:(BOOL)animated afterDelay:(NSTimeInterval)delay; 220 | 221 | /** 222 | * Shows the HUD while a background task is executing in a new thread, then hides the HUD. 223 | * 224 | * This method also takes care of autorelease pools so your method does not have to be concerned with setting up a 225 | * pool. 226 | * 227 | * @param method The method to be executed while the HUD is shown. This method will be executed in a new thread. 228 | * @param target The object that the target method belongs to. 229 | * @param object An optional object to be passed to the method. 230 | * @param animated If set to YES the HUD will (dis)appear using the current animationType. If set to NO the HUD will not use 231 | * animations while (dis)appearing. 232 | */ 233 | - (void)showWhileExecuting:(SEL)method onTarget:(id)target withObject:(id)object animated:(BOOL)animated; 234 | 235 | #if NS_BLOCKS_AVAILABLE 236 | 237 | /** 238 | * Shows the HUD while a block is executing on a background queue, then hides the HUD. 239 | * 240 | * @see showAnimated:whileExecutingBlock:onQueue:completionBlock: 241 | */ 242 | - (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block; 243 | 244 | /** 245 | * Shows the HUD while a block is executing on a background queue, then hides the HUD. 246 | * 247 | * @see showAnimated:whileExecutingBlock:onQueue:completionBlock: 248 | */ 249 | - (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block completionBlock:(MBProgressHUDCompletionBlock)completion; 250 | 251 | /** 252 | * Shows the HUD while a block is executing on the specified dispatch queue, then hides the HUD. 253 | * 254 | * @see showAnimated:whileExecutingBlock:onQueue:completionBlock: 255 | */ 256 | - (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block onQueue:(dispatch_queue_t)queue; 257 | 258 | /** 259 | * Shows the HUD while a block is executing on the specified dispatch queue, executes completion block on the main queue, and then hides the HUD. 260 | * 261 | * @param animated If set to YES the HUD will (dis)appear using the current animationType. If set to NO the HUD will 262 | * not use animations while (dis)appearing. 263 | * @param block The block to be executed while the HUD is shown. 264 | * @param queue The dispatch queue on which the block should be executed. 265 | * @param completion The block to be executed on completion. 266 | * 267 | * @see completionBlock 268 | */ 269 | - (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block onQueue:(dispatch_queue_t)queue 270 | completionBlock:(MBProgressHUDCompletionBlock)completion; 271 | 272 | /** 273 | * A block that gets called after the HUD was completely hidden. 274 | */ 275 | @property (copy) MBProgressHUDCompletionBlock completionBlock; 276 | 277 | #endif 278 | 279 | /** 280 | * MBProgressHUD operation mode. The default is MBProgressHUDModeIndeterminate. 281 | * 282 | * @see MBProgressHUDMode 283 | */ 284 | @property (assign) MBProgressHUDMode mode; 285 | 286 | /** 287 | * The animation type that should be used when the HUD is shown and hidden. 288 | * 289 | * @see MBProgressHUDAnimation 290 | */ 291 | @property (assign) MBProgressHUDAnimation animationType; 292 | 293 | /** 294 | * The UIView (e.g., a UIImageView) to be shown when the HUD is in MBProgressHUDModeCustomView. 295 | * For best results use a 37 by 37 pixel view (so the bounds match the built in indicator bounds). 296 | */ 297 | @property (MB_STRONG) UIView *customView; 298 | 299 | /** 300 | * The HUD delegate object. 301 | * 302 | * @see MBProgressHUDDelegate 303 | */ 304 | @property (MB_WEAK) id delegate; 305 | 306 | /** 307 | * An optional short message to be displayed below the activity indicator. The HUD is automatically resized to fit 308 | * the entire text. If the text is too long it will get clipped by displaying "..." at the end. If left unchanged or 309 | * set to @"", then no message is displayed. 310 | */ 311 | @property (copy) NSString *labelText; 312 | 313 | /** 314 | * An optional details message displayed below the labelText message. This message is displayed only if the labelText 315 | * property is also set and is different from an empty string (@""). The details text can span multiple lines. 316 | */ 317 | @property (copy) NSString *detailsLabelText; 318 | 319 | /** 320 | * The opacity of the HUD window. Defaults to 0.8 (80% opacity). 321 | */ 322 | @property (assign) float opacity; 323 | 324 | /** 325 | * The color of the HUD window. Defaults to black. If this property is set, color is set using 326 | * this UIColor and the opacity property is not used. using retain because performing copy on 327 | * UIColor base colors (like [UIColor greenColor]) cause problems with the copyZone. 328 | */ 329 | @property (MB_STRONG) UIColor *color; 330 | 331 | /** 332 | * The x-axis offset of the HUD relative to the centre of the superview. 333 | */ 334 | @property (assign) float xOffset; 335 | 336 | /** 337 | * The y-axis offset of the HUD relative to the centre of the superview. 338 | */ 339 | @property (assign) float yOffset; 340 | 341 | /** 342 | * The amount of space between the HUD edge and the HUD elements (labels, indicators or custom views). 343 | * Defaults to 20.0 344 | */ 345 | @property (assign) float margin; 346 | 347 | /** 348 | * The corner radius for the HUD 349 | * Defaults to 10.0 350 | */ 351 | @property (assign) float cornerRadius; 352 | 353 | /** 354 | * Cover the HUD background view with a radial gradient. 355 | */ 356 | @property (assign) BOOL dimBackground; 357 | 358 | /* 359 | * Grace period is the time (in seconds) that the invoked method may be run without 360 | * showing the HUD. If the task finishes before the grace time runs out, the HUD will 361 | * not be shown at all. 362 | * This may be used to prevent HUD display for very short tasks. 363 | * Defaults to 0 (no grace time). 364 | * Grace time functionality is only supported when the task status is known! 365 | * @see taskInProgress 366 | */ 367 | @property (assign) float graceTime; 368 | 369 | /** 370 | * The minimum time (in seconds) that the HUD is shown. 371 | * This avoids the problem of the HUD being shown and than instantly hidden. 372 | * Defaults to 0 (no minimum show time). 373 | */ 374 | @property (assign) float minShowTime; 375 | 376 | /** 377 | * Indicates that the executed operation is in progress. Needed for correct graceTime operation. 378 | * If you don't set a graceTime (different than 0.0) this does nothing. 379 | * This property is automatically set when using showWhileExecuting:onTarget:withObject:animated:. 380 | * When threading is done outside of the HUD (i.e., when the show: and hide: methods are used directly), 381 | * you need to set this property when your task starts and completes in order to have normal graceTime 382 | * functionality. 383 | */ 384 | @property (assign) BOOL taskInProgress; 385 | 386 | /** 387 | * Removes the HUD from its parent view when hidden. 388 | * Defaults to NO. 389 | */ 390 | @property (assign) BOOL removeFromSuperViewOnHide; 391 | 392 | /** 393 | * Font to be used for the main label. Set this property if the default is not adequate. 394 | */ 395 | @property (MB_STRONG) UIFont* labelFont; 396 | 397 | /** 398 | * Color to be used for the main label. Set this property if the default is not adequate. 399 | */ 400 | @property (MB_STRONG) UIColor* labelColor; 401 | 402 | /** 403 | * Font to be used for the details label. Set this property if the default is not adequate. 404 | */ 405 | @property (MB_STRONG) UIFont* detailsLabelFont; 406 | 407 | /** 408 | * Color to be used for the details label. Set this property if the default is not adequate. 409 | */ 410 | @property (MB_STRONG) UIColor* detailsLabelColor; 411 | 412 | /** 413 | * The color of the activity indicator. Defaults to [UIColor whiteColor] 414 | * Does nothing on pre iOS 5. 415 | */ 416 | @property (MB_STRONG) UIColor *activityIndicatorColor; 417 | 418 | /** 419 | * The progress of the progress indicator, from 0.0 to 1.0. Defaults to 0.0. 420 | */ 421 | @property (assign) float progress; 422 | 423 | /** 424 | * The minimum size of the HUD bezel. Defaults to CGSizeZero (no minimum size). 425 | */ 426 | @property (assign) CGSize minSize; 427 | 428 | 429 | /** 430 | * The actual size of the HUD bezel. 431 | * You can use this to limit touch handling on the bezel aria only. 432 | * @see https://github.com/jdg/MBProgressHUD/pull/200 433 | */ 434 | @property (atomic, assign, readonly) CGSize size; 435 | 436 | 437 | /** 438 | * Force the HUD dimensions to be equal if possible. 439 | */ 440 | @property (assign, getter = isSquare) BOOL square; 441 | 442 | @end 443 | 444 | 445 | @protocol MBProgressHUDDelegate 446 | 447 | @optional 448 | 449 | /** 450 | * Called after the HUD was fully hidden from the screen. 451 | */ 452 | - (void)hudWasHidden:(MBProgressHUD *)hud; 453 | 454 | @end 455 | 456 | 457 | /** 458 | * A progress view for showing definite progress by filling up a circle (pie chart). 459 | */ 460 | @interface MBRoundProgressView : UIView 461 | 462 | /** 463 | * Progress (0.0 to 1.0) 464 | */ 465 | @property (nonatomic, assign) float progress; 466 | 467 | /** 468 | * Indicator progress color. 469 | * Defaults to white [UIColor whiteColor] 470 | */ 471 | @property (nonatomic, MB_STRONG) UIColor *progressTintColor; 472 | 473 | /** 474 | * Indicator background (non-progress) color. 475 | * Defaults to translucent white (alpha 0.1) 476 | */ 477 | @property (nonatomic, MB_STRONG) UIColor *backgroundTintColor; 478 | 479 | /* 480 | * Display mode - NO = round or YES = annular. Defaults to round. 481 | */ 482 | @property (nonatomic, assign, getter = isAnnular) BOOL annular; 483 | 484 | @end 485 | 486 | 487 | /** 488 | * A flat bar progress view. 489 | */ 490 | @interface MBBarProgressView : UIView 491 | 492 | /** 493 | * Progress (0.0 to 1.0) 494 | */ 495 | @property (nonatomic, assign) float progress; 496 | 497 | /** 498 | * Bar border line color. 499 | * Defaults to white [UIColor whiteColor]. 500 | */ 501 | @property (nonatomic, MB_STRONG) UIColor *lineColor; 502 | 503 | /** 504 | * Bar background color. 505 | * Defaults to clear [UIColor clearColor]; 506 | */ 507 | @property (nonatomic, MB_STRONG) UIColor *progressRemainingColor; 508 | 509 | /** 510 | * Bar progress color. 511 | * Defaults to white [UIColor whiteColor]. 512 | */ 513 | @property (nonatomic, MB_STRONG) UIColor *progressColor; 514 | 515 | @end 516 | -------------------------------------------------------------------------------- /YoutuYunDemo/common/Server/ServerAPI.h: -------------------------------------------------------------------------------- 1 | // 2 | // ServerAPI.h 3 | // MeetingCheck 4 | // 5 | // Created by Patrick Yang on 15/7/15. 6 | // Copyright (c) 2015年 Tencent. All rights reserved. 7 | // 8 | 9 | #import 10 | //#import "YTEntity.h" 11 | 12 | @interface HttpResult : NSObject 13 | 14 | @property int httpCode; 15 | @property int error; 16 | @property NSDictionary *json; 17 | 18 | @end 19 | 20 | @interface ServerAPI : NSObject 21 | 22 | @property (nonatomic, strong) NSString *HOST; 23 | 24 | - (NSOperationQueue *)networkQueue; 25 | - (void)setAPIKeyHeader:(NSMutableURLRequest *)request; 26 | - (void)setAPIReqBody:(NSMutableURLRequest *)request withData:(id)data; // NSArray & NSDictionary 27 | - (NSMutableURLRequest *)createHttpRequest:(NSString *)strurl andMethod:(NSString *)method; 28 | - (NSMutableURLRequest *)createPostHttpRequest:(NSString *)strurl; 29 | - (NSMutableURLRequest *)createGetHttpRequest:(NSString *)strurl; 30 | - (void)sendRequest:(NSMutableURLRequest *)request withData:(id)data callback:(void (^)(HttpResult *))callback; 31 | - (void)sendRequestForTimeout:(NSMutableURLRequest *)request withData:(id)data callback:(void (^)(HttpResult *))callback; 32 | 33 | - (id)parseDictonary:(NSDictionary *)dict withEntity:(Class)clazz; 34 | - (NSArray *)parseArray:(NSArray *)array withEntity:(Class)clazz; 35 | 36 | //////////////////////////////////////////////////////////////////////////////////////////////// 37 | //Base CURL operation 38 | - (void)createResource:(NSString *)url withEntity:(Class) clazz withData:(id)data andCallback:(void (^)(NSInteger error, id newResource)) callback; 39 | - (void)putResource:(NSString *) url withEntity:(Class) clazz withData:(NSObject *)dict andCallback:(void (^)(NSInteger error, id newResource))callback; 40 | - (void)deleteResourse:(NSString *) url andCallback:(void (^)(NSInteger error)) callback; 41 | - (void)getResourse:(NSString *) url withEntity:(Class) clazz andCallback:(void (^)(NSInteger error, id resouse)) callback; 42 | - (void)listResourse:(NSString *) url data:(NSDictionary *)data entity:(Class) clazz andCallback:(void (^)(NSInteger error, NSArray *resouses)) callback; 43 | 44 | @end 45 | -------------------------------------------------------------------------------- /YoutuYunDemo/common/Server/ServerAPI.m: -------------------------------------------------------------------------------- 1 | // 2 | // ServerAPI.m 3 | // MeetingCheck 4 | // 5 | // Created by Patrick Yang on 15/7/15. 6 | // Copyright (c) 2015年 Tencent. All rights reserved. 7 | // 8 | 9 | #import "ServerAPI.h" 10 | //#import "LogUtil.h" 11 | //#import "GTMNSString+HTML.h" 12 | 13 | @implementation HttpResult 14 | 15 | @end 16 | 17 | 18 | 19 | @interface ServerAPI () 20 | { 21 | NSMutableDictionary *errorCodeMap; 22 | NSOperationQueue *_networkQueue; 23 | } 24 | 25 | @end 26 | 27 | @implementation ServerAPI 28 | 29 | - (id)init 30 | { 31 | self = [super init]; 32 | if (self) { 33 | _networkQueue = [[NSOperationQueue alloc] init]; 34 | _networkQueue.maxConcurrentOperationCount = 1; 35 | } 36 | return self; 37 | } 38 | 39 | - (NSOperationQueue *)networkQueue 40 | { 41 | return _networkQueue; 42 | } 43 | 44 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 45 | 46 | - (HttpResult *)parseResponse:(NSURLResponse * )resp andData:(NSData *) data 47 | { 48 | HttpResult * result = [[HttpResult alloc] init]; 49 | NSHTTPURLResponse * httpResp = (NSHTTPURLResponse*) resp; 50 | int status = (int)httpResp.statusCode; 51 | result.httpCode = status; 52 | 53 | if(status == 200 || status == 201 || status == 204) { 54 | result.error = 0; 55 | } else { 56 | result.error = -1; 57 | } 58 | 59 | if(data != nil) { 60 | NSString* aStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 61 | // aStr = [[aStr gtm_stringByUnescapingFromHTML] gtm_stringByUnescapingFromHTML]; 62 | NSLog(@"httpcode=%d, resp:%@", status, aStr); 63 | 64 | NSData *nsData = [aStr dataUsingEncoding:NSUTF8StringEncoding]; 65 | NSError * err; 66 | NSDictionary *json = [NSJSONSerialization JSONObjectWithData:nsData options:kNilOptions error:&err]; 67 | 68 | result.json = json; 69 | 70 | if([json objectForKey:@"code"] != nil) { 71 | result.error = [[json objectForKey:@"code"] intValue]; 72 | } 73 | } 74 | 75 | return result; 76 | } 77 | 78 | - (HttpResult *)parseResponseForTimeout:(NSURLResponse * )resp andData:(NSData *) data andError:(NSError*) error 79 | { 80 | HttpResult * result = [[HttpResult alloc] init]; 81 | NSHTTPURLResponse * httpResp = (NSHTTPURLResponse*) resp; 82 | int status = (int)httpResp.statusCode; 83 | result.httpCode = status; 84 | 85 | if(status == 200 || status == 201 || status == 204) { 86 | result.error = 0; 87 | }else { 88 | if (error.code == -1001) { 89 | result.error = -10; 90 | }else{ 91 | result.error = -1; 92 | } 93 | } 94 | 95 | if(data != nil) { 96 | NSString* aStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 97 | // aStr = [[aStr gtm_stringByUnescapingFromHTML] gtm_stringByUnescapingFromHTML]; 98 | NSLog(@"httpcode=%d, resp:%@", status, aStr); 99 | 100 | NSData *nsData = [aStr dataUsingEncoding:NSUTF8StringEncoding]; 101 | NSError * err; 102 | NSDictionary *json = [NSJSONSerialization JSONObjectWithData:nsData options:kNilOptions error:&err]; 103 | 104 | result.json = json; 105 | 106 | if([json objectForKey:@"code"] != nil) { 107 | result.error = [[json objectForKey:@"code"] intValue]; 108 | } 109 | } 110 | 111 | return result; 112 | } 113 | 114 | - (void)setAPIKeyHeader:(NSMutableURLRequest *)request 115 | { 116 | } 117 | - (void)setAPIReqBody:(NSMutableURLRequest *)request withData:(id)data 118 | { 119 | if(data != nil) { 120 | if([data isKindOfClass:[NSDictionary class]]) { 121 | NSDictionary *dict = (NSDictionary *)data; 122 | [request addValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; 123 | NSString *postContent = [self dictionary2String:dict]; 124 | NSData *postData = [postContent dataUsingEncoding:NSUTF8StringEncoding]; 125 | NSLog(@"postContent:%@", postContent); 126 | [request setHTTPBody:postData]; 127 | } else if([data isKindOfClass:[NSString class]]) { 128 | NSString *array = (NSString *)data; 129 | NSData *postData = [array dataUsingEncoding:NSUTF8StringEncoding]; 130 | [request setHTTPBody:postData]; 131 | } else if ([data isKindOfClass:[NSData class]]) { 132 | [request setHTTPBody:data]; 133 | } 134 | } 135 | } 136 | - (NSMutableURLRequest *)createHttpRequest:(NSString *)strurl andMethod:(NSString *)method 137 | { 138 | NSURL * url = [NSURL URLWithString:[strurl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; 139 | NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; 140 | [request setTimeoutInterval:30]; 141 | [request setHTTPMethod:method]; 142 | [request addValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; 143 | 144 | return request; 145 | } 146 | 147 | - (NSMutableURLRequest *)createPostHttpRequest:(NSString *)strurl 148 | { 149 | NSString *url = [NSString stringWithFormat:@"%@%@", self.HOST, strurl]; 150 | NSLog(@"Create Http request for : %@", url); 151 | NSMutableURLRequest *request = [self createHttpRequest:url andMethod:@"POST"]; 152 | [self setAPIKeyHeader:request]; 153 | 154 | return request; 155 | } 156 | 157 | - (NSMutableURLRequest *)createGetHttpRequest:(NSString *)strurl 158 | { 159 | NSString * url = [NSString stringWithFormat:@"%@%@", self.HOST, strurl]; 160 | NSMutableURLRequest *request = [self createHttpRequest:url andMethod:@"GET"]; 161 | [self setAPIKeyHeader:request]; 162 | return request; 163 | } 164 | - (void)sendRequest:(NSMutableURLRequest *)request withData:(id)data callback:(void (^)(HttpResult *result))callback 165 | { 166 | [self setAPIReqBody:request withData:data]; 167 | [NSURLConnection sendAsynchronousRequest:request queue:[self networkQueue] completionHandler:^(NSURLResponse * resp, NSData * data, NSError * error) { 168 | if(callback == nil) return; 169 | dispatch_async(dispatch_get_main_queue(), ^{ 170 | HttpResult *result = [self parseResponse:resp andData:data]; 171 | callback(result); 172 | }); 173 | }]; 174 | } 175 | 176 | - (void)sendRequestForTimeout:(NSMutableURLRequest *)request withData:(id)data callback:(void (^)(HttpResult *result))callback 177 | { 178 | [self setAPIReqBody:request withData:data]; 179 | [NSURLConnection sendAsynchronousRequest:request queue:[self networkQueue] completionHandler:^(NSURLResponse * resp, NSData * data, NSError * error) { 180 | if(callback == nil) return; 181 | dispatch_async(dispatch_get_main_queue(), ^{ 182 | HttpResult *result = [self parseResponseForTimeout:resp andData:data andError:error]; 183 | callback(result); 184 | }); 185 | }]; 186 | } 187 | 188 | //- (id)parseDictonary:(NSDictionary *)dict withEntity:(Class)clazz 189 | //{ 190 | // id obj = dict; 191 | // if(dict && clazz != nil){ 192 | // YTEntity *entity = [clazz new]; 193 | // obj = [entity parse:dict]; 194 | // } 195 | // return obj; 196 | //} 197 | //- (NSArray *)parseArray:(NSArray *)array withEntity:(Class)clazz 198 | //{ 199 | // NSMutableArray *resources = [NSMutableArray array]; 200 | // if (array) { 201 | // YTEntity *entity = [clazz new]; 202 | // for(int i=0; i 11 | 12 | @interface YTServerAPI : ServerAPI 13 | 14 | + (YTServerAPI *)instance; 15 | - (void)idcardOCR:(UIImage *)image withCardType:(NSInteger)type callback:(void (^)(NSInteger error, NSDictionary* dic))callback; 16 | - (void)getLivefour:(void (^)(NSInteger error, NSString* number))callback; 17 | - (void)idcardLivedetectFour:(NSData *)video withCardId:(NSString*)cardId withCardName:(NSString*)name withValidateId:(NSString*)validate callback:(void (^)(NSInteger error, NSInteger liveStatus, NSInteger compareStatus, NSInteger sim))callback; 18 | 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /YoutuYunDemo/common/Server/YTServerAPI.m: -------------------------------------------------------------------------------- 1 | // 2 | // YTServerAPI.m 3 | // MeetingCheck 4 | // 5 | // Created by Patrick Yang on 15/7/14. 6 | // Copyright (c) 2015年 Tencent. All rights reserved. 7 | 8 | 9 | //人脸核身相关接口调用 10 | // 11 | 12 | #import "YTServerAPI.h" 13 | #import "NSData+Base64.h" 14 | #import "Auth.h" 15 | #import "GTMNSString+HTML.h" 16 | #import "Conf.h" 17 | 18 | //#define AppID @"10008768" 19 | //#define SecretID @"AKIDN8lBPUYSHuNdkCAjhVhnhQwISHyumQvd" 20 | //#define SecretKey @"jV6rTt782nU4hgaN3bkkXBbzGNI1a0oS" 21 | 22 | //#define HOST_KEY @"Host" 23 | //#define HOST_VALUE @"api.youtu.qq.com" 24 | //#define AUTORIZATION_KEY @"Authorization" 25 | 26 | NSString *AppID; 27 | 28 | @implementation YTServerAPI 29 | 30 | + (YTServerAPI *)instance 31 | { 32 | static YTServerAPI *api = nil; 33 | if (api == nil) { 34 | api = [[YTServerAPI alloc] init]; 35 | api.HOST = @"https://vip-api.youtu.qq.com"; 36 | AppID = [Conf instance].appId; 37 | } 38 | return api; 39 | } 40 | 41 | - (void)setAPIKeyHeader:(NSMutableURLRequest *)request 42 | { 43 | // YTSignature *signature = [[YTSignature alloc] init]; 44 | // signature.appId = (int)[AppID integerValue]; 45 | // signature.secretId = SecretID; 46 | // signature.secretKey = SecretKey; 47 | // signature.expired = 1000000.0; 48 | // signature.userId = nil; 49 | NSString *auth = [Auth appSign:1000000 userId:nil];; 50 | [request setValue:auth forHTTPHeaderField:@"Authorization"]; 51 | } 52 | 53 | //////////////////////////////////////////////////////////////////////////////////////// 54 | - (void)idcardOCR:(UIImage *)image withCardType:(NSInteger)type callback:(void (^)(NSInteger error, NSDictionary* dic))callback 55 | { 56 | NSData *data = UIImageJPEGRepresentation(image, 0.45); 57 | NSDictionary *dict = @{@"app_id":AppID, @"image":[data base64String], @"card_type":@(type)}; 58 | NSMutableURLRequest *request = [self createPostHttpRequest:@"/youtu/ocrapi/idcardocr"]; 59 | request.timeoutInterval = 10.0f; 60 | [self sendRequest:request withData:dict callback:^(HttpResult *result) { 61 | NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithCapacity:10]; 62 | if (result.error == 0) { 63 | NSString* name = [result.json valueForKey:@"name"]; 64 | NSString* idCardNo = [result.json valueForKey:@"id"]; 65 | 66 | [dic setValue:name forKey:@"name"]; 67 | [dic setValue:idCardNo forKey:@"id"]; 68 | 69 | } 70 | callback(result.error, dic); 71 | }]; 72 | } 73 | 74 | 75 | - (void)getLivefour:(void (^)(NSInteger error, NSString* number))callback { 76 | NSDictionary *dict = @{@"app_id":AppID}; 77 | NSMutableURLRequest *request = [self createPostHttpRequest:@"/youtu/openliveapi/livegetfour"]; 78 | request.timeoutInterval = 10.0f; 79 | [self sendRequest:request withData:dict callback:^(HttpResult *result) { 80 | NSString *number = @""; 81 | if (result.error == 0) { 82 | number = [result.json valueForKey:@"validate_data"]; 83 | 84 | } 85 | callback(result.error, number); 86 | }]; 87 | 88 | } 89 | 90 | - (void)idcardLivedetectFour:(NSData *)video withCardId:(NSString*)cardId withCardName:(NSString*)name withValidateId:(NSString*)validate callback:(void (^)(NSInteger error, NSInteger liveStatus, NSInteger compareStatus, NSInteger sim))callback{ 91 | 92 | NSDictionary *dict = @{@"app_id":AppID, @"video":[video base64String], @"idcard_number":cardId, @"idcard_name":name, @"validate_data":validate}; 93 | NSMutableURLRequest *request = [self createPostHttpRequest:@"/youtu/openliveapi/idcardlivedetectfour"]; 94 | request.timeoutInterval = 20.0f; 95 | [self sendRequest:request withData:dict callback:^(HttpResult *result) { 96 | NSInteger liveStatus; 97 | NSInteger compareStatus; 98 | NSInteger sim; 99 | if (result.error == 0) { 100 | liveStatus = [[result.json valueForKey:@"live_status"] intValue]; 101 | compareStatus = [[result.json valueForKey:@"compare_status"] intValue]; 102 | sim = [[result.json valueForKey:@"sim"] intValue]; 103 | } 104 | callback(result.error, liveStatus, compareStatus, sim); 105 | }]; 106 | 107 | } 108 | 109 | //////////////////////////////////////////////////////////////////////////////////////// 110 | - (HttpResult *)parseResponse:(NSURLResponse * )resp andData:(NSData *) data 111 | { 112 | HttpResult * result = [[HttpResult alloc] init]; 113 | NSHTTPURLResponse * httpResp = (NSHTTPURLResponse*) resp; 114 | int status = (int)httpResp.statusCode; 115 | result.httpCode = status; 116 | 117 | if(status == 200 || status == 201 || status == 204) { 118 | result.error = 0; 119 | } else { 120 | result.error = -1; 121 | } 122 | 123 | if(data != nil) { 124 | NSString* aStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 125 | aStr = [[aStr gtm_stringByUnescapingFromHTML] gtm_stringByUnescapingFromHTML]; 126 | NSLog(@"httpcode=%d, resp:%@", status, aStr); 127 | 128 | NSData *nsData = [aStr dataUsingEncoding:NSUTF8StringEncoding]; 129 | 130 | NSError *err = nil; 131 | NSDictionary *json = [NSJSONSerialization JSONObjectWithData:nsData options:kNilOptions error:&err]; 132 | 133 | result.json = json; 134 | 135 | if([json objectForKey:@"errorcode"] != nil) { 136 | result.error = [[json objectForKey:@"errorcode"] intValue]; 137 | } 138 | } 139 | 140 | return result; 141 | } 142 | 143 | @end 144 | -------------------------------------------------------------------------------- /YoutuYunDemo/common/WBObjectExtension.h: -------------------------------------------------------------------------------- 1 | // 2 | // MSDKObjectExtension.h 3 | // WGFrameworkDemo 4 | // 5 | // Created by fred on 13-8-26. 6 | // Copyright (c) 2013年 tencent.com. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef enum { 12 | NSStringOperationTypeTrim, // 去空 13 | NSStringOperationTypeDecodeUnicode, // 解汉字 14 | NSStringOperationTypeNone, // 无需额外操作 15 | } NSStringOperationType; 16 | 17 | // Extension of NSString 18 | @interface NSString (KFExtension) 19 | 20 | // 去除尾部space, /n, /t 21 | - (NSString*)trim; 22 | 23 | // 解出汉字 24 | - (NSString*)decodeUnicode; 25 | 26 | // 压缩生成 NSData 27 | - (NSData*)compressGZip; 28 | 29 | @end 30 | 31 | @interface NSData (KFExtension) 32 | 33 | // 解压缩 34 | - (NSString*)decompressGZip; 35 | 36 | @end 37 | 38 | // Extension of NSDictionary 39 | @interface NSDictionary (KFExtension) 40 | 41 | // 从 NSDictionary 中获取 key 对应的 字典型value; 若无,则返回 defaultValue 42 | - (NSDictionary*)dictionaryValueForKey:(NSString*)key defaultValue:(NSDictionary*)defaultValue; 43 | 44 | // 从 NSDictionary 中获取 key 对应的 数组型value; 若无,则返回 defaultValue 45 | - (NSArray*)arrayValueForKey:(NSString*)key defaultValue:(NSArray*)defaultValue; 46 | 47 | // 从 NSDictionary 中获取 key 对应的 NSString型value, 并进行特殊处理; 若无,则返回 defaultValue 48 | - (NSString*)stringValueForKey:(NSString*)key defaultValue:(NSString*)defaultValue operation:(NSStringOperationType)type; 49 | 50 | // 从 NSDictionary 中获取 key 对应的 int 型value; 若无,则返回 defaultValue 51 | - (int)intValueForKey:(NSString*)key defaultValue:(int)defaultValue; 52 | 53 | // 从 NSDictionary 中获取 key 对应的 uint64_t 型value; 若无,则返回 defaultValue 54 | - (uint64_t)longLongValueForKey:(NSString*)key defaultValue:(uint64_t)defaultValue; 55 | 56 | // 从 NSDictionary 中获取 key 对应的 double 型value; 若无,则返回 defaultValue 57 | - (double)doubleValueForKey:(NSString*)key defaultValue:(double)defaultValue; 58 | 59 | // 从 NSDictionary 中获取 key 对应的 float 型value; 若无,则返回 defaultValue 60 | - (float)floatValueForKey:(NSString*)key defaultValue:(float)defaultValue; 61 | 62 | // 从 NSDictionary 中获取 key 对应的 bool 型value; 若无,则返回 defaultValue 63 | - (BOOL)boolValueForKey:(NSString*)key defaultValue:(BOOL)defaultValue; 64 | 65 | @end 66 | -------------------------------------------------------------------------------- /YoutuYunDemo/common/WBObjectExtension.m: -------------------------------------------------------------------------------- 1 | // 2 | // WBObjectExtension.m 3 | // WeBank 4 | // 5 | // Created by doufeifei on 14/11/4. 6 | // 7 | // 8 | 9 | #import "WBObjectExtension.h" 10 | 11 | #import "zlib.h" 12 | 13 | #define kMemoryChunkSize 1024 14 | 15 | @implementation NSString (KFExtension) 16 | 17 | - (NSString*)trim { 18 | return [self stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; 19 | } 20 | 21 | - (NSString*)decodeUnicode { 22 | NSString* result = [[NSPropertyListSerialization propertyListFromData:[[[@"\"" stringByAppendingString:[[self stringByReplacingOccurrencesOfString:@"\\u" withString:@"\\U"] stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""]] stringByAppendingString:@"\""] dataUsingEncoding:NSUTF8StringEncoding] mutabilityOption:NSPropertyListImmutable format:NULL errorDescription:NULL] stringByReplacingOccurrencesOfString:@"\\r\\n" withString:@"\n"]; // need autorelease ? 23 | return result; 24 | } 25 | 26 | - (NSData*)compressGZip { 27 | const char *str = [self UTF8String]; 28 | NSData *data = [NSData dataWithBytes:str length:strlen(str)]; 29 | 30 | NSUInteger length = [data length]; 31 | int windowBits = 15 + 16, //Default + gzip header instead of zlib header 32 | memLevel = 8, //Default 33 | retCode; 34 | NSMutableData* result; 35 | z_stream stream; 36 | unsigned char output[kMemoryChunkSize]; 37 | uInt gotBack; 38 | 39 | if ((length == 0) || (length > UINT_MAX)) {//FIXME: Support 64 bit inputs 40 | return nil; 41 | } 42 | 43 | bzero(&stream, sizeof(z_stream)); 44 | stream.avail_in = (uInt)length; 45 | stream.next_in = (unsigned char*)[data bytes]; 46 | 47 | retCode = deflateInit2(&stream, Z_BEST_COMPRESSION, Z_DEFLATED, windowBits, memLevel, Z_DEFAULT_STRATEGY); 48 | if(retCode != Z_OK) { 49 | // KFLog(@"KF Error: %s: deflateInit2() failed with error %i", __FUNCTION__, retCode); 50 | return nil; 51 | } 52 | 53 | result = [NSMutableData dataWithCapacity:(length / 4)]; 54 | do { 55 | stream.avail_out = kMemoryChunkSize; 56 | stream.next_out = output; 57 | retCode = deflate(&stream, Z_FINISH); 58 | if((retCode != Z_OK) && (retCode != Z_STREAM_END)) { 59 | // KFLog(@"KF Error: %s: deflate() failed with error %i", __FUNCTION__, retCode); 60 | deflateEnd(&stream); 61 | return nil; 62 | } 63 | gotBack = kMemoryChunkSize - stream.avail_out; 64 | if(gotBack > 0) 65 | [result appendBytes:output length:gotBack]; 66 | } 67 | while (retCode == Z_OK); 68 | deflateEnd(&stream); 69 | 70 | return (retCode == Z_STREAM_END ? result : nil); 71 | } 72 | 73 | @end 74 | 75 | @implementation NSData (KFExtension) 76 | 77 | - (NSString*)decompressGZip { 78 | if ([self length] == 0) { 79 | return nil; 80 | } 81 | 82 | unsigned full_length = [self length]; 83 | unsigned half_length = [self length]/2; 84 | 85 | NSMutableData *decompressed = [NSMutableData dataWithLength:full_length+half_length]; 86 | BOOL done = NO; 87 | int status; 88 | z_stream strm; 89 | strm.next_in = (Bytef *)[self bytes]; 90 | strm.avail_in = [self length]; 91 | strm.total_out = 0; 92 | strm.zalloc = Z_NULL; 93 | strm.zfree = Z_NULL; 94 | if (inflateInit2(&strm, (15+32)) != Z_OK) { 95 | return nil; 96 | } 97 | 98 | while (!done) { 99 | if (strm.total_out >= [decompressed length]) { 100 | [decompressed increaseLengthBy: half_length]; 101 | } 102 | strm.next_out = (Bytef*)[decompressed mutableBytes] + strm.total_out; 103 | strm.avail_out = [decompressed length] - strm.total_out; 104 | status = inflate (&strm, Z_SYNC_FLUSH); 105 | if (status == Z_STREAM_END) { 106 | done = YES; 107 | } 108 | else if (status != Z_OK) { 109 | break; 110 | } 111 | } 112 | 113 | if (inflateEnd (&strm) != Z_OK || !done) { 114 | return nil; 115 | } 116 | 117 | [decompressed setLength: strm.total_out]; 118 | 119 | return [[[NSString alloc] initWithBytes:decompressed.bytes length:decompressed.length encoding:NSUTF8StringEncoding] autorelease]; 120 | } 121 | 122 | @end 123 | 124 | @implementation NSDictionary (KFExtension) 125 | 126 | - (NSDictionary*)dictionaryValueForKey:(NSString*)key defaultValue:(NSDictionary*)defaultValue { 127 | if (key != nil && [key length] > 0) { 128 | id ret = [self objectForKey:key]; 129 | if (ret != nil && ret != [NSNull null] && [ret isKindOfClass:[NSDictionary class]]) { 130 | return ret; 131 | } 132 | } 133 | return defaultValue; 134 | } 135 | 136 | - (NSArray*)arrayValueForKey:(NSString*)key defaultValue:(NSArray*)defaultValue { 137 | if (key != nil && [key length] > 0) { 138 | id ret = [self objectForKey:key]; 139 | if (ret != nil && ret != [NSNull null] && [ret isKindOfClass:[NSArray class]]) { 140 | return ret; 141 | } 142 | } 143 | return defaultValue; 144 | } 145 | 146 | - (NSString*)stringValueForKey:(NSString*)key defaultValue:(NSString*)defaultValue operation:(NSStringOperationType)type { 147 | if (key != nil && [key length] > 0) { 148 | id ret = [self objectForKey:key]; 149 | if (ret != nil && ret != [NSNull null]) { 150 | if ([ret isKindOfClass:[NSString class]]) { 151 | switch (type) { 152 | case NSStringOperationTypeDecodeUnicode: { 153 | return [[ret trim] decodeUnicode]; 154 | } 155 | case NSStringOperationTypeNone: { 156 | return ret; 157 | } 158 | case NSStringOperationTypeTrim: 159 | default: { 160 | return [ret trim]; 161 | } 162 | } 163 | } 164 | else if ([ret isKindOfClass:[NSDecimalNumber class]]) { 165 | return [NSString stringWithFormat:@"%@", ret]; 166 | } 167 | else if ([ret isKindOfClass:[NSNumber class]]) { 168 | return [NSString stringWithFormat:@"%@", ret]; 169 | } 170 | } 171 | } 172 | return defaultValue; 173 | } 174 | 175 | - (int)intValueForKey:(NSString*)key defaultValue:(int)defaultValue { 176 | if (key != nil && [key length] > 0) { 177 | id ret = [self objectForKey:key]; 178 | if (ret != nil && ret != [NSNull null] && ([ret isKindOfClass:[NSDecimalNumber class]] || [ret isKindOfClass:[NSNumber class]] || [ret isKindOfClass:[NSString class]])) { 179 | return [ret intValue]; 180 | } 181 | } 182 | return defaultValue; 183 | } 184 | 185 | - (uint64_t)longLongValueForKey:(NSString*)key defaultValue:(uint64_t)defaultValue { 186 | if (key != nil && [key length] > 0) { 187 | id ret = [self objectForKey:key]; 188 | if (ret != nil && ret != [NSNull null] && ([ret isKindOfClass:[NSDecimalNumber class]] || [ret isKindOfClass:[NSNumber class]] || [ret isKindOfClass:[NSString class]])) { 189 | return [ret longLongValue]; 190 | } 191 | } 192 | return defaultValue; 193 | } 194 | 195 | - (double)doubleValueForKey:(NSString*)key defaultValue:(double)defaultValue { 196 | if (key != nil && [key length] > 0) { 197 | id ret = [self objectForKey:key]; 198 | if (ret != nil && ret != [NSNull null] && ([ret isKindOfClass:[NSDecimalNumber class]] || [ret isKindOfClass:[NSNumber class]] || [ret isKindOfClass:[NSString class]])) { 199 | return [ret doubleValue]; 200 | } 201 | } 202 | return defaultValue; 203 | } 204 | 205 | - (float)floatValueForKey:(NSString*)key defaultValue:(float)defaultValue { 206 | if (key != nil && [key length] > 0) { 207 | id ret = [self objectForKey:key]; 208 | if (ret != nil && ret != [NSNull null] && ([ret isKindOfClass:[NSDecimalNumber class]] || [ret isKindOfClass:[NSNumber class]] || [ret isKindOfClass:[NSString class]])) { 209 | return [ret floatValue]; 210 | } 211 | } 212 | return defaultValue; 213 | } 214 | 215 | - (BOOL)boolValueForKey:(NSString*)key defaultValue:(BOOL)defaultValue { 216 | if (key != nil && [key length] > 0) { 217 | id ret = [self objectForKey:key]; 218 | if (ret != nil && ret != [NSNull null]) { 219 | return [ret boolValue]; 220 | } 221 | } 222 | return defaultValue; 223 | } 224 | 225 | @end 226 | -------------------------------------------------------------------------------- /YoutuYunDemo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // YoutuYunDemo 4 | // 5 | // Created by Patrick Yang on 15/9/15. 6 | // Copyright (c) 2015年 Tencent. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "DemoAppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([DemoAppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /YoutuYunDemoTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.tencent.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /YoutuYunDemoTests/YoutuYunDemoTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // YoutuYunDemoTests.m 3 | // YoutuYunDemoTests 4 | // 5 | // Created by Patrick Yang on 15/9/15. 6 | // Copyright (c) 2015年 Tencent. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface YoutuYunDemoTests : XCTestCase 13 | 14 | @end 15 | 16 | @implementation YoutuYunDemoTests 17 | 18 | - (void)setUp { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown { 24 | // Put teardown code here. This method is called after the invocation of each test method in the class. 25 | [super tearDown]; 26 | } 27 | 28 | - (void)testExample { 29 | // This is an example of a functional test case. 30 | XCTAssert(YES, @"Pass"); 31 | } 32 | 33 | - (void)testPerformanceExample { 34 | // This is an example of a performance test case. 35 | [self measureBlock:^{ 36 | // Put the code you want to measure the time of here. 37 | }]; 38 | } 39 | 40 | @end 41 | --------------------------------------------------------------------------------