You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by sh...@apache.org on 2015/03/18 00:51:43 UTC
cordova-plugins git commit: CB-8475 - Create plugin to handle
local/remote push notification delegates in the app delegate
Repository: cordova-plugins
Updated Branches:
refs/heads/master 60de2dbd5 -> 976fe8185
CB-8475 - Create plugin to handle local/remote push notification delegates in the app delegate
Project: http://git-wip-us.apache.org/repos/asf/cordova-plugins/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-plugins/commit/976fe818
Tree: http://git-wip-us.apache.org/repos/asf/cordova-plugins/tree/976fe818
Diff: http://git-wip-us.apache.org/repos/asf/cordova-plugins/diff/976fe818
Branch: refs/heads/master
Commit: 976fe818556eca390dc433b098ac3bdb38cb1a40
Parents: 60de2db
Author: Shazron Abdullah <sh...@apache.org>
Authored: Tue Mar 17 16:51:42 2015 -0700
Committer: Shazron Abdullah <sh...@apache.org>
Committed: Tue Mar 17 16:51:42 2015 -0700
----------------------------------------------------------------------
notification-rebroadcast/README.md | 39 +++-
.../src/ios/CDVNotificationRebroadcast.h | 6 +-
.../src/ios/CDVNotificationRebroadcast.m | 184 ++++++++++++++++---
3 files changed, 202 insertions(+), 27 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cordova-plugins/blob/976fe818/notification-rebroadcast/README.md
----------------------------------------------------------------------
diff --git a/notification-rebroadcast/README.md b/notification-rebroadcast/README.md
index 7d94246..51f6a19 100644
--- a/notification-rebroadcast/README.md
+++ b/notification-rebroadcast/README.md
@@ -3,9 +3,44 @@ Cordova Notification Rebroadcast Plugin
See [CB-8475](https://issues.apache.org/jira/browse/CB-8475). This plugin rebroadcasts remote push notifications as well as local notifications to other plugins.
-Install:
+This plugin currently needs to use the `4.0.x` branch of `cordova-ios`.
- cordova plugin add https://github.com/apache/cordova-plugins.git#master:notification-rebroadcast
+To `alpha test` this:
+
+You may have to remove the cached 4.0.x platform:
+
+ rm -rf ~/.cordova/lib/ios/cordova/4.0.x
+
+Then:
+
+ cordova create nrtest my.project.id nrtest
+ cd nrtest
+ cordova platform add ios@4.0.x --usegit
+ cordova plugin add https://github.com/apache/cordova-plugins.git#master:notification-rebroadcast
+
+Document Events
+-----------
+
+Listen for these 3 types of document events in JavaScript:
+
+1. CDVLocalNotification
+
+ data is a JSON object of the UILocalNotification details
+
+2. CDVRemoteNotification
+
+ data is a JSON object containing one key, "token" which is the push device token
+
+3. CDVRemoteNotificationError
+
+ data is a JSON object containing one key, "error", which is the localized error message
+
+Usage
+=====
+
+ document.addEventListener('CDVLocalNotification', function(event) { console.log(event.data); });
+ document.addEventListener('CDVRemoteNotification', function(event) { console.log(event.data.token); });
+ document.addEventListener('CDVRemoteNotificationError', function(event) { console.log(event.data.error); });
Permissions
-----------
http://git-wip-us.apache.org/repos/asf/cordova-plugins/blob/976fe818/notification-rebroadcast/src/ios/CDVNotificationRebroadcast.h
----------------------------------------------------------------------
diff --git a/notification-rebroadcast/src/ios/CDVNotificationRebroadcast.h b/notification-rebroadcast/src/ios/CDVNotificationRebroadcast.h
index 2cc27be..9fe278d 100644
--- a/notification-rebroadcast/src/ios/CDVNotificationRebroadcast.h
+++ b/notification-rebroadcast/src/ios/CDVNotificationRebroadcast.h
@@ -21,11 +21,11 @@
@interface CDVAppDelegate (SwizzledMethods)
-- (void) customApplication:(UIApplication*)application didReceiveLocalNotification:(UILocalNotification*)notification;
+- (void) cdv_notification_rebroadcastApplication:(UIApplication*)application didReceiveLocalNotification:(UILocalNotification*)notification;
-- (void) customApplication:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken;
+- (void) cdv_notification_rebroadcastApplication:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken;
-- (void) customApplication:(UIApplication*)application didFailToRegisterForRemoteNotificationsWithError:(NSError*)error;
+- (void) cdv_notification_rebroadcastApplication:(UIApplication*)application didFailToRegisterForRemoteNotificationsWithError:(NSError*)error;
@end
http://git-wip-us.apache.org/repos/asf/cordova-plugins/blob/976fe818/notification-rebroadcast/src/ios/CDVNotificationRebroadcast.m
----------------------------------------------------------------------
diff --git a/notification-rebroadcast/src/ios/CDVNotificationRebroadcast.m b/notification-rebroadcast/src/ios/CDVNotificationRebroadcast.m
index f064151..b8aae30 100644
--- a/notification-rebroadcast/src/ios/CDVNotificationRebroadcast.m
+++ b/notification-rebroadcast/src/ios/CDVNotificationRebroadcast.m
@@ -20,35 +20,105 @@
#import "CDVNotificationRebroadcast.h"
#import <objc/runtime.h>
-@implementation CDVAppDelegate (SwizzledMethods)
+#pragma mark Global Methods
-+ (void)load
+// Return a NSArray<Class> containing all subclasses of a Class
+NSArray* ClassGetSubclasses(Class parentClass)
+{
+ int numClasses = objc_getClassList(nil, 0);
+ Class* classes = nil;
+
+ classes = (Class*)malloc(sizeof(Class) * numClasses);
+ numClasses = objc_getClassList(classes, numClasses);
+
+ NSMutableArray* result = [NSMutableArray array];
+ for (NSInteger i = 0; i < numClasses; i++) {
+
+ Class superClass = classes[i];
+ do {
+ superClass = class_getSuperclass(superClass);
+ }
+ while(superClass && superClass != parentClass);
+
+ if (superClass == nil) {
+ continue;
+ }
+
+ [result addObject:classes[i]];
+ }
+
+ free(classes);
+
+ return result;
+}
+
+// Replace or Exchange method implementations
+// Return YES if method was exchanged, NO if replaced
+BOOL MethodSwizzle(Class clazz, SEL originalSelector, SEL overrideSelector)
{
- Method original, custom;
+ Method originalMethod = class_getInstanceMethod(clazz, originalSelector);
+ Method overrideMethod = class_getInstanceMethod(clazz, overrideSelector);
- original = class_getInstanceMethod(self, @selector(application:didReceiveLocalNotification:));
- custom = class_getInstanceMethod(self, @selector(customApplication:didReceiveLocalNotification:));
- method_exchangeImplementations(original, custom);
+ // try to add, if it does not exist, replace
+ if (class_addMethod(clazz, originalSelector, method_getImplementation(overrideMethod), method_getTypeEncoding(overrideMethod))) {
+ class_replaceMethod(clazz, overrideSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
+ }
+ // add failed, so we exchange
+ else {
+ method_exchangeImplementations(originalMethod, overrideMethod);
+ return YES;
+ }
- original = class_getInstanceMethod(self, @selector(application:didRegisterForRemoteNotificationsWithDeviceToken:));
- custom = class_getInstanceMethod(self, @selector(customApplication:didRegisterForRemoteNotificationsWithDeviceToken:));
- method_exchangeImplementations(original, custom);
+ return NO;
+}
- original = class_getInstanceMethod(self, @selector(application:didFailToRegisterForRemoteNotificationsWithError:));
- custom = class_getInstanceMethod(self, @selector(customApplication:didFailToRegisterForRemoteNotificationsWithError:));
- method_exchangeImplementations(original, custom);
+// Helper to return the Class to swizzle
+// We need to swizzle the subclass (if available) of CDVAppDelegate
+Class ClassToSwizzle() {
+ Class clazz = [CDVAppDelegate class];
+
+ NSArray* subClazz = ClassGetSubclasses(clazz);
+ if ([subClazz count] > 0) {
+ clazz = [subClazz objectAtIndex:0];
+ }
+
+ return clazz;
}
-- (void) customApplication:(UIApplication*)application didReceiveLocalNotification:(UILocalNotification*)notification
+#pragma mark Global Variables
+
+static BOOL cdvLocalNotifSelExchanged = NO;
+static BOOL cdvRemoteNotifSelExchanged = NO;
+static BOOL cdvRemoteNotifErrorSelExchanged = NO;
+
+#pragma mark CDVAppDelegate (SwizzledMethods)
+
+@implementation CDVAppDelegate (SwizzledMethods)
+
++ (void)load
+{
+ static dispatch_once_t onceToken;
+ dispatch_once(&onceToken, ^{
+ Class clazz = ClassToSwizzle();
+
+ cdvLocalNotifSelExchanged = MethodSwizzle(clazz, @selector(application:didReceiveLocalNotification:), @selector(cdv_notification_rebroadcastApplication:didReceiveLocalNotification:));
+ cdvRemoteNotifSelExchanged = MethodSwizzle(clazz, @selector(application:didRegisterForRemoteNotificationsWithDeviceToken:), @selector(cdv_notification_rebroadcastApplication:didRegisterForRemoteNotificationsWithDeviceToken:));
+ cdvRemoteNotifErrorSelExchanged = MethodSwizzle(clazz, @selector(application:didFailToRegisterForRemoteNotificationsWithError:), @selector(cdv_notification_rebroadcastApplication:didFailToRegisterForRemoteNotificationsWithError:));
+ });
+}
+
+- (void) cdv_notification_rebroadcastApplication:(UIApplication*)application didReceiveLocalNotification:(UILocalNotification*)notification
{
// re-post ( broadcast )
[[NSNotificationCenter defaultCenter] postNotificationName:CDVLocalNotification object:notification];
- // no, not recursion. we swapped implementations, remember. calling original implementation
- [self customApplication:application didReceiveLocalNotification:notification];
+ // if method was exchanged through method_exchangeImplementations, we call ourselves (no, it's not a recursion)
+ if (cdvLocalNotifSelExchanged) {
+ [self cdv_notification_rebroadcastApplication:application didReceiveLocalNotification:notification];
+ }
}
-- (void) customApplication:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken;
+- (void) cdv_notification_rebroadcastApplication:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken;
{
// re-post ( broadcast )
NSString* token = [[[[deviceToken description]
@@ -58,28 +128,98 @@
[[NSNotificationCenter defaultCenter] postNotificationName:CDVRemoteNotification object:token];
- // no, not recursion. we swapped implementations, remember. calling original implementation
- [self customApplication:application didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
+ // if method was exchanged through method_exchangeImplementations, we call ourselves (no, it's not a recursion)
+ if (cdvRemoteNotifSelExchanged) {
+ [self cdv_notification_rebroadcastApplication:application didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
+ }
}
-- (void) customApplication:(UIApplication*)application didFailToRegisterForRemoteNotificationsWithError:(NSError*)error;
+- (void) cdv_notification_rebroadcastApplication:(UIApplication*)application didFailToRegisterForRemoteNotificationsWithError:(NSError*)error;
{
// re-post ( broadcast )
[[NSNotificationCenter defaultCenter] postNotificationName:CDVRemoteNotificationError object:error];
- // no, not recursion. we swapped implementations, remember. calling original implementation
- [self customApplication:application didFailToRegisterForRemoteNotificationsWithError:error];
+ // if method was exchanged through method_exchangeImplementations, we call ourselves (no, it's not a recursion)
+ if (cdvRemoteNotifErrorSelExchanged) {
+ [self cdv_notification_rebroadcastApplication:application didFailToRegisterForRemoteNotificationsWithError:error];
+ }
}
+@end
+
+#pragma mark UILocalNotification (JSONString)
+
+@implementation UILocalNotification (JSONString)
+
+- (NSString*) cdv_notification_rebroadcastJSONString
+{
+ NSMutableDictionary* dict = [NSMutableDictionary dictionary];
+
+ if ([self alertAction]) {
+ [dict setValue:[self alertAction] forKey:@"alertAction"];
+ }
+ if ([self alertBody]) {
+ [dict setValue:[self alertBody] forKey:@"alertBody"];
+ }
+ if ([self alertLaunchImage]) {
+ [dict setValue:[self alertLaunchImage] forKey:@"alertLaunchImage"];
+ }
+ if ([self alertTitle]) {
+ [dict setValue:[self alertTitle] forKey:@"alertTitle"];
+ }
+ if ([self userInfo]) {
+ [dict setValue:[self userInfo] forKey:@"userInfo"];
+ }
+
+ NSError* error = nil;
+ NSData* jsonData = [NSJSONSerialization dataWithJSONObject:dict options:0 error:&error];
+ NSString* val = nil;
+
+ if (error == nil) {
+ val = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
+ }
+
+ return val;
+}
@end
+#pragma mark CDVNotificationRebroadcast Plugin
+
@implementation CDVNotificationRebroadcast : CDVPlugin
- (void)pluginInitialize
{
- // TODO: listen to the notifications, and send to JavaScript as events?
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onLocalNotification:) name:CDVLocalNotification object:nil];
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onRemoteNotification:) name:CDVRemoteNotification object:nil];
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onRemoteNotificationError:) name:CDVRemoteNotificationError object:nil];
+}
+
+ - (void)onLocalNotification:(NSNotification*)notification
+{
+ UILocalNotification* localNotification = notification.object;
+ NSString* jsString = [NSString stringWithFormat:@"cordova.fireDocumentEvent('CDVLocalNotification', %@);", [localNotification cdv_notification_rebroadcastJSONString]];
+
+ [self.commandDelegate evalJs:jsString];
+}
+
+- (void)onRemoteNotification:(NSNotification*)notification
+{
+ NSString* token = notification.object;
+ NSString* jsString = [NSString stringWithFormat:@"cordova.fireDocumentEvent('CDVRemoteNotification', { 'token': '%@'});", token];
+
+ [self.commandDelegate evalJs:jsString];
}
+- (void)onRemoteNotificationError:(NSNotification*)notification
+{
+ NSError* error = notification.object;
+ NSString* desc = [error localizedDescription];
+ NSString* jsString = [NSString stringWithFormat:@"cordova.fireDocumentEvent('CDVRemoteNotificationError', { 'error': '%@'});", desc];
+
+ [self.commandDelegate evalJs:jsString];
+}
+
+
@end
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org