Skip to content

Commit

Permalink
Support send push notification by topic
Browse files Browse the repository at this point in the history
  • Loading branch information
cheungpat committed Jan 6, 2017
2 parents 0ba6d91 + 22698d1 commit e417977
Show file tree
Hide file tree
Showing 9 changed files with 162 additions and 38 deletions.
10 changes: 5 additions & 5 deletions Example/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@ PODS:
- OHHTTPStubs/NSURLSession (4.6.0):
- OHHTTPStubs/Core
- OHHTTPStubs/OHPathHelpers (4.6.0)
- SKYKit (0.19.0):
- SKYKit/Core (= 0.19.0)
- SKYKit/Core (0.19.0):
- SKYKit (0.20.0):
- SKYKit/Core (= 0.20.0)
- SKYKit/Core (0.20.0):
- FMDB (~> 2.5)
- SocketRocket (~> 0.4)
- SKYKit/Facebook (0.19.0):
- SKYKit/Facebook (0.20.0):
- FBSDKCoreKit (~> 4.0)
- SKYKit/Core
- SocketRocket (0.5.1)
Expand All @@ -55,7 +55,7 @@ SPEC CHECKSUMS:
FMDB: 854a0341b4726e53276f2a8996f06f1b80f9259a
OCMock: 28def049ef47f996b515a8eeea958be7ccab2dbb
OHHTTPStubs: cb1aefbbeb4de4e741644455d4b945538e5248a2
SKYKit: 14d7ffed0350e0ca95aa60c76f2aaa5d7bbb24d2
SKYKit: 0639950ad14f99cdfe5a4013de4ae69993d83aa8
SocketRocket: d57c7159b83c3c6655745cd15302aa24b6bae531
Specta: ac94d110b865115fe60ff2c6d7281053c6f8e8a2

Expand Down
48 changes: 34 additions & 14 deletions Example/Swift Example/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,28 +36,48 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
if let apiKeyValue = apiKey {
SKYContainer.defaultContainer().configureWithAPIKey(apiKeyValue)
}

application.registerUserNotificationSettings(UIUserNotificationSettings(
forTypes: [.Alert, .Badge, .Sound],
categories: nil
))

return true
}

func applicationWillResignActive(application: UIApplication) {
// 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.
// 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.
}
func application(application: UIApplication, didRegisterUserNotificationSettings notificationSettings: UIUserNotificationSettings) {
guard !notificationSettings.types.isEmpty else {
print("User does not allow notification")
return
}

func applicationDidEnterBackground(application: UIApplication) {
// 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.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
application.registerForRemoteNotifications()
}

func applicationWillEnterForeground(application: UIApplication) {
// 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.
}
func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
print("Successfully registered remote notification")

func applicationDidBecomeActive(application: UIApplication) {
// 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.
let skygear = SKYContainer.defaultContainer()
guard skygear.currentUser != nil else {
print("User not yet login, abort registering device")
return
}

skygear.registerRemoteNotificationDeviceToken(deviceToken) { (deviceID, error) in
guard error == nil else {
print("Failed to register device: \(error.localizedDescription)")
return
}

if let id = deviceID {
print("Successfully registered device with ID: \(id)")
} else {
print("Warning: Got nil device ID")
}
}
}

func applicationWillTerminate(application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
func application(application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: NSError) {
print("Failed to register remote notification: \(error.localizedDescription)")
}
}
20 changes: 14 additions & 6 deletions Example/Tests/SKYRegisterDeviceOperationTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@

it(@"new device request", ^{
SKYRegisterDeviceOperation *operation = [SKYRegisterDeviceOperation
operationWithDeviceToken:[SKYHexer dataWithHexString:@"abcdef1234567890"]];
operationWithDeviceToken:[SKYHexer dataWithHexString:@"abcdef1234567890"]
topic:@"com.example.app"];
operation.container = container;
[operation prepareForRequest];

Expand All @@ -47,11 +48,12 @@
expect(request.payload[@"type"]).to.equal(@"ios");
expect(request.payload[@"device_token"]).to.equal(@"abcdef1234567890");
expect(request.payload[@"id"]).to.beNil();
expect(request.payload[@"topic"]).to.equal(@"com.example.app");
});

it(@"new device request without device token", ^{
SKYRegisterDeviceOperation *operation =
[SKYRegisterDeviceOperation operationWithDeviceToken:nil];
[SKYRegisterDeviceOperation operationWithDeviceToken:nil topic:@"com.example.app"];
operation.container = container;
[operation prepareForRequest];

Expand All @@ -62,11 +64,13 @@
expect(request.payload[@"type"]).to.equal(@"ios");
expect(request.payload[@"device_token"]).to.beNil();
expect(request.payload[@"id"]).to.beNil();
expect(request.payload[@"topic"]).to.equal(@"com.example.app");
});

it(@"update device request", ^{
SKYRegisterDeviceOperation *operation = [SKYRegisterDeviceOperation
operationWithDeviceToken:[SKYHexer dataWithHexString:@"abcdef1234567890"]];
operationWithDeviceToken:[SKYHexer dataWithHexString:@"abcdef1234567890"]
topic:@"com.example.app"];
operation.deviceID = @"DEVICE_ID";
operation.container = container;
[operation prepareForRequest];
Expand All @@ -78,11 +82,13 @@
expect(request.payload[@"type"]).to.equal(@"ios");
expect(request.payload[@"device_token"]).to.equal(@"abcdef1234567890");
expect(request.payload[@"id"]).to.equal(@"DEVICE_ID");
expect(request.payload[@"topic"]).to.equal(@"com.example.app");
});

it(@"new device response", ^{
SKYRegisterDeviceOperation *operation = [SKYRegisterDeviceOperation
operationWithDeviceToken:[SKYHexer dataWithHexString:@"abcdef1234567890"]];
operationWithDeviceToken:[SKYHexer dataWithHexString:@"abcdef1234567890"]
topic:@"com.example.app"];

[OHHTTPStubs stubRequestsPassingTest:^BOOL(NSURLRequest *request) {
return YES;
Expand Down Expand Up @@ -113,7 +119,8 @@

it(@"error with response without id", ^{
SKYRegisterDeviceOperation *operation = [SKYRegisterDeviceOperation
operationWithDeviceToken:[SKYHexer dataWithHexString:@"abcdef1234567890"]];
operationWithDeviceToken:[SKYHexer dataWithHexString:@"abcdef1234567890"]
topic:@"com.example.app"];

[OHHTTPStubs stubRequestsPassingTest:^BOOL(NSURLRequest *request) {
return YES;
Expand Down Expand Up @@ -142,7 +149,8 @@

it(@"pass error", ^{
SKYRegisterDeviceOperation *operation = [SKYRegisterDeviceOperation
operationWithDeviceToken:[SKYHexer dataWithHexString:@"abcdef1234567890"]];
operationWithDeviceToken:[SKYHexer dataWithHexString:@"abcdef1234567890"]
topic:@"com.example.app"];
[OHHTTPStubs stubRequestsPassingTest:^BOOL(NSURLRequest *request) {
return YES;
}
Expand Down
19 changes: 19 additions & 0 deletions Example/Tests/SKYSendPushNotificationOperationTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,25 @@
});
});

it(@"topic", ^{
SKYSendPushNotificationOperation *operation = [SKYSendPushNotificationOperation
operationWithNotificationInfo:notificationInfo
userIDsToSend:@[ @"johndoe" ]
topic:@"io.skygear.example"];
operation.container = container;
[operation prepareForRequest];

SKYRequest *request = operation.request;
expect([request class]).to.beSubclassOf([SKYRequest class]);
expect(request.APIKey).to.equal(container.APIKey);
expect(request.action).to.equal(@"push:user");
expect(request.payload).to.equal(@{
@"user_ids" : @[ @"johndoe" ],
@"notification" : expectedNotificationPayload,
@"topic" : @"io.skygear.example"
});
});

it(@"make request", ^{
SKYSendPushNotificationOperation *operation = [SKYSendPushNotificationOperation
operationWithNotificationInfo:notificationInfo
Expand Down
9 changes: 7 additions & 2 deletions Pod/Classes/Operations/SKYRegisterDeviceOperation.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@

@interface SKYRegisterDeviceOperation : SKYOperation

- (instancetype)initWithDeviceToken:(NSData *)deviceToken;
- (instancetype)initWithDeviceToken:(NSData *)deviceToken
__attribute__((deprecated("Use -initWithDeviceToken:topic: instead")));
- (instancetype)initWithDeviceToken:(NSData *)deviceToken topic:(NSString *)topic;

/**
Returns an instance of operation that registers a device without supplying a device token.
Expand All @@ -32,9 +34,12 @@
instead of remote notification.
*/
+ (instancetype)operation;
+ (instancetype)operationWithDeviceToken:(NSData *)deviceToken;
+ (instancetype)operationWithDeviceToken:(NSData *)deviceToken
__attribute__((deprecated("Use +operationWithDeviceToken:topic: instead")));
+ (instancetype)operationWithDeviceToken:(NSData *)topic topic:(NSString *)topic;

@property (nonatomic, readonly, copy) NSData *deviceToken;
@property (nonatomic, readonly, copy) NSString *topic;
@property (nonatomic, readwrite, copy) NSString *deviceID;
@property (nonatomic, copy) void (^registerCompletionBlock)(NSString *deviceID, NSError *error);

Expand Down
18 changes: 17 additions & 1 deletion Pod/Classes/Operations/SKYRegisterDeviceOperation.m
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,22 @@ @interface SKYRegisterDeviceOperation ()

@implementation SKYRegisterDeviceOperation

- (instancetype)initWithDeviceToken:(NSData *)deviceToken
- (instancetype)initWithDeviceToken:(NSData *)deviceToken topic:(NSString *)topic
{
self = [super init];
if (self) {
_deviceToken = [deviceToken copy];
_topic = [topic copy];
_deviceID = nil;
}
return self;
}

- (instancetype)initWithDeviceToken:(NSData *)deviceToken
{
return [self initWithDeviceToken:deviceToken topic:nil];
}

+ (instancetype)operation
{
return [[self alloc] initWithDeviceToken:nil];
Expand All @@ -49,6 +55,11 @@ + (instancetype)operationWithDeviceToken:(NSData *)deviceToken
return [[self alloc] initWithDeviceToken:deviceToken];
}

+ (instancetype)operationWithDeviceToken:(NSData *)deviceToken topic:(NSString *)topic
{
return [[self alloc] initWithDeviceToken:deviceToken topic:topic];
}

- (NSString *)hexDeviceToken
{
if (!self.deviceToken) {
Expand Down Expand Up @@ -80,6 +91,11 @@ - (void)prepareForRequest
payload[@"device_token"] = deviceToken;
}

NSString *topic = self.topic;
if (topic.length) {
payload[@"topic"] = topic;
}

NSString *deviceID = self.deviceID;
if (deviceID.length) {
payload[@"id"] = deviceID;
Expand Down
22 changes: 19 additions & 3 deletions Pod/Classes/Operations/SKYSendPushNotificationOperation.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,33 @@ typedef enum : NSUInteger {

@interface SKYSendPushNotificationOperation : SKYOperation

- (instancetype)initWithNotificationInfo:(SKYNotificationInfo *)noteInfo
- (instancetype)initWithNotificationInfo:(SKYNotificationInfo *)notificationInfo
pushTarget:(SKYPushTarget)pushTarget
IDsToSend:(NSArray *)IDsToSend;
+ (instancetype)operationWithNotificationInfo:(SKYNotificationInfo *)noteInfo

- (instancetype)initWithNotificationInfo:(SKYNotificationInfo *)notificationInfo
pushTarget:(SKYPushTarget)pushTarget
IDsToSend:(NSArray *)IDsToSend
topic:(NSString *)topic;

+ (instancetype)operationWithNotificationInfo:(SKYNotificationInfo *)notificationInfo
userIDsToSend:(NSArray *)userIDsToSend;
+ (instancetype)operationWithNotificationInfo:(SKYNotificationInfo *)noteInfo

+ (instancetype)operationWithNotificationInfo:(SKYNotificationInfo *)notificationInfo
userIDsToSend:(NSArray *)userIDsToSend
topic:(NSString *)topic;

+ (instancetype)operationWithNotificationInfo:(SKYNotificationInfo *)notificationInfo
deviceIDsToSend:(NSArray *)deviceIDsToSend;

+ (instancetype)operationWithNotificationInfo:(SKYNotificationInfo *)notificationInfo
deviceIDsToSend:(NSArray *)deviceIDsToSend
topic:(NSString *)topic;

@property (nonatomic, readwrite, copy) SKYNotificationInfo *notificationInfo;
@property (nonatomic, readwrite) SKYPushTarget pushTarget;
@property (nonatomic, readwrite, copy) NSArray *IDsToSend;
@property (nonatomic, readwrite, copy) NSString *topic;
@property (nonatomic, copy) void (^perSendCompletionHandler)(NSString *userID, NSError *error);
@property (nonatomic, copy) void (^sendCompletionHandler)(NSArray *userIDs, NSError *error);

Expand Down
51 changes: 45 additions & 6 deletions Pod/Classes/Operations/SKYSendPushNotificationOperation.m
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,23 @@ @implementation SKYSendPushNotificationOperation
- (instancetype)initWithNotificationInfo:(SKYNotificationInfo *)notificationInfo
pushTarget:(SKYPushTarget)pushTarget
IDsToSend:(NSArray *)IDsToSend
{
return [self initWithNotificationInfo:notificationInfo
pushTarget:pushTarget
IDsToSend:IDsToSend
topic:nil];
}

- (instancetype)initWithNotificationInfo:(SKYNotificationInfo *)notificationInfo
pushTarget:(SKYPushTarget)pushTarget
IDsToSend:(NSArray *)IDsToSend
topic:(NSString *)topic
{
self = [super init];
if (self) {
_notificationInfo = [notificationInfo copy];
_IDsToSend = [IDsToSend copy];
_topic = [topic copy];
_pushTarget = pushTarget;

[_IDsToSend enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
Expand All @@ -52,20 +64,42 @@ - (instancetype)initWithNotificationInfo:(SKYNotificationInfo *)notificationInfo
return self;
}

+ (instancetype)operationWithNotificationInfo:(SKYNotificationInfo *)noteInfo
+ (instancetype)operationWithNotificationInfo:(SKYNotificationInfo *)notificationInfo
userIDsToSend:(NSArray *)userIDsToSend
{
return [[self alloc] initWithNotificationInfo:noteInfo
return [[self alloc] initWithNotificationInfo:notificationInfo
pushTarget:SKYPushTargetIsUser
IDsToSend:userIDsToSend];
IDsToSend:userIDsToSend
topic:nil];
}

+ (instancetype)operationWithNotificationInfo:(SKYNotificationInfo *)noteInfo
+ (instancetype)operationWithNotificationInfo:(SKYNotificationInfo *)notificationInfo
userIDsToSend:(NSArray *)userIDsToSend
topic:(NSString *)topic
{
return [[self alloc] initWithNotificationInfo:notificationInfo
pushTarget:SKYPushTargetIsUser
IDsToSend:userIDsToSend
topic:topic];
}

+ (instancetype)operationWithNotificationInfo:(SKYNotificationInfo *)notificationInfo
deviceIDsToSend:(NSArray *)deviceIDsToSend
{
return [[self alloc] initWithNotificationInfo:noteInfo
return [[self alloc] initWithNotificationInfo:notificationInfo
pushTarget:SKYPushTargetIsDevice
IDsToSend:deviceIDsToSend];
IDsToSend:deviceIDsToSend
topic:nil];
}

+ (instancetype)operationWithNotificationInfo:(SKYNotificationInfo *)notificationInfo
deviceIDsToSend:(NSArray *)deviceIDsToSend
topic:(NSString *)topic
{
return [[self alloc] initWithNotificationInfo:notificationInfo
pushTarget:SKYPushTargetIsDevice
IDsToSend:deviceIDsToSend
topic:topic];
}

+ (Class)responseClass
Expand Down Expand Up @@ -105,6 +139,11 @@ - (void)prepareForRequest
userInfo:nil];
}
}

if (self.topic.length) {
[payload setObject:self.topic forKey:@"topic"];
}

self.request = [[SKYRequest alloc] initWithAction:action payload:payload];
self.request.APIKey = self.container.APIKey;
}
Expand Down
3 changes: 2 additions & 1 deletion Pod/Classes/SKYContainer.m
Original file line number Diff line number Diff line change
Expand Up @@ -593,8 +593,9 @@ - (void)registerRemoteNotificationDeviceToken:(NSData *)deviceToken
existingDeviceID:(NSString *)existingDeviceID
completionHandler:(void (^)(NSString *, NSError *))completionHandler
{
NSString *topic = [[NSBundle mainBundle] bundleIdentifier];
SKYRegisterDeviceOperation *op =
[[SKYRegisterDeviceOperation alloc] initWithDeviceToken:deviceToken];
[[SKYRegisterDeviceOperation alloc] initWithDeviceToken:deviceToken topic:topic];
op.deviceID = existingDeviceID;
op.registerCompletionBlock = ^(NSString *deviceID, NSError *error) {
BOOL willRetry = NO;
Expand Down

0 comments on commit e417977

Please sign in to comment.