Skip to content

Commit

Permalink
Merge pull request #211 from urbanairship/MB-2531
Browse files Browse the repository at this point in the history
[MB-2531] Add response info to notification event
  • Loading branch information
rlepinski authored Feb 1, 2018
2 parents 176d728 + b996b85 commit a7bbcc4
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 58 deletions.
4 changes: 2 additions & 2 deletions plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
</feature>
</config-file>

<config-file parent="/*" target="AndroidManifest.xml">
<config-file parent="/manifest/application" target="AndroidManifest.xml">
<meta-data
android:name="com.urbanairship.autopilot"
android:value="com.urbanairship.cordova.CordovaAutopilot"/>
Expand Down Expand Up @@ -123,7 +123,7 @@
src="src/android/UAirshipPluginManager.java"
target-dir="src/com/urbanairship/cordova"/>
<source-file
src="src/android/events/ChannelEvent.java"
src="src/android/events/RegistrationEvent.java"
target-dir="src/com/urbanairship/cordova/events"/>
<source-file
src="src/android/events/DeepLinkEvent.java"
Expand Down
4 changes: 2 additions & 2 deletions src/android/CordovaAirshipReceiver.java
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ protected void onNotificationPosted(@NonNull Context context, @NonNull Notificat
protected boolean onNotificationOpened(@NonNull Context context, @NonNull NotificationInfo notificationInfo) {
Log.i(TAG, "Notification opened. Alert: " + notificationInfo.getMessage().getAlert() + ". NotificationId: " + notificationInfo.getNotificationId());

UAirshipPluginManager.shared().notificationOpened(notificationInfo.getNotificationId(), notificationInfo.getMessage());
UAirshipPluginManager.shared().notificationOpened(notificationInfo);

// Return false here to allow Urban Airship to auto launch the launcher activity
return false;
Expand All @@ -91,7 +91,7 @@ protected boolean onNotificationOpened(@NonNull Context context, @NonNull Notifi
protected boolean onNotificationOpened(@NonNull Context context, @NonNull NotificationInfo notificationInfo, @NonNull ActionButtonInfo actionButtonInfo) {
Log.i(TAG, "Notification action button opened. Button ID: " + actionButtonInfo.getButtonId() + ". NotificationId: " + notificationInfo.getNotificationId());

UAirshipPluginManager.shared().notificationOpened(notificationInfo.getNotificationId(), notificationInfo.getMessage());
UAirshipPluginManager.shared().notificationOpened(notificationInfo, actionButtonInfo);

// Return false here to allow Urban Airship to auto launch the launcher
// activity for foreground notification action buttons
Expand Down
22 changes: 18 additions & 4 deletions src/android/UAirshipPluginManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE

import android.content.Context;
import android.content.SharedPreferences;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;

import com.urbanairship.AirshipReceiver;
import com.urbanairship.UAirship;
import com.urbanairship.cordova.events.RegistrationEvent;
import com.urbanairship.cordova.events.DeepLinkEvent;
Expand Down Expand Up @@ -140,12 +143,23 @@ void checkOptInStatus(Context context) {
/**
* Called when the notification is opened.
*
* @param notificationId The notification ID.
* @param pushMessage The push message.
* @param notificationInfo The notification info.
*/
void notificationOpened(@NonNull AirshipReceiver.NotificationInfo notificationInfo) {
notificationOpened(new NotificationOpenedEvent(notificationInfo));
}

/**
* Called when the notification is opened.
*
* @param notificationInfo The notification info.
*/
void notificationOpened(int notificationId, PushMessage pushMessage) {
void notificationOpened(@NonNull AirshipReceiver.NotificationInfo notificationInfo, @Nullable AirshipReceiver.ActionButtonInfo actionButtonInfo) {
notificationOpened(new NotificationOpenedEvent(notificationInfo, actionButtonInfo));
}

private void notificationOpened(NotificationOpenedEvent event) {
synchronized (shared) {
NotificationOpenedEvent event = new NotificationOpenedEvent(notificationId, pushMessage);
this.notificationOpenedEvent = event;

if (!notifyListener(event)) {
Expand Down
52 changes: 46 additions & 6 deletions src/android/events/NotificationOpenedEvent.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE

package com.urbanairship.cordova.events;

import android.support.annotation.NonNull;
import android.support.annotation.Nullable;

import com.urbanairship.AirshipReceiver;
import com.urbanairship.Logger;
import com.urbanairship.push.PushMessage;

Expand All @@ -41,17 +45,53 @@ public class NotificationOpenedEvent extends PushEvent {

private static final String EVENT_NOTIFICATION_OPENED = "urbanairship.notification_opened";

private final PushMessage message;
private final Integer notificationId;
private static final String ACTION_ID = "actionID";
private static final String IS_FOREGROUND = "isForeground";

private final AirshipReceiver.ActionButtonInfo actionButtonInfo;


public NotificationOpenedEvent(Integer notificationId, PushMessage message) {
super(notificationId, message);
this.notificationId = notificationId;
this.message = message;
/**
* Creates an event for a notification response.
*
* @param notificationInfo The notification info.
*/
public NotificationOpenedEvent(@NonNull AirshipReceiver.NotificationInfo notificationInfo) {
this(notificationInfo, null);
}

/**
* Creates an event for a notification action button response.
*
* @param notificationInfo The notification info.
* @param actionButtonInfo The action button info.
*/
public NotificationOpenedEvent(@NonNull AirshipReceiver.NotificationInfo notificationInfo, @Nullable AirshipReceiver.ActionButtonInfo actionButtonInfo) {
super(notificationInfo.getNotificationId(), notificationInfo.getMessage());
this.actionButtonInfo = actionButtonInfo;
}

@Override
public String getEventName() {
return EVENT_NOTIFICATION_OPENED;
}


@Override
public JSONObject getEventData() {
JSONObject jsonObject = super.getEventData();

try {
if (actionButtonInfo != null) {
jsonObject.put(ACTION_ID, actionButtonInfo.getButtonId());
jsonObject.put(IS_FOREGROUND, actionButtonInfo.isForeground());
} else {
jsonObject.put(IS_FOREGROUND, true);
}
} catch (JSONException e) {
Logger.error("Error constructing notification object", e);
}

return jsonObject;
}
}
119 changes: 75 additions & 44 deletions src/ios/UAirshipPlugin.m
Original file line number Diff line number Diff line change
Expand Up @@ -237,24 +237,22 @@ - (CDVPluginResult *)pluginResultForValue:(id)value status:(CDVCommandStatus)sta
}

/**
* Helper method to perform a cordova command asynchronously.
* Helper method to perform a cordova command.
*
* @param command The cordova command.
* @param block The UACordovaExecutionBlock to execute.
*/
- (void)performCallbackWithCommand:(CDVInvokedUrlCommand *)command withBlock:(UACordovaExecutionBlock)block {
[self.commandDelegate runInBackground:^{
UACordovaCompletionHandler completionHandler = ^(CDVCommandStatus status, id value) {
CDVPluginResult *result = [self pluginResultForValue:value status:status];
[self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
};
UACordovaCompletionHandler completionHandler = ^(CDVCommandStatus status, id value) {
CDVPluginResult *result = [self pluginResultForValue:value status:status];
[self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
};

if (!block) {
completionHandler(CDVCommandStatus_OK, nil);
} else {
block(command.arguments, completionHandler);
}
}];
if (!block) {
completionHandler(CDVCommandStatus_OK, nil);
} else {
block(command.arguments, completionHandler);
}
}

#pragma mark Phonegap bridge
Expand Down Expand Up @@ -736,11 +734,11 @@ - (void)notificationAuthorizedOptionsDidChange:(UANotificationOptions)options {
optedIn = alertBool || badgeBool || soundBool;

NSDictionary *eventBody = @{ @"optIn": @(optedIn),
@"notificationOptions" : @{
NotificationPresentationAlertKey : @(alertBool),
NotificationPresentationBadgeKey : @(badgeBool),
NotificationPresentationSoundKey : @(soundBool) }
};
@"notificationOptions" : @{
NotificationPresentationAlertKey : @(alertBool),
NotificationPresentationBadgeKey : @(badgeBool),
NotificationPresentationSoundKey : @(soundBool) }
};

UA_LINFO(@"Opt in status changed.");
[self notifyListener:EventNotificationOptInStatus data:eventBody];
Expand All @@ -749,15 +747,25 @@ - (void)notificationAuthorizedOptionsDidChange:(UANotificationOptions)options {
#pragma mark UAPushNotificationDelegate

- (void)receivedNotificationResponse:(UANotificationResponse *)notificationResponse completionHandler:(void(^)())completionHandler {
UA_LDEBUG(@"The application was launched or resumed from a notification %@", notificationResponse);
self.launchNotificationResponse = notificationResponse;

NSDictionary *pushEvent = [self pushEventFromNotification:notificationResponse.notificationContent];
NSMutableDictionary *event = [NSMutableDictionary dictionaryWithDictionary:pushEvent];

if ([notificationResponse.actionIdentifier isEqualToString:UANotificationDefaultActionIdentifier]) {
UA_LDEBUG(@"The application was launched or resumed from a notification %@", notificationResponse);
[event setValue:@(YES) forKey:@"isForeground"];
} else {
UANotificationAction *notificationAction = [self notificationActionForCategory:notificationResponse.notificationContent.categoryIdentifier
actionIdentifier:notificationResponse.actionIdentifier];

self.launchNotificationResponse = notificationResponse;
BOOL isForeground = notificationAction.options & UNNotificationActionOptionForeground;
[event setValue:@(isForeground) forKey:@"isForeground"];
[event setValue:notificationResponse.actionIdentifier forKey:@"actionID"];
}

id event = [self pushEventFromNotification:notificationResponse.notificationContent];
if (![self notifyListener:EventNotificationOpened data:event]) {
[self.pendingEvents setValue:event forKey:EventNotificationOpened];
}
if (![self notifyListener:EventNotificationOpened data:event]) {
[self.pendingEvents setValue:event forKey:EventNotificationOpened];
}

completionHandler();
Expand Down Expand Up @@ -791,18 +799,14 @@ - (void)showInbox {

- (void)displayMessageCenter:(CDVInvokedUrlCommand *)command {
[self performCallbackWithCommand:command withBlock:^(NSArray *args, UACordovaCompletionHandler completionHandler) {
dispatch_async(dispatch_get_main_queue(), ^{
[[UAirship defaultMessageCenter] display];
});
[[UAirship defaultMessageCenter] display];
completionHandler(CDVCommandStatus_OK, nil);
}];
}

- (void)dismissMessageCenter:(CDVInvokedUrlCommand *)command {
[self performCallbackWithCommand:command withBlock:^(NSArray *args, UACordovaCompletionHandler completionHandler) {
dispatch_async(dispatch_get_main_queue(), ^{
[[UAirship defaultMessageCenter] dismiss];
});
[[UAirship defaultMessageCenter] dismiss];
completionHandler(CDVCommandStatus_OK, nil);
}];
}
Expand Down Expand Up @@ -895,30 +899,23 @@ - (void)displayInboxMessage:(CDVInvokedUrlCommand *)command {
// Store a weak reference to the MessageViewController so we can dismiss it later
self.messageViewController = mvc;

dispatch_async(dispatch_get_main_queue(), ^{
[[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:navController animated:YES completion:nil];
});
[[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:navController animated:YES completion:nil];

completionHandler(CDVCommandStatus_OK, nil);
}];
}

- (void)dismissInboxMessage:(CDVInvokedUrlCommand *)command {
[self performCallbackWithCommand:command withBlock:^(NSArray *args, UACordovaCompletionHandler completionHandler) {
dispatch_async(dispatch_get_main_queue(), ^{
[self.messageViewController dismissViewControllerAnimated:YES completion:nil];
self.messageViewController = nil;
});

[self.messageViewController dismissViewControllerAnimated:YES completion:nil];
self.messageViewController = nil;
completionHandler(CDVCommandStatus_OK, nil);
}];
}

- (void)dismissOverlayInboxMessage:(CDVInvokedUrlCommand *)command {
[self performCallbackWithCommand:command withBlock:^(NSArray *args, UACordovaCompletionHandler completionHandler) {
dispatch_async(dispatch_get_main_queue(), ^{
[UALandingPageOverlayController closeAll:YES];
});
[UALandingPageOverlayController closeAll:YES];
completionHandler(CDVCommandStatus_OK, nil);
}];
}
Expand All @@ -934,9 +931,7 @@ - (void)overlayInboxMessage:(CDVInvokedUrlCommand *)command {
return;
}

dispatch_async(dispatch_get_main_queue(), ^{
[UALandingPageOverlayController showMessage:message];
});
[UALandingPageOverlayController showMessage:message];

completionHandler(CDVCommandStatus_OK, nil);
}];
Expand Down Expand Up @@ -970,7 +965,7 @@ - (BOOL)notifyListener:(NSString *)eventType data:(NSDictionary *)data {
}


- (id)pushEventFromNotification:(UANotificationContent *)notificationContent {
- (NSDictionary *)pushEventFromNotification:(UANotificationContent *)notificationContent {
if (!notificationContent) {
return @{ @"message": @"", @"extras": @{}};
}
Expand Down Expand Up @@ -1014,4 +1009,40 @@ -(NSInteger)parseLogLevel:(NSString *)logLevel defaultLogLevel:(NSInteger)defaul
return defaultValue;
}


- (UANotificationAction *)notificationActionForCategory:(NSString *)category actionIdentifier:(NSString *)identifier {
NSSet *categories = [UAirship push].combinedCategories;

UANotificationCategory *notificationCategory;
UANotificationAction *notificationAction;

for (UANotificationCategory *possibleCategory in categories) {
if ([possibleCategory.identifier isEqualToString:category]) {
notificationCategory = possibleCategory;
break;
}
}

if (!notificationCategory) {
UA_LERR(@"Unknown notification category identifier %@", category);
return nil;
}

NSMutableArray *possibleActions = [NSMutableArray arrayWithArray:notificationCategory.actions];

for (UANotificationAction *possibleAction in possibleActions) {
if ([possibleAction.identifier isEqualToString:identifier]) {
notificationAction = possibleAction;
break;
}
}

if (!notificationAction) {
UA_LERR(@"Unknown notification action identifier %@", identifier);
return nil;
}

return notificationAction;
}

@end
2 changes: 2 additions & 0 deletions www/UrbanAirship.js
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,8 @@ module.exports = {
* @param {string} message The push alert message.
* @param {object} extras Any push extras.
* @param {number} [notification_id] The Android notification ID.
* @param {string} [actionID] The ID of the notification action button if available.
* @param {boolean} isForeground Will always be true if the user taps the main notification. Otherwise its defined by the notificaiton action button.
*/

/**
Expand Down

0 comments on commit a7bbcc4

Please sign in to comment.