Skip to content

Commit 508f772

Browse files
committed
Pulling live activities into 5.0.0
1 parent 3e851d9 commit 508f772

File tree

6 files changed

+403
-0
lines changed

6 files changed

+403
-0
lines changed

iOS_SDK/OneSignalSDK/OneSignalCore/Source/API/OSRequests.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,5 +115,18 @@ NS_ASSUME_NONNULL_END
115115
+ (instancetype _Nonnull)trackUsageData:(NSString * _Nonnull)osUsageData
116116
appId:(NSString * _Nonnull)appId;
117117
@end
118+
119+
@interface OSRequestLiveActivityEnter: OneSignalRequest
120+
+ (instancetype _Nonnull)withUserId:(NSString * _Nonnull)userId
121+
appId:(NSString * _Nonnull)appId
122+
activityId:(NSString * _Nonnull)activityId
123+
token:(NSString * _Nonnull)token;
124+
@end
125+
126+
@interface OSRequestLiveActivityExit: OneSignalRequest
127+
+ (instancetype _Nonnull)withUserId:(NSString * _Nonnull)userId
128+
appId:(NSString * _Nonnull)appId
129+
activityId:(NSString * _Nonnull)activityId;
130+
@end
118131
#endif /* Requests_h */
119132

iOS_SDK/OneSignalSDK/OneSignalCore/Source/API/OSRequests.m

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,4 +371,38 @@ + (instancetype)trackUsageData:(NSString *)osUsageData appId:(NSString *)appId {
371371
request.additionalHeaders = headers;
372372
return request;
373373
}
374+
375+
@implementation OSRequestLiveActivityEnter
376+
+ (instancetype)withUserId:(NSString * _Nonnull)userId
377+
appId:(NSString * _Nonnull)appId
378+
activityId:(NSString * _Nonnull)activityId
379+
token:(NSString * _Nonnull)token {
380+
let request = [OSRequestLiveActivityEnter new];
381+
let params = [NSMutableDictionary new];
382+
params[@"push_token"] = token;
383+
params[@"subscription_id"] = userId; // pre-5.X.X subscription_id = player_id = userId
384+
params[@"device_type"] = @0;
385+
request.parameters = params;
386+
request.method = POST;
387+
388+
NSString *urlSafeActivityId = [activityId stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLUserAllowedCharacterSet]];
389+
390+
request.path = [NSString stringWithFormat:@"apps/%@/live_activities/%@/token", appId, urlSafeActivityId];
391+
return request;
392+
}
393+
@end
394+
395+
@implementation OSRequestLiveActivityExit
396+
+ (instancetype)withUserId:(NSString * _Nonnull)userId
397+
appId:(NSString * _Nonnull)appId
398+
activityId:(NSString * _Nonnull)activityId {
399+
let request = [OSRequestLiveActivityExit new];
400+
request.method = DELETE;
401+
402+
NSString *urlSafeActivityId = [activityId stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLUserAllowedCharacterSet]];
403+
404+
request.path = [NSString stringWithFormat:@"apps/%@/live_activities/%@/token/%@", appId, urlSafeActivityId, userId];
405+
406+
return request;
407+
}
374408
@end

iOS_SDK/OneSignalSDK/Source/OneSignal.m

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,34 @@
9292
@interface OneSignal (SessionStatusDelegate)
9393
@end
9494

95+
@interface OSPendingLiveActivityUpdate: NSObject
96+
@property NSString* token;
97+
@property NSString* activityId;
98+
@property BOOL isEnter;
99+
@property OSResultSuccessBlock successBlock;
100+
@property OSFailureBlock failureBlock;
101+
- (id)initWith:(NSString * _Nonnull)activityId
102+
withToken:(NSString * _Nonnull)token
103+
isEnter:(BOOL)isEnter
104+
withSuccess:(OSResultSuccessBlock _Nullable)successBlock
105+
withFailure:(OSFailureBlock _Nullable)failureBlock;
106+
@end
107+
@implementation OSPendingLiveActivityUpdate
108+
109+
- (id)initWith:(NSString *)activityId
110+
withToken:(NSString *)token
111+
isEnter:(BOOL)isEnter
112+
withSuccess:(OSResultSuccessBlock)successBlock
113+
withFailure:(OSFailureBlock)failureBlock {
114+
self.token = token;
115+
self.activityId = activityId;
116+
self.isEnter = isEnter;
117+
self.successBlock = successBlock;
118+
self.failureBlock = failureBlock;
119+
return self;
120+
};
121+
@end
122+
95123
@implementation OneSignal
96124

97125
static NSString* mSDKType = @"native";
@@ -100,6 +128,8 @@ @implementation OneSignal
100128
static OSResultSuccessBlock pendingGetTagsSuccessBlock;
101129
static OSFailureBlock pendingGetTagsFailureBlock;
102130

131+
static NSMutableArray* pendingLiveActivityUpdates;
132+
103133
// Has attempted to register for push notifications with Apple since app was installed.
104134
static BOOL registeredWithApple = NO;
105135

@@ -363,6 +393,109 @@ + (void)setProvidesNotificationSettingsView:(BOOL)providesView {
363393
}
364394
}
365395

396+
#pragma mark: LIVE ACTIVITIES
397+
398+
+ (void)enterLiveActivity:(NSString * _Nonnull)activityId withToken:(NSString * _Nonnull)token {
399+
400+
if ([OSPrivacyConsentController shouldLogMissingPrivacyConsentErrorWithMethodName:@"enterLiveActivity:"])
401+
return;
402+
403+
[self enterLiveActivity:activityId withToken:token withSuccess:nil withFailure:nil];
404+
}
405+
406+
+ (void)enterLiveActivity:(NSString * _Nonnull)activityId withToken:(NSString * _Nonnull)token withSuccess:(OSResultSuccessBlock _Nullable)successBlock withFailure:(OSFailureBlock _Nullable)failureBlock{
407+
408+
if ([OSPrivacyConsentController shouldLogMissingPrivacyConsentErrorWithMethodName:@"enterLiveActivity:onSuccess:onFailure:"]) {
409+
if (failureBlock) {
410+
NSError *error = [NSError errorWithDomain:@"com.onesignal.tags" code:0 userInfo:@{@"error" : @"Your application has called enterLiveActivity:onSuccess:onFailure: before the user granted privacy permission. Please call `consentGranted(bool)` in order to provide user privacy consent"}];
411+
failureBlock(error);
412+
}
413+
return;
414+
}
415+
416+
417+
if(self.currentSubscriptionState.userId) {
418+
[OneSignalClient.sharedClient executeRequest:[OSRequestLiveActivityEnter withUserId:self.currentSubscriptionState.userId appId:appId activityId:activityId token:token]
419+
onSuccess:^(NSDictionary *result) {
420+
[self callSuccessBlockOnMainThread:successBlock withResult:result];
421+
} onFailure:^(NSError *error) {
422+
[self callFailureBlockOnMainThread:failureBlock withError:error];
423+
}];
424+
} else {
425+
[self addPendingLiveActivityUpdate:activityId withToken:token isEnter:true withSuccess:successBlock withFailure:failureBlock];
426+
}
427+
}
428+
429+
+ (void)exitLiveActivity:(NSString * _Nonnull)activityId{
430+
431+
if ([OSPrivacyConsentController shouldLogMissingPrivacyConsentErrorWithMethodName:@"enterLiveActivity:"])
432+
return;
433+
434+
[self exitLiveActivity:activityId withSuccess:nil withFailure:nil];
435+
}
436+
437+
+ (void)exitLiveActivity:(NSString * _Nonnull)activityId withSuccess:(OSResultSuccessBlock _Nullable)successBlock withFailure:(OSFailureBlock _Nullable)failureBlock{
438+
439+
if ([OSPrivacyConsentController shouldLogMissingPrivacyConsentErrorWithMethodName:@"exitLiveActivity:onSuccess:onFailure:"]) {
440+
if (failureBlock) {
441+
NSError *error = [NSError errorWithDomain:@"com.onesignal.tags" code:0 userInfo:@{@"error" : @"Your application has called exitLiveActivity:onSuccess:onFailure: before the user granted privacy permission. Please call `consentGranted(bool)` in order to provide user privacy consent"}];
442+
failureBlock(error);
443+
}
444+
return;
445+
}
446+
if(self.currentSubscriptionState.userId) {
447+
[OneSignalClient.sharedClient executeRequest:[OSRequestLiveActivityExit withUserId:self.currentSubscriptionState.userId appId:appId activityId:activityId]
448+
onSuccess:^(NSDictionary *result) {
449+
[self callSuccessBlockOnMainThread:successBlock withResult:result];
450+
} onFailure:^(NSError *error) {
451+
[self callFailureBlockOnMainThread:failureBlock withError:error];
452+
}];
453+
} else {
454+
[self addPendingLiveActivityUpdate:activityId withToken:nil isEnter:false withSuccess:successBlock withFailure:failureBlock];
455+
}
456+
}
457+
458+
+ (void)addPendingLiveActivityUpdate:(NSString * _Nonnull)activityId
459+
withToken:(NSString * _Nullable)token
460+
isEnter:(BOOL)isEnter
461+
withSuccess:(OSResultSuccessBlock _Nullable)successBlock
462+
withFailure:(OSFailureBlock _Nullable)failureBlock {
463+
OSPendingLiveActivityUpdate *pendingLiveActivityUpdate = [[OSPendingLiveActivityUpdate alloc] initWith:activityId withToken:token isEnter:isEnter withSuccess:successBlock withFailure:failureBlock];
464+
465+
if (!pendingLiveActivityUpdates) {
466+
pendingLiveActivityUpdates = [NSMutableArray new];
467+
}
468+
[pendingLiveActivityUpdates addObject:pendingLiveActivityUpdate];
469+
}
470+
471+
+ (void)executePendingLiveActivityUpdates {
472+
if(pendingLiveActivityUpdates.count <= 0) {
473+
return;
474+
}
475+
476+
OSPendingLiveActivityUpdate * updateToProcess = [pendingLiveActivityUpdates objectAtIndex:0];
477+
[pendingLiveActivityUpdates removeObjectAtIndex: 0];
478+
if (updateToProcess.isEnter) {
479+
[OneSignalClient.sharedClient executeRequest:[OSRequestLiveActivityEnter withUserId:self.currentSubscriptionState.userId appId:appId activityId:updateToProcess.activityId token:updateToProcess.token]
480+
onSuccess:^(NSDictionary *result) {
481+
[self callSuccessBlockOnMainThread:updateToProcess.successBlock withResult:result];
482+
[self executePendingLiveActivityUpdates];
483+
} onFailure:^(NSError *error) {
484+
[self callFailureBlockOnMainThread:updateToProcess.failureBlock withError:error];
485+
[self executePendingLiveActivityUpdates];
486+
}];
487+
} else {
488+
[OneSignalClient.sharedClient executeRequest:[OSRequestLiveActivityExit withUserId:self.currentSubscriptionState.userId appId:appId activityId:updateToProcess.activityId]
489+
onSuccess:^(NSDictionary *result) {
490+
[self callSuccessBlockOnMainThread:updateToProcess.successBlock withResult:result];
491+
[self executePendingLiveActivityUpdates];
492+
} onFailure:^(NSError *error) {
493+
[self callFailureBlockOnMainThread:updateToProcess.failureBlock withError:error];
494+
[self executePendingLiveActivityUpdates];
495+
}];
496+
}
497+
}
498+
366499
#pragma mark Initialization
367500

368501
+ (BOOL)shouldStartNewSession {

iOS_SDK/OneSignalSDK/Source/OneSignalFramework.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,13 @@ NS_SWIFT_NAME(login(externalId:token:));
111111
+ (void)setLaunchURLsInApp:(BOOL)launchInApp;
112112
+ (void)setProvidesNotificationSettingsView:(BOOL)providesView;
113113

114+
#pragma mark Live Activity
115+
+ (void)enterLiveActivity:(NSString * _Nonnull)activityId withToken:(NSString * _Nonnull)token;
116+
+ (void)enterLiveActivity:(NSString * _Nonnull)activityId withToken:(NSString * _Nonnull)token withSuccess:(OSResultSuccessBlock _Nullable)successBlock withFailure:(OSFailureBlock _Nullable)failureBlock;
117+
118+
+ (void)exitLiveActivity:(NSString * _Nonnull)activityId;
119+
+ (void)exitLiveActivity:(NSString * _Nonnull)activityId withSuccess:(OSResultSuccessBlock _Nullable)successBlock withFailure:(OSFailureBlock _Nullable)failureBlock;
120+
114121
#pragma mark Logging
115122
+ (Class<OSDebug>)Debug NS_REFINED_FOR_SWIFT;
116123

iOS_SDK/OneSignalSDK/UnitTests/RequestTests.m

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ @implementation RequestTests {
5757
NSString *testInAppMessageAppId;
5858
NSString *testInAppMessageVariantId;
5959
NSString *testInAppMessagePageId;
60+
NSString *testLiveActivityId;
61+
NSString *testLiveActivityToken;
6062
NSString *testNotificationId;
6163
OSOutcomeEvent *testOutcome;
6264
NSNumber *testDeviceType;
@@ -84,6 +86,8 @@ - (void)setUp {
8486
testInAppMessageAppId = @"test_in_app_message_app_id";
8587
testInAppMessageVariantId = @"test_in_app_message_variant_id";
8688
testInAppMessagePageId = @"test_in_app_message_page_id";
89+
testLiveActivityId = @"test_live_activity_id";
90+
testLiveActivityToken = @"test_live_activity_token";
8791
testNotificationId = @"test_notification_id";
8892

8993
testOutcome = [[OSOutcomeEvent new] initWithSession:UNATTRIBUTED
@@ -763,6 +767,39 @@ - (void)testSendTrackUsageRequest {
763767
}));
764768
}
765769

770+
- (void)testEnterLiveActivity {
771+
let request = [OSRequestLiveActivityEnter withUserId:testUserId appId:testAppId activityId:testLiveActivityId token:testLiveActivityToken];
772+
773+
let testEnterLiveActivityUrlPath = [NSString stringWithFormat:@"apps/%@/live_activities/%@/token",
774+
testAppId,
775+
testLiveActivityId];
776+
777+
let correctUrl = correctUrlWithPath(testEnterLiveActivityUrlPath);
778+
779+
XCTAssertTrue([correctUrl isEqualToString:request.urlRequest.URL.absoluteString]);
780+
XCTAssertTrue(checkHttpBody(request.urlRequest.HTTPBody, @{@"push_token" : testLiveActivityToken, @"subscription_id" : testUserId, @"device_type" : @0 }));
781+
782+
XCTAssertEqualObjects(request.urlRequest.HTTPMethod, @"POST");
783+
XCTAssertEqualObjects(request.urlRequest.allHTTPHeaderFields[@"Accept"], @"application/vnd.onesignal.v1+json");
784+
}
785+
786+
- (void)testExitLiveActivity {
787+
let request = [OSRequestLiveActivityExit withUserId:testUserId appId:testAppId activityId:testLiveActivityId];
788+
789+
let testExitLiveActivityUrlPath = [NSString stringWithFormat:@"apps/%@/live_activities/%@/token/%@",
790+
testAppId,
791+
testLiveActivityId,
792+
testUserId];
793+
794+
let correctUrl = correctUrlWithPath(testExitLiveActivityUrlPath);
795+
796+
XCTAssertTrue([correctUrl isEqualToString:request.urlRequest.URL.absoluteString]);
797+
798+
XCTAssertEqualObjects(request.urlRequest.HTTPBody, nil);
799+
XCTAssertEqualObjects(request.urlRequest.HTTPMethod, @"DELETE");
800+
XCTAssertEqualObjects(request.urlRequest.allHTTPHeaderFields[@"Accept"], @"application/vnd.onesignal.v1+json");
801+
}
802+
766803
- (void)testAdditionalHeaders {
767804
// Create a fake request
768805
let request = [OneSignalRequest new];

0 commit comments

Comments
 (0)