Skip to content

Intercom #703

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions plugin.xml
Original file line number Diff line number Diff line change
@@ -55,16 +55,17 @@
<category android:name="$PACKAGE_NAME" />
</intent-filter>
</receiver>
<receiver android:name="com.plugin.gcm.BackgroundNotificationReceiver"/>
<service android:name="com.plugin.gcm.GCMIntentService" />
</config-file>

<source-file src="src/android/libs/gcm.jar" target-dir="libs/" />
<source-file src="src/android/com/plugin/gcm/CordovaGCMBroadcastReceiver.java" target-dir="src/com/plugin/gcm/" />
<source-file src="src/android/com/plugin/gcm/BackgroundNotificationReceiver.java" target-dir="src/com/plugin/gcm/" />
<source-file src="src/android/com/plugin/gcm/GCMIntentService.java" target-dir="src/com/plugin/gcm/" />
<source-file src="src/android/com/plugin/gcm/PushHandlerActivity.java" target-dir="src/com/plugin/gcm/" />
<source-file src="src/android/com/plugin/gcm/PushPlugin.java" target-dir="src/com/plugin/gcm/" />
<source-file src="src/android/com/plugin/android-support-v13.jar" target-dir="libs/" />

<framework src="com.android.support:support-v4:22.1.1" />
</platform>

<!-- amazon-fireos -->
Binary file removed src/android/com/plugin/android-support-v13.jar
Binary file not shown.
37 changes: 37 additions & 0 deletions src/android/com/plugin/gcm/BackgroundNotificationReceiver.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.plugin.gcm;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.app.NotificationManager;
import android.os.Bundle;

public class BackgroundNotificationReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
Log.v("NOTIFS", "BROADCAST RECEIVER");

Bundle extras = intent.getExtras();
boolean isPushPluginActive = PushPlugin.isActive();


if (extras != null) {
Bundle originalExtras = extras.getBundle("pushBundle");

originalExtras.putBoolean("foreground", false);
originalExtras.putBoolean("coldstart", !isPushPluginActive);

String actionSelected = extras.getString(GCMIntentService.ACTION_KEY);
originalExtras.putString("actionSelected", actionSelected);

PushPlugin.sendExtras(originalExtras);

// cancel the notification when an action button is clicked
final NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.cancel(GCMIntentService.getAppName(context), extras.getInt("notId"));
}
}

}
Original file line number Diff line number Diff line change
@@ -16,4 +16,4 @@ protected String getGCMIntentServiceClassName(Context context) {
return "com.plugin.gcm" + DEFAULT_INTENT_SERVICE_CLASS_NAME;
}

}
}
43 changes: 39 additions & 4 deletions src/android/com/plugin/gcm/GCMIntentService.java
Original file line number Diff line number Diff line change
@@ -2,6 +2,8 @@

import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONArray;
import java.util.Random;

import android.annotation.SuppressLint;
import android.app.Notification;
@@ -13,12 +15,14 @@
import android.support.v4.app.NotificationCompat;
import android.util.Log;


import com.google.android.gcm.GCMBaseIntentService;

@SuppressLint("NewApi")
public class GCMIntentService extends GCMBaseIntentService {

private static final String TAG = "GCMIntentService";
public static final String ACTION_KEY = "PUSH_NOTIFICATION_ACTION_IDENTIFIER";

public GCMIntentService() {
super("GCMIntentService");
@@ -61,7 +65,9 @@ protected void onMessage(Context context, Intent intent) {

// Extract the payload from the message
Bundle extras = intent.getExtras();
if (extras != null)

Log.v(TAG, "extras: " + extras.toString());
if (extras != null && !PushPlugin.isIntercomPush(extras))
{
// if we are in the foreground, just surface the payload, else post it to the statusbar
if (PushPlugin.isInForeground()) {
@@ -97,7 +103,7 @@ public void createNotification(Context context, Bundle extras)
defaults = Integer.parseInt(extras.getString("defaults"));
} catch (NumberFormatException e) {}
}

NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(context)
.setDefaults(defaults)
@@ -131,11 +137,40 @@ public void createNotification(Context context, Bundle extras)
catch(Exception e) {
Log.e(TAG, "Number format exception - Error parsing Notification ID" + e.getMessage());
}


String cat_id = extras.getString("categoryName");
if(cat_id != null) {
JSONObject category = PushPlugin.categories.optJSONObject(cat_id);
JSONArray actions = category.optJSONArray("actions");
int requestCode;

// add each action
for(int i = 0; i < actions.length(); i++) {
JSONObject action = actions.optJSONObject(i);
requestCode = new Random().nextInt();

// set up correct receiver for foreground or background handler
//if(extras.getString("activationMode") == "background") {
// notificationIntent = new Intent(this, BackgroundNotificationReceiver.class);
//}
//else {
notificationIntent = new Intent(this, PushHandlerActivity.class);
//}
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
notificationIntent.putExtra("pushBundle", extras);
notificationIntent.putExtra("notId", notId);
notificationIntent.putExtra(ACTION_KEY, action.optString("identifier"));

contentIntent = PendingIntent.getBroadcast(this, requestCode, notificationIntent, PendingIntent.FLAG_CANCEL_CURRENT);

mBuilder = mBuilder.addAction(action.optInt("icon"), action.optString("title"), contentIntent);
}
}

mNotificationManager.notify((String) appName, notId, mBuilder.build());
}

private static String getAppName(Context context)
public static String getAppName(Context context)
{
CharSequence appName =
context
14 changes: 11 additions & 3 deletions src/android/com/plugin/gcm/PushHandlerActivity.java
Original file line number Diff line number Diff line change
@@ -27,6 +27,7 @@ public void onCreate(Bundle savedInstanceState)
boolean isPushPluginActive = PushPlugin.isActive();
processPushBundle(isPushPluginActive);


finish();

if (!isPushPluginActive) {
@@ -38,17 +39,24 @@ public void onCreate(Bundle savedInstanceState)
* Takes the pushBundle extras from the intent,
* and sends it through to the PushPlugin for processing.
*/
private void processPushBundle(boolean isPushPluginActive)
public void processPushBundle(boolean isPushPluginActive)
{
Bundle extras = getIntent().getExtras();

if (extras != null) {
if (extras != null && !PushPlugin.isIntercomPush(extras)) {
Bundle originalExtras = extras.getBundle("pushBundle");

originalExtras.putBoolean("foreground", false);
originalExtras.putBoolean("coldstart", !isPushPluginActive);

String actionSelected = extras.getString(GCMIntentService.ACTION_KEY);
originalExtras.putString("actionSelected", actionSelected);

PushPlugin.sendExtras(originalExtras);

// cancel the notification when an action button is clicked
final NotificationManager notificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.cancel(GCMIntentService.getAppName(this), extras.getInt("notId"));
}
}

@@ -69,4 +77,4 @@ protected void onResume() {
notificationManager.cancelAll();
}

}
}
14 changes: 12 additions & 2 deletions src/android/com/plugin/gcm/PushPlugin.java
Original file line number Diff line number Diff line change
@@ -23,6 +23,7 @@ public class PushPlugin extends CordovaPlugin {
public static final String TAG = "PushPlugin";

public static final String REGISTER = "register";
public static final String REGISTER_CATEGORIES = "registerUserNotificationSettings";
public static final String UNREGISTER = "unregister";
public static final String EXIT = "exit";

@@ -31,6 +32,7 @@ public class PushPlugin extends CordovaPlugin {
private static String gSenderID;
private static Bundle gCachedExtras = null;
private static boolean gForeground = false;
public static JSONObject categories;

/**
* Gets the application context from cordova's main activity.
@@ -40,6 +42,10 @@ private Context getApplicationContext() {
return this.cordova.getActivity().getApplicationContext();
}

public static boolean isIntercomPush(Bundle extras) {
return extras.containsKey("receiver") && "intercom_sdk".equals(extras.getString("receiver"));
}

@Override
public boolean execute(String action, JSONArray data, CallbackContext callbackContext) {

@@ -78,13 +84,17 @@ public boolean execute(String action, JSONArray data, CallbackContext callbackCo
}

} else if (UNREGISTER.equals(action)) {

GCMRegistrar.unregister(getApplicationContext());

Log.v(TAG, "UNREGISTER");
result = true;
callbackContext.success();
} else {
} else if(REGISTER_CATEGORIES.equals(action)) {
JSONObject fullSettings = data.optJSONObject(0);
this.categories = fullSettings.optJSONObject("categories");

result = true;
} else {
result = false;
Log.e(TAG, "Invalid action : " + action);
callbackContext.error("Invalid action : " + action);
3 changes: 3 additions & 0 deletions src/ios/AppDelegate+notification.h
Original file line number Diff line number Diff line change
@@ -15,6 +15,9 @@
- (void)applicationDidBecomeActive:(UIApplication *)application;
- (id) getCommandInstance:(NSString*)className;

- (void)applicationPushPlugin:(UIApplication *) application handleActionWithIdentifier: (NSString *) identifier
forLocalNotification: (NSDictionary *) notification;

@property (nonatomic, retain) NSDictionary *launchNotification;

@end
52 changes: 51 additions & 1 deletion src/ios/AppDelegate+notification.m
Original file line number Diff line number Diff line change
@@ -10,6 +10,8 @@
#import "PushPlugin.h"
#import <objc/runtime.h>

#import "Hurdlr-Swift.h"

static char launchNotificationKey;

@implementation AppDelegate (notification)
@@ -40,14 +42,24 @@ - (AppDelegate *)swizzled_init
return [self swizzled_init];
}

+ (BOOL)isIntercomPushMessage:(NSDictionary *)userInfo {
//check if we contain the key icm_cid
return userInfo && [userInfo isKindOfClass:[NSDictionary class]] && userInfo[@"icm_cid"] != nil;
}

+ (BOOL)isTrackerPushMessage:(NSDictionary *)userInfo {
//check if we contain the key icm_cid
return userInfo && [userInfo isKindOfClass:[NSDictionary class]] && userInfo[@"checkTracker"] != nil;
}

// This code will be called immediately after application:didFinishLaunchingWithOptions:. We need
// to process notifications in cold-start situations
- (void)createNotificationChecker:(NSNotification *)notification
{
if (notification)
{
NSDictionary *launchOptions = [notification userInfo];
if (launchOptions)
if (launchOptions && ![[self class] isIntercomPushMessage:launchOptions])
self.launchNotification = [launchOptions objectForKey: @"UIApplicationLaunchOptionsRemoteNotificationKey"];
}
}
@@ -64,6 +76,10 @@ - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotif

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
NSLog(@"didReceiveNotification");

if ([[self class] isIntercomPushMessage:userInfo]) {
return;
}

// Get application state for iOS4.x+ devices, otherwise assume active
UIApplicationState appState = UIApplicationStateActive;
@@ -98,6 +114,40 @@ - (void)applicationDidBecomeActive:(UIApplication *)application {
}
}

- (void)application:(UIApplication *) application handleActionWithIdentifier: (NSString *) identifier
forRemoteNotification: (NSDictionary *) notification
completionHandler: (void (^)()) completionHandler {

PushPlugin *pushHandler = [self getCommandInstance:@"PushPlugin"];

NSMutableDictionary * userInfo = [notification mutableCopy];
[userInfo setValue:identifier forKey:@"actionSelected"];
pushHandler.notificationMessage = userInfo;

[pushHandler performSelectorOnMainThread:@selector(notificationReceived) withObject:pushHandler waitUntilDone:NO];

// Must be called when finished
completionHandler();
}

- (void)applicationPushPlugin:(UIApplication *) application handleActionWithIdentifier: (NSString *) identifier
forLocalNotification: (NSDictionary *) notification
completionHandler: (void (^)()) completionHandler {

PushPlugin *pushHandler = [self getCommandInstance:@"PushPlugin"];

NSMutableDictionary * userInfo = [[notification valueForKey:@"userInfo"] mutableCopy];
[userInfo setValue:identifier forKey:@"actionSelected"];
pushHandler.notificationMessage = userInfo;

[pushHandler performSelectorOnMainThread:@selector(notificationReceived) withObject:pushHandler waitUntilDone:NO];

// Must be called when finished
completionHandler();
}



// The accessors use an Associative Reference since you can't define a iVar in a category
// http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/objectivec/Chapters/ocAssociativeReferences.html
- (NSMutableArray *)launchNotification
7 changes: 5 additions & 2 deletions src/ios/PushPlugin.h
Original file line number Diff line number Diff line change
@@ -33,7 +33,6 @@
BOOL isInline;
NSString *notificationCallbackId;
NSString *callback;

BOOL ready;
}

@@ -45,11 +44,15 @@
@property BOOL isInline;

- (void)register:(CDVInvokedUrlCommand*)command;
- (void)registerUserNotificationSettings:(CDVInvokedUrlCommand*)command;

- (void)areNotificationsEnabled:(CDVInvokedUrlCommand*)command;

- (void)didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken;
- (void)didFailToRegisterForRemoteNotificationsWithError:(NSError *)error;

- (void)setNotificationMessage:(NSDictionary *)notification;
- (void)notificationReceived;

@end
+ (NSDictionary*) getCategories;
@end
403 changes: 303 additions & 100 deletions src/ios/PushPlugin.m

Large diffs are not rendered by default.

62 changes: 49 additions & 13 deletions www/PushNotification.js
Original file line number Diff line number Diff line change
@@ -19,15 +19,33 @@ PushNotification.prototype.register = function(successCallback, errorCallback, o
cordova.exec(successCallback, errorCallback, "PushPlugin", "register", [options]);
};

// Call this to unregister for push notifications
PushNotification.prototype.unregister = function(successCallback, errorCallback, options) {
PushNotification.prototype.UserNotificationTypes = {
Badge : "badge",
Alert : "alert",
Sound : "sound"
};

PushNotification.prototype.UserNotificationActivationMode = {
Foreground : "foreground",
Background : "background"
};

PushNotification.prototype.registerUserNotificationSettings = function(successCallback, errorCallback, options) {
if (errorCallback == null) { errorCallback = function() {}}

if (typeof errorCallback != "function") {
console.log("PushNotification.unregister failure: failure parameter not a function");
if (typeof successCallback != "function") {
console.log("PushNotification.registerUserNotificationSettings failure: success callback parameter must be a function");
return
}

cordova.exec(successCallback, errorCallback, "PushPlugin", "registerUserNotificationSettings", [options]);
};


// Call this to unregister for push notifications
PushNotification.prototype.unregister = function(successCallback, errorCallback, options) {
errorCallback = errorCallback || function () {}

if (typeof successCallback != "function") {
console.log("PushNotification.unregister failure: success callback parameter must be a function");
return
@@ -36,17 +54,35 @@ PushNotification.prototype.unregister = function(successCallback, errorCallback,
cordova.exec(successCallback, errorCallback, "PushPlugin", "unregister", [options]);
};

// Call this if you want to show toast notification on WP8
PushNotification.prototype.showToastNotification = function (successCallback, errorCallback, options) {
if (errorCallback == null) { errorCallback = function () { } }
// Check to see if we've already registered
PushNotification.prototype.areNotificationsEnabled = function(successCallback, errorCallback, options) {
if (errorCallback == null) { errorCallback = function() {}}

if (typeof errorCallback != "function") {
console.log("PushNotification.register failure: failure parameter not a function");
return
}
if (typeof errorCallback != "function") {
console.log("PushNotification.areNotificationsEnabled failure: failure parameter not a function");
return
}

cordova.exec(successCallback, errorCallback, "PushPlugin", "showToastNotification", [options]);
if (typeof successCallback != "function") {
console.log("PushNotification.areNotificationsEnabled failure: success callback parameter must be a function");
return
}

cordova.exec(successCallback, errorCallback, "PushPlugin", "areNotificationsEnabled", [options]);
};

// Call this if you want to show toast notification on WP8
PushNotification.prototype.showToastNotification = function (successCallback, errorCallback, options) {
if (errorCallback == null) { errorCallback = function () { } }

if (typeof errorCallback != "function") {
console.log("PushNotification.register failure: failure parameter not a function");
return
}

cordova.exec(successCallback, errorCallback, "PushPlugin", "showToastNotification", [options]);
};

// Call this to set the application icon badge
PushNotification.prototype.setApplicationIconBadgeNumber = function(successCallback, errorCallback, badge) {
if (errorCallback == null) { errorCallback = function() {}}
@@ -75,4 +111,4 @@ if (!window.plugins.pushNotification) {

if (typeof module != 'undefined' && module.exports) {
module.exports = PushNotification;
}
}