UIApplication+YYAdd.m 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. //
  2. // UIApplication+YYAdd.m
  3. // YYKit <https://github.com/ibireme/YYKit>
  4. //
  5. // Created by ibireme on 13/4/4.
  6. // Copyright (c) 2015 ibireme.
  7. //
  8. // This source code is licensed under the MIT-style license found in the
  9. // LICENSE file in the root directory of this source tree.
  10. //
  11. #import "UIApplication+YYAdd.h"
  12. #import "NSArray+YYAdd.h"
  13. #import "NSObject+YYAdd.h"
  14. #import "YYKitMacro.h"
  15. #import "UIDevice+YYAdd.h"
  16. #import <sys/sysctl.h>
  17. #import <mach/mach.h>
  18. #import <objc/runtime.h>
  19. YYSYNTH_DUMMY_CLASS(UIApplication_YYAdd)
  20. #define kNetworkIndicatorDelay (1/30.0)
  21. @interface _YYUIApplicationNetworkIndicatorInfo : NSObject
  22. @property (nonatomic, assign) NSInteger count;
  23. @property (nonatomic, strong) NSTimer *timer;
  24. @end
  25. @implementation _YYUIApplicationNetworkIndicatorInfo
  26. @end
  27. @implementation UIApplication (YYAdd)
  28. - (NSURL *)documentsURL {
  29. return [[[NSFileManager defaultManager]
  30. URLsForDirectory:NSDocumentDirectory
  31. inDomains:NSUserDomainMask] lastObject];
  32. }
  33. - (NSString *)documentsPath {
  34. return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
  35. }
  36. - (NSURL *)cachesURL {
  37. return [[[NSFileManager defaultManager]
  38. URLsForDirectory:NSCachesDirectory
  39. inDomains:NSUserDomainMask] lastObject];
  40. }
  41. - (NSString *)cachesPath {
  42. return [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
  43. }
  44. - (NSURL *)libraryURL {
  45. return [[[NSFileManager defaultManager]
  46. URLsForDirectory:NSLibraryDirectory
  47. inDomains:NSUserDomainMask] lastObject];
  48. }
  49. - (NSString *)libraryPath {
  50. return [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) firstObject];
  51. }
  52. - (BOOL)isPirated {
  53. if ([[UIDevice currentDevice] isSimulator]) return YES; // Simulator is not from appstore
  54. if (getgid() <= 10) return YES; // process ID shouldn't be root
  55. if ([[[NSBundle mainBundle] infoDictionary] objectForKey:@"SignerIdentity"]) {
  56. return YES;
  57. }
  58. if (![self _yy_fileExistInMainBundle:@"_CodeSignature"]) {
  59. return YES;
  60. }
  61. if (![self _yy_fileExistInMainBundle:@"SC_Info"]) {
  62. return YES;
  63. }
  64. //if someone really want to crack your app, this method is useless..
  65. //you may change this method's name, encrypt the code and do more check..
  66. return NO;
  67. }
  68. - (BOOL)_yy_fileExistInMainBundle:(NSString *)name {
  69. NSString *bundlePath = [[NSBundle mainBundle] bundlePath];
  70. NSString *path = [NSString stringWithFormat:@"%@/%@", bundlePath, name];
  71. return [[NSFileManager defaultManager] fileExistsAtPath:path];
  72. }
  73. - (NSString *)appBundleName {
  74. return [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleName"];
  75. }
  76. - (NSString *)appBundleID {
  77. return [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleIdentifier"];
  78. }
  79. - (NSString *)appVersion {
  80. return [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"];
  81. }
  82. - (NSString *)appBuildVersion {
  83. return [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"];
  84. }
  85. - (BOOL)isBeingDebugged {
  86. size_t size = sizeof(struct kinfo_proc);
  87. struct kinfo_proc info;
  88. int ret = 0, name[4];
  89. memset(&info, 0, sizeof(struct kinfo_proc));
  90. name[0] = CTL_KERN;
  91. name[1] = KERN_PROC;
  92. name[2] = KERN_PROC_PID; name[3] = getpid();
  93. if (ret == (sysctl(name, 4, &info, &size, NULL, 0))) {
  94. return ret != 0;
  95. }
  96. return (info.kp_proc.p_flag & P_TRACED) ? YES : NO;
  97. }
  98. - (int64_t)memoryUsage {
  99. struct task_basic_info info;
  100. mach_msg_type_number_t size = sizeof(info);
  101. kern_return_t kern = task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&info, &size);
  102. if (kern != KERN_SUCCESS) return -1;
  103. return info.resident_size;
  104. }
  105. - (float)cpuUsage {
  106. kern_return_t kr;
  107. task_info_data_t tinfo;
  108. mach_msg_type_number_t task_info_count;
  109. task_info_count = TASK_INFO_MAX;
  110. kr = task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)tinfo, &task_info_count);
  111. if (kr != KERN_SUCCESS) {
  112. return -1;
  113. }
  114. thread_array_t thread_list;
  115. mach_msg_type_number_t thread_count;
  116. thread_info_data_t thinfo;
  117. mach_msg_type_number_t thread_info_count;
  118. thread_basic_info_t basic_info_th;
  119. kr = task_threads(mach_task_self(), &thread_list, &thread_count);
  120. if (kr != KERN_SUCCESS) {
  121. return -1;
  122. }
  123. long tot_sec = 0;
  124. long tot_usec = 0;
  125. float tot_cpu = 0;
  126. int j;
  127. for (j = 0; j < thread_count; j++) {
  128. thread_info_count = THREAD_INFO_MAX;
  129. kr = thread_info(thread_list[j], THREAD_BASIC_INFO,
  130. (thread_info_t)thinfo, &thread_info_count);
  131. if (kr != KERN_SUCCESS) {
  132. return -1;
  133. }
  134. basic_info_th = (thread_basic_info_t)thinfo;
  135. if (!(basic_info_th->flags & TH_FLAGS_IDLE)) {
  136. tot_sec = tot_sec + basic_info_th->user_time.seconds + basic_info_th->system_time.seconds;
  137. tot_usec = tot_usec + basic_info_th->system_time.microseconds + basic_info_th->system_time.microseconds;
  138. tot_cpu = tot_cpu + basic_info_th->cpu_usage / (float)TH_USAGE_SCALE;
  139. }
  140. }
  141. kr = vm_deallocate(mach_task_self(), (vm_offset_t)thread_list, thread_count * sizeof(thread_t));
  142. assert(kr == KERN_SUCCESS);
  143. return tot_cpu;
  144. }
  145. YYSYNTH_DYNAMIC_PROPERTY_OBJECT(networkActivityInfo, setNetworkActivityInfo, RETAIN_NONATOMIC, _YYUIApplicationNetworkIndicatorInfo *);
  146. - (void)_delaySetActivity:(NSTimer *)timer {
  147. NSNumber *visiable = timer.userInfo;
  148. if (self.networkActivityIndicatorVisible != visiable.boolValue) {
  149. //modify by leo
  150. [self setNetworkActivityIndicatorVisible:visiable.boolValue];
  151. }
  152. [timer invalidate];
  153. }
  154. - (void)_changeNetworkActivityCount:(NSInteger)delta {
  155. @synchronized(self){
  156. dispatch_async_on_main_queue(^{
  157. _YYUIApplicationNetworkIndicatorInfo *info = [self networkActivityInfo];
  158. if (!info) {
  159. info = [_YYUIApplicationNetworkIndicatorInfo new];
  160. [self setNetworkActivityInfo:info];
  161. }
  162. NSInteger count = info.count;
  163. count += delta;
  164. info.count = count;
  165. [info.timer invalidate];
  166. info.timer = [NSTimer timerWithTimeInterval:kNetworkIndicatorDelay target:self selector:@selector(_delaySetActivity:) userInfo:@(info.count > 0) repeats:NO];
  167. [[NSRunLoop mainRunLoop] addTimer:info.timer forMode:NSRunLoopCommonModes];
  168. });
  169. }
  170. }
  171. - (void)incrementNetworkActivityCount {
  172. [self _changeNetworkActivityCount:1];
  173. }
  174. - (void)decrementNetworkActivityCount {
  175. [self _changeNetworkActivityCount:-1];
  176. }
  177. + (BOOL)isAppExtension {
  178. static BOOL isAppExtension = NO;
  179. static dispatch_once_t onceToken;
  180. dispatch_once(&onceToken, ^{
  181. Class cls = NSClassFromString(@"UIApplication");
  182. if(!cls || ![cls respondsToSelector:@selector(sharedApplication)]) isAppExtension = YES;
  183. if ([[[NSBundle mainBundle] bundlePath] hasSuffix:@".appex"]) isAppExtension = YES;
  184. });
  185. return isAppExtension;
  186. }
  187. + (UIApplication *)sharedExtensionApplication {
  188. #pragma clang diagnostic push
  189. #pragma clang diagnostic ignored "-Wundeclared-selector"
  190. return [self isAppExtension] ? nil : [UIApplication performSelector:@selector(sharedApplication)];
  191. #pragma clang diagnostic pop
  192. }
  193. @end