GlobalMethod+Authority.m 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. //
  2. // GlobalMethod+Authority.m
  3. // 乐销
  4. //
  5. // Created by 隋林栋 on 2017/6/16.
  6. // Copyright © 2017年 ping. All rights reserved.
  7. //
  8. #import "GlobalMethod+Authority.h"
  9. //照相机权限
  10. #import <Photos/Photos.h>
  11. //通讯录
  12. #import <AddressBook/AddressBook.h>
  13. //获取运营商
  14. #import <CoreTelephony/CTCarrier.h>
  15. #import <CoreTelephony/CTTelephonyNetworkInfo.h>
  16. @implementation GlobalMethod (Authority)
  17. //获取照相机权限
  18. + (void)fetchCameraAuthorityBlock:(void (^)(void))block{
  19. if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
  20. //设备没有照相机
  21. return;
  22. }
  23. AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
  24. switch (authStatus) {
  25. case AVAuthorizationStatusAuthorized://agree
  26. {
  27. if (block) {
  28. block();
  29. }
  30. }
  31. break;
  32. case AVAuthorizationStatusDenied://disagree
  33. {
  34. //弹窗提示
  35. [GlobalMethod showAlertOpenAuthority:AUTHORITY_CAMERA];
  36. }
  37. break;
  38. case AVAuthorizationStatusNotDetermined://undetermined
  39. {
  40. [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {//相机权限
  41. [GlobalMethod mainQueueBlock:^{
  42. if (granted) {
  43. if (block) {
  44. block();
  45. }
  46. }else{
  47. //弹窗提示
  48. [GlobalMethod showAlertOpenAuthority:AUTHORITY_CAMERA];
  49. }
  50. }];
  51. }];
  52. }
  53. break;
  54. default:
  55. break;
  56. }
  57. }
  58. //获取相册权限
  59. + (void)fetchPhotoAuthorityBlock:(void (^)(void))block{
  60. if (! [UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) {
  61. //设备没有相册
  62. return;
  63. }
  64. PHAuthorizationStatus authStatus = [PHPhotoLibrary authorizationStatus];
  65. switch (authStatus) {
  66. case PHAuthorizationStatusAuthorized://agree
  67. {
  68. if (block) {
  69. block();
  70. }
  71. }
  72. break;
  73. case PHAuthorizationStatusDenied://disagree
  74. {
  75. //弹窗提示
  76. [GlobalMethod showAlertOpenAuthority:AUTHORITY_PHOTO];
  77. }
  78. break;
  79. case PHAuthorizationStatusNotDetermined://undetermined
  80. {
  81. [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
  82. [GlobalMethod mainQueueBlock:^{
  83. if (status == PHAuthorizationStatusAuthorized) {
  84. if (block) {
  85. block();
  86. }
  87. }else {
  88. //弹窗提示
  89. [GlobalMethod showAlertOpenAuthority:AUTHORITY_PHOTO];
  90. }
  91. }];
  92. }];
  93. }
  94. break;
  95. default:
  96. break;
  97. }
  98. }
  99. #pragma mark - 通讯录
  100. + (void)fetchAddressBookAuthorityBlock:(void (^)(void))block {
  101. ABAuthorizationStatus authStatus = ABAddressBookGetAuthorizationStatus();
  102. if (authStatus == kABAuthorizationStatusNotDetermined) {
  103. __block ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
  104. if (addressBook == NULL) {
  105. //设备没有通讯录功能
  106. return;
  107. }
  108. ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
  109. [GlobalMethod mainQueueBlock:^{
  110. if (granted) {//允许
  111. if (block) {
  112. block();
  113. }
  114. } else {
  115. [self showAlertOpenAuthority:AUTHORITY_ADDRESSBOOK];
  116. }
  117. if (addressBook) {
  118. CFRelease(addressBook);
  119. addressBook = NULL;
  120. }
  121. }];
  122. });
  123. return;
  124. } else if (authStatus == kABAuthorizationStatusAuthorized) {
  125. if (block) {
  126. block();
  127. }
  128. } else if (authStatus == kABAuthorizationStatusDenied) {
  129. [self showAlertOpenAuthority:AUTHORITY_ADDRESSBOOK];
  130. } else if (authStatus == kABAuthorizationStatusRestricted) {
  131. [self showAlertOpenAuthority:AUTHORITY_ADDRESSBOOK];
  132. }
  133. }
  134. #pragma mark - 麦克风
  135. + (void)fetchMicAuthorityBlock:(void (^)(void))block{
  136. AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeAudio];
  137. switch (authStatus) {
  138. case AVAuthorizationStatusNotDetermined:
  139. //没有询问是否开启麦克风
  140. {
  141. AVAudioSession *avSession = [AVAudioSession sharedInstance];
  142. if ([avSession respondsToSelector:@selector(requestRecordPermission:)]) {
  143. [avSession requestRecordPermission:^(BOOL available) {
  144. [GlobalMethod mainQueueBlock:^{
  145. if (available) {
  146. if (block) {
  147. block();
  148. }
  149. }else {
  150. //弹窗提示
  151. [GlobalMethod showAlertOpenAuthority:AUTHORITY_MIC];
  152. }
  153. }];
  154. }];
  155. }
  156. }
  157. break;
  158. case AVAuthorizationStatusRestricted:
  159. //未授权,家长限制
  160. case AVAuthorizationStatusDenied:
  161. //玩家未授权
  162. {
  163. [GlobalMethod showAlertOpenAuthority:AUTHORITY_MIC];
  164. }
  165. break;
  166. case AVAuthorizationStatusAuthorized:
  167. {
  168. //玩家授权
  169. if (block) {
  170. block();
  171. }
  172. }
  173. break;
  174. default:
  175. break;
  176. }
  177. }
  178. + (void)showAlertOpenAuthority:(AUTHORITY_TYPE)type{
  179. ModelBtn * modelDismiss = [ModelBtn modelWithTitle:@"取消" imageName:nil highImageName:nil tag:TAG_LINE color:[UIColor redColor]];
  180. modelDismiss.blockClick = ^(void){
  181. };
  182. ModelBtn * modelConfirm = [ModelBtn modelWithTitle:@"确认" imageName:nil highImageName:nil tag:TAG_LINE color:COLOR_BLUE];
  183. modelConfirm.blockClick = ^(void){
  184. NSURL *settingUrl = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
  185. if ([[UIApplication sharedApplication] canOpenURL:settingUrl]) {
  186. [[UIApplication sharedApplication] openURL:settingUrl];
  187. }
  188. };
  189. NSString * strTitle = @"";
  190. switch (type) {
  191. case AUTHORITY_PHOTO:
  192. {
  193. strTitle = @"相册功能";
  194. }
  195. break;
  196. case AUTHORITY_CAMERA:
  197. {
  198. strTitle = @"照相机功能";
  199. }
  200. break;
  201. case AUTHORITY_LOCAL:
  202. {
  203. strTitle = @"定位功能";
  204. }
  205. break;
  206. case AUTHORITY_ADDRESSBOOK:
  207. {
  208. strTitle = @"通讯录功能";
  209. }
  210. break;
  211. default:
  212. break;
  213. }
  214. [GlobalMethod mainQueueBlock:^{
  215. [BaseAlertView initWithTitle:[NSString stringWithFormat:@"请前往设置打开%@",UnPackStr(strTitle)] content:[NSString stringWithFormat:@"不打开将无法使用%@",UnPackStr(strTitle)] aryBtnModels:@[modelDismiss,modelConfirm] viewShow:[UIApplication sharedApplication].keyWindow];
  216. }];
  217. }
  218. /**
  219. 调用电话功能
  220. @param ViewController 调用类
  221. @param phoneStr 电话号码
  222. */
  223. +(void)gotoCallPhoneClick:(UIViewController *)ViewController phone:(NSString *)phoneStr{
  224. if (!isStr(phoneStr)) {
  225. return;
  226. }
  227. NSDictionary * sourceDic = @{@"VC":ViewController,
  228. @"phone":phoneStr};
  229. [self cancelTapGestureAction:sourceDic];
  230. }
  231. +(void)cancelTapGestureAction:(id)sourceDic{
  232. [[self class] cancelPreviousPerformRequestsWithTarget:self selector:@selector(gotoTelClick:) object:sourceDic];
  233. [self performSelector:@selector(gotoTelClick:) withObject:sourceDic afterDelay:0.5f];
  234. }
  235. //调用系统电话功能
  236. +(void)gotoTelClick:(id)sourceDic{
  237. NSString *callPhone = [NSString stringWithFormat:@"tel://%@" ,sourceDic[@"phone"]];
  238. NSComparisonResult compare = [[UIDevice currentDevice].systemVersion compare:@"10.0"];
  239. UIApplication * application = [UIApplication sharedApplication];
  240. if ([application canOpenURL:[NSURL URLWithString:callPhone]]) {
  241. if (compare == NSOrderedAscending || compare == NSOrderedSame) {
  242. /// 大于等于10.0系统使用此openURL方法
  243. if (@available(iOS 10.0, *)) {
  244. [application openURL:[NSURL URLWithString:callPhone] options:@{} completionHandler:nil];
  245. } else {
  246. // Fallback on earlier versions
  247. }
  248. } else {
  249. [application openURL:[NSURL URLWithString:callPhone]];
  250. }
  251. }
  252. }
  253. /**
  254. 获取设备唯一信息 包括 UUID系统(逻辑) 运营商 版本号 系统名
  255. */
  256. + (NSString *)fetchDeviceID{
  257. ///UUID
  258. NSString *bundleID = [[NSBundle mainBundle] bundleIdentifier];
  259. NSString * strUUID = (NSString *)[self load:bundleID];
  260. //首次执行该方法时,uuid为空
  261. if ([strUUID isEqualToString:@""] || !strUUID)
  262. {
  263. NSString * UUID = [[UIDevice currentDevice] identifierForVendor].UUIDString;
  264. //将该uuid保存到keychain
  265. [self save:bundleID data:UUID];
  266. }
  267. ///获取运营商
  268. CTTelephonyNetworkInfo *info = [[CTTelephonyNetworkInfo alloc] init];
  269. CTCarrier *carrier = [info subscriberCellularProvider];
  270. NSString *mCarrier = [NSString stringWithFormat:@"%@",[carrier carrierName]];
  271. NSLog(@"运营商:%@",mCarrier);
  272. // 获取设备所有者的名称——"My iPhone"
  273. NSString * Devicename = [[UIDevice currentDevice] name];
  274. NSLog(@"获取设备所有者的名称:%@",Devicename);
  275. // 获取设备的型号——@"iPhone"
  276. NSString * version = [[UIDevice currentDevice] model];
  277. NSLog(@"获取设备的型号:%@",version);
  278. // 获取当前运行的系统名称——@"iOS"
  279. NSString * systemName = [[UIDevice currentDevice] systemName];
  280. NSLog(@"获取当前运行的系统名称:%@",systemName);
  281. // 获取当前系统的版本——@"10.0"、@"11.3.1"
  282. NSString * systemVersion = [[UIDevice currentDevice] systemVersion];
  283. NSLog(@"获取当前系统的版本:%@",systemVersion);
  284. return strUUID;
  285. }
  286. + (NSMutableDictionary *)getKeychainQuery:(NSString *)service {
  287. return [NSMutableDictionary dictionaryWithObjectsAndKeys:
  288. (id)kSecClassGenericPassword,(id)kSecClass,service, (id)kSecAttrService,service, (id)kSecAttrAccount,(id)kSecAttrAccessibleAfterFirstUnlock,(id)kSecAttrAccessible,nil];
  289. }
  290. + (void)save:(NSString *)service data:(id)data {
  291. //Get search dictionary
  292. NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
  293. //Delete old item before add new item
  294. SecItemDelete((CFDictionaryRef)keychainQuery);
  295. //Add new object to search dictionary(Attention:the data format)
  296. [keychainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:data] forKey:(id)kSecValueData];
  297. //Add item to keychain with the search dictionary
  298. SecItemAdd((CFDictionaryRef)keychainQuery, NULL);
  299. }
  300. + (id)load:(NSString *)service {
  301. id ret = nil;
  302. NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
  303. //Configure the search setting
  304. //Since in our simple case we are expecting only a single attribute to be returned (the password) we can set the attribute kSecReturnData to kCFBooleanTrue
  305. [keychainQuery setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData];
  306. [keychainQuery setObject:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit];
  307. CFDataRef keyData = NULL;
  308. if (SecItemCopyMatching((CFDictionaryRef)keychainQuery, (CFTypeRef *)&keyData) == noErr) {
  309. @try {
  310. ret = [NSKeyedUnarchiver unarchiveObjectWithData:(__bridge NSData *)keyData];
  311. } @catch (NSException *e) {
  312. NSLog(@"Unarchive of %@ failed: %@", service, e);
  313. } @finally {
  314. }
  315. }
  316. if (keyData)
  317. CFRelease(keyData);
  318. return ret;
  319. }
  320. @end