From 8dae6a5044f9c1b7a8497cc1c96155fd262b40cf Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Thu, 26 Oct 2017 01:41:16 +0200 Subject: iphone x fixes --- StoneIsland/platforms/android/AndroidManifest.xml | 23 +- StoneIsland/platforms/android/android.json | 78 +- .../android/assets/www/cordova_plugins.js | 22 +- .../www/splashscreen.js | 3 +- .../www/plugins/phonegap-plugin-push/www/push.js | 496 ++++++------ StoneIsland/platforms/android/build.gradle | 6 +- .../phonegap-plugin-push/stoneisland-push.gradle | 18 - .../android/platform_www/cordova_plugins.js | 22 +- .../www/splashscreen.js | 3 +- .../plugins/phonegap-plugin-push/www/push.js | 496 ++++++------ StoneIsland/platforms/android/project.properties | 8 +- .../platforms/android/res/values/strings.xml | 1 + StoneIsland/platforms/android/res/xml/config.xml | 8 +- .../push/BackgroundActionButtonHandler.java | 4 +- .../src/com/adobe/phonegap/push/FCMService.java | 891 --------------------- .../com/adobe/phonegap/push/GCMIntentService.java | 802 +++++++++++++++++++ .../com/adobe/phonegap/push/PermissionUtils.java | 4 - .../src/com/adobe/phonegap/push/PushConstants.java | 16 +- .../adobe/phonegap/push/PushDismissedHandler.java | 25 - .../adobe/phonegap/push/PushHandlerActivity.java | 32 +- .../push/PushInstanceIDListenerService.java | 19 +- .../src/com/adobe/phonegap/push/PushPlugin.java | 132 ++- .../phonegap/push/RegistrationIntentService.java | 38 + 23 files changed, 1481 insertions(+), 1666 deletions(-) delete mode 100644 StoneIsland/platforms/android/src/com/adobe/phonegap/push/FCMService.java create mode 100644 StoneIsland/platforms/android/src/com/adobe/phonegap/push/GCMIntentService.java delete mode 100644 StoneIsland/platforms/android/src/com/adobe/phonegap/push/PushDismissedHandler.java create mode 100644 StoneIsland/platforms/android/src/com/adobe/phonegap/push/RegistrationIntentService.java (limited to 'StoneIsland/platforms/android') diff --git a/StoneIsland/platforms/android/AndroidManifest.xml b/StoneIsland/platforms/android/AndroidManifest.xml index bb6ffaef..75322df7 100755 --- a/StoneIsland/platforms/android/AndroidManifest.xml +++ b/StoneIsland/platforms/android/AndroidManifest.xml @@ -23,23 +23,36 @@ - - + - + + + + + + + - + - + + + + + + + + + diff --git a/StoneIsland/platforms/android/android.json b/StoneIsland/platforms/android/android.json index 1a860dfb..3e69085c 100755 --- a/StoneIsland/platforms/android/android.json +++ b/StoneIsland/platforms/android/android.json @@ -36,10 +36,6 @@ "xml": "", "count": 1 }, - { - "xml": "", - "count": 1 - }, { "xml": "", "count": 1 @@ -52,6 +48,10 @@ "xml": "", "count": 1 }, + { + "xml": "", + "count": 1 + }, { "xml": "", "count": 1 @@ -71,15 +71,19 @@ "count": 1 }, { - "xml": "", + "xml": "", + "count": 1 + }, + { + "xml": "", "count": 1 }, { - "xml": "", + "xml": "", "count": 1 }, { - "xml": "", + "xml": "", "count": 1 } ], @@ -99,6 +103,26 @@ { "xml": "", "count": 1 + }, + { + "xml": "", + "count": 1 + }, + { + "xml": "", + "count": 1 + }, + { + "xml": "", + "count": 1 + }, + { + "xml": "", + "count": 1 + }, + { + "xml": "", + "count": 1 } ], "/*/application/activity": [], @@ -143,7 +167,12 @@ }, "res/values/strings.xml": { "parents": { - "/resources": [] + "/resources": [ + { + "xml": "85075801930", + "count": 1 + } + ] } }, "config.xml": { @@ -175,9 +204,6 @@ "cordova-plugin-whitelist": { "PACKAGE_NAME": "us.okfoc.stoneisland" }, - "cordova-plugin-console": { - "PACKAGE_NAME": "us.okfoc.stoneisland" - }, "cordova-plugin-device": { "PACKAGE_NAME": "us.okfoc.stoneisland" }, @@ -187,9 +213,6 @@ "cordova-plugin-dialogs": { "PACKAGE_NAME": "us.okfoc.stoneisland" }, - "cordova-plugin-splashscreen": { - "PACKAGE_NAME": "us.okfoc.stoneisland" - }, "cordova-plugin-compat": { "PACKAGE_NAME": "us.okfoc.stoneisland" }, @@ -206,10 +229,11 @@ "APP_NAME": "Stone Island", "PACKAGE_NAME": "us.okfoc.stoneisland" }, - "phonegap-plugin-push": { + "cordova-plugin-splashscreen": { "PACKAGE_NAME": "us.okfoc.stoneisland" }, - "cordova-plugin-wkwebview-engine": { + "phonegap-plugin-push": { + "SENDER_ID": "85075801930", "PACKAGE_NAME": "us.okfoc.stoneisland" } }, @@ -281,14 +305,6 @@ "navigator.notification" ] }, - { - "file": "plugins/cordova-plugin-splashscreen/www/splashscreen.js", - "id": "cordova-plugin-splashscreen.SplashScreen", - "pluginId": "cordova-plugin-splashscreen", - "clobbers": [ - "navigator.splashscreen" - ] - }, { "file": "plugins/cordova-plugin-geolocation/www/android/geolocation.js", "id": "cordova-plugin-geolocation.geolocation", @@ -320,6 +336,14 @@ "window.StatusBar" ] }, + { + "id": "cordova-plugin-splashscreen.SplashScreen", + "file": "plugins/cordova-plugin-splashscreen/www/splashscreen.js", + "pluginId": "cordova-plugin-splashscreen", + "clobbers": [ + "navigator.splashscreen" + ] + }, { "id": "phonegap-plugin-push.PushNotification", "file": "plugins/phonegap-plugin-push/www/push.js", @@ -334,17 +358,15 @@ "cordova-plugin-x-socialsharing": "5.1.3", "cordova-plugin-customurlscheme": "4.2.0", "cordova-plugin-whitelist": "1.3.0", - "cordova-plugin-console": "1.0.4", "cordova-plugin-device": "1.1.3", "cordova-plugin-network-information": "1.3.0", "cordova-plugin-dialogs": "1.3.0", - "cordova-plugin-splashscreen": "4.0.0", "cordova-plugin-compat": "1.1.0", "cordova-plugin-geolocation": "2.4.0", "ionic-plugin-keyboard": "2.2.1", "cordova-plugin-statusbar": "2.2.3", "cordova-plugin-app-name": "1.0.4", - "phonegap-plugin-push": "2.0.0", - "cordova-plugin-wkwebview-engine": "1.1.3" + "cordova-plugin-splashscreen": "4.0.3", + "phonegap-plugin-push": "1.9.2" } } \ No newline at end of file diff --git a/StoneIsland/platforms/android/assets/www/cordova_plugins.js b/StoneIsland/platforms/android/assets/www/cordova_plugins.js index 1b6d56ac..8f70abd6 100755 --- a/StoneIsland/platforms/android/assets/www/cordova_plugins.js +++ b/StoneIsland/platforms/android/assets/www/cordova_plugins.js @@ -66,14 +66,6 @@ module.exports = [ "navigator.notification" ] }, - { - "file": "plugins/cordova-plugin-splashscreen/www/splashscreen.js", - "id": "cordova-plugin-splashscreen.SplashScreen", - "pluginId": "cordova-plugin-splashscreen", - "clobbers": [ - "navigator.splashscreen" - ] - }, { "file": "plugins/cordova-plugin-geolocation/www/android/geolocation.js", "id": "cordova-plugin-geolocation.geolocation", @@ -105,6 +97,14 @@ module.exports = [ "window.StatusBar" ] }, + { + "id": "cordova-plugin-splashscreen.SplashScreen", + "file": "plugins/cordova-plugin-splashscreen/www/splashscreen.js", + "pluginId": "cordova-plugin-splashscreen", + "clobbers": [ + "navigator.splashscreen" + ] + }, { "id": "phonegap-plugin-push.PushNotification", "file": "plugins/phonegap-plugin-push/www/push.js", @@ -121,18 +121,16 @@ module.exports.metadata = "cordova-plugin-x-socialsharing": "5.1.3", "cordova-plugin-customurlscheme": "4.2.0", "cordova-plugin-whitelist": "1.3.0", - "cordova-plugin-console": "1.0.4", "cordova-plugin-device": "1.1.3", "cordova-plugin-network-information": "1.3.0", "cordova-plugin-dialogs": "1.3.0", - "cordova-plugin-splashscreen": "4.0.0", "cordova-plugin-compat": "1.1.0", "cordova-plugin-geolocation": "2.4.0", "ionic-plugin-keyboard": "2.2.1", "cordova-plugin-statusbar": "2.2.3", "cordova-plugin-app-name": "1.0.4", - "phonegap-plugin-push": "2.0.0", - "cordova-plugin-wkwebview-engine": "1.1.3" + "cordova-plugin-splashscreen": "4.0.3", + "phonegap-plugin-push": "1.9.2" }; // BOTTOM OF METADATA }); \ No newline at end of file diff --git a/StoneIsland/platforms/android/assets/www/plugins/cordova-plugin-splashscreen/www/splashscreen.js b/StoneIsland/platforms/android/assets/www/plugins/cordova-plugin-splashscreen/www/splashscreen.js index 0e6a10af..5beaa5fd 100644 --- a/StoneIsland/platforms/android/assets/www/plugins/cordova-plugin-splashscreen/www/splashscreen.js +++ b/StoneIsland/platforms/android/assets/www/plugins/cordova-plugin-splashscreen/www/splashscreen.js @@ -1,4 +1,5 @@ -cordova.define("cordova-plugin-splashscreen.SplashScreen", function(require, exports, module) { /* +cordova.define("cordova-plugin-splashscreen.SplashScreen", function(require, exports, module) { +/* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file diff --git a/StoneIsland/platforms/android/assets/www/plugins/phonegap-plugin-push/www/push.js b/StoneIsland/platforms/android/assets/www/plugins/phonegap-plugin-push/www/push.js index 7234d474..a5315486 100644 --- a/StoneIsland/platforms/android/assets/www/plugins/phonegap-plugin-push/www/push.js +++ b/StoneIsland/platforms/android/assets/www/plugins/phonegap-plugin-push/www/push.js @@ -1,16 +1,4 @@ cordova.define("phonegap-plugin-push.PushNotification", function(require, exports, module) { -/** -* This file has been generated by Babel. -* -* DO NOT EDIT IT DIRECTLY -* -* Edit the JS source file src/js/push.js -**/'use strict'; - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - /* global cordova:false */ /* globals window */ @@ -20,358 +8,322 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons var exec = cordova.require('cordova/exec'); -var PushNotification = function () { - /** - * PushNotification constructor. - * - * @param {Object} options to initiate Push Notifications. - * @return {PushNotification} instance that can be monitored and cancelled. - */ - function PushNotification(options) { - var _this = this; - - _classCallCheck(this, PushNotification); - - this.handlers = { - registration: [], - notification: [], - error: [] +/** + * PushNotification constructor. + * + * @param {Object} options to initiate Push Notifications. + * @return {PushNotification} instance that can be monitored and cancelled. + */ + +var PushNotification = function(options) { + this._handlers = { + 'registration': [], + 'notification': [], + 'error': [] }; // require options parameter if (typeof options === 'undefined') { - throw new Error('The options argument is required.'); + throw new Error('The options argument is required.'); } // store the options to this object instance this.options = options; // triggered on registration and notification - var success = function success(result) { - if (result && typeof result.registrationId !== 'undefined') { - _this.emit('registration', result); - } else if (result && result.additionalData && typeof result.additionalData.actionCallback !== 'undefined') { - var executeFuctionOrEmitEventByName = function executeFuctionOrEmitEventByName(functionName, context) { - for (var _len = arguments.length, args = Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) { - args[_key - 2] = arguments[_key]; - } - - var namespaces = functionName.split('.'); - var func = namespaces.pop(); - for (var i = 0; i < namespaces.length; i++) { - context = context[namespaces[i]]; - } - - if (typeof context[func] === 'function') { - context[func].call(context, args); - } else { - _this.emit(functionName, args); - } - }; - - executeFuctionOrEmitEventByName(result.additionalData.actionCallback, window, result); - } else if (result) { - _this.emit('notification', result); - } + var that = this; + var success = function(result) { + if (result && typeof result.registrationId !== 'undefined') { + that.emit('registration', result); + } else if (result && result.additionalData && typeof result.additionalData.actionCallback !== 'undefined') { + var executeFuctionOrEmitEventByName = function(callbackName, context, arg) { + var namespaces = callbackName.split('.'); + var func = namespaces.pop(); + for (var i = 0; i < namespaces.length; i++) { + context = context[namespaces[i]]; + } + + if (typeof context[func] === 'function') { + context[func].call(context, arg); + } else { + that.emit(callbackName, arg); + } + }; + + executeFuctionOrEmitEventByName(result.additionalData.actionCallback, window, result); + } else if (result) { + that.emit('notification', result); + } }; // triggered on error - var fail = function fail(msg) { - var e = typeof msg === 'string' ? new Error(msg) : msg; - _this.emit('error', e); + var fail = function(msg) { + var e = (typeof msg === 'string') ? new Error(msg) : msg; + that.emit('error', e); }; // wait at least one process tick to allow event subscriptions - setTimeout(function () { - exec(success, fail, 'PushNotification', 'init', [options]); + setTimeout(function() { + exec(success, fail, 'PushNotification', 'init', [options]); }, 10); - } - - /** - * Unregister from push notifications - */ - +}; - _createClass(PushNotification, [{ - key: 'unregister', - value: function unregister(successCallback) { - var _this2 = this; +/** + * Unregister from push notifications + */ - var errorCallback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : function () {}; - var options = arguments[2]; +PushNotification.prototype.unregister = function(successCallback, errorCallback, options) { + if (!errorCallback) { errorCallback = function() {}; } - if (typeof errorCallback !== 'function') { + if (typeof errorCallback !== 'function') { console.log('PushNotification.unregister failure: failure parameter not a function'); return; - } + } - if (typeof successCallback !== 'function') { - console.log('PushNotification.unregister failure: success callback parameter ' + ' must be a function'); + if (typeof successCallback !== 'function') { + console.log('PushNotification.unregister failure: success callback parameter must be a function'); return; - } + } - var cleanHandlersAndPassThrough = function cleanHandlersAndPassThrough() { + var that = this; + var cleanHandlersAndPassThrough = function() { if (!options) { - _this2.handlers = { - registration: [], - notification: [], - error: [] - }; + that._handlers = { + 'registration': [], + 'notification': [], + 'error': [] + }; } successCallback(); - }; - - exec(cleanHandlersAndPassThrough, errorCallback, 'PushNotification', 'unregister', [options]); - } + }; - /** - * subscribe to a topic - * @param {String} topic topic to subscribe - * @param {Function} successCallback success callback - * @param {Function} errorCallback error callback - * @return {void} - */ + exec(cleanHandlersAndPassThrough, errorCallback, 'PushNotification', 'unregister', [options]); +}; - }, { - key: 'subscribe', - value: function subscribe(topic, successCallback) { - var errorCallback = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : function () {}; +/** + * subscribe to a topic + * @param {String} topic topic to subscribe + * @param {Function} successCallback success callback + * @param {Function} errorCallback error callback + * @return {void} + */ +PushNotification.prototype.subscribe = function(topic, successCallback, errorCallback) { + if (!errorCallback) { errorCallback = function() {}; } - if (typeof errorCallback !== 'function') { - console.log('PushNotification.subscribe failure: ' + 'failure parameter not a function'); + if (typeof errorCallback !== 'function') { + console.log('PushNotification.subscribe failure: failure parameter not a function'); return; - } + } - if (typeof successCallback !== 'function') { - console.log('PushNotification.subscribe failure: ' + 'success callback parameter must be a function'); + if (typeof successCallback !== 'function') { + console.log('PushNotification.subscribe failure: success callback parameter must be a function'); return; - } - - exec(successCallback, errorCallback, 'PushNotification', 'subscribe', [topic]); } - /** - * unsubscribe to a topic - * @param {String} topic topic to unsubscribe - * @param {Function} successCallback success callback - * @param {Function} errorCallback error callback - * @return {void} - */ + exec(successCallback, errorCallback, 'PushNotification', 'subscribe', [topic]); +}; - }, { - key: 'unsubscribe', - value: function unsubscribe(topic, successCallback) { - var errorCallback = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : function () {}; +/** + * unsubscribe to a topic + * @param {String} topic topic to unsubscribe + * @param {Function} successCallback success callback + * @param {Function} errorCallback error callback + * @return {void} + */ +PushNotification.prototype.unsubscribe = function(topic, successCallback, errorCallback) { + if (!errorCallback) { errorCallback = function() {}; } - if (typeof errorCallback !== 'function') { + if (typeof errorCallback !== 'function') { console.log('PushNotification.unsubscribe failure: failure parameter not a function'); return; - } + } - if (typeof successCallback !== 'function') { - console.log('PushNotification.unsubscribe failure: ' + 'success callback parameter must be a function'); + if (typeof successCallback !== 'function') { + console.log('PushNotification.unsubscribe failure: success callback parameter must be a function'); return; - } - - exec(successCallback, errorCallback, 'PushNotification', 'unsubscribe', [topic]); } - /** - * Call this to set the application icon badge - */ + exec(successCallback, errorCallback, 'PushNotification', 'unsubscribe', [topic]); +}; - }, { - key: 'setApplicationIconBadgeNumber', - value: function setApplicationIconBadgeNumber(successCallback) { - var errorCallback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : function () {}; - var badge = arguments[2]; +/** + * Call this to set the application icon badge + */ - if (typeof errorCallback !== 'function') { - console.log('PushNotification.setApplicationIconBadgeNumber failure: failure ' + 'parameter not a function'); - return; - } +PushNotification.prototype.setApplicationIconBadgeNumber = function(successCallback, errorCallback, badge) { + if (!errorCallback) { errorCallback = function() {}; } - if (typeof successCallback !== 'function') { - console.log('PushNotification.setApplicationIconBadgeNumber failure: success ' + 'callback parameter must be a function'); + if (typeof errorCallback !== 'function') { + console.log('PushNotification.setApplicationIconBadgeNumber failure: failure parameter not a function'); return; - } + } - exec(successCallback, errorCallback, 'PushNotification', 'setApplicationIconBadgeNumber', [{ badge: badge }]); + if (typeof successCallback !== 'function') { + console.log('PushNotification.setApplicationIconBadgeNumber failure: success callback parameter must be a function'); + return; } - /** - * Get the application icon badge - */ + exec(successCallback, errorCallback, 'PushNotification', 'setApplicationIconBadgeNumber', [{badge: badge}]); +}; + +/** + * Get the application icon badge + */ - }, { - key: 'getApplicationIconBadgeNumber', - value: function getApplicationIconBadgeNumber(successCallback) { - var errorCallback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : function () {}; +PushNotification.prototype.getApplicationIconBadgeNumber = function(successCallback, errorCallback) { + if (!errorCallback) { errorCallback = function() {}; } - if (typeof errorCallback !== 'function') { - console.log('PushNotification.getApplicationIconBadgeNumber failure: failure ' + 'parameter not a function'); + if (typeof errorCallback !== 'function') { + console.log('PushNotification.getApplicationIconBadgeNumber failure: failure parameter not a function'); return; - } + } - if (typeof successCallback !== 'function') { - console.log('PushNotification.getApplicationIconBadgeNumber failure: success ' + 'callback parameter must be a function'); + if (typeof successCallback !== 'function') { + console.log('PushNotification.getApplicationIconBadgeNumber failure: success callback parameter must be a function'); return; - } - - exec(successCallback, errorCallback, 'PushNotification', 'getApplicationIconBadgeNumber', []); } - /** - * Clear all notifications - */ + exec(successCallback, errorCallback, 'PushNotification', 'getApplicationIconBadgeNumber', []); +}; - }, { - key: 'clearAllNotifications', - value: function clearAllNotifications() { - var successCallback = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function () {}; - var errorCallback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : function () {}; +/** + * Get the application icon badge + */ - if (typeof errorCallback !== 'function') { - console.log('PushNotification.clearAllNotifications failure: failure parameter ' + 'not a function'); - return; - } +PushNotification.prototype.clearAllNotifications = function(successCallback, errorCallback) { + if (!successCallback) { successCallback = function() {}; } + if (!errorCallback) { errorCallback = function() {}; } - if (typeof successCallback !== 'function') { - console.log('PushNotification.clearAllNotifications failure: success callback ' + 'parameter must be a function'); + if (typeof errorCallback !== 'function') { + console.log('PushNotification.clearAllNotifications failure: failure parameter not a function'); return; - } + } - exec(successCallback, errorCallback, 'PushNotification', 'clearAllNotifications', []); + if (typeof successCallback !== 'function') { + console.log('PushNotification.clearAllNotifications failure: success callback parameter must be a function'); + return; } - /** - * Listen for an event. - * - * The following events are supported: - * - * - registration - * - notification - * - error - * - * @param {String} eventName to subscribe to. - * @param {Function} callback triggered on the event. - */ - }, { - key: 'on', - value: function on(eventName, callback) { - if (!this.handlers.hasOwnProperty(eventName)) { - this.handlers[eventName] = []; - } - this.handlers[eventName].push(callback); + exec(successCallback, errorCallback, 'PushNotification', 'clearAllNotifications', []); +}; + +/** + * Listen for an event. + * + * Any event is supported, but the following are built-in: + * + * - registration + * - notification + * - error + * + * @param {String} eventName to subscribe to. + * @param {Function} callback triggered on the event. + */ + +PushNotification.prototype.on = function(eventName, callback) { + if (!this._handlers.hasOwnProperty(eventName)) { + this._handlers[eventName] = []; } + this._handlers[eventName].push(callback); +}; - /** - * Remove event listener. - * - * @param {String} eventName to match subscription. - * @param {Function} handle function associated with event. - */ +/** + * Remove event listener. + * + * @param {String} eventName to match subscription. + * @param {Function} handle function associated with event. + */ - }, { - key: 'off', - value: function off(eventName, handle) { - if (this.handlers.hasOwnProperty(eventName)) { - var handleIndex = this.handlers[eventName].indexOf(handle); +PushNotification.prototype.off = function (eventName, handle) { + if (this._handlers.hasOwnProperty(eventName)) { + var handleIndex = this._handlers[eventName].indexOf(handle); if (handleIndex >= 0) { - this.handlers[eventName].splice(handleIndex, 1); + this._handlers[eventName].splice(handleIndex, 1); } - } } +}; - /** - * Emit an event. - * - * This is intended for internal use only. - * - * @param {String} eventName is the event to trigger. - * @param {*} all arguments are passed to the event listeners. - * - * @return {Boolean} is true when the event is triggered otherwise false. - */ - - }, { - key: 'emit', - value: function emit() { - for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { - args[_key2] = arguments[_key2]; - } +/** + * Emit an event. + * + * This is intended for internal use only. + * + * @param {String} eventName is the event to trigger. + * @param {*} all arguments are passed to the event listeners. + * + * @return {Boolean} is true when the event is triggered otherwise false. + */ - var eventName = args.shift(); +PushNotification.prototype.emit = function() { + var args = Array.prototype.slice.call(arguments); + var eventName = args.shift(); - if (!this.handlers.hasOwnProperty(eventName)) { + if (!this._handlers.hasOwnProperty(eventName)) { return false; - } + } - for (var i = 0, length = this.handlers[eventName].length; i < length; i++) { - var callback = this.handlers[eventName][i]; + for (var i = 0, length = this._handlers[eventName].length; i < length; i++) { + var callback = this._handlers[eventName][i]; if (typeof callback === 'function') { - callback.apply(undefined, args); + callback.apply(undefined,args); } else { - console.log('event handler: ' + eventName + ' must be a function'); + console.log('event handler: ' + eventName + ' must be a function'); } - } - - return true; } - }, { - key: 'finish', - value: function finish() { - var successCallback = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function () {}; - var errorCallback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : function () {}; - var id = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'handler'; - - if (typeof successCallback !== 'function') { + + return true; +}; + +PushNotification.prototype.finish = function(successCallback, errorCallback, id) { + if (!successCallback) { successCallback = function() {}; } + if (!errorCallback) { errorCallback = function() {}; } + if (!id) { id = 'handler'; } + + if (typeof successCallback !== 'function') { console.log('finish failure: success callback parameter must be a function'); return; - } + } - if (typeof errorCallback !== 'function') { + if (typeof errorCallback !== 'function') { console.log('finish failure: failure parameter not a function'); return; - } - - exec(successCallback, errorCallback, 'PushNotification', 'finish', [id]); } - }]); - return PushNotification; -}(); + exec(successCallback, errorCallback, 'PushNotification', 'finish', [id]); +}; /*! * Push Notification Plugin. */ module.exports = { - /** - * Register for Push Notifications. - * - * This method will instantiate a new copy of the PushNotification object - * and start the registration process. - * - * @param {Object} options - * @return {PushNotification} instance - */ - - init: function init(options) { - return new PushNotification(options); - }, - - hasPermission: function hasPermission(successCallback, errorCallback) { - exec(successCallback, errorCallback, 'PushNotification', 'hasPermission', []); - }, - - /** - * PushNotification Object. - * - * Expose the PushNotification object for direct use - * and testing. Typically, you should use the - * .init helper method. - */ - PushNotification: PushNotification + /** + * Register for Push Notifications. + * + * This method will instantiate a new copy of the PushNotification object + * and start the registration process. + * + * @param {Object} options + * @return {PushNotification} instance + */ + + init: function(options) { + return new PushNotification(options); + }, + + hasPermission: function(successCallback, errorCallback) { + exec(successCallback, errorCallback, 'PushNotification', 'hasPermission', []); + }, + + /** + * PushNotification Object. + * + * Expose the PushNotification object for direct use + * and testing. Typically, you should use the + * .init helper method. + */ + + PushNotification: PushNotification }; + }); diff --git a/StoneIsland/platforms/android/build.gradle b/StoneIsland/platforms/android/build.gradle index dde2c8c1..b9163fbd 100644 --- a/StoneIsland/platforms/android/build.gradle +++ b/StoneIsland/platforms/android/build.gradle @@ -250,9 +250,9 @@ dependencies { // SUB-PROJECT DEPENDENCIES START debugCompile(project(path: "CordovaLib", configuration: "debug")) releaseCompile(project(path: "CordovaLib", configuration: "release")) - compile "com.android.support:support-v13:25.1.0" - compile "me.leolin:ShortcutBadger:1.1.17@aar" - compile "com.google.firebase:firebase-messaging:11.0.1" + compile "com.android.support:support-v13:23+" + compile "com.google.android.gms:play-services-gcm:9.8+" + compile "me.leolin:ShortcutBadger:1.1.11@aar" // SUB-PROJECT DEPENDENCIES END } diff --git a/StoneIsland/platforms/android/phonegap-plugin-push/stoneisland-push.gradle b/StoneIsland/platforms/android/phonegap-plugin-push/stoneisland-push.gradle index 1506191b..11e735ae 100644 --- a/StoneIsland/platforms/android/phonegap-plugin-push/stoneisland-push.gradle +++ b/StoneIsland/platforms/android/phonegap-plugin-push/stoneisland-push.gradle @@ -16,24 +16,6 @@ android { } defaultConfig { - multiDexEnabled true applicationId = doExtractStringFromManifest("package") } } - -buildscript { - repositories { - jcenter() - mavenLocal() - } - dependencies { - classpath 'com.android.tools.build:gradle:+' - classpath 'com.google.gms:google-services:3.0.0' - } -} - -// apply plugin: 'com.google.gms.google-services' -// class must be used instead of id(string) to be able to apply plugin from non-root gradle file -ext.postBuildExtras = { - apply plugin: com.google.gms.googleservices.GoogleServicesPlugin -} diff --git a/StoneIsland/platforms/android/platform_www/cordova_plugins.js b/StoneIsland/platforms/android/platform_www/cordova_plugins.js index 1b6d56ac..8f70abd6 100755 --- a/StoneIsland/platforms/android/platform_www/cordova_plugins.js +++ b/StoneIsland/platforms/android/platform_www/cordova_plugins.js @@ -66,14 +66,6 @@ module.exports = [ "navigator.notification" ] }, - { - "file": "plugins/cordova-plugin-splashscreen/www/splashscreen.js", - "id": "cordova-plugin-splashscreen.SplashScreen", - "pluginId": "cordova-plugin-splashscreen", - "clobbers": [ - "navigator.splashscreen" - ] - }, { "file": "plugins/cordova-plugin-geolocation/www/android/geolocation.js", "id": "cordova-plugin-geolocation.geolocation", @@ -105,6 +97,14 @@ module.exports = [ "window.StatusBar" ] }, + { + "id": "cordova-plugin-splashscreen.SplashScreen", + "file": "plugins/cordova-plugin-splashscreen/www/splashscreen.js", + "pluginId": "cordova-plugin-splashscreen", + "clobbers": [ + "navigator.splashscreen" + ] + }, { "id": "phonegap-plugin-push.PushNotification", "file": "plugins/phonegap-plugin-push/www/push.js", @@ -121,18 +121,16 @@ module.exports.metadata = "cordova-plugin-x-socialsharing": "5.1.3", "cordova-plugin-customurlscheme": "4.2.0", "cordova-plugin-whitelist": "1.3.0", - "cordova-plugin-console": "1.0.4", "cordova-plugin-device": "1.1.3", "cordova-plugin-network-information": "1.3.0", "cordova-plugin-dialogs": "1.3.0", - "cordova-plugin-splashscreen": "4.0.0", "cordova-plugin-compat": "1.1.0", "cordova-plugin-geolocation": "2.4.0", "ionic-plugin-keyboard": "2.2.1", "cordova-plugin-statusbar": "2.2.3", "cordova-plugin-app-name": "1.0.4", - "phonegap-plugin-push": "2.0.0", - "cordova-plugin-wkwebview-engine": "1.1.3" + "cordova-plugin-splashscreen": "4.0.3", + "phonegap-plugin-push": "1.9.2" }; // BOTTOM OF METADATA }); \ No newline at end of file diff --git a/StoneIsland/platforms/android/platform_www/plugins/cordova-plugin-splashscreen/www/splashscreen.js b/StoneIsland/platforms/android/platform_www/plugins/cordova-plugin-splashscreen/www/splashscreen.js index 0e6a10af..5beaa5fd 100644 --- a/StoneIsland/platforms/android/platform_www/plugins/cordova-plugin-splashscreen/www/splashscreen.js +++ b/StoneIsland/platforms/android/platform_www/plugins/cordova-plugin-splashscreen/www/splashscreen.js @@ -1,4 +1,5 @@ -cordova.define("cordova-plugin-splashscreen.SplashScreen", function(require, exports, module) { /* +cordova.define("cordova-plugin-splashscreen.SplashScreen", function(require, exports, module) { +/* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file diff --git a/StoneIsland/platforms/android/platform_www/plugins/phonegap-plugin-push/www/push.js b/StoneIsland/platforms/android/platform_www/plugins/phonegap-plugin-push/www/push.js index 7234d474..a5315486 100644 --- a/StoneIsland/platforms/android/platform_www/plugins/phonegap-plugin-push/www/push.js +++ b/StoneIsland/platforms/android/platform_www/plugins/phonegap-plugin-push/www/push.js @@ -1,16 +1,4 @@ cordova.define("phonegap-plugin-push.PushNotification", function(require, exports, module) { -/** -* This file has been generated by Babel. -* -* DO NOT EDIT IT DIRECTLY -* -* Edit the JS source file src/js/push.js -**/'use strict'; - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - /* global cordova:false */ /* globals window */ @@ -20,358 +8,322 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons var exec = cordova.require('cordova/exec'); -var PushNotification = function () { - /** - * PushNotification constructor. - * - * @param {Object} options to initiate Push Notifications. - * @return {PushNotification} instance that can be monitored and cancelled. - */ - function PushNotification(options) { - var _this = this; - - _classCallCheck(this, PushNotification); - - this.handlers = { - registration: [], - notification: [], - error: [] +/** + * PushNotification constructor. + * + * @param {Object} options to initiate Push Notifications. + * @return {PushNotification} instance that can be monitored and cancelled. + */ + +var PushNotification = function(options) { + this._handlers = { + 'registration': [], + 'notification': [], + 'error': [] }; // require options parameter if (typeof options === 'undefined') { - throw new Error('The options argument is required.'); + throw new Error('The options argument is required.'); } // store the options to this object instance this.options = options; // triggered on registration and notification - var success = function success(result) { - if (result && typeof result.registrationId !== 'undefined') { - _this.emit('registration', result); - } else if (result && result.additionalData && typeof result.additionalData.actionCallback !== 'undefined') { - var executeFuctionOrEmitEventByName = function executeFuctionOrEmitEventByName(functionName, context) { - for (var _len = arguments.length, args = Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) { - args[_key - 2] = arguments[_key]; - } - - var namespaces = functionName.split('.'); - var func = namespaces.pop(); - for (var i = 0; i < namespaces.length; i++) { - context = context[namespaces[i]]; - } - - if (typeof context[func] === 'function') { - context[func].call(context, args); - } else { - _this.emit(functionName, args); - } - }; - - executeFuctionOrEmitEventByName(result.additionalData.actionCallback, window, result); - } else if (result) { - _this.emit('notification', result); - } + var that = this; + var success = function(result) { + if (result && typeof result.registrationId !== 'undefined') { + that.emit('registration', result); + } else if (result && result.additionalData && typeof result.additionalData.actionCallback !== 'undefined') { + var executeFuctionOrEmitEventByName = function(callbackName, context, arg) { + var namespaces = callbackName.split('.'); + var func = namespaces.pop(); + for (var i = 0; i < namespaces.length; i++) { + context = context[namespaces[i]]; + } + + if (typeof context[func] === 'function') { + context[func].call(context, arg); + } else { + that.emit(callbackName, arg); + } + }; + + executeFuctionOrEmitEventByName(result.additionalData.actionCallback, window, result); + } else if (result) { + that.emit('notification', result); + } }; // triggered on error - var fail = function fail(msg) { - var e = typeof msg === 'string' ? new Error(msg) : msg; - _this.emit('error', e); + var fail = function(msg) { + var e = (typeof msg === 'string') ? new Error(msg) : msg; + that.emit('error', e); }; // wait at least one process tick to allow event subscriptions - setTimeout(function () { - exec(success, fail, 'PushNotification', 'init', [options]); + setTimeout(function() { + exec(success, fail, 'PushNotification', 'init', [options]); }, 10); - } - - /** - * Unregister from push notifications - */ - +}; - _createClass(PushNotification, [{ - key: 'unregister', - value: function unregister(successCallback) { - var _this2 = this; +/** + * Unregister from push notifications + */ - var errorCallback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : function () {}; - var options = arguments[2]; +PushNotification.prototype.unregister = function(successCallback, errorCallback, options) { + if (!errorCallback) { errorCallback = function() {}; } - if (typeof errorCallback !== 'function') { + if (typeof errorCallback !== 'function') { console.log('PushNotification.unregister failure: failure parameter not a function'); return; - } + } - if (typeof successCallback !== 'function') { - console.log('PushNotification.unregister failure: success callback parameter ' + ' must be a function'); + if (typeof successCallback !== 'function') { + console.log('PushNotification.unregister failure: success callback parameter must be a function'); return; - } + } - var cleanHandlersAndPassThrough = function cleanHandlersAndPassThrough() { + var that = this; + var cleanHandlersAndPassThrough = function() { if (!options) { - _this2.handlers = { - registration: [], - notification: [], - error: [] - }; + that._handlers = { + 'registration': [], + 'notification': [], + 'error': [] + }; } successCallback(); - }; - - exec(cleanHandlersAndPassThrough, errorCallback, 'PushNotification', 'unregister', [options]); - } + }; - /** - * subscribe to a topic - * @param {String} topic topic to subscribe - * @param {Function} successCallback success callback - * @param {Function} errorCallback error callback - * @return {void} - */ + exec(cleanHandlersAndPassThrough, errorCallback, 'PushNotification', 'unregister', [options]); +}; - }, { - key: 'subscribe', - value: function subscribe(topic, successCallback) { - var errorCallback = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : function () {}; +/** + * subscribe to a topic + * @param {String} topic topic to subscribe + * @param {Function} successCallback success callback + * @param {Function} errorCallback error callback + * @return {void} + */ +PushNotification.prototype.subscribe = function(topic, successCallback, errorCallback) { + if (!errorCallback) { errorCallback = function() {}; } - if (typeof errorCallback !== 'function') { - console.log('PushNotification.subscribe failure: ' + 'failure parameter not a function'); + if (typeof errorCallback !== 'function') { + console.log('PushNotification.subscribe failure: failure parameter not a function'); return; - } + } - if (typeof successCallback !== 'function') { - console.log('PushNotification.subscribe failure: ' + 'success callback parameter must be a function'); + if (typeof successCallback !== 'function') { + console.log('PushNotification.subscribe failure: success callback parameter must be a function'); return; - } - - exec(successCallback, errorCallback, 'PushNotification', 'subscribe', [topic]); } - /** - * unsubscribe to a topic - * @param {String} topic topic to unsubscribe - * @param {Function} successCallback success callback - * @param {Function} errorCallback error callback - * @return {void} - */ + exec(successCallback, errorCallback, 'PushNotification', 'subscribe', [topic]); +}; - }, { - key: 'unsubscribe', - value: function unsubscribe(topic, successCallback) { - var errorCallback = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : function () {}; +/** + * unsubscribe to a topic + * @param {String} topic topic to unsubscribe + * @param {Function} successCallback success callback + * @param {Function} errorCallback error callback + * @return {void} + */ +PushNotification.prototype.unsubscribe = function(topic, successCallback, errorCallback) { + if (!errorCallback) { errorCallback = function() {}; } - if (typeof errorCallback !== 'function') { + if (typeof errorCallback !== 'function') { console.log('PushNotification.unsubscribe failure: failure parameter not a function'); return; - } + } - if (typeof successCallback !== 'function') { - console.log('PushNotification.unsubscribe failure: ' + 'success callback parameter must be a function'); + if (typeof successCallback !== 'function') { + console.log('PushNotification.unsubscribe failure: success callback parameter must be a function'); return; - } - - exec(successCallback, errorCallback, 'PushNotification', 'unsubscribe', [topic]); } - /** - * Call this to set the application icon badge - */ + exec(successCallback, errorCallback, 'PushNotification', 'unsubscribe', [topic]); +}; - }, { - key: 'setApplicationIconBadgeNumber', - value: function setApplicationIconBadgeNumber(successCallback) { - var errorCallback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : function () {}; - var badge = arguments[2]; +/** + * Call this to set the application icon badge + */ - if (typeof errorCallback !== 'function') { - console.log('PushNotification.setApplicationIconBadgeNumber failure: failure ' + 'parameter not a function'); - return; - } +PushNotification.prototype.setApplicationIconBadgeNumber = function(successCallback, errorCallback, badge) { + if (!errorCallback) { errorCallback = function() {}; } - if (typeof successCallback !== 'function') { - console.log('PushNotification.setApplicationIconBadgeNumber failure: success ' + 'callback parameter must be a function'); + if (typeof errorCallback !== 'function') { + console.log('PushNotification.setApplicationIconBadgeNumber failure: failure parameter not a function'); return; - } + } - exec(successCallback, errorCallback, 'PushNotification', 'setApplicationIconBadgeNumber', [{ badge: badge }]); + if (typeof successCallback !== 'function') { + console.log('PushNotification.setApplicationIconBadgeNumber failure: success callback parameter must be a function'); + return; } - /** - * Get the application icon badge - */ + exec(successCallback, errorCallback, 'PushNotification', 'setApplicationIconBadgeNumber', [{badge: badge}]); +}; + +/** + * Get the application icon badge + */ - }, { - key: 'getApplicationIconBadgeNumber', - value: function getApplicationIconBadgeNumber(successCallback) { - var errorCallback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : function () {}; +PushNotification.prototype.getApplicationIconBadgeNumber = function(successCallback, errorCallback) { + if (!errorCallback) { errorCallback = function() {}; } - if (typeof errorCallback !== 'function') { - console.log('PushNotification.getApplicationIconBadgeNumber failure: failure ' + 'parameter not a function'); + if (typeof errorCallback !== 'function') { + console.log('PushNotification.getApplicationIconBadgeNumber failure: failure parameter not a function'); return; - } + } - if (typeof successCallback !== 'function') { - console.log('PushNotification.getApplicationIconBadgeNumber failure: success ' + 'callback parameter must be a function'); + if (typeof successCallback !== 'function') { + console.log('PushNotification.getApplicationIconBadgeNumber failure: success callback parameter must be a function'); return; - } - - exec(successCallback, errorCallback, 'PushNotification', 'getApplicationIconBadgeNumber', []); } - /** - * Clear all notifications - */ + exec(successCallback, errorCallback, 'PushNotification', 'getApplicationIconBadgeNumber', []); +}; - }, { - key: 'clearAllNotifications', - value: function clearAllNotifications() { - var successCallback = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function () {}; - var errorCallback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : function () {}; +/** + * Get the application icon badge + */ - if (typeof errorCallback !== 'function') { - console.log('PushNotification.clearAllNotifications failure: failure parameter ' + 'not a function'); - return; - } +PushNotification.prototype.clearAllNotifications = function(successCallback, errorCallback) { + if (!successCallback) { successCallback = function() {}; } + if (!errorCallback) { errorCallback = function() {}; } - if (typeof successCallback !== 'function') { - console.log('PushNotification.clearAllNotifications failure: success callback ' + 'parameter must be a function'); + if (typeof errorCallback !== 'function') { + console.log('PushNotification.clearAllNotifications failure: failure parameter not a function'); return; - } + } - exec(successCallback, errorCallback, 'PushNotification', 'clearAllNotifications', []); + if (typeof successCallback !== 'function') { + console.log('PushNotification.clearAllNotifications failure: success callback parameter must be a function'); + return; } - /** - * Listen for an event. - * - * The following events are supported: - * - * - registration - * - notification - * - error - * - * @param {String} eventName to subscribe to. - * @param {Function} callback triggered on the event. - */ - }, { - key: 'on', - value: function on(eventName, callback) { - if (!this.handlers.hasOwnProperty(eventName)) { - this.handlers[eventName] = []; - } - this.handlers[eventName].push(callback); + exec(successCallback, errorCallback, 'PushNotification', 'clearAllNotifications', []); +}; + +/** + * Listen for an event. + * + * Any event is supported, but the following are built-in: + * + * - registration + * - notification + * - error + * + * @param {String} eventName to subscribe to. + * @param {Function} callback triggered on the event. + */ + +PushNotification.prototype.on = function(eventName, callback) { + if (!this._handlers.hasOwnProperty(eventName)) { + this._handlers[eventName] = []; } + this._handlers[eventName].push(callback); +}; - /** - * Remove event listener. - * - * @param {String} eventName to match subscription. - * @param {Function} handle function associated with event. - */ +/** + * Remove event listener. + * + * @param {String} eventName to match subscription. + * @param {Function} handle function associated with event. + */ - }, { - key: 'off', - value: function off(eventName, handle) { - if (this.handlers.hasOwnProperty(eventName)) { - var handleIndex = this.handlers[eventName].indexOf(handle); +PushNotification.prototype.off = function (eventName, handle) { + if (this._handlers.hasOwnProperty(eventName)) { + var handleIndex = this._handlers[eventName].indexOf(handle); if (handleIndex >= 0) { - this.handlers[eventName].splice(handleIndex, 1); + this._handlers[eventName].splice(handleIndex, 1); } - } } +}; - /** - * Emit an event. - * - * This is intended for internal use only. - * - * @param {String} eventName is the event to trigger. - * @param {*} all arguments are passed to the event listeners. - * - * @return {Boolean} is true when the event is triggered otherwise false. - */ - - }, { - key: 'emit', - value: function emit() { - for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { - args[_key2] = arguments[_key2]; - } +/** + * Emit an event. + * + * This is intended for internal use only. + * + * @param {String} eventName is the event to trigger. + * @param {*} all arguments are passed to the event listeners. + * + * @return {Boolean} is true when the event is triggered otherwise false. + */ - var eventName = args.shift(); +PushNotification.prototype.emit = function() { + var args = Array.prototype.slice.call(arguments); + var eventName = args.shift(); - if (!this.handlers.hasOwnProperty(eventName)) { + if (!this._handlers.hasOwnProperty(eventName)) { return false; - } + } - for (var i = 0, length = this.handlers[eventName].length; i < length; i++) { - var callback = this.handlers[eventName][i]; + for (var i = 0, length = this._handlers[eventName].length; i < length; i++) { + var callback = this._handlers[eventName][i]; if (typeof callback === 'function') { - callback.apply(undefined, args); + callback.apply(undefined,args); } else { - console.log('event handler: ' + eventName + ' must be a function'); + console.log('event handler: ' + eventName + ' must be a function'); } - } - - return true; } - }, { - key: 'finish', - value: function finish() { - var successCallback = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function () {}; - var errorCallback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : function () {}; - var id = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'handler'; - - if (typeof successCallback !== 'function') { + + return true; +}; + +PushNotification.prototype.finish = function(successCallback, errorCallback, id) { + if (!successCallback) { successCallback = function() {}; } + if (!errorCallback) { errorCallback = function() {}; } + if (!id) { id = 'handler'; } + + if (typeof successCallback !== 'function') { console.log('finish failure: success callback parameter must be a function'); return; - } + } - if (typeof errorCallback !== 'function') { + if (typeof errorCallback !== 'function') { console.log('finish failure: failure parameter not a function'); return; - } - - exec(successCallback, errorCallback, 'PushNotification', 'finish', [id]); } - }]); - return PushNotification; -}(); + exec(successCallback, errorCallback, 'PushNotification', 'finish', [id]); +}; /*! * Push Notification Plugin. */ module.exports = { - /** - * Register for Push Notifications. - * - * This method will instantiate a new copy of the PushNotification object - * and start the registration process. - * - * @param {Object} options - * @return {PushNotification} instance - */ - - init: function init(options) { - return new PushNotification(options); - }, - - hasPermission: function hasPermission(successCallback, errorCallback) { - exec(successCallback, errorCallback, 'PushNotification', 'hasPermission', []); - }, - - /** - * PushNotification Object. - * - * Expose the PushNotification object for direct use - * and testing. Typically, you should use the - * .init helper method. - */ - PushNotification: PushNotification + /** + * Register for Push Notifications. + * + * This method will instantiate a new copy of the PushNotification object + * and start the registration process. + * + * @param {Object} options + * @return {PushNotification} instance + */ + + init: function(options) { + return new PushNotification(options); + }, + + hasPermission: function(successCallback, errorCallback) { + exec(successCallback, errorCallback, 'PushNotification', 'hasPermission', []); + }, + + /** + * PushNotification Object. + * + * Expose the PushNotification object for direct use + * and testing. Typically, you should use the + * .init helper method. + */ + + PushNotification: PushNotification }; + }); diff --git a/StoneIsland/platforms/android/project.properties b/StoneIsland/platforms/android/project.properties index 0a077db0..6936daa2 100755 --- a/StoneIsland/platforms/android/project.properties +++ b/StoneIsland/platforms/android/project.properties @@ -11,8 +11,8 @@ #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt # Project target. target=android-25 -cordova.gradle.include.1=phonegap-plugin-push/stoneisland-push.gradle -cordova.system.library.1=com.android.support:support-v13:25.1.0 -cordova.system.library.2=me.leolin:ShortcutBadger:1.1.17@aar -cordova.system.library.3=com.google.firebase:firebase-messaging:11.0.1 android.library.reference.1=CordovaLib +cordova.gradle.include.1=phonegap-plugin-push/stoneisland-push.gradle +cordova.system.library.1=com.android.support:support-v13:23+ +cordova.system.library.2=com.google.android.gms:play-services-gcm:9.8+ +cordova.system.library.3=me.leolin:ShortcutBadger:1.1.11@aar \ No newline at end of file diff --git a/StoneIsland/platforms/android/res/values/strings.xml b/StoneIsland/platforms/android/res/values/strings.xml index bd922fe9..4a48baa7 100755 --- a/StoneIsland/platforms/android/res/values/strings.xml +++ b/StoneIsland/platforms/android/res/values/strings.xml @@ -3,4 +3,5 @@ Stone Island @string/app_name @string/launcher_name + 85075801930 diff --git a/StoneIsland/platforms/android/res/xml/config.xml b/StoneIsland/platforms/android/res/xml/config.xml index 549366ea..9f4cb684 100644 --- a/StoneIsland/platforms/android/res/xml/config.xml +++ b/StoneIsland/platforms/android/res/xml/config.xml @@ -22,10 +22,6 @@ - - - - @@ -71,6 +67,10 @@ + + + + diff --git a/StoneIsland/platforms/android/src/com/adobe/phonegap/push/BackgroundActionButtonHandler.java b/StoneIsland/platforms/android/src/com/adobe/phonegap/push/BackgroundActionButtonHandler.java index 4456f525..3ccea6cb 100644 --- a/StoneIsland/platforms/android/src/com/adobe/phonegap/push/BackgroundActionButtonHandler.java +++ b/StoneIsland/platforms/android/src/com/adobe/phonegap/push/BackgroundActionButtonHandler.java @@ -9,7 +9,7 @@ import android.util.Log; import android.support.v4.app.RemoteInput; public class BackgroundActionButtonHandler extends BroadcastReceiver implements PushConstants { - private static String LOG_TAG = "Push_BGActionButton"; + private static String LOG_TAG = "PushPlugin_BackgroundActionButtonHandler"; @Override public void onReceive(Context context, Intent intent) { @@ -19,7 +19,7 @@ public class BackgroundActionButtonHandler extends BroadcastReceiver implements int notId = intent.getIntExtra(NOT_ID, 0); Log.d(LOG_TAG, "not id = " + notId); NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); - notificationManager.cancel(FCMService.getAppName(context), notId); + notificationManager.cancel(GCMIntentService.getAppName(context), notId); if (extras != null) { Bundle originalExtras = extras.getBundle(PUSH_BUNDLE); diff --git a/StoneIsland/platforms/android/src/com/adobe/phonegap/push/FCMService.java b/StoneIsland/platforms/android/src/com/adobe/phonegap/push/FCMService.java deleted file mode 100644 index af328fb2..00000000 --- a/StoneIsland/platforms/android/src/com/adobe/phonegap/push/FCMService.java +++ /dev/null @@ -1,891 +0,0 @@ -package com.adobe.phonegap.push; - -import android.annotation.SuppressLint; -import android.app.Notification; -import android.app.NotificationManager; -import android.app.PendingIntent; -import android.content.ContentResolver; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.content.res.AssetManager; -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Color; -import android.graphics.PorterDuff; -import android.graphics.PorterDuffXfermode; -import android.graphics.Rect; -import android.graphics.RectF; -import android.graphics.Paint; -import android.graphics.Canvas; -import android.net.Uri; -import android.os.Bundle; -import android.support.v4.app.NotificationCompat; -import android.support.v4.app.NotificationCompat.WearableExtender; -import android.support.v4.app.RemoteInput; -import android.text.Html; -import android.text.Spanned; -import android.util.Log; - -import com.google.firebase.messaging.FirebaseMessagingService; -import com.google.firebase.messaging.RemoteMessage; - -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - -import java.io.IOException; -import java.io.InputStream; -import java.net.HttpURLConnection; -import java.net.URL; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.Random; - -@SuppressLint("NewApi") -public class FCMService extends FirebaseMessagingService implements PushConstants { - - private static final String LOG_TAG = "Push_FCMService"; - private static HashMap> messageMap = new HashMap>(); - - public void setNotification(int notId, String message){ - ArrayList messageList = messageMap.get(notId); - if(messageList == null) { - messageList = new ArrayList(); - messageMap.put(notId, messageList); - } - - if(message.isEmpty()){ - messageList.clear(); - }else{ - messageList.add(message); - } - } - - @Override - public void onMessageReceived(RemoteMessage message){ - - String from = message.getFrom(); - Log.d(LOG_TAG, "onMessage - from: " + from); - - Bundle extras = new Bundle(); - - if (message.getNotification()!=null) { - extras.putString(TITLE,message.getNotification().getTitle()); - extras.putString(MESSAGE,message.getNotification().getBody()); - } - for (Map.Entry entry : message.getData().entrySet()) { - extras.putString(entry.getKey(), entry.getValue()); - } - - if (extras != null && isAvailableSender(from)) { - Context applicationContext = getApplicationContext(); - - SharedPreferences prefs = applicationContext.getSharedPreferences(PushPlugin.COM_ADOBE_PHONEGAP_PUSH, Context.MODE_PRIVATE); - boolean forceShow = prefs.getBoolean(FORCE_SHOW, false); - boolean clearBadge = prefs.getBoolean(CLEAR_BADGE, false); - String messageKey = prefs.getString(MESSAGE_KEY, MESSAGE); - String titleKey = prefs.getString(TITLE_KEY, TITLE); - - extras = normalizeExtras(applicationContext, extras, messageKey, titleKey); - - if (clearBadge) { - PushPlugin.setApplicationIconBadgeNumber(getApplicationContext(), 0); - } - - // if we are in the foreground and forceShow is `false` only send data - if (!forceShow && PushPlugin.isInForeground()) { - Log.d(LOG_TAG, "foreground"); - extras.putBoolean(FOREGROUND, true); - extras.putBoolean(COLDSTART, false); - PushPlugin.sendExtras(extras); - } - // if we are in the foreground and forceShow is `true`, force show the notification if the data has at least a message or title - else if (forceShow && PushPlugin.isInForeground()) { - Log.d(LOG_TAG, "foreground force"); - extras.putBoolean(FOREGROUND, true); - extras.putBoolean(COLDSTART, false); - - showNotificationIfPossible(applicationContext, extras); - } - // if we are not in the foreground always send notification if the data has at least a message or title - else { - Log.d(LOG_TAG, "background"); - extras.putBoolean(FOREGROUND, false); - extras.putBoolean(COLDSTART, PushPlugin.isActive()); - - showNotificationIfPossible(applicationContext, extras); - } - } - } - - /* - * Change a values key in the extras bundle - */ - private void replaceKey(Context context, String oldKey, String newKey, Bundle extras, Bundle newExtras) { - Object value = extras.get(oldKey); - if ( value != null ) { - if (value instanceof String) { - value = localizeKey(context, newKey, (String) value); - - newExtras.putString(newKey, (String) value); - } else if (value instanceof Boolean) { - newExtras.putBoolean(newKey, (Boolean) value); - } else if (value instanceof Number) { - newExtras.putDouble(newKey, ((Number) value).doubleValue()); - } else { - newExtras.putString(newKey, String.valueOf(value)); - } - } - } - - /* - * Normalize localization for key - */ - private String localizeKey(Context context, String key, String value) { - if (key.equals(TITLE) || key.equals(MESSAGE) || key.equals(SUMMARY_TEXT)) { - try { - JSONObject localeObject = new JSONObject(value); - - String localeKey = localeObject.getString(LOC_KEY); - - ArrayList localeFormatData = new ArrayList(); - if (!localeObject.isNull(LOC_DATA)) { - String localeData = localeObject.getString(LOC_DATA); - JSONArray localeDataArray = new JSONArray(localeData); - for (int i = 0 ; i < localeDataArray.length(); i++) { - localeFormatData.add(localeDataArray.getString(i)); - } - } - - String packageName = context.getPackageName(); - Resources resources = context.getResources(); - - int resourceId = resources.getIdentifier(localeKey, "string", packageName); - - if (resourceId != 0) { - return resources.getString(resourceId, localeFormatData.toArray()); - } - else { - Log.d(LOG_TAG, "can't find resource for locale key = " + localeKey); - - return value; - } - } - catch(JSONException e) { - Log.d(LOG_TAG, "no locale found for key = " + key + ", error " + e.getMessage()); - - return value; - } - } - - return value; - } - - /* - * Replace alternate keys with our canonical value - */ - private String normalizeKey(String key, String messageKey, String titleKey) { - if (key.equals(BODY) || key.equals(ALERT) || key.equals(MP_MESSAGE) || key.equals(GCM_NOTIFICATION_BODY) || key.equals(TWILIO_BODY) || key.equals(messageKey)) { - return MESSAGE; - } else if (key.equals(TWILIO_TITLE) || key.equals(SUBJECT) || key.equals(titleKey)) { - return TITLE; - }else if (key.equals(MSGCNT) || key.equals(BADGE)) { - return COUNT; - } else if (key.equals(SOUNDNAME) || key.equals(TWILIO_SOUND)) { - return SOUND; - } else if (key.startsWith(GCM_NOTIFICATION)) { - return key.substring(GCM_NOTIFICATION.length()+1, key.length()); - } else if (key.startsWith(GCM_N)) { - return key.substring(GCM_N.length()+1, key.length()); - } else if (key.startsWith(UA_PREFIX)) { - key = key.substring(UA_PREFIX.length()+1, key.length()); - return key.toLowerCase(); - } else { - return key; - } - } - - /* - * Parse bundle into normalized keys. - */ - private Bundle normalizeExtras(Context context, Bundle extras, String messageKey, String titleKey) { - Log.d(LOG_TAG, "normalize extras"); - Iterator it = extras.keySet().iterator(); - Bundle newExtras = new Bundle(); - - while (it.hasNext()) { - String key = it.next(); - - Log.d(LOG_TAG, "key = " + key); - - // If normalizeKeythe key is "data" or "message" and the value is a json object extract - // This is to support parse.com and other services. Issue #147 and pull #218 - if (key.equals(PARSE_COM_DATA) || key.equals(MESSAGE) || key.equals(messageKey)) { - Object json = extras.get(key); - // Make sure data is json object stringified - if ( json instanceof String && ((String) json).startsWith("{") ) { - Log.d(LOG_TAG, "extracting nested message data from key = " + key); - try { - // If object contains message keys promote each value to the root of the bundle - JSONObject data = new JSONObject((String) json); - if ( data.has(ALERT) || data.has(MESSAGE) || data.has(BODY) || data.has(TITLE) || - data.has(messageKey) || data.has(titleKey) ) { - Iterator jsonIter = data.keys(); - while (jsonIter.hasNext()) { - String jsonKey = jsonIter.next(); - - Log.d(LOG_TAG, "key = data/" + jsonKey); - - String value = data.getString(jsonKey); - jsonKey = normalizeKey(jsonKey, messageKey, titleKey); - value = localizeKey(context, jsonKey, value); - - newExtras.putString(jsonKey, value); - } - } - } catch( JSONException e) { - Log.e(LOG_TAG, "normalizeExtras: JSON exception"); - } - } else { - String newKey = normalizeKey(key, messageKey, titleKey); - Log.d(LOG_TAG, "replace key " + key + " with " + newKey); - replaceKey(context, key, newKey, extras, newExtras); - } - } else if (key.equals(("notification"))) { - Bundle value = extras.getBundle(key); - Iterator iterator = value.keySet().iterator(); - while (iterator.hasNext()) { - String notifkey = iterator.next(); - - Log.d(LOG_TAG, "notifkey = " + notifkey); - String newKey = normalizeKey(notifkey, messageKey, titleKey); - Log.d(LOG_TAG, "replace key " + notifkey + " with " + newKey); - - String valueData = value.getString(notifkey); - valueData = localizeKey(context, newKey, valueData); - - newExtras.putString(newKey, valueData); - } - continue; - // In case we weren't working on the payload data node or the notification node, - // normalize the key. - // This allows to have "message" as the payload data key without colliding - // with the other "message" key (holding the body of the payload) - // See issue #1663 - } else { - String newKey = normalizeKey(key, messageKey, titleKey); - Log.d(LOG_TAG, "replace key " + key + " with " + newKey); - replaceKey(context, key, newKey, extras, newExtras); - } - - } // while - - return newExtras; - } - - private int extractBadgeCount(Bundle extras) { - int count = -1; - String msgcnt = extras.getString(COUNT); - - try { - if (msgcnt != null) { - count = Integer.parseInt(msgcnt); - } - } catch (NumberFormatException e) { - Log.e(LOG_TAG, e.getLocalizedMessage(), e); - } - - return count; - } - - private void showNotificationIfPossible (Context context, Bundle extras) { - - // Send a notification if there is a message or title, otherwise just send data - String message = extras.getString(MESSAGE); - String title = extras.getString(TITLE); - String contentAvailable = extras.getString(CONTENT_AVAILABLE); - String forceStart = extras.getString(FORCE_START); - int badgeCount = extractBadgeCount(extras); - if (badgeCount >= 0) { - Log.d(LOG_TAG, "count =[" + badgeCount + "]"); - PushPlugin.setApplicationIconBadgeNumber(context, badgeCount); - } - - Log.d(LOG_TAG, "message =[" + message + "]"); - Log.d(LOG_TAG, "title =[" + title + "]"); - Log.d(LOG_TAG, "contentAvailable =[" + contentAvailable + "]"); - Log.d(LOG_TAG, "forceStart =[" + forceStart + "]"); - - if ((message != null && message.length() != 0) || - (title != null && title.length() != 0)) { - - Log.d(LOG_TAG, "create notification"); - - if(title == null || title.isEmpty()){ - extras.putString(TITLE, getAppName(this)); - } - - createNotification(context, extras); - } - - if(!PushPlugin.isActive() && "1".equals(forceStart)){ - Log.d(LOG_TAG, "app is not running but we should start it and put in background"); - Intent intent = new Intent(this, PushHandlerActivity.class); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - intent.putExtra(PUSH_BUNDLE, extras); - intent.putExtra(START_IN_BACKGROUND, true); - intent.putExtra(FOREGROUND, false); - startActivity(intent); - } else if ("1".equals(contentAvailable)) { - Log.d(LOG_TAG, "app is not running and content available true"); - Log.d(LOG_TAG, "send notification event"); - PushPlugin.sendExtras(extras); - } - } - - public void createNotification(Context context, Bundle extras) { - NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); - String appName = getAppName(this); - String packageName = context.getPackageName(); - Resources resources = context.getResources(); - - int notId = parseInt(NOT_ID, extras); - Intent notificationIntent = new Intent(this, PushHandlerActivity.class); - notificationIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP); - notificationIntent.putExtra(PUSH_BUNDLE, extras); - notificationIntent.putExtra(NOT_ID, notId); - - int requestCode = new Random().nextInt(); - PendingIntent contentIntent = PendingIntent.getActivity(this, requestCode, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT); - - Intent dismissedNotificationIntent = new Intent(this, PushDismissedHandler.class); - dismissedNotificationIntent.putExtra(PUSH_BUNDLE, extras); - dismissedNotificationIntent.putExtra(NOT_ID, notId); - dismissedNotificationIntent.putExtra(DISMISSED, true); - dismissedNotificationIntent.setAction(PUSH_DISMISSED); - - requestCode = new Random().nextInt(); - PendingIntent deleteIntent = PendingIntent.getBroadcast(this, requestCode, dismissedNotificationIntent, PendingIntent.FLAG_CANCEL_CURRENT); - - NotificationCompat.Builder mBuilder = - new NotificationCompat.Builder(context) - .setWhen(System.currentTimeMillis()) - .setContentTitle(fromHtml(extras.getString(TITLE))) - .setTicker(fromHtml(extras.getString(TITLE))) - .setContentIntent(contentIntent) - .setDeleteIntent(deleteIntent) - .setAutoCancel(true); - - SharedPreferences prefs = context.getSharedPreferences(PushPlugin.COM_ADOBE_PHONEGAP_PUSH, Context.MODE_PRIVATE); - String localIcon = prefs.getString(ICON, null); - String localIconColor = prefs.getString(ICON_COLOR, null); - boolean soundOption = prefs.getBoolean(SOUND, true); - boolean vibrateOption = prefs.getBoolean(VIBRATE, true); - Log.d(LOG_TAG, "stored icon=" + localIcon); - Log.d(LOG_TAG, "stored iconColor=" + localIconColor); - Log.d(LOG_TAG, "stored sound=" + soundOption); - Log.d(LOG_TAG, "stored vibrate=" + vibrateOption); - - /* - * Notification Vibration - */ - - setNotificationVibration(extras, vibrateOption, mBuilder); - - /* - * Notification Icon Color - * - * Sets the small-icon background color of the notification. - * To use, add the `iconColor` key to plugin android options - * - */ - setNotificationIconColor(extras.getString("color"), mBuilder, localIconColor); - - /* - * Notification Icon - * - * Sets the small-icon of the notification. - * - * - checks the plugin options for `icon` key - * - if none, uses the application icon - * - * The icon value must be a string that maps to a drawable resource. - * If no resource is found, falls - * - */ - setNotificationSmallIcon(context, extras, packageName, resources, mBuilder, localIcon); - - /* - * Notification Large-Icon - * - * Sets the large-icon of the notification - * - * - checks the gcm data for the `image` key - * - checks to see if remote image, loads it. - * - checks to see if assets image, Loads It. - * - checks to see if resource image, LOADS IT! - * - if none, we don't set the large icon - * - */ - setNotificationLargeIcon(extras, packageName, resources, mBuilder); - - /* - * Notification Sound - */ - if (soundOption) { - setNotificationSound(context, extras, mBuilder); - } - - /* - * LED Notification - */ - setNotificationLedColor(extras, mBuilder); - - /* - * Priority Notification - */ - setNotificationPriority(extras, mBuilder); - - /* - * Notification message - */ - setNotificationMessage(notId, extras, mBuilder); - - /* - * Notification count - */ - setNotificationCount(context, extras, mBuilder); - - /* - * Notification count - */ - setVisibility(context, extras, mBuilder); - - /* - * Notification add actions - */ - createActions(extras, mBuilder, resources, packageName, notId); - - mNotificationManager.notify(appName, notId, mBuilder.build()); - } - - private void updateIntent(Intent intent, String callback, Bundle extras, boolean foreground, int notId) { - intent.putExtra(CALLBACK, callback); - intent.putExtra(PUSH_BUNDLE, extras); - intent.putExtra(FOREGROUND, foreground); - intent.putExtra(NOT_ID, notId); - } - - private void createActions(Bundle extras, NotificationCompat.Builder mBuilder, Resources resources, String packageName, int notId) { - Log.d(LOG_TAG, "create actions: with in-line"); - String actions = extras.getString(ACTIONS); - if (actions != null) { - try { - JSONArray actionsArray = new JSONArray(actions); - ArrayList wActions = new ArrayList(); - for (int i=0; i < actionsArray.length(); i++) { - int min = 1; - int max = 2000000000; - Random random = new Random(); - int uniquePendingIntentRequestCode = random.nextInt((max - min) + 1) + min; - Log.d(LOG_TAG, "adding action"); - JSONObject action = actionsArray.getJSONObject(i); - Log.d(LOG_TAG, "adding callback = " + action.getString(CALLBACK)); - boolean foreground = action.optBoolean(FOREGROUND, true); - boolean inline = action.optBoolean("inline", false); - Intent intent = null; - PendingIntent pIntent = null; - if (inline) { - Log.d(LOG_TAG, "Version: " + android.os.Build.VERSION.SDK_INT + " = " + android.os.Build.VERSION_CODES.M); - if (android.os.Build.VERSION.SDK_INT <= android.os.Build.VERSION_CODES.M) { - Log.d(LOG_TAG, "push activity"); - intent = new Intent(this, PushHandlerActivity.class); - } else { - Log.d(LOG_TAG, "push receiver"); - intent = new Intent(this, BackgroundActionButtonHandler.class); - } - - updateIntent(intent, action.getString(CALLBACK), extras, foreground, notId); - - if (android.os.Build.VERSION.SDK_INT <= android.os.Build.VERSION_CODES.M) { - Log.d(LOG_TAG, "push activity for notId " + notId); - pIntent = PendingIntent.getActivity(this, uniquePendingIntentRequestCode, intent, PendingIntent.FLAG_ONE_SHOT); - } else { - Log.d(LOG_TAG, "push receiver for notId " + notId); - pIntent = PendingIntent.getBroadcast(this, uniquePendingIntentRequestCode, intent, PendingIntent.FLAG_ONE_SHOT); - } - } else if (foreground) { - intent = new Intent(this, PushHandlerActivity.class); - updateIntent(intent, action.getString(CALLBACK), extras, foreground, notId); - pIntent = PendingIntent.getActivity(this, uniquePendingIntentRequestCode, intent, PendingIntent.FLAG_UPDATE_CURRENT); - } else { - intent = new Intent(this, BackgroundActionButtonHandler.class); - updateIntent(intent, action.getString(CALLBACK), extras, foreground, notId); - pIntent = PendingIntent.getBroadcast(this, uniquePendingIntentRequestCode, intent, PendingIntent.FLAG_UPDATE_CURRENT); - } - - NotificationCompat.Action.Builder actionBuilder = - new NotificationCompat.Action.Builder(resources.getIdentifier(action.optString(ICON, ""), DRAWABLE, packageName), - action.getString(TITLE), pIntent); - - RemoteInput remoteInput = null; - if (inline) { - Log.d(LOG_TAG, "create remote input"); - String replyLabel = "Enter your reply here"; - remoteInput = - new RemoteInput.Builder(INLINE_REPLY) - .setLabel(replyLabel) - .build(); - actionBuilder.addRemoteInput(remoteInput); - } - - NotificationCompat.Action wAction = actionBuilder.build(); - wActions.add(actionBuilder.build()); - - if (inline) { - mBuilder.addAction(wAction); - } else { - mBuilder.addAction(resources.getIdentifier(action.optString(ICON, ""), DRAWABLE, packageName), - action.getString(TITLE), pIntent); - } - wAction = null; - pIntent = null; - } - mBuilder.extend(new WearableExtender().addActions(wActions)); - wActions.clear(); - } catch(JSONException e) { - // nope - } - } - } - - private void setNotificationCount(Context context, Bundle extras, NotificationCompat.Builder mBuilder) { - int count = extractBadgeCount(extras); - if (count >= 0) { - Log.d(LOG_TAG, "count =[" + count + "]"); - mBuilder.setNumber(count); - } - } - - - private void setVisibility(Context context, Bundle extras, NotificationCompat.Builder mBuilder) { - String visibilityStr = extras.getString(VISIBILITY); - if (visibilityStr != null) { - try { - Integer visibility = Integer.parseInt(visibilityStr); - if (visibility >= NotificationCompat.VISIBILITY_SECRET && visibility <= NotificationCompat.VISIBILITY_PUBLIC) { - mBuilder.setVisibility(visibility); - } else { - Log.e(LOG_TAG, "Visibility parameter must be between -1 and 1"); - } - } catch (NumberFormatException e) { - e.printStackTrace(); - } - } - } - - private void setNotificationVibration(Bundle extras, Boolean vibrateOption, NotificationCompat.Builder mBuilder) { - String vibrationPattern = extras.getString(VIBRATION_PATTERN); - if (vibrationPattern != null) { - String[] items = vibrationPattern.replaceAll("\\[", "").replaceAll("\\]", "").split(","); - long[] results = new long[items.length]; - for (int i = 0; i < items.length; i++) { - try { - results[i] = Long.parseLong(items[i].trim()); - } catch (NumberFormatException nfe) {} - } - mBuilder.setVibrate(results); - } else { - if (vibrateOption) { - mBuilder.setDefaults(Notification.DEFAULT_VIBRATE); - } - } - } - - private void setNotificationMessage(int notId, Bundle extras, NotificationCompat.Builder mBuilder) { - String message = extras.getString(MESSAGE); - - String style = extras.getString(STYLE, STYLE_TEXT); - if(STYLE_INBOX.equals(style)) { - setNotification(notId, message); - - mBuilder.setContentText(fromHtml(message)); - - ArrayList messageList = messageMap.get(notId); - Integer sizeList = messageList.size(); - if (sizeList > 1) { - String sizeListMessage = sizeList.toString(); - String stacking = sizeList + " more"; - if (extras.getString(SUMMARY_TEXT) != null) { - stacking = extras.getString(SUMMARY_TEXT); - stacking = stacking.replace("%n%", sizeListMessage); - } - NotificationCompat.InboxStyle notificationInbox = new NotificationCompat.InboxStyle() - .setBigContentTitle(fromHtml(extras.getString(TITLE))) - .setSummaryText(fromHtml(stacking)); - - for (int i = messageList.size() - 1; i >= 0; i--) { - notificationInbox.addLine(fromHtml(messageList.get(i))); - } - - mBuilder.setStyle(notificationInbox); - } else { - NotificationCompat.BigTextStyle bigText = new NotificationCompat.BigTextStyle(); - if (message != null) { - bigText.bigText(fromHtml(message)); - bigText.setBigContentTitle(fromHtml(extras.getString(TITLE))); - mBuilder.setStyle(bigText); - } - } - } else if (STYLE_PICTURE.equals(style)) { - setNotification(notId, ""); - - NotificationCompat.BigPictureStyle bigPicture = new NotificationCompat.BigPictureStyle(); - bigPicture.bigPicture(getBitmapFromURL(extras.getString(PICTURE))); - bigPicture.setBigContentTitle(fromHtml(extras.getString(TITLE))); - bigPicture.setSummaryText(fromHtml(extras.getString(SUMMARY_TEXT))); - - mBuilder.setContentTitle(fromHtml(extras.getString(TITLE))); - mBuilder.setContentText(fromHtml(message)); - - mBuilder.setStyle(bigPicture); - } else { - setNotification(notId, ""); - - NotificationCompat.BigTextStyle bigText = new NotificationCompat.BigTextStyle(); - - if (message != null) { - mBuilder.setContentText(fromHtml(message)); - - bigText.bigText(fromHtml(message)); - bigText.setBigContentTitle(fromHtml(extras.getString(TITLE))); - - String summaryText = extras.getString(SUMMARY_TEXT); - if (summaryText != null) { - bigText.setSummaryText(fromHtml(summaryText)); - } - - mBuilder.setStyle(bigText); - } - /* - else { - mBuilder.setContentText(""); - } - */ - } - } - - private void setNotificationSound(Context context, Bundle extras, NotificationCompat.Builder mBuilder) { - String soundname = extras.getString(SOUNDNAME); - if (soundname == null) { - soundname = extras.getString(SOUND); - } - if (SOUND_RINGTONE.equals(soundname)) { - mBuilder.setSound(android.provider.Settings.System.DEFAULT_RINGTONE_URI); - } else if (soundname != null && !soundname.contentEquals(SOUND_DEFAULT)) { - Uri sound = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE - + "://" + context.getPackageName() + "/raw/" + soundname); - Log.d(LOG_TAG, sound.toString()); - mBuilder.setSound(sound); - } else { - mBuilder.setSound(android.provider.Settings.System.DEFAULT_NOTIFICATION_URI); - } - } - - private void setNotificationLedColor(Bundle extras, NotificationCompat.Builder mBuilder) { - String ledColor = extras.getString(LED_COLOR); - if (ledColor != null) { - // Converts parse Int Array from ledColor - String[] items = ledColor.replaceAll("\\[", "").replaceAll("\\]", "").split(","); - int[] results = new int[items.length]; - for (int i = 0; i < items.length; i++) { - try { - results[i] = Integer.parseInt(items[i].trim()); - } catch (NumberFormatException nfe) {} - } - if (results.length == 4) { - mBuilder.setLights(Color.argb(results[0], results[1], results[2], results[3]), 500, 500); - } else { - Log.e(LOG_TAG, "ledColor parameter must be an array of length == 4 (ARGB)"); - } - } - } - - private void setNotificationPriority(Bundle extras, NotificationCompat.Builder mBuilder) { - String priorityStr = extras.getString(PRIORITY); - if (priorityStr != null) { - try { - Integer priority = Integer.parseInt(priorityStr); - if (priority >= NotificationCompat.PRIORITY_MIN && priority <= NotificationCompat.PRIORITY_MAX) { - mBuilder.setPriority(priority); - } else { - Log.e(LOG_TAG, "Priority parameter must be between -2 and 2"); - } - } catch (NumberFormatException e) { - e.printStackTrace(); - } - } - } - - private Bitmap getCircleBitmap(Bitmap bitmap) { - if (bitmap == null) { - return null; - } - - final Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888); - final Canvas canvas = new Canvas(output); - final int color = Color.RED; - final Paint paint = new Paint(); - final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); - final RectF rectF = new RectF(rect); - - paint.setAntiAlias(true); - canvas.drawARGB(0, 0, 0, 0); - paint.setColor(color); - float cx = bitmap.getWidth()/2; - float cy = bitmap.getHeight()/2; - float radius = cx < cy ? cx : cy; - canvas.drawCircle(cx,cy,radius,paint); - - paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); - canvas.drawBitmap(bitmap, rect, rect, paint); - - bitmap.recycle(); - - return output; - } - - private void setNotificationLargeIcon(Bundle extras, String packageName, Resources resources, NotificationCompat.Builder mBuilder) { - String gcmLargeIcon = extras.getString(IMAGE); // from gcm - String imageType = extras.getString(IMAGE_TYPE, IMAGE_TYPE_SQUARE); - if (gcmLargeIcon != null && !"".equals(gcmLargeIcon)) { - if (gcmLargeIcon.startsWith("http://") || gcmLargeIcon.startsWith("https://")) { - Bitmap bitmap = getBitmapFromURL(gcmLargeIcon); - if (IMAGE_TYPE_SQUARE.equalsIgnoreCase(imageType)) { - mBuilder.setLargeIcon(bitmap); - } else { - Bitmap bm = getCircleBitmap(bitmap); - mBuilder.setLargeIcon(bm); - } - Log.d(LOG_TAG, "using remote large-icon from gcm"); - } else { - AssetManager assetManager = getAssets(); - InputStream istr; - try { - istr = assetManager.open(gcmLargeIcon); - Bitmap bitmap = BitmapFactory.decodeStream(istr); - if (IMAGE_TYPE_SQUARE.equalsIgnoreCase(imageType)) { - mBuilder.setLargeIcon(bitmap); - } else { - Bitmap bm = getCircleBitmap(bitmap); - mBuilder.setLargeIcon(bm); - } - Log.d(LOG_TAG, "using assets large-icon from gcm"); - } catch (IOException e) { - int largeIconId = 0; - largeIconId = resources.getIdentifier(gcmLargeIcon, DRAWABLE, packageName); - if (largeIconId != 0) { - Bitmap largeIconBitmap = BitmapFactory.decodeResource(resources, largeIconId); - mBuilder.setLargeIcon(largeIconBitmap); - Log.d(LOG_TAG, "using resources large-icon from gcm"); - } else { - Log.d(LOG_TAG, "Not setting large icon"); - } - } - } - } - } - - private void setNotificationSmallIcon(Context context, Bundle extras, String packageName, Resources resources, NotificationCompat.Builder mBuilder, String localIcon) { - int iconId = 0; - String icon = extras.getString(ICON); - if (icon != null && !"".equals(icon)) { - iconId = resources.getIdentifier(icon, DRAWABLE, packageName); - Log.d(LOG_TAG, "using icon from plugin options"); - } - else if (localIcon != null && !"".equals(localIcon)) { - iconId = resources.getIdentifier(localIcon, DRAWABLE, packageName); - Log.d(LOG_TAG, "using icon from plugin options"); - } - if (iconId == 0) { - Log.d(LOG_TAG, "no icon resource found - using application icon"); - iconId = context.getApplicationInfo().icon; - } - mBuilder.setSmallIcon(iconId); - } - - private void setNotificationIconColor(String color, NotificationCompat.Builder mBuilder, String localIconColor) { - int iconColor = 0; - if (color != null && !"".equals(color)) { - try { - iconColor = Color.parseColor(color); - } catch (IllegalArgumentException e) { - Log.e(LOG_TAG, "couldn't parse color from android options"); - } - } - else if (localIconColor != null && !"".equals(localIconColor)) { - try { - iconColor = Color.parseColor(localIconColor); - } catch (IllegalArgumentException e) { - Log.e(LOG_TAG, "couldn't parse color from android options"); - } - } - if (iconColor != 0) { - mBuilder.setColor(iconColor); - } - } - - public Bitmap getBitmapFromURL(String strURL) { - try { - URL url = new URL(strURL); - HttpURLConnection connection = (HttpURLConnection) url.openConnection(); - connection.setConnectTimeout(15000); - connection.setDoInput(true); - connection.connect(); - InputStream input = connection.getInputStream(); - return BitmapFactory.decodeStream(input); - } catch (IOException e) { - e.printStackTrace(); - return null; - } - } - - public static String getAppName(Context context) { - CharSequence appName = context.getPackageManager().getApplicationLabel(context.getApplicationInfo()); - return (String)appName; - } - - private int parseInt(String value, Bundle extras) { - int retval = 0; - - try { - retval = Integer.parseInt(extras.getString(value)); - } - catch(NumberFormatException e) { - Log.e(LOG_TAG, "Number format exception - Error parsing " + value + ": " + e.getMessage()); - } - catch(Exception e) { - Log.e(LOG_TAG, "Number format exception - Error parsing " + value + ": " + e.getMessage()); - } - - return retval; - } - - private Spanned fromHtml(String source) { - if (source != null) - return Html.fromHtml(source); - else - return null; - } - - private boolean isAvailableSender(String from) { - SharedPreferences sharedPref = getApplicationContext().getSharedPreferences(PushPlugin.COM_ADOBE_PHONEGAP_PUSH, Context.MODE_PRIVATE); - String savedSenderID = sharedPref.getString(SENDER_ID, ""); - - return from.equals(savedSenderID) || from.startsWith("/topics/"); - } -} diff --git a/StoneIsland/platforms/android/src/com/adobe/phonegap/push/GCMIntentService.java b/StoneIsland/platforms/android/src/com/adobe/phonegap/push/GCMIntentService.java new file mode 100644 index 00000000..e1a2b75c --- /dev/null +++ b/StoneIsland/platforms/android/src/com/adobe/phonegap/push/GCMIntentService.java @@ -0,0 +1,802 @@ +package com.adobe.phonegap.push; + +import android.annotation.SuppressLint; +import android.app.Notification; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.content.ContentResolver; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.res.AssetManager; +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Color; +import android.net.Uri; +import android.os.Bundle; +import android.support.v4.app.NotificationCompat; +import android.support.v4.app.NotificationManagerCompat; +import android.support.v4.app.NotificationCompat.WearableExtender; +import android.support.v4.app.RemoteInput; +import android.text.Html; +import android.text.Spanned; +import android.util.Log; + +import com.google.android.gms.gcm.GcmListenerService; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Random; + +@SuppressLint("NewApi") +public class GCMIntentService extends GcmListenerService implements PushConstants { + + private static final String LOG_TAG = "PushPlugin_GCMIntentService"; + private static HashMap> messageMap = new HashMap>(); + + public void setNotification(int notId, String message){ + ArrayList messageList = messageMap.get(notId); + if(messageList == null) { + messageList = new ArrayList(); + messageMap.put(notId, messageList); + } + + if(message.isEmpty()){ + messageList.clear(); + }else{ + messageList.add(message); + } + } + + @Override + public void onMessageReceived(String from, Bundle extras) { + Log.d(LOG_TAG, "onMessage - from: " + from); + + if (extras != null) { + Context applicationContext = getApplicationContext(); + + SharedPreferences prefs = applicationContext.getSharedPreferences(PushPlugin.COM_ADOBE_PHONEGAP_PUSH, Context.MODE_PRIVATE); + boolean forceShow = prefs.getBoolean(FORCE_SHOW, false); + boolean clearBadge = prefs.getBoolean(CLEAR_BADGE, false); + + extras = normalizeExtras(applicationContext, extras); + + if (clearBadge) { + PushPlugin.setApplicationIconBadgeNumber(getApplicationContext(), 0); + } + + // if we are in the foreground and forceShow is `false` only send data + if (!forceShow && PushPlugin.isInForeground()) { + Log.d(LOG_TAG, "foreground"); + extras.putBoolean(FOREGROUND, true); + extras.putBoolean(COLDSTART, false); + PushPlugin.sendExtras(extras); + } + // if we are in the foreground and forceShow is `true`, force show the notification if the data has at least a message or title + else if (forceShow && PushPlugin.isInForeground()) { + Log.d(LOG_TAG, "foreground force"); + extras.putBoolean(FOREGROUND, true); + extras.putBoolean(COLDSTART, false); + + showNotificationIfPossible(applicationContext, extras); + } + // if we are not in the foreground always send notification if the data has at least a message or title + else { + Log.d(LOG_TAG, "background"); + extras.putBoolean(FOREGROUND, false); + extras.putBoolean(COLDSTART, PushPlugin.isActive()); + + showNotificationIfPossible(applicationContext, extras); + } + } + } + + /* + * Change a values key in the extras bundle + */ + private void replaceKey(Context context, String oldKey, String newKey, Bundle extras, Bundle newExtras) { + Object value = extras.get(oldKey); + if ( value != null ) { + if (value instanceof String) { + value = localizeKey(context, newKey, (String) value); + + newExtras.putString(newKey, (String) value); + } else if (value instanceof Boolean) { + newExtras.putBoolean(newKey, (Boolean) value); + } else if (value instanceof Number) { + newExtras.putDouble(newKey, ((Number) value).doubleValue()); + } else { + newExtras.putString(newKey, String.valueOf(value)); + } + } + } + + /* + * Normalize localization for key + */ + private String localizeKey(Context context, String key, String value) { + if (key.equals(TITLE) || key.equals(MESSAGE) || key.equals(SUMMARY_TEXT)) { + try { + JSONObject localeObject = new JSONObject(value); + + String localeKey = localeObject.getString(LOC_KEY); + + ArrayList localeFormatData = new ArrayList(); + if (!localeObject.isNull(LOC_DATA)) { + String localeData = localeObject.getString(LOC_DATA); + JSONArray localeDataArray = new JSONArray(localeData); + for (int i = 0 ; i < localeDataArray.length(); i++) { + localeFormatData.add(localeDataArray.getString(i)); + } + } + + String packageName = context.getPackageName(); + Resources resources = context.getResources(); + + int resourceId = resources.getIdentifier(localeKey, "string", packageName); + + if (resourceId != 0) { + return resources.getString(resourceId, localeFormatData.toArray()); + } + else { + Log.d(LOG_TAG, "can't find resource for locale key = " + localeKey); + + return value; + } + } + catch(JSONException e) { + Log.d(LOG_TAG, "no locale found for key = " + key + ", error " + e.getMessage()); + + return value; + } + } + + return value; + } + + /* + * Replace alternate keys with our canonical value + */ + private String normalizeKey(String key) { + if (key.equals(BODY) || key.equals(ALERT) || key.equals(GCM_NOTIFICATION_BODY) || key.equals(TWILIO_BODY)) { + return MESSAGE; + } else if (key.equals(TWILIO_TITLE)) { + return TITLE; + }else if (key.equals(MSGCNT) || key.equals(BADGE)) { + return COUNT; + } else if (key.equals(SOUNDNAME) || key.equals(TWILIO_SOUND)) { + return SOUND; + } else if (key.startsWith(GCM_NOTIFICATION)) { + return key.substring(GCM_NOTIFICATION.length()+1, key.length()); + } else if (key.startsWith(GCM_N)) { + return key.substring(GCM_N.length()+1, key.length()); + } else if (key.startsWith(UA_PREFIX)) { + key = key.substring(UA_PREFIX.length()+1, key.length()); + return key.toLowerCase(); + } else { + return key; + } + } + + /* + * Parse bundle into normalized keys. + */ + private Bundle normalizeExtras(Context context, Bundle extras) { + Log.d(LOG_TAG, "normalize extras"); + Iterator it = extras.keySet().iterator(); + Bundle newExtras = new Bundle(); + + while (it.hasNext()) { + String key = it.next(); + + Log.d(LOG_TAG, "key = " + key); + + // If normalizeKeythe key is "data" or "message" and the value is a json object extract + // This is to support parse.com and other services. Issue #147 and pull #218 + if (key.equals(PARSE_COM_DATA) || key.equals(MESSAGE)) { + Object json = extras.get(key); + // Make sure data is json object stringified + if ( json instanceof String && ((String) json).startsWith("{") ) { + Log.d(LOG_TAG, "extracting nested message data from key = " + key); + try { + // If object contains message keys promote each value to the root of the bundle + JSONObject data = new JSONObject((String) json); + if ( data.has(ALERT) || data.has(MESSAGE) || data.has(BODY) || data.has(TITLE) ) { + Iterator jsonIter = data.keys(); + while (jsonIter.hasNext()) { + String jsonKey = jsonIter.next(); + + Log.d(LOG_TAG, "key = data/" + jsonKey); + + String value = data.getString(jsonKey); + jsonKey = normalizeKey(jsonKey); + value = localizeKey(context, jsonKey, value); + + newExtras.putString(jsonKey, value); + } + } + } catch( JSONException e) { + Log.e(LOG_TAG, "normalizeExtras: JSON exception"); + } + } + } else if (key.equals(("notification"))) { + Bundle value = extras.getBundle(key); + Iterator iterator = value.keySet().iterator(); + while (iterator.hasNext()) { + String notifkey = iterator.next(); + + Log.d(LOG_TAG, "notifkey = " + notifkey); + String newKey = normalizeKey(notifkey); + Log.d(LOG_TAG, "replace key " + notifkey + " with " + newKey); + + String valueData = value.getString(notifkey); + valueData = localizeKey(context, newKey, valueData); + + newExtras.putString(newKey, valueData); + } + continue; + } + + String newKey = normalizeKey(key); + Log.d(LOG_TAG, "replace key " + key + " with " + newKey); + replaceKey(context, key, newKey, extras, newExtras); + + } // while + + return newExtras; + } + + private int extractBadgeCount(Bundle extras) { + int count = -1; + String msgcnt = extras.getString(COUNT); + + try { + if (msgcnt != null) { + count = Integer.parseInt(msgcnt); + } + } catch (NumberFormatException e) { + Log.e(LOG_TAG, e.getLocalizedMessage(), e); + } + + return count; + } + + private void showNotificationIfPossible (Context context, Bundle extras) { + + // Send a notification if there is a message or title, otherwise just send data + String message = extras.getString(MESSAGE); + String title = extras.getString(TITLE); + String contentAvailable = extras.getString(CONTENT_AVAILABLE); + String forceStart = extras.getString(FORCE_START); + int badgeCount = extractBadgeCount(extras); + if (badgeCount >= 0) { + Log.d(LOG_TAG, "count =[" + badgeCount + "]"); + PushPlugin.setApplicationIconBadgeNumber(context, badgeCount); + } + + Log.d(LOG_TAG, "message =[" + message + "]"); + Log.d(LOG_TAG, "title =[" + title + "]"); + Log.d(LOG_TAG, "contentAvailable =[" + contentAvailable + "]"); + Log.d(LOG_TAG, "forceStart =[" + forceStart + "]"); + + if ((message != null && message.length() != 0) || + (title != null && title.length() != 0)) { + + Log.d(LOG_TAG, "create notification"); + + if(title == null || title.isEmpty()){ + extras.putString(TITLE, getAppName(this)); + } + + createNotification(context, extras); + } + + if(!PushPlugin.isActive() && "1".equals(forceStart)){ + Log.d(LOG_TAG, "app is not running but we should start it and put in background"); + Intent intent = new Intent(this, PushHandlerActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.putExtra(PUSH_BUNDLE, extras); + intent.putExtra(START_IN_BACKGROUND, true); + intent.putExtra(FOREGROUND, false); + startActivity(intent); + } else if ("1".equals(contentAvailable)) { + Log.d(LOG_TAG, "app is not running and content available true"); + Log.d(LOG_TAG, "send notification event"); + PushPlugin.sendExtras(extras); + } + } + + public void createNotification(Context context, Bundle extras) { + NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); + String appName = getAppName(this); + String packageName = context.getPackageName(); + Resources resources = context.getResources(); + + int notId = parseInt(NOT_ID, extras); + Intent notificationIntent = new Intent(this, PushHandlerActivity.class); + notificationIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP); + notificationIntent.putExtra(PUSH_BUNDLE, extras); + notificationIntent.putExtra(NOT_ID, notId); + + int requestCode = new Random().nextInt(); + PendingIntent contentIntent = PendingIntent.getActivity(this, requestCode, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT); + + NotificationCompat.Builder mBuilder = + new NotificationCompat.Builder(context) + .setWhen(System.currentTimeMillis()) + .setContentTitle(fromHtml(extras.getString(TITLE))) + .setTicker(fromHtml(extras.getString(TITLE))) + .setContentIntent(contentIntent) + .setAutoCancel(true); + + SharedPreferences prefs = context.getSharedPreferences(PushPlugin.COM_ADOBE_PHONEGAP_PUSH, Context.MODE_PRIVATE); + String localIcon = prefs.getString(ICON, null); + String localIconColor = prefs.getString(ICON_COLOR, null); + boolean soundOption = prefs.getBoolean(SOUND, true); + boolean vibrateOption = prefs.getBoolean(VIBRATE, true); + Log.d(LOG_TAG, "stored icon=" + localIcon); + Log.d(LOG_TAG, "stored iconColor=" + localIconColor); + Log.d(LOG_TAG, "stored sound=" + soundOption); + Log.d(LOG_TAG, "stored vibrate=" + vibrateOption); + + /* + * Notification Vibration + */ + + setNotificationVibration(extras, vibrateOption, mBuilder); + + /* + * Notification Icon Color + * + * Sets the small-icon background color of the notification. + * To use, add the `iconColor` key to plugin android options + * + */ + setNotificationIconColor(extras.getString("color"), mBuilder, localIconColor); + + /* + * Notification Icon + * + * Sets the small-icon of the notification. + * + * - checks the plugin options for `icon` key + * - if none, uses the application icon + * + * The icon value must be a string that maps to a drawable resource. + * If no resource is found, falls + * + */ + setNotificationSmallIcon(context, extras, packageName, resources, mBuilder, localIcon); + + /* + * Notification Large-Icon + * + * Sets the large-icon of the notification + * + * - checks the gcm data for the `image` key + * - checks to see if remote image, loads it. + * - checks to see if assets image, Loads It. + * - checks to see if resource image, LOADS IT! + * - if none, we don't set the large icon + * + */ + setNotificationLargeIcon(extras, packageName, resources, mBuilder); + + /* + * Notification Sound + */ + if (soundOption) { + setNotificationSound(context, extras, mBuilder); + } + + /* + * LED Notification + */ + setNotificationLedColor(extras, mBuilder); + + /* + * Priority Notification + */ + setNotificationPriority(extras, mBuilder); + + /* + * Notification message + */ + setNotificationMessage(notId, extras, mBuilder); + + /* + * Notification count + */ + setNotificationCount(context, extras, mBuilder); + + /* + * Notification count + */ + setVisibility(context, extras, mBuilder); + + /* + * Notification add actions + */ + createActions(extras, mBuilder, resources, packageName, notId); + + mNotificationManager.notify(appName, notId, mBuilder.build()); + } + + private void updateIntent(Intent intent, String callback, Bundle extras, boolean foreground, int notId) { + intent.putExtra(CALLBACK, callback); + intent.putExtra(PUSH_BUNDLE, extras); + intent.putExtra(FOREGROUND, foreground); + intent.putExtra(NOT_ID, notId); + } + + private void createActions(Bundle extras, NotificationCompat.Builder mBuilder, Resources resources, String packageName, int notId) { + Log.d(LOG_TAG, "create actions: with in-line"); + String actions = extras.getString(ACTIONS); + if (actions != null) { + try { + JSONArray actionsArray = new JSONArray(actions); + ArrayList wActions = new ArrayList(); + for (int i=0; i < actionsArray.length(); i++) { + int min = 1; + int max = 2000000000; + Random random = new Random(); + int uniquePendingIntentRequestCode = random.nextInt((max - min) + 1) + min; + Log.d(LOG_TAG, "adding action"); + JSONObject action = actionsArray.getJSONObject(i); + Log.d(LOG_TAG, "adding callback = " + action.getString(CALLBACK)); + boolean foreground = action.optBoolean(FOREGROUND, true); + boolean inline = action.optBoolean("inline", false); + Intent intent = null; + PendingIntent pIntent = null; + if (inline) { + Log.d(LOG_TAG, "Version: " + android.os.Build.VERSION.SDK_INT + " = " + android.os.Build.VERSION_CODES.M); + if (android.os.Build.VERSION.SDK_INT <= android.os.Build.VERSION_CODES.M) { + Log.d(LOG_TAG, "push activity"); + intent = new Intent(this, PushHandlerActivity.class); + } else { + Log.d(LOG_TAG, "push receiver"); + intent = new Intent(this, BackgroundActionButtonHandler.class); + } + + updateIntent(intent, action.getString(CALLBACK), extras, foreground, notId); + + if (android.os.Build.VERSION.SDK_INT <= android.os.Build.VERSION_CODES.M) { + Log.d(LOG_TAG, "push activity for notId " + notId); + pIntent = PendingIntent.getActivity(this, uniquePendingIntentRequestCode, intent, PendingIntent.FLAG_ONE_SHOT); + } else { + Log.d(LOG_TAG, "push receiver for notId " + notId); + pIntent = PendingIntent.getBroadcast(this, uniquePendingIntentRequestCode, intent, PendingIntent.FLAG_ONE_SHOT); + } + } else if (foreground) { + intent = new Intent(this, PushHandlerActivity.class); + updateIntent(intent, action.getString(CALLBACK), extras, foreground, notId); + pIntent = PendingIntent.getActivity(this, uniquePendingIntentRequestCode, intent, PendingIntent.FLAG_UPDATE_CURRENT); + } else { + intent = new Intent(this, BackgroundActionButtonHandler.class); + updateIntent(intent, action.getString(CALLBACK), extras, foreground, notId); + pIntent = PendingIntent.getBroadcast(this, uniquePendingIntentRequestCode, intent, PendingIntent.FLAG_UPDATE_CURRENT); + } + + NotificationCompat.Action.Builder actionBuilder = + new NotificationCompat.Action.Builder(resources.getIdentifier(action.optString(ICON, ""), DRAWABLE, packageName), + action.getString(TITLE), pIntent); + + RemoteInput remoteInput = null; + if (inline) { + Log.d(LOG_TAG, "create remote input"); + String replyLabel = "Enter your reply here"; + remoteInput = + new RemoteInput.Builder(INLINE_REPLY) + .setLabel(replyLabel) + .build(); + actionBuilder.addRemoteInput(remoteInput); + } + + NotificationCompat.Action wAction = actionBuilder.build(); + wActions.add(actionBuilder.build()); + + if (inline) { + mBuilder.addAction(wAction); + } else { + mBuilder.addAction(resources.getIdentifier(action.optString(ICON, ""), DRAWABLE, packageName), + action.getString(TITLE), pIntent); + } + wAction = null; + pIntent = null; + } + mBuilder.extend(new WearableExtender().addActions(wActions)); + wActions.clear(); + } catch(JSONException e) { + // nope + } + } + } + + private void setNotificationCount(Context context, Bundle extras, NotificationCompat.Builder mBuilder) { + int count = extractBadgeCount(extras); + if (count >= 0) { + Log.d(LOG_TAG, "count =[" + count + "]"); + mBuilder.setNumber(count); + } + } + + + private void setVisibility(Context context, Bundle extras, NotificationCompat.Builder mBuilder) { + String visibilityStr = extras.getString(VISIBILITY); + if (visibilityStr != null) { + try { + Integer visibility = Integer.parseInt(visibilityStr); + if (visibility >= NotificationCompat.VISIBILITY_SECRET && visibility <= NotificationCompat.VISIBILITY_PUBLIC) { + mBuilder.setVisibility(visibility); + } else { + Log.e(LOG_TAG, "Visibility parameter must be between -1 and 1"); + } + } catch (NumberFormatException e) { + e.printStackTrace(); + } + } + } + + private void setNotificationVibration(Bundle extras, Boolean vibrateOption, NotificationCompat.Builder mBuilder) { + String vibrationPattern = extras.getString(VIBRATION_PATTERN); + if (vibrationPattern != null) { + String[] items = vibrationPattern.replaceAll("\\[", "").replaceAll("\\]", "").split(","); + long[] results = new long[items.length]; + for (int i = 0; i < items.length; i++) { + try { + results[i] = Long.parseLong(items[i].trim()); + } catch (NumberFormatException nfe) {} + } + mBuilder.setVibrate(results); + } else { + if (vibrateOption) { + mBuilder.setDefaults(Notification.DEFAULT_VIBRATE); + } + } + } + + private void setNotificationMessage(int notId, Bundle extras, NotificationCompat.Builder mBuilder) { + String message = extras.getString(MESSAGE); + + String style = extras.getString(STYLE, STYLE_TEXT); + if(STYLE_INBOX.equals(style)) { + setNotification(notId, message); + + mBuilder.setContentText(fromHtml(message)); + + ArrayList messageList = messageMap.get(notId); + Integer sizeList = messageList.size(); + if (sizeList > 1) { + String sizeListMessage = sizeList.toString(); + String stacking = sizeList + " more"; + if (extras.getString(SUMMARY_TEXT) != null) { + stacking = extras.getString(SUMMARY_TEXT); + stacking = stacking.replace("%n%", sizeListMessage); + } + NotificationCompat.InboxStyle notificationInbox = new NotificationCompat.InboxStyle() + .setBigContentTitle(fromHtml(extras.getString(TITLE))) + .setSummaryText(fromHtml(stacking)); + + for (int i = messageList.size() - 1; i >= 0; i--) { + notificationInbox.addLine(fromHtml(messageList.get(i))); + } + + mBuilder.setStyle(notificationInbox); + } else { + NotificationCompat.BigTextStyle bigText = new NotificationCompat.BigTextStyle(); + if (message != null) { + bigText.bigText(fromHtml(message)); + bigText.setBigContentTitle(fromHtml(extras.getString(TITLE))); + mBuilder.setStyle(bigText); + } + } + } else if (STYLE_PICTURE.equals(style)) { + setNotification(notId, ""); + + NotificationCompat.BigPictureStyle bigPicture = new NotificationCompat.BigPictureStyle(); + bigPicture.bigPicture(getBitmapFromURL(extras.getString(PICTURE))); + bigPicture.setBigContentTitle(fromHtml(extras.getString(TITLE))); + bigPicture.setSummaryText(fromHtml(extras.getString(SUMMARY_TEXT))); + + mBuilder.setContentTitle(fromHtml(extras.getString(TITLE))); + mBuilder.setContentText(fromHtml(message)); + + mBuilder.setStyle(bigPicture); + } else { + setNotification(notId, ""); + + NotificationCompat.BigTextStyle bigText = new NotificationCompat.BigTextStyle(); + + if (message != null) { + mBuilder.setContentText(fromHtml(message)); + + bigText.bigText(fromHtml(message)); + bigText.setBigContentTitle(fromHtml(extras.getString(TITLE))); + + String summaryText = extras.getString(SUMMARY_TEXT); + if (summaryText != null) { + bigText.setSummaryText(fromHtml(summaryText)); + } + + mBuilder.setStyle(bigText); + } + /* + else { + mBuilder.setContentText(""); + } + */ + } + } + + private void setNotificationSound(Context context, Bundle extras, NotificationCompat.Builder mBuilder) { + String soundname = extras.getString(SOUNDNAME); + if (soundname == null) { + soundname = extras.getString(SOUND); + } + if (SOUND_RINGTONE.equals(soundname)) { + mBuilder.setSound(android.provider.Settings.System.DEFAULT_RINGTONE_URI); + } else if (soundname != null && !soundname.contentEquals(SOUND_DEFAULT)) { + Uri sound = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + + "://" + context.getPackageName() + "/raw/" + soundname); + Log.d(LOG_TAG, sound.toString()); + mBuilder.setSound(sound); + } else { + mBuilder.setSound(android.provider.Settings.System.DEFAULT_NOTIFICATION_URI); + } + } + + private void setNotificationLedColor(Bundle extras, NotificationCompat.Builder mBuilder) { + String ledColor = extras.getString(LED_COLOR); + if (ledColor != null) { + // Converts parse Int Array from ledColor + String[] items = ledColor.replaceAll("\\[", "").replaceAll("\\]", "").split(","); + int[] results = new int[items.length]; + for (int i = 0; i < items.length; i++) { + try { + results[i] = Integer.parseInt(items[i].trim()); + } catch (NumberFormatException nfe) {} + } + if (results.length == 4) { + mBuilder.setLights(Color.argb(results[0], results[1], results[2], results[3]), 500, 500); + } else { + Log.e(LOG_TAG, "ledColor parameter must be an array of length == 4 (ARGB)"); + } + } + } + + private void setNotificationPriority(Bundle extras, NotificationCompat.Builder mBuilder) { + String priorityStr = extras.getString(PRIORITY); + if (priorityStr != null) { + try { + Integer priority = Integer.parseInt(priorityStr); + if (priority >= NotificationCompat.PRIORITY_MIN && priority <= NotificationCompat.PRIORITY_MAX) { + mBuilder.setPriority(priority); + } else { + Log.e(LOG_TAG, "Priority parameter must be between -2 and 2"); + } + } catch (NumberFormatException e) { + e.printStackTrace(); + } + } + } + + private void setNotificationLargeIcon(Bundle extras, String packageName, Resources resources, NotificationCompat.Builder mBuilder) { + String gcmLargeIcon = extras.getString(IMAGE); // from gcm + if (gcmLargeIcon != null && !"".equals(gcmLargeIcon)) { + if (gcmLargeIcon.startsWith("http://") || gcmLargeIcon.startsWith("https://")) { + mBuilder.setLargeIcon(getBitmapFromURL(gcmLargeIcon)); + Log.d(LOG_TAG, "using remote large-icon from gcm"); + } else { + AssetManager assetManager = getAssets(); + InputStream istr; + try { + istr = assetManager.open(gcmLargeIcon); + Bitmap bitmap = BitmapFactory.decodeStream(istr); + mBuilder.setLargeIcon(bitmap); + Log.d(LOG_TAG, "using assets large-icon from gcm"); + } catch (IOException e) { + int largeIconId = 0; + largeIconId = resources.getIdentifier(gcmLargeIcon, DRAWABLE, packageName); + if (largeIconId != 0) { + Bitmap largeIconBitmap = BitmapFactory.decodeResource(resources, largeIconId); + mBuilder.setLargeIcon(largeIconBitmap); + Log.d(LOG_TAG, "using resources large-icon from gcm"); + } else { + Log.d(LOG_TAG, "Not setting large icon"); + } + } + } + } + } + + private void setNotificationSmallIcon(Context context, Bundle extras, String packageName, Resources resources, NotificationCompat.Builder mBuilder, String localIcon) { + int iconId = 0; + String icon = extras.getString(ICON); + if (icon != null && !"".equals(icon)) { + iconId = resources.getIdentifier(icon, DRAWABLE, packageName); + Log.d(LOG_TAG, "using icon from plugin options"); + } + else if (localIcon != null && !"".equals(localIcon)) { + iconId = resources.getIdentifier(localIcon, DRAWABLE, packageName); + Log.d(LOG_TAG, "using icon from plugin options"); + } + if (iconId == 0) { + Log.d(LOG_TAG, "no icon resource found - using application icon"); + iconId = context.getApplicationInfo().icon; + } + mBuilder.setSmallIcon(iconId); + } + + private void setNotificationIconColor(String color, NotificationCompat.Builder mBuilder, String localIconColor) { + int iconColor = 0; + if (color != null && !"".equals(color)) { + try { + iconColor = Color.parseColor(color); + } catch (IllegalArgumentException e) { + Log.e(LOG_TAG, "couldn't parse color from android options"); + } + } + else if (localIconColor != null && !"".equals(localIconColor)) { + try { + iconColor = Color.parseColor(localIconColor); + } catch (IllegalArgumentException e) { + Log.e(LOG_TAG, "couldn't parse color from android options"); + } + } + if (iconColor != 0) { + mBuilder.setColor(iconColor); + } + } + + public Bitmap getBitmapFromURL(String strURL) { + try { + URL url = new URL(strURL); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setDoInput(true); + connection.connect(); + InputStream input = connection.getInputStream(); + return BitmapFactory.decodeStream(input); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } + + public static String getAppName(Context context) { + CharSequence appName = context.getPackageManager().getApplicationLabel(context.getApplicationInfo()); + return (String)appName; + } + + private int parseInt(String value, Bundle extras) { + int retval = 0; + + try { + retval = Integer.parseInt(extras.getString(value)); + } + catch(NumberFormatException e) { + Log.e(LOG_TAG, "Number format exception - Error parsing " + value + ": " + e.getMessage()); + } + catch(Exception e) { + Log.e(LOG_TAG, "Number format exception - Error parsing " + value + ": " + e.getMessage()); + } + + return retval; + } + + private Spanned fromHtml(String source) { + if (source != null) + return Html.fromHtml(source); + else + return null; + } +} diff --git a/StoneIsland/platforms/android/src/com/adobe/phonegap/push/PermissionUtils.java b/StoneIsland/platforms/android/src/com/adobe/phonegap/push/PermissionUtils.java index 41bc6a6f..6aa5c9bf 100644 --- a/StoneIsland/platforms/android/src/com/adobe/phonegap/push/PermissionUtils.java +++ b/StoneIsland/platforms/android/src/com/adobe/phonegap/push/PermissionUtils.java @@ -10,12 +10,8 @@ import java.lang.reflect.Method; public class PermissionUtils { private static final String CHECK_OP_NO_THROW = "checkOpNoThrow"; - private static final int MIN_API_LEVEL = 19; // required by AppOpsManager public static boolean hasPermission(Context appContext, String appOpsServiceId) throws UnknownError { - if (android.os.Build.VERSION.SDK_INT < MIN_API_LEVEL) { - return true; - } ApplicationInfo appInfo = appContext.getApplicationInfo(); diff --git a/StoneIsland/platforms/android/src/com/adobe/phonegap/push/PushConstants.java b/StoneIsland/platforms/android/src/com/adobe/phonegap/push/PushConstants.java index e3aa217c..37874e04 100644 --- a/StoneIsland/platforms/android/src/com/adobe/phonegap/push/PushConstants.java +++ b/StoneIsland/platforms/android/src/com/adobe/phonegap/push/PushConstants.java @@ -3,7 +3,6 @@ package com.adobe.phonegap.push; public interface PushConstants { public static final String COM_ADOBE_PHONEGAP_PUSH = "com.adobe.phonegap.push"; public static final String REGISTRATION_ID = "registrationId"; - public static final String REGISTRATION_TYPE = "registrationType"; public static final String FOREGROUND = "foreground"; public static final String TITLE = "title"; public static final String NOT_ID = "notId"; @@ -56,11 +55,10 @@ public interface PushConstants { public static final String FROM = "from"; public static final String COLLAPSE_KEY = "collapse_key"; public static final String FORCE_SHOW = "forceShow"; - public static final String FCM = "FCM"; + public static final String GCM = "GCM"; public static final String CONTENT_AVAILABLE = "content-available"; public static final String TOPICS = "topics"; public static final String SET_APPLICATION_ICON_BADGE_NUMBER = "setApplicationIconBadgeNumber"; - public static final String GET_APPLICATION_ICON_BADGE_NUMBER = "getApplicationIconBadgeNumber"; public static final String CLEAR_ALL_NOTIFICATIONS = "clearAllNotifications"; public static final String VISIBILITY = "visibility"; public static final String INLINE_REPLY = "inlineReply"; @@ -69,18 +67,6 @@ public interface PushConstants { public static final String TWILIO_BODY = "twi_body"; public static final String TWILIO_TITLE = "twi_title"; public static final String TWILIO_SOUND = "twi_sound"; - public static final String MP_MESSAGE = "mp_message"; public static final String START_IN_BACKGROUND = "cdvStartInBackground"; public static final String FORCE_START = "force-start"; - public static final String MESSAGE_KEY = "messageKey"; - public static final String TITLE_KEY = "titleKey"; - public static final String NO_CACHE = "no-cache"; - public static final String DISMISSED = "dismissed"; - public static final String IMAGE_TYPE = "image-type"; - public static final String IMAGE_TYPE_SQUARE = "square"; - public static final String IMAGE_TYPE_CIRCLE = "circle"; - public static final String SUBJECT = "subject"; - public static final String GOOGLE_APP_ID = "google_app_id"; - public static final String GCM_DEFAULT_SENDER_ID = "gcm_defaultSenderId"; - public static final String PUSH_DISMISSED = "push_dismissed"; } diff --git a/StoneIsland/platforms/android/src/com/adobe/phonegap/push/PushDismissedHandler.java b/StoneIsland/platforms/android/src/com/adobe/phonegap/push/PushDismissedHandler.java deleted file mode 100644 index a517bc1e..00000000 --- a/StoneIsland/platforms/android/src/com/adobe/phonegap/push/PushDismissedHandler.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.adobe.phonegap.push; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.util.Log; - -public class PushDismissedHandler extends BroadcastReceiver implements PushConstants { - private static String LOG_TAG = "Push_DismissedHandler"; - - @Override - public void onReceive(Context context, Intent intent) { - Bundle extras = intent.getExtras(); - FCMService fcm = new FCMService(); - String action = intent.getAction(); - int notID = intent.getIntExtra(NOT_ID, 0); - - if (action.equals(PUSH_DISMISSED)) { - Log.d(LOG_TAG, "PushDismissedHandler = " + extras); - Log.d(LOG_TAG, "not id = " + notID); - - fcm.setNotification(notID, ""); - } - } -} diff --git a/StoneIsland/platforms/android/src/com/adobe/phonegap/push/PushHandlerActivity.java b/StoneIsland/platforms/android/src/com/adobe/phonegap/push/PushHandlerActivity.java index 0d399a61..23682ac8 100644 --- a/StoneIsland/platforms/android/src/com/adobe/phonegap/push/PushHandlerActivity.java +++ b/StoneIsland/platforms/android/src/com/adobe/phonegap/push/PushHandlerActivity.java @@ -11,7 +11,7 @@ import android.support.v4.app.RemoteInput; public class PushHandlerActivity extends Activity implements PushConstants { - private static String LOG_TAG = "Push_HandlerActivity"; + private static String LOG_TAG = "PushPlugin_PushHandlerActivity"; /* * this activity will be started if the user touches a notification that we own. @@ -21,7 +21,7 @@ public class PushHandlerActivity extends Activity implements PushConstants { */ @Override public void onCreate(Bundle savedInstanceState) { - FCMService gcm = new FCMService(); + GCMIntentService gcm = new GCMIntentService(); Intent intent = getIntent(); @@ -34,18 +34,16 @@ public class PushHandlerActivity extends Activity implements PushConstants { Log.d(LOG_TAG, "callback = " + callback); boolean foreground = getIntent().getExtras().getBoolean("foreground", true); boolean startOnBackground = getIntent().getExtras().getBoolean(START_IN_BACKGROUND, false); - boolean dismissed = getIntent().getExtras().getBoolean(DISMISSED, false); - Log.d(LOG_TAG, "dismissed = " + dismissed); if(!startOnBackground){ NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); - notificationManager.cancel(FCMService.getAppName(this), notId); + notificationManager.cancel(GCMIntentService.getAppName(this), notId); } boolean isPushPluginActive = PushPlugin.isActive(); boolean inline = processPushBundle(isPushPluginActive, intent); - if(inline && android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.N && !startOnBackground){ + if(inline && android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.N){ foreground = true; } @@ -53,17 +51,15 @@ public class PushHandlerActivity extends Activity implements PushConstants { finish(); - if(!dismissed) { - Log.d(LOG_TAG, "isPushPluginActive = " + isPushPluginActive); - if (!isPushPluginActive && foreground && inline) { - Log.d(LOG_TAG, "forceMainActivityReload"); - forceMainActivityReload(false); - } else if(startOnBackground) { - Log.d(LOG_TAG, "startOnBackgroundTrue"); - forceMainActivityReload(true); - } else { - Log.d(LOG_TAG, "don't want main activity"); - } + Log.d(LOG_TAG, "isPushPluginActive = " + isPushPluginActive); + if (!isPushPluginActive && foreground && inline) { + Log.d(LOG_TAG, "forceMainActivityReload"); + forceMainActivityReload(false); + } else if(startOnBackground) { + Log.d(LOG_TAG, "startOnBackgroundTrue"); + forceMainActivityReload(true); + } else { + Log.d(LOG_TAG, "don't want main activity"); } } @@ -80,9 +76,7 @@ public class PushHandlerActivity extends Activity implements PushConstants { originalExtras.putBoolean(FOREGROUND, false); originalExtras.putBoolean(COLDSTART, !isPushPluginActive); - originalExtras.putBoolean(DISMISSED, extras.getBoolean(DISMISSED)); originalExtras.putString(ACTION_CALLBACK, extras.getString(CALLBACK)); - originalExtras.remove(NO_CACHE); remoteInput = RemoteInput.getResultsFromIntent(intent); if (remoteInput != null) { diff --git a/StoneIsland/platforms/android/src/com/adobe/phonegap/push/PushInstanceIDListenerService.java b/StoneIsland/platforms/android/src/com/adobe/phonegap/push/PushInstanceIDListenerService.java index 176b7419..eaa39a48 100644 --- a/StoneIsland/platforms/android/src/com/adobe/phonegap/push/PushInstanceIDListenerService.java +++ b/StoneIsland/platforms/android/src/com/adobe/phonegap/push/PushInstanceIDListenerService.java @@ -5,22 +5,23 @@ import android.content.Context; import android.content.SharedPreferences; import android.util.Log; -import com.google.firebase.iid.FirebaseInstanceId; -import com.google.firebase.iid.FirebaseInstanceIdService; +import com.google.android.gms.iid.InstanceID; +import com.google.android.gms.iid.InstanceIDListenerService; import org.json.JSONException; import java.io.IOException; -public class PushInstanceIDListenerService extends FirebaseInstanceIdService implements PushConstants { - public static final String LOG_TAG = "Push_InsIdService"; +public class PushInstanceIDListenerService extends InstanceIDListenerService implements PushConstants { + public static final String LOG_TAG = "PushPlugin_PushInstanceIDListenerService"; @Override public void onTokenRefresh() { - // Get updated InstanceID token. - String refreshedToken = FirebaseInstanceId.getInstance().getToken(); - Log.d(LOG_TAG, "Refreshed token: " + refreshedToken); - // TODO: Implement this method to send any registration to your app's servers. - //sendRegistrationToServer(refreshedToken); + SharedPreferences sharedPref = getApplicationContext().getSharedPreferences(COM_ADOBE_PHONEGAP_PUSH, Context.MODE_PRIVATE); + String senderID = sharedPref.getString(SENDER_ID, ""); + if (!"".equals(senderID)) { + Intent intent = new Intent(this, RegistrationIntentService.class); + startService(intent); + } } } diff --git a/StoneIsland/platforms/android/src/com/adobe/phonegap/push/PushPlugin.java b/StoneIsland/platforms/android/src/com/adobe/phonegap/push/PushPlugin.java index 32f72bf3..f6faaa2b 100644 --- a/StoneIsland/platforms/android/src/com/adobe/phonegap/push/PushPlugin.java +++ b/StoneIsland/platforms/android/src/com/adobe/phonegap/push/PushPlugin.java @@ -1,14 +1,13 @@ package com.adobe.phonegap.push; -import android.app.Activity; import android.app.NotificationManager; import android.content.Context; import android.content.SharedPreferences; import android.os.Bundle; import android.util.Log; -import com.google.firebase.iid.FirebaseInstanceId; -import com.google.firebase.messaging.FirebaseMessaging; +import com.google.android.gms.gcm.GcmPubSub; +import com.google.android.gms.iid.InstanceID; import org.apache.cordova.CallbackContext; import org.apache.cordova.CordovaInterface; @@ -30,7 +29,7 @@ import me.leolin.shortcutbadger.ShortcutBadger; public class PushPlugin extends CordovaPlugin implements PushConstants { - public static final String LOG_TAG = "Push_Plugin"; + public static final String LOG_TAG = "PushPlugin"; private static CallbackContext pushContext; private static CordovaWebView gWebView; @@ -60,7 +59,6 @@ public class PushPlugin extends CordovaPlugin implements PushConstants { Log.v(LOG_TAG, "execute: data=" + data.toString()); SharedPreferences sharedPref = getApplicationContext().getSharedPreferences(COM_ADOBE_PHONEGAP_PUSH, Context.MODE_PRIVATE); - String token = null; String senderID = null; try { @@ -68,19 +66,15 @@ public class PushPlugin extends CordovaPlugin implements PushConstants { Log.v(LOG_TAG, "execute: jo=" + jo.toString()); - senderID = getStringResourceByName(GCM_DEFAULT_SENDER_ID); + senderID = jo.getString(SENDER_ID); Log.v(LOG_TAG, "execute: senderID=" + senderID); - token = FirebaseInstanceId.getInstance().getToken(); + String savedSenderID = sharedPref.getString(SENDER_ID, ""); + registration_id = InstanceID.getInstance(getApplicationContext()).getToken(senderID, GCM); - if (token == null) { - token = FirebaseInstanceId.getInstance().getToken(senderID,FCM); - } - - if (!"".equals(token)) { - JSONObject json = new JSONObject().put(REGISTRATION_ID, token); - json.put(REGISTRATION_TYPE, FCM); + if (!"".equals(registration_id)) { + JSONObject json = new JSONObject().put(REGISTRATION_ID, registration_id); Log.v(LOG_TAG, "onRegistered: " + json.toString()); @@ -89,14 +83,14 @@ public class PushPlugin extends CordovaPlugin implements PushConstants { PushPlugin.sendEvent( json ); } else { - callbackContext.error("Empty registration ID received from FCM"); + callbackContext.error("Empty registration ID received from GCM"); return; } } catch (JSONException e) { Log.e(LOG_TAG, "execute: Got JSON Exception " + e.getMessage()); callbackContext.error(e.getMessage()); } catch (IOException e) { - Log.e(LOG_TAG, "execute: Got IO Exception " + e.getMessage()); + Log.e(LOG_TAG, "execute: Got JSON Exception " + e.getMessage()); callbackContext.error(e.getMessage()); } @@ -124,8 +118,6 @@ public class PushPlugin extends CordovaPlugin implements PushConstants { editor.putBoolean(CLEAR_NOTIFICATIONS, jo.optBoolean(CLEAR_NOTIFICATIONS, true)); editor.putBoolean(FORCE_SHOW, jo.optBoolean(FORCE_SHOW, false)); editor.putString(SENDER_ID, senderID); - editor.putString(MESSAGE_KEY, jo.optString(MESSAGE_KEY)); - editor.putString(TITLE_KEY, jo.optString(TITLE_KEY)); editor.commit(); } @@ -151,7 +143,7 @@ public class PushPlugin extends CordovaPlugin implements PushConstants { if (topics != null && !"".equals(registration_id)) { unsubscribeFromTopics(topics, registration_id); } else { - FirebaseInstanceId.getInstance().deleteInstanceId(); + InstanceID.getInstance(getApplicationContext()).deleteInstanceID(); Log.v(LOG_TAG, "UNREGISTER"); // Remove shared prefs @@ -202,13 +194,6 @@ public class PushPlugin extends CordovaPlugin implements PushConstants { callbackContext.success(); } }); - } else if (GET_APPLICATION_ICON_BADGE_NUMBER.equals(action)) { - cordova.getThreadPool().execute(new Runnable() { - public void run() { - Log.v(LOG_TAG, "getApplicationIconBadgeNumber"); - callbackContext.success(getApplicationIconBadgeNumber(getApplicationContext())); - } - }); } else if (CLEAR_ALL_NOTIFICATIONS.equals(action)) { cordova.getThreadPool().execute(new Runnable() { public void run() { @@ -227,6 +212,8 @@ public class PushPlugin extends CordovaPlugin implements PushConstants { callbackContext.success(); } catch (JSONException e) { callbackContext.error(e.getMessage()); + } catch (IOException e) { + callbackContext.error(e.getMessage()); } } }); @@ -240,6 +227,8 @@ public class PushPlugin extends CordovaPlugin implements PushConstants { callbackContext.success(); } catch (JSONException e) { callbackContext.error(e.getMessage()); + } catch (IOException e) { + callbackContext.error(e.getMessage()); } } }); @@ -270,41 +259,25 @@ public class PushPlugin extends CordovaPlugin implements PushConstants { /* * Sends the pushbundle extras to the client application. - * If the client application isn't currently active and the no-cache flag is not set, it is cached for later processing. + * If the client application isn't currently active, it is cached for later processing. */ public static void sendExtras(Bundle extras) { if (extras != null) { - String noCache = extras.getString(NO_CACHE); if (gWebView != null) { sendEvent(convertBundleToJson(extras)); - } else if(!"1".equals(noCache)){ + } else { Log.v(LOG_TAG, "sendExtras: caching extras to send at a later time."); gCachedExtras.add(extras); } } } - /* - * Retrives badge count from SharedPreferences - */ - public static int getApplicationIconBadgeNumber(Context context){ - SharedPreferences settings = context.getSharedPreferences(BADGE, Context.MODE_PRIVATE); - return settings.getInt(BADGE, 0); - } - - /* - * Sets badge count on application icon and in SharedPreferences - */ public static void setApplicationIconBadgeNumber(Context context, int badgeCount) { if (badgeCount > 0) { ShortcutBadger.applyCount(context, badgeCount); - }else{ + } else { ShortcutBadger.removeCount(context); } - - SharedPreferences.Editor editor = context.getSharedPreferences(BADGE, Context.MODE_PRIVATE).edit(); - editor.putInt(BADGE, Math.max(badgeCount, 0)); - editor.apply(); } @Override @@ -342,7 +315,23 @@ public class PushPlugin extends CordovaPlugin implements PushConstants { notificationManager.cancelAll(); } - private void subscribeToTopics(JSONArray topics, String registrationToken) { + /** + * Transform `topic name` to `topic path` + * Normally, the `topic` inputed from end-user is `topic name` only. + * We should convert them to GCM `topic path` + * Example: + * when topic name = 'my-topic' + * then topic path = '/topics/my-topic' + * + * @param String topic The topic name + * @return The topic path + */ + private String getTopicPath(String topic) + { + return "/topics/" + topic; + } + + private void subscribeToTopics(JSONArray topics, String registrationToken) throws IOException { if (topics != null) { String topic = null; for (int i=0; i