GDTCORPlatform.m 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. /*
  2. * Copyright 2019 Google
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #import <GoogleDataTransport/GDTCORPlatform.h>
  17. #import <GoogleDataTransport/GDTCORAssert.h>
  18. #import "GDTCORLibrary/Private/GDTCORRegistrar_Private.h"
  19. #ifdef GDTCOR_VERSION
  20. #define STR(x) STR_EXPAND(x)
  21. #define STR_EXPAND(x) #x
  22. NSString *const kGDTCORVersion = @STR(GDTCOR_VERSION);
  23. #else
  24. NSString *const kGDTCORVersion = @"Unknown";
  25. #endif // GDTCOR_VERSION
  26. const GDTCORBackgroundIdentifier GDTCORBackgroundIdentifierInvalid = 0;
  27. NSString *const kGDTCORApplicationDidEnterBackgroundNotification =
  28. @"GDTCORApplicationDidEnterBackgroundNotification";
  29. NSString *const kGDTCORApplicationWillEnterForegroundNotification =
  30. @"GDTCORApplicationWillEnterForegroundNotification";
  31. NSString *const kGDTCORApplicationWillTerminateNotification =
  32. @"GDTCORApplicationWillTerminateNotification";
  33. BOOL GDTCORReachabilityFlagsContainWWAN(SCNetworkReachabilityFlags flags) {
  34. #if TARGET_OS_IOS
  35. return (flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN;
  36. #else
  37. return NO;
  38. #endif // TARGET_OS_IOS
  39. }
  40. @interface GDTCORApplication ()
  41. /**
  42. Private flag to match the existing `readonly` public flag. This will be accurate for all platforms,
  43. since we handle each platform's lifecycle notifications separately.
  44. */
  45. @property(atomic, readwrite) BOOL isRunningInBackground;
  46. @end
  47. @implementation GDTCORApplication
  48. + (void)load {
  49. #if TARGET_OS_IOS || TARGET_OS_TV
  50. // If this asserts, please file a bug at https://github.com/firebase/firebase-ios-sdk/issues.
  51. GDTCORFatalAssert(
  52. GDTCORBackgroundIdentifierInvalid == UIBackgroundTaskInvalid,
  53. @"GDTCORBackgroundIdentifierInvalid and UIBackgroundTaskInvalid should be the same.");
  54. #endif
  55. [self sharedApplication];
  56. }
  57. + (nullable GDTCORApplication *)sharedApplication {
  58. static GDTCORApplication *application;
  59. static dispatch_once_t onceToken;
  60. dispatch_once(&onceToken, ^{
  61. application = [[GDTCORApplication alloc] init];
  62. });
  63. return application;
  64. }
  65. - (instancetype)init {
  66. self = [super init];
  67. if (self) {
  68. // This class will be instantiated in the foreground.
  69. _isRunningInBackground = NO;
  70. #if TARGET_OS_IOS || TARGET_OS_TV
  71. NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
  72. [notificationCenter addObserver:self
  73. selector:@selector(iOSApplicationDidEnterBackground:)
  74. name:UIApplicationDidEnterBackgroundNotification
  75. object:nil];
  76. [notificationCenter addObserver:self
  77. selector:@selector(iOSApplicationWillEnterForeground:)
  78. name:UIApplicationWillEnterForegroundNotification
  79. object:nil];
  80. NSString *name = UIApplicationWillTerminateNotification;
  81. [notificationCenter addObserver:self
  82. selector:@selector(iOSApplicationWillTerminate:)
  83. name:name
  84. object:nil];
  85. #if defined(__IPHONE_13_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
  86. if (@available(iOS 13, tvOS 13.0, *)) {
  87. [notificationCenter addObserver:self
  88. selector:@selector(iOSApplicationWillEnterForeground:)
  89. name:UISceneWillEnterForegroundNotification
  90. object:nil];
  91. [notificationCenter addObserver:self
  92. selector:@selector(iOSApplicationDidEnterBackground:)
  93. name:UISceneWillDeactivateNotification
  94. object:nil];
  95. }
  96. #endif // defined(__IPHONE_13_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
  97. #elif TARGET_OS_OSX
  98. NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
  99. [notificationCenter addObserver:self
  100. selector:@selector(macOSApplicationWillTerminate:)
  101. name:NSApplicationWillTerminateNotification
  102. object:nil];
  103. #endif // TARGET_OS_IOS || TARGET_OS_TV
  104. }
  105. return self;
  106. }
  107. - (GDTCORBackgroundIdentifier)beginBackgroundTaskWithName:(NSString *)name
  108. expirationHandler:(void (^)(void))handler {
  109. return [[self sharedApplicationForBackgroundTask] beginBackgroundTaskWithName:name
  110. expirationHandler:handler];
  111. }
  112. - (void)endBackgroundTask:(GDTCORBackgroundIdentifier)bgID {
  113. if (bgID != GDTCORBackgroundIdentifierInvalid) {
  114. [[self sharedApplicationForBackgroundTask] endBackgroundTask:bgID];
  115. }
  116. }
  117. #pragma mark - App environment helpers
  118. - (BOOL)isAppExtension {
  119. #if TARGET_OS_IOS || TARGET_OS_TV
  120. BOOL appExtension = [[[NSBundle mainBundle] bundlePath] hasSuffix:@".appex"];
  121. return appExtension;
  122. #elif TARGET_OS_OSX
  123. return NO;
  124. #endif
  125. }
  126. /** Returns a UIApplication instance if on the appropriate platform.
  127. *
  128. * @return The shared UIApplication if on the appropriate platform.
  129. */
  130. #if TARGET_OS_IOS || TARGET_OS_TV
  131. - (nullable UIApplication *)sharedApplicationForBackgroundTask {
  132. #else
  133. - (nullable id)sharedApplicationForBackgroundTask {
  134. #endif
  135. if ([self isAppExtension]) {
  136. return nil;
  137. }
  138. id sharedApplication = nil;
  139. Class uiApplicationClass = NSClassFromString(@"UIApplication");
  140. if (uiApplicationClass &&
  141. [uiApplicationClass respondsToSelector:(NSSelectorFromString(@"sharedApplication"))]) {
  142. sharedApplication = [uiApplicationClass sharedApplication];
  143. }
  144. return sharedApplication;
  145. }
  146. #pragma mark - UIApplicationDelegate
  147. #if TARGET_OS_IOS || TARGET_OS_TV
  148. - (void)iOSApplicationDidEnterBackground:(NSNotification *)notif {
  149. _isRunningInBackground = YES;
  150. NSNotificationCenter *notifCenter = [NSNotificationCenter defaultCenter];
  151. [notifCenter postNotificationName:kGDTCORApplicationDidEnterBackgroundNotification object:nil];
  152. }
  153. - (void)iOSApplicationWillEnterForeground:(NSNotification *)notif {
  154. _isRunningInBackground = NO;
  155. NSNotificationCenter *notifCenter = [NSNotificationCenter defaultCenter];
  156. [notifCenter postNotificationName:kGDTCORApplicationWillEnterForegroundNotification object:nil];
  157. }
  158. - (void)iOSApplicationWillTerminate:(NSNotification *)notif {
  159. NSNotificationCenter *notifCenter = [NSNotificationCenter defaultCenter];
  160. [notifCenter postNotificationName:kGDTCORApplicationWillTerminateNotification object:nil];
  161. }
  162. #endif // TARGET_OS_IOS || TARGET_OS_TV
  163. #pragma mark - NSApplicationDelegate
  164. #if TARGET_OS_OSX
  165. - (void)macOSApplicationWillTerminate:(NSNotification *)notif {
  166. NSNotificationCenter *notifCenter = [NSNotificationCenter defaultCenter];
  167. [notifCenter postNotificationName:kGDTCORApplicationWillTerminateNotification object:nil];
  168. }
  169. #endif // TARGET_OS_OSX
  170. @end