Skip to content

Commit

Permalink
Merge pull request #63 from andrehtissot/ios9-support-wip
Browse files Browse the repository at this point in the history
IOS 9 support ready to be included
  • Loading branch information
andrehtissot authored Apr 26, 2020
2 parents 72cca36 + 2aa4c98 commit c73fe2d
Show file tree
Hide file tree
Showing 5 changed files with 176 additions and 27 deletions.
3 changes: 3 additions & 0 deletions plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,9 @@
<header-file src="src/ios/AppDelegate+FCMPlugin.h" />
<source-file src="src/ios/AppDelegate+FCMPlugin.m" />

<header-file src="src/ios/FCMPluginIOS9Support.h" />
<source-file src="src/ios/FCMPluginIOS9Support.m" />

<!-- FIREBASE COCOAPODS-->
<podspec>
<config>
Expand Down
9 changes: 1 addition & 8 deletions src/ios/AppDelegate+FCMPlugin.h
Original file line number Diff line number Diff line change
@@ -1,11 +1,3 @@
//
// AppDelegate+FCMPlugin.h
// TestApp
//
// Created by felipe on 12/06/16.
//
//

#import "AppDelegate.h"
#import <UIKit/UIKit.h>
#import <Cordova/CDVViewController.h>
Expand All @@ -15,6 +7,7 @@
+ (NSData*)getLastPush;
+ (NSString*)getFCMToken;
+ (NSString*)getAPNSToken;
+ (void)setLastPush:(NSData*)push;
+ (void)requestPushPermission;
+ (void)hasPushPermission:(void (^)(NSNumber* yesNoOrNil))block;

Expand Down
65 changes: 46 additions & 19 deletions src/ios/AppDelegate+FCMPlugin.m
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#import "AppDelegate+FCMPlugin.h"
#import "FCMPlugin.h"
#import "FCMPluginIOS9Support.h"
#import <objc/runtime.h>
#import <Foundation/Foundation.h>

Expand Down Expand Up @@ -39,13 +40,18 @@ - (void)configureForNotifications {
if([FIRApp defaultApp] == nil) {
[FIRApp configure];
}
// For iOS 10 display notification (sent via APNS)
[UNUserNotificationCenter currentNotificationCenter].delegate = self;
// For iOS 10 data message (sent via FCM)
if ([UNUserNotificationCenter class] != nil) {
// For iOS 10 display notification (sent via APNS)
[UNUserNotificationCenter currentNotificationCenter].delegate = self;
}
// For iOS message (sent via FCM)
[FIRMessaging messaging].delegate = self;
}

+ (void)requestPushPermission {
if ([UNUserNotificationCenter class] == nil) {
return [FCMPluginIOS9Support requestPushPermission];
}
UNAuthorizationOptions authOptions = UNAuthorizationOptionAlert | UNAuthorizationOptionSound | UNAuthorizationOptionBadge;
[[UNUserNotificationCenter currentNotificationCenter] requestAuthorizationWithOptions:authOptions completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (granted) {
Expand Down Expand Up @@ -123,28 +129,42 @@ - (void)application:(UIApplication *)application didRegisterForRemoteNotificatio
NSLog(@"Device APNS Token: %@", deviceToken);
}

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-implementations"
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
if (@available(iOS 10, *)) {
return;
}
[FCMPluginIOS9Support application:application didReceiveRemoteNotification:userInfo];
}
#pragma clang diagnostic pop

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
[[FIRMessaging messaging] appDidReceiveMessage:userInfo];

// Print message ID.
NSLog(@"Message ID: %@", userInfo[@"gcm.message_id"]);

// Pring full message.
NSLog(@"%@", userInfo);
if (@available(iOS 10, *)) {
// Print message ID.
NSLog(@"Message ID: %@", userInfo[@"gcm.message_id"]);

// If the app is in the background, keep it for later, in case it's not tapped.
if(application.applicationState == UIApplicationStateBackground) {
NSError *error;
NSDictionary *userInfoMutable = [userInfo mutableCopy];
[userInfoMutable setValue:@(NO) forKey:@"wasTapped"];
NSLog(@"app active");
lastPush = [NSJSONSerialization dataWithJSONObject:userInfoMutable options:0 error:&error];
// Pring full message.
NSLog(@"%@", userInfo);

// If the app is in the background, keep it for later, in case it's not tapped.
if(application.applicationState == UIApplicationStateBackground) {
NSError *error;
NSDictionary *userInfoMutable = [userInfo mutableCopy];
[userInfoMutable setValue:@(NO) forKey:@"wasTapped"];
NSLog(@"app active");
lastPush = [NSJSONSerialization dataWithJSONObject:userInfoMutable options:0 error:&error];
}

completionHandler(UIBackgroundFetchResultNoData);
return;
}

completionHandler(UIBackgroundFetchResultNoData);
[FCMPluginIOS9Support application:application didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
}
// [END receive_message iOS < 10]
// [END message_handling]

- (void)messaging:(nonnull FIRMessaging *)messaging didReceiveRegistrationToken:(nonnull NSString *)deviceToken {
Expand All @@ -168,8 +188,7 @@ - (void)connectToFcm {
}
// [END connect_to_fcm]

- (void)applicationDidBecomeActive:(UIApplication *)application
{
- (void)applicationDidBecomeActive:(UIApplication *)application {
NSLog(@"app become active");
[FCMPlugin.fcmPlugin appEnterForeground];
[self connectToFcm];
Expand All @@ -183,6 +202,10 @@ - (void)applicationDidEnterBackground:(UIApplication *)application {
}
// [END disconnect_from_fcm]

+ (void)setLastPush:(NSData*)push {
lastPush = push;
}

+ (NSData*)getLastPush {
NSData* returnValue = lastPush;
lastPush = nil;
Expand All @@ -198,6 +221,10 @@ + (NSString*)getAPNSToken {
}

+ (void)hasPushPermission:(void (^)(NSNumber* yesNoOrNil))block {
if ([UNUserNotificationCenter class] == nil) {
[FCMPluginIOS9Support hasPushPermission:block];
return;
}
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
[center getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings *settings){
switch (settings.authorizationStatus) {
Expand Down
10 changes: 10 additions & 0 deletions src/ios/FCMPluginIOS9Support.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
@interface FCMPluginIOS9Support : NSObject
{
}

+ (void)requestPushPermission;
+ (void)hasPushPermission:(void (^)(NSNumber* yesNoOrNil))block;
+ (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo;
+ (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler;

@end
116 changes: 116 additions & 0 deletions src/ios/FCMPluginIOS9Support.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
#import <objc/runtime.h>
#import <Foundation/Foundation.h>
#import "FCMPlugin.h"
#import "FCMPluginIOS9Support.h"
#import "AppDelegate+FCMPlugin.h"

@interface FCMPluginIOS9Support () {}
@end

@implementation FCMPluginIOS9Support

NSString *const hasRequestedPushPermissionPersistenceKey = @"FCMPlugin.iOS9.hasRequestedPushPermission";

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+ (void)requestPushPermission {
UIUserNotificationType allNotificationTypes =
(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge);
UIUserNotificationSettings *settings =
[UIUserNotificationSettings settingsForTypes:allNotificationTypes categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:settings];
dispatch_async(dispatch_get_main_queue(), ^{
[[UIApplication sharedApplication] registerForRemoteNotifications];
[self setHasRequestedPushPermissionWithTimeout:10.0f];
});
}
#pragma clang diagnostic pop

+ (void)setHasRequestedPushPermissionWithTimeout:(float) timeout {
[self hasPushPermission:^(NSNumber* pushPermission){
float tryInterval = 0.3f;
if (timeout > 0 && (pushPermission == nil || [pushPermission boolValue] == NO)) {
float remainingTimeout = timeout - tryInterval;
SEL thisMethodSelector = NSSelectorFromString(@"setHasRequestedPushPermissionWithTimeout:");
if([self respondsToSelector:thisMethodSelector]) {
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[self methodSignatureForSelector:thisMethodSelector]];
[invocation setSelector:thisMethodSelector];
[invocation setTarget:self];
[invocation setArgument:&(remainingTimeout) atIndex:2]; //arguments 0 and 1 are self and _cmd respectively, automatically set by NSInvocationion
[NSTimer scheduledTimerWithTimeInterval:tryInterval invocation:invocation repeats:NO];
return;
}
}
[[NSUserDefaults standardUserDefaults]
setObject:[NSNumber numberWithBool:YES] forKey:hasRequestedPushPermissionPersistenceKey];
[[NSUserDefaults standardUserDefaults] synchronize];
}];
}

+ (BOOL)getHasRequestedPushPermission {
if ([[NSUserDefaults standardUserDefaults] objectForKey:hasRequestedPushPermissionPersistenceKey]) {
bool hasRequestedPushPermission = [[[NSUserDefaults standardUserDefaults]
objectForKey:hasRequestedPushPermissionPersistenceKey] boolValue];
return hasRequestedPushPermission;
}
return NO;
}

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+ (void)hasPushPermission:(void (^)(NSNumber* yesNoOrNil))block {
NSString* apnsToken = [AppDelegate getAPNSToken];
if(apnsToken != nil) {
block([NSNumber numberWithBool:YES]);
return;
}
if ([[UIApplication sharedApplication] isRegisteredForRemoteNotifications]) {
block([NSNumber numberWithBool:YES]);
return;
}
UIUserNotificationSettings *notificationSettings = [[UIApplication sharedApplication] currentUserNotificationSettings];
BOOL itDoesHaveNotificationSettings = ((int) notificationSettings.types) != 0;
if(itDoesHaveNotificationSettings) {
block([NSNumber numberWithBool:YES]);
}
BOOL alreadyRequested = [self getHasRequestedPushPermission];
block(alreadyRequested ? [NSNumber numberWithBool:NO] : nil);
}
#pragma clang diagnostic pop

+ (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
NSLog(@"Message ID: %@", userInfo[@"gcm.message_id"]);
NSError *error;
NSDictionary *userInfoMutable = [userInfo mutableCopy];
if (application.applicationState != UIApplicationStateActive) {
NSLog(@"New method with push callback: %@", userInfo);
[userInfoMutable setValue:@(YES) forKey:@"wasTapped"];
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:userInfoMutable options:0 error:&error];
NSLog(@"APP WAS CLOSED DURING PUSH RECEPTION Saved data: %@", jsonData);
[AppDelegate setLastPush:jsonData];
}
}

+ (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
NSLog(@"Message ID: %@", userInfo[@"gcm.message_id"]);
NSLog(@"%@", userInfo);
NSError *error;
NSDictionary *userInfoMutable = [userInfo mutableCopy];

// Has user tapped the notificaiton?
// UIApplicationStateActive - app is currently active
// UIApplicationStateInactive - app is transitioning from background to
// foreground (user taps notification)
if (application.applicationState == UIApplicationStateActive
|| application.applicationState == UIApplicationStateInactive) {
[userInfoMutable setValue:@(NO) forKey:@"wasTapped"];
NSLog(@"app active");
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:userInfoMutable
options:0
error:&error];
[FCMPlugin.fcmPlugin notifyOfMessage:jsonData];
}
completionHandler(UIBackgroundFetchResultNoData);
}

@end

0 comments on commit c73fe2d

Please sign in to comment.