diff --git a/GoogleService-Info.plist b/GoogleService-Info.plist
new file mode 100644
index 000000000..b80564cf9
--- /dev/null
+++ b/GoogleService-Info.plist
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>AD_UNIT_ID_FOR_BANNER_TEST</key>
+	<string>ca-app-pub-3940256099942544/2934735716</string>
+	<key>AD_UNIT_ID_FOR_INTERSTITIAL_TEST</key>
+	<string>ca-app-pub-3940256099942544/4411468910</string>
+	<key>CLIENT_ID</key>
+	<string>694767596569-c2cjrca92k99f6nkp3363lsb7ljhdgdr.apps.googleusercontent.com</string>
+	<key>REVERSED_CLIENT_ID</key>
+	<string>com.googleusercontent.apps.694767596569-c2cjrca92k99f6nkp3363lsb7ljhdgdr</string>
+	<key>API_KEY</key>
+	<string>AIzaSyA-77ZjkxII6GV97CC9rdUl83rzdEXu_rM</string>
+	<key>GCM_SENDER_ID</key>
+	<string>694767596569</string>
+	<key>PLIST_VERSION</key>
+	<string>1</string>
+	<key>BUNDLE_ID</key>
+	<string>com.moodle.moodlemobile</string>
+	<key>PROJECT_ID</key>
+	<string>moodlemobile-push</string>
+	<key>STORAGE_BUCKET</key>
+	<string>moodlemobile-push.appspot.com</string>
+	<key>IS_ADS_ENABLED</key>
+	<true></true>
+	<key>IS_ANALYTICS_ENABLED</key>
+	<false></false>
+	<key>IS_APPINVITE_ENABLED</key>
+	<true></true>
+	<key>IS_GCM_ENABLED</key>
+	<true></true>
+	<key>IS_SIGNIN_ENABLED</key>
+	<true></true>
+	<key>GOOGLE_APP_ID</key>
+	<string>1:694767596569:ios:a4cdad4d168c9d1a</string>
+	<key>DATABASE_URL</key>
+	<string>https://moodlemobile-push.firebaseio.com</string>
+</dict>
+</plist>
\ No newline at end of file
diff --git a/config.xml b/config.xml
index cdc0b199d..265b5a0a5 100644
--- a/config.xml
+++ b/config.xml
@@ -41,6 +41,7 @@
         <param name="ios-package" onload="true" value="CDVStatusBar" />
     </feature>
     <platform name="android">
+        <resource-file src="google-services.json" target="app/google-services.json" />
         <splash qualifier="land-ldpi" src="resources/android/splash/drawable-land-ldpi-screen.png" />
         <splash qualifier="land-mdpi" src="resources/android/splash/drawable-land-mdpi-screen.png" />
         <splash qualifier="land-hdpi" src="resources/android/splash/drawable-land-hdpi-screen.png" />
@@ -77,6 +78,7 @@
         <resource-file src="resources/android/splash/drawable-port-xxxhdpi-screen.png" target="app/src/main/res/drawable-port-xxxhdpi/screen.png" />
     </platform>
     <platform name="ios">
+        <resource-file src="GoogleService-Info.plist" />
         <icon height="57" src="resources/ios/icon/icon.png" width="57" />
         <icon height="114" src="resources/ios/icon/icon@2x.png" width="114" />
         <icon height="40" src="resources/ios/icon/icon-40.png" width="40" />
@@ -127,7 +129,7 @@
     <plugin name="cordova-plugin-globalization" spec="^1.11.0" />
     <plugin name="cordova-plugin-inappbrowser" spec="^3.0.0" />
     <plugin name="cordova-plugin-ionic-keyboard" spec="^2.1.3" />
-    <plugin name="cordova-plugin-local-notification" spec="^0.9.0-beta.2" />
+    <plugin name="cordova-plugin-local-notification" spec="^0.9.0-beta.3" />
     <plugin name="cordova-plugin-media-capture" spec="^3.0.2" />
     <plugin name="cordova-plugin-network-information" spec="^2.0.1" />
     <plugin name="cordova-plugin-screen-orientation" spec="^3.0.1" />
@@ -137,8 +139,9 @@
     <plugin name="cordova-plugin-zip" spec="^3.1.0" />
     <plugin name="cordova-sqlite-storage" spec="^2.6.0" />
     <plugin name="nl.kingsquare.cordova.background-audio" spec="^1.0.1" />
-    <plugin name="phonegap-plugin-push" spec="https://github.com/moodlemobile/phonegap-plugin-push.git#moodle">
-        <variable name="SENDER_ID" value="694767596569" />
+    <plugin name="phonegap-plugin-push" spec="^2.2.3">
+        <variable name="ANDROID_SUPPORT_V13_VERSION" value="27.+" />
+        <variable name="FCM_VERSION" value="11.6.2" />
     </plugin>
     <edit-config file="AndroidManifest.xml" mode="merge" target="/manifest/application/activity[@android:name='MainActivity']">
         <activity android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|screenLayout|smallestScreenSize" android:debuggable="true" />
diff --git a/google-services.json b/google-services.json
new file mode 100644
index 000000000..ff50800df
--- /dev/null
+++ b/google-services.json
@@ -0,0 +1,45 @@
+{
+  "project_info": {
+    "project_number": "694767596569",
+    "firebase_url": "https://moodlemobile-push.firebaseio.com",
+    "project_id": "moodlemobile-push",
+    "storage_bucket": "moodlemobile-push.appspot.com"
+  },
+  "client": [
+    {
+      "client_info": {
+        "mobilesdk_app_id": "1:694767596569:android:a4cdad4d168c9d1a",
+        "android_client_info": {
+          "package_name": "com.moodle.moodlemobile"
+        }
+      },
+      "oauth_client": [
+        {
+          "client_id": "694767596569-icveqqa2n56oh44l6ev1dr2oh67nh8il.apps.googleusercontent.com",
+          "client_type": 3
+        }
+      ],
+      "api_key": [
+        {
+          "current_key": "AIzaSyCb2zogu0P_aZ2LNgdwzshWExITPKTXJyk"
+        },
+        {
+          "current_key": "AIzaSyDRT1HwT0gSsTty0whOVtoNKAh8SPrJXLE"
+        }
+      ],
+      "services": {
+        "analytics_service": {
+          "status": 1
+        },
+        "appinvite_service": {
+          "status": 1,
+          "other_platform_oauth_client": []
+        },
+        "ads_service": {
+          "status": 2
+        }
+      }
+    }
+  ],
+  "configuration_version": "1"
+}
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index a72c22b50..8b112c0e9 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -161,9 +161,9 @@
       "integrity": "sha512-2BHO1bV4mehWZNfdsWQ/uojxYFNvk4I6u0KYnNb61RiJRY83joCEw3oFkOMRGLZthPf6TN1cueZUIAGMHXA3nA=="
     },
     "@ionic-native/local-notifications": {
-      "version": "4.17.0",
-      "resolved": "https://registry.npmjs.org/@ionic-native/local-notifications/-/local-notifications-4.17.0.tgz",
-      "integrity": "sha512-NGLGtGRduRU3f/4N2nv4hF550+NkJ9CP7mOS9vlZcZJBzlIup9X67u1M2j/+KFOpWqzS2avZ1gvZbxOmCjPNPw=="
+      "version": "4.20.0",
+      "resolved": "https://registry.npmjs.org/@ionic-native/local-notifications/-/local-notifications-4.20.0.tgz",
+      "integrity": "sha512-Ht/0zau8/2+G/bH/okXXhhWB6YrkCNL2QxVJHQ2dophXFGxQPOZAN3CKWhuQSjfbr76fa2nvQXF6jsXLpIR/ng=="
     },
     "@ionic-native/media-capture": {
       "version": "4.17.0",
@@ -1716,6 +1716,11 @@
         }
       }
     },
+    "babel-plugin-add-header-comment": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/babel-plugin-add-header-comment/-/babel-plugin-add-header-comment-1.0.3.tgz",
+      "integrity": "sha1-URxJAQYmQNWkgLSsPt1pRBlYUOw="
+    },
     "bach": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz",
@@ -3168,9 +3173,9 @@
       "integrity": "sha512-6ucQ6FdlLdBm8kJfFnzozmBTjru/0xekHP/dAhjoCZggkGRlgs8TsUJFkxa/bV+qi7Dlo50JjmpE4UMWAO+aOQ=="
     },
     "cordova-plugin-local-notification": {
-      "version": "0.9.0-beta.2",
-      "resolved": "https://registry.npmjs.org/cordova-plugin-local-notification/-/cordova-plugin-local-notification-0.9.0-beta.2.tgz",
-      "integrity": "sha512-63n77K1pt8dnbWnNR8QWETi9Glezi1bvNHvHWmGNIOv0xCb0phZnm+Ku49BQ+omwe8Z5voMvrA4I03SYPpv38w=="
+      "version": "0.9.0-beta.3",
+      "resolved": "https://registry.npmjs.org/cordova-plugin-local-notification/-/cordova-plugin-local-notification-0.9.0-beta.3.tgz",
+      "integrity": "sha512-L3Z1velxrkm9nHFcvLnMgBPZjKFt6hwM6hn1lA+JFwIR26Yw6UF72z+/lRMBclAcOxBIDYCqeaLgvezmajjuEg=="
     },
     "cordova-plugin-media-capture": {
       "version": "3.0.2",
@@ -3220,6 +3225,11 @@
       "resolved": "https://registry.npmjs.org/cordova-sqlite-storage-dependencies/-/cordova-sqlite-storage-dependencies-1.2.1.tgz",
       "integrity": "sha512-4ihQApBGVKR1QZ4oOSGctKFfthtCfiWMTcIIfxe97vKxlvGr9NyXOvYG9vXU9S7yVR7Ua+Rj47hkE7pQIKvQTg=="
     },
+    "cordova-support-google-services": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/cordova-support-google-services/-/cordova-support-google-services-1.1.0.tgz",
+      "integrity": "sha1-RjTFIgD4cGDReV6yhw6ZRC12Lm0="
+    },
     "core-js": {
       "version": "2.3.0",
       "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.3.0.tgz",
@@ -6314,6 +6324,11 @@
       "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==",
       "dev": true
     },
+    "install": {
+      "version": "0.8.9",
+      "resolved": "https://registry.npmjs.org/install/-/install-0.8.9.tgz",
+      "integrity": "sha1-n0tcDRhR74cunfheT3Fi1OXc2+0="
+    },
     "interpret": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz",
@@ -8554,9 +8569,19 @@
       "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=",
       "dev": true
     },
+    "phonegap-plugin-multidex": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/phonegap-plugin-multidex/-/phonegap-plugin-multidex-1.0.0.tgz",
+      "integrity": "sha512-1wvc3iQOQpEBaQbXgLxA2JUiLSQ2azdF/bF29ghXDiQJWSpQ1BF8gSuqttM8WZoj081Ps8OKL0gYxdDBkFNPqA=="
+    },
     "phonegap-plugin-push": {
-      "version": "git+https://github.com/moodlemobile/phonegap-plugin-push.git#cf2ed2075d9d2d58a4c4f79543f669ed6366c148",
-      "from": "git+https://github.com/moodlemobile/phonegap-plugin-push.git#moodle"
+      "version": "2.2.3",
+      "resolved": "https://registry.npmjs.org/phonegap-plugin-push/-/phonegap-plugin-push-2.2.3.tgz",
+      "integrity": "sha512-5mjT0G1vfRhXVnZFLwjfzcFwYjVRMibgYDCfYvEujGsP8YwwrIIzcf+xBYAjQV/W2JCjzuNaYd7xJ0yVQaPeig==",
+      "requires": {
+        "babel-plugin-add-header-comment": "^1.0.3",
+        "install": "^0.8.2"
+      }
     },
     "pify": {
       "version": "2.3.0",
diff --git a/package.json b/package.json
index 87f697455..4ffaa3c37 100644
--- a/package.json
+++ b/package.json
@@ -93,7 +93,7 @@
     "cordova-plugin-globalization": "^1.11.0",
     "cordova-plugin-inappbrowser": "^3.0.0",
     "cordova-plugin-ionic-keyboard": "^2.1.3",
-    "cordova-plugin-local-notification": "^0.9.0-beta.2",
+    "cordova-plugin-local-notification": "^0.9.0-beta.3",
     "cordova-plugin-media-capture": "^3.0.2",
     "cordova-plugin-network-information": "^2.0.1",
     "cordova-plugin-screen-orientation": "^3.0.1",
@@ -102,6 +102,7 @@
     "cordova-plugin-whitelist": "^1.3.3",
     "cordova-plugin-zip": "^3.1.0",
     "cordova-sqlite-storage": "^2.6.0",
+    "cordova-support-google-services": "^1.1.0",
     "es6-promise-plugin": "^4.2.2",
     "font-awesome": "^4.7.0",
     "ionic-angular": "3.9.3",
@@ -109,7 +110,8 @@
     "jszip": "^3.1.5",
     "moment": "^2.22.2",
     "nl.kingsquare.cordova.background-audio": "^1.0.1",
-    "phonegap-plugin-push": "git+https://github.com/moodlemobile/phonegap-plugin-push.git#moodle",
+    "phonegap-plugin-multidex": "^1.0.0",
+    "phonegap-plugin-push": "^2.2.3",
     "promise.prototype.finally": "^3.1.0",
     "rxjs": "^5.5.11",
     "sw-toolbox": "^3.6.0",
@@ -169,7 +171,8 @@
       "cordova-sqlite-storage": {},
       "nl.kingsquare.cordova.background-audio": {},
       "phonegap-plugin-push": {
-        "SENDER_ID": "694767596569"
+        "ANDROID_SUPPORT_V13_VERSION": "27.+",
+        "FCM_VERSION": "11.6.2"
       }
     }
   },
diff --git a/scripts/langindex.json b/scripts/langindex.json
index c87296df8..a9d2e941e 100644
--- a/scripts/langindex.json
+++ b/scripts/langindex.json
@@ -68,6 +68,7 @@
   "addon.blog.siteblogheading": "blog",
   "addon.calendar.calendar": "calendar",
   "addon.calendar.calendarevents": "local_moodlemobileapp",
+  "addon.calendar.calendarreminders": "local_moodlemobileapp",
   "addon.calendar.defaultnotificationtime": "local_moodlemobileapp",
   "addon.calendar.errorloadevent": "local_moodlemobileapp",
   "addon.calendar.errorloadevents": "local_moodlemobileapp",
@@ -1508,6 +1509,7 @@
   "core.maxsizeandattachments": "moodle",
   "core.min": "moodle",
   "core.mins": "moodle",
+  "core.misc": "admin",
   "core.mod_assign": "assign/pluginname",
   "core.mod_assignment": "assignment/pluginname",
   "core.mod_book": "book/pluginname",
@@ -1660,6 +1662,7 @@
   "core.settings.navigatoruseragent": "local_moodlemobileapp",
   "core.settings.networkstatus": "local_moodlemobileapp",
   "core.settings.privacypolicy": "local_moodlemobileapp",
+  "core.settings.pushid": "local_moodlemobileapp",
   "core.settings.reportinbackground": "local_moodlemobileapp",
   "core.settings.settings": "moodle",
   "core.settings.showdownloadoptions": "local_moodlemobileapp",
diff --git a/src/addon/calendar/lang/en.json b/src/addon/calendar/lang/en.json
index 1fc6d2e34..6ccb04caa 100644
--- a/src/addon/calendar/lang/en.json
+++ b/src/addon/calendar/lang/en.json
@@ -1,6 +1,7 @@
 {
     "calendar": "Calendar",
     "calendarevents": "Calendar events",
+    "calendarreminders": "Calendar reminders",
     "defaultnotificationtime": "Default notification time",
     "errorloadevent": "Error loading event.",
     "errorloadevents": "Error loading events.",
diff --git a/src/addon/pushnotifications/providers/pushnotifications.ts b/src/addon/pushnotifications/providers/pushnotifications.ts
index fce797a79..df36c3bed 100644
--- a/src/addon/pushnotifications/providers/pushnotifications.ts
+++ b/src/addon/pushnotifications/providers/pushnotifications.ts
@@ -13,13 +13,16 @@
 // limitations under the License.
 
 import { Injectable, NgZone } from '@angular/core';
+import { Platform } from 'ionic-angular';
 import { Badge } from '@ionic-native/badge';
 import { Push, PushObject, PushOptions } from '@ionic-native/push';
 import { Device } from '@ionic-native/device';
+import { TranslateService } from '@ngx-translate/core';
 import { CoreAppProvider } from '@providers/app';
 import { CoreInitDelegate } from '@providers/init';
 import { CoreLoggerProvider } from '@providers/logger';
-import { CoreSitesProvider } from '@providers/sites';
+import { CoreSitesProvider, CoreSiteSchema } from '@providers/sites';
+import { CoreSitesFactoryProvider } from '@providers/sites-factory';
 import { AddonPushNotificationsDelegate } from './delegate';
 import { CoreLocalNotificationsProvider } from '@providers/local-notifications';
 import { CoreUtilsProvider } from '@providers/utils/utils';
@@ -28,7 +31,55 @@ import { CoreConfigProvider } from '@providers/config';
 import { CoreConstants } from '@core/constants';
 import { CoreConfigConstants } from '../../../configconstants';
 import { ILocalNotification } from '@ionic-native/local-notifications';
-import { SQLiteDBTableSchema } from '@classes/sqlitedb';
+import { SQLiteDB, SQLiteDBTableSchema } from '@classes/sqlitedb';
+import { CoreSite } from '@classes/site';
+
+/**
+ * Data needed to register a device in a Moodle site.
+ */
+export interface AddonPushNotificationsRegisterData {
+    /**
+     * App ID.
+     * @type {string}
+     */
+    appid: string;
+
+    /**
+     * Device UUID.
+     * @type {string}
+     */
+    uuid: string;
+
+    /**
+     * Device name.
+     * @type {string}
+     */
+    name: string;
+
+    /**
+     * Device model.
+     * @type {string}
+     */
+    model: string;
+
+    /**
+     * Device platform.
+     * @type {string}
+     */
+    platform: string;
+
+    /**
+     * Device version.
+     * @type {string}
+     */
+    version: string;
+
+    /**
+     * Push ID.
+     * @type {string}
+     */
+    pushid: string;
+}
 
 /**
  * Service to handle push notifications.
@@ -37,12 +88,14 @@ import { SQLiteDBTableSchema } from '@classes/sqlitedb';
 export class AddonPushNotificationsProvider {
     protected logger;
     protected pushID: string;
-    protected appDB: any;
+    protected appDB: SQLiteDB;
     static COMPONENT = 'AddonPushNotificationsProvider';
 
     // Variables for database.
     static BADGE_TABLE = 'addon_pushnotifications_badge';
-    protected tablesSchema: SQLiteDBTableSchema[] = [
+    static PENDING_UNREGISTER_TABLE = 'addon_pushnotifications_pending_unregister';
+    static REGISTERED_DEVICES_TABLE = 'addon_pushnotifications_registered_devices';
+    protected appTablesSchema: SQLiteDBTableSchema[] = [
         {
             name: AddonPushNotificationsProvider.BADGE_TABLE,
             columns: [
@@ -60,17 +113,91 @@ export class AddonPushNotificationsProvider {
                 }
             ],
             primaryKeys: ['siteid', 'addon']
+        },
+        {
+            name: AddonPushNotificationsProvider.PENDING_UNREGISTER_TABLE,
+            columns: [
+                {
+                    name: 'siteid',
+                    type: 'TEXT',
+                    primaryKey: true
+                },
+                {
+                    name: 'siteurl',
+                    type: 'TEXT'
+                },
+                {
+                    name: 'token',
+                    type: 'TEXT'
+                },
+                {
+                    name: 'info',
+                    type: 'TEXT'
+                }
+            ]
         }
     ];
+    protected siteSchema: CoreSiteSchema = {
+        name: 'AddonPushNotificationsProvider',
+        version: 1,
+        tables: [
+            {
+                name: AddonPushNotificationsProvider.REGISTERED_DEVICES_TABLE,
+                columns: [
+                    {
+                        name: 'appid',
+                        type: 'TEXT',
+                    },
+                    {
+                        name: 'uuid',
+                        type: 'TEXT'
+                    },
+                    {
+                        name: 'name',
+                        type: 'TEXT'
+                    },
+                    {
+                        name: 'model',
+                        type: 'TEXT'
+                    },
+                    {
+                        name: 'platform',
+                        type: 'TEXT'
+                    },
+                    {
+                        name: 'version',
+                        type: 'TEXT'
+                    },
+                    {
+                        name: 'pushid',
+                        type: 'TEXT'
+                    },
+                ],
+                primaryKeys: ['appid', 'uuid']
+            }
+        ],
+    };
 
     constructor(logger: CoreLoggerProvider, protected appProvider: CoreAppProvider, private initDelegate: CoreInitDelegate,
             protected pushNotificationsDelegate: AddonPushNotificationsDelegate, protected sitesProvider: CoreSitesProvider,
             private badge: Badge, private localNotificationsProvider: CoreLocalNotificationsProvider,
             private utils: CoreUtilsProvider, private textUtils: CoreTextUtilsProvider, private push: Push,
-            private configProvider: CoreConfigProvider, private device: Device, private zone: NgZone) {
+            private configProvider: CoreConfigProvider, private device: Device, private zone: NgZone,
+            private translate: TranslateService, private platform: Platform, private sitesFactory: CoreSitesFactoryProvider) {
         this.logger = logger.getInstance('AddonPushNotificationsProvider');
         this.appDB = appProvider.getDB();
-        this.appDB.createTablesFromSchema(this.tablesSchema);
+        this.appDB.createTablesFromSchema(this.appTablesSchema);
+        this.sitesProvider.registerSiteSchema(this.siteSchema);
+
+        platform.ready().then(() => {
+            // Create the default channel.
+            this.createDefaultChannel();
+
+            translate.onLangChange.subscribe((event: any) => {
+                // Update the channel name.
+                this.createDefaultChannel();
+            });
+        });
     }
 
     /**
@@ -85,6 +212,25 @@ export class AddonPushNotificationsProvider {
         });
     }
 
+    /**
+     * Create the default push channel. It is used to change the name.
+     *
+     * @return {Promise<any>} Promise resolved when done.
+     */
+    protected createDefaultChannel(): Promise<any> {
+        if (!this.platform.is('android')) {
+            return Promise.resolve();
+        }
+
+        return this.push.createChannel({
+            id: 'PushPluginChannel',
+            description: this.translate.instant('core.misc'),
+            importance: 4
+        }).catch((error) => {
+            this.logger.error('Error changing push channel name', error);
+        });
+    }
+
     /**
      * Returns options for push notifications based on device.
      *
@@ -94,7 +240,6 @@ export class AddonPushNotificationsProvider {
         return this.configProvider.get(CoreConstants.SETTINGS_NOTIFICATION_SOUND, true).then((soundEnabled) => {
             return {
                 android: {
-                    senderID: CoreConfigConstants.gcmpn,
                     sound: !!soundEnabled,
                     icon: 'smallicon'
                 },
@@ -119,6 +264,23 @@ export class AddonPushNotificationsProvider {
         return this.pushID;
     }
 
+    /**
+     * Get data to register the device in Moodle.
+     *
+     * @return {AddonPushNotificationsRegisterData} Data.
+     */
+    protected getRegisterData(): AddonPushNotificationsRegisterData {
+        return {
+            appid:      CoreConfigConstants.app_id,
+            name:       this.device.manufacturer || '',
+            model:      this.device.model,
+            platform:   this.device.platform + '-fcm',
+            version:    this.device.version,
+            pushid:     this.pushID,
+            uuid:       this.device.uuid
+        };
+    }
+
     /**
      * Get Sitebadge  counter from the database.
      *
@@ -156,13 +318,7 @@ export class AddonPushNotificationsProvider {
                 if (this.localNotificationsProvider.isAvailable()) {
                     const localNotif: ILocalNotification = {
                             id: 1,
-                            trigger: {
-                                at: new Date()
-                            },
-                            data: {
-                                notif: data.notif,
-                                site: data.site
-                            },
+                            data: data,
                             title: '',
                             text: ''
                         },
@@ -194,9 +350,6 @@ export class AddonPushNotificationsProvider {
                 });
             } else {
                 // The notification was clicked.
-                // For compatibility with old push plugin implementation we'll merge all the notification data in a single object.
-                data.title = notification.title;
-                data.message = notification.message;
                 this.notificationClicked(data);
             }
         });
@@ -205,10 +358,10 @@ export class AddonPushNotificationsProvider {
     /**
      * Unregisters a device from a certain Moodle site.
      *
-     * @param {any} site Site to unregister from.
-     * @return {Promise<any>}    Promise resolved when device is unregistered.
+     * @param {CoreSite} site Site to unregister from.
+     * @return {Promise<any>} Promise resolved when device is unregistered.
      */
-    unregisterDeviceOnMoodle(site: any): Promise<any> {
+    unregisterDeviceOnMoodle(site: CoreSite): Promise<any> {
         if (!site || !this.appProvider.isMobile()) {
             return Promise.reject(null);
         }
@@ -224,6 +377,34 @@ export class AddonPushNotificationsProvider {
             if (!response || !response.removed) {
                 return Promise.reject(null);
             }
+
+            const promises = [];
+
+            // Remove the device from the local DB.
+            promises.push(site.getDb().deleteRecords(AddonPushNotificationsProvider.REGISTERED_DEVICES_TABLE,
+                    this.getRegisterData()));
+
+            // Remove pending unregisters for this site.
+            promises.push(this.appDB.deleteRecords(AddonPushNotificationsProvider.PENDING_UNREGISTER_TABLE, {siteid: site.id}));
+
+            return Promise.all(promises).catch(() => {
+                // Ignore errors.
+            });
+        }).catch((error) => {
+            if (this.utils.isWebServiceError(error)) {
+                // It's a WebService error, can't unregister.
+                return Promise.reject(error);
+            }
+
+            // Store the pending unregister so it's retried again later.
+            return this.appDB.insertRecord(AddonPushNotificationsProvider.PENDING_UNREGISTER_TABLE, {
+                siteid: site.id,
+                siteurl: site.getURL(),
+                token: site.getToken(),
+                info: JSON.stringify(site.getInfo())
+            }).then(() => {
+                return Promise.reject(error);
+            });
         });
     }
 
@@ -366,28 +547,58 @@ export class AddonPushNotificationsProvider {
     }
 
     /**
-     * Registers a device on current Moodle site.
+     * Registers a device on a Moodle site if needed.
      *
-     * @return {Promise<any>}      Promise resolved when device is registered.
+     * @param {string} [siteId] Site ID. If not defined, current site.
+     * @param {boolean} [forceUnregister] Whether to force unregister and register.
+     * @return {Promise<any>} Promise resolved when device is registered.
      */
-    registerDeviceOnMoodle(): Promise<any> {
+    registerDeviceOnMoodle(siteId?: string, forceUnregister?: boolean): Promise<any> {
         this.logger.debug('Register device on Moodle.');
 
-        if (!this.sitesProvider.isLoggedIn() || !this.pushID || !this.appProvider.isMobile()) {
+        if (!this.pushID || !this.appProvider.isMobile()) {
             return Promise.reject(null);
         }
 
-        const data = {
-            appid:      CoreConfigConstants.app_id,
-            name:       this.device.manufacturer || '',
-            model:      this.device.model,
-            platform:   this.device.platform,
-            version:    this.device.version,
-            pushid:     this.pushID,
-            uuid:       this.device.uuid
-        };
+        const data = this.getRegisterData();
+        let result,
+            site: CoreSite;
 
-        return this.sitesProvider.getCurrentSite().write('core_user_add_user_device', data);
+        return this.sitesProvider.getSite(siteId).then((s) => {
+            site = s;
+
+            if (forceUnregister) {
+                return {unregister: true, register: true};
+            } else {
+                // Check if the device is already registered.
+                return this.shouldRegister(data, site);
+            }
+        }).then((res) => {
+            result = res;
+
+            if (result.unregister) {
+                // Unregister the device first.
+                return this.unregisterDeviceOnMoodle(site).catch(() => {
+                    // Ignore errors.
+                });
+            }
+        }).then(() => {
+            if (result.register) {
+                // Now register the device.
+                return site.write('core_user_add_user_device', this.utils.clone(data)).then((response) => {
+                    // Insert the device in the local DB.
+                    return site.getDb().insertRecord(AddonPushNotificationsProvider.REGISTERED_DEVICES_TABLE, data)
+                            .catch((error) => {
+                        // Ignore errors.
+                    });
+                });
+            }
+        }).finally(() => {
+            // Remove pending unregisters for this site.
+            this.appDB.deleteRecords(AddonPushNotificationsProvider.PENDING_UNREGISTER_TABLE, {siteid: site.id}).catch(() => {
+                // Ignore errors.
+            });
+        });
     }
 
     /**
@@ -405,6 +616,38 @@ export class AddonPushNotificationsProvider {
         });
     }
 
+    /**
+     * Retry pending unregisters.
+     *
+     * @param {string} [siteId] If defined, retry only for that site if needed. Otherwise, retry all pending unregisters.
+     * @return {Promise<any>} Promise resolved when done.
+     */
+    retryUnregisters(siteId?: string): Promise<any> {
+        let promise;
+
+        if (siteId) {
+            // Check if the site has a pending unregister.
+            promise = this.appDB.getRecords(AddonPushNotificationsProvider.REGISTERED_DEVICES_TABLE, {siteid: siteId});
+        } else {
+            // Get all pending unregisters.
+            promise = this.appDB.getAllRecords(AddonPushNotificationsProvider.PENDING_UNREGISTER_TABLE);
+        }
+
+        return promise.then((results) => {
+            const promises = [];
+
+            results.forEach((result) => {
+                // Create a temporary site to unregister.
+                const tmpSite = this.sitesFactory.makeSite(result.siteid, result.siteurl, result.token,
+                        this.textUtils.parseJSON(result.info, {}));
+
+                promises.push(this.unregisterDeviceOnMoodle(tmpSite));
+            });
+
+            return Promise.all(promises);
+        });
+    }
+
     /**
      * Save the addon/site badgecounter on the database.
      *
@@ -426,4 +669,58 @@ export class AddonPushNotificationsProvider {
             return value;
         });
     }
+
+    /**
+     * Check if device should be registered (and unregistered first).
+     *
+     * @param {AddonPushNotificationsRegisterData} data Data of the device.
+     * @param {CoreSite} site Site to use.
+     * @return {Promise<{register: boolean, unregister: boolean}>} Promise resolved with booleans: whether to register/unregister.
+     */
+    protected shouldRegister(data: AddonPushNotificationsRegisterData, site: CoreSite)
+            : Promise<{register: boolean, unregister: boolean}> {
+
+        // Check if the device is already registered.
+        return site.getDb().getRecords(AddonPushNotificationsProvider.REGISTERED_DEVICES_TABLE, {
+            appid: data.appid,
+            uuid: data.uuid
+        }).catch(() => {
+            // Ignore errors.
+            return [];
+        }).then((records: AddonPushNotificationsRegisterData[]) => {
+            let isStored = false,
+                versionOrPushChanged = false;
+
+            records.forEach((record) => {
+                if (record.name == data.name && record.model == data.model && record.platform == data.platform) {
+                    if (record.version == data.version && record.pushid == data.pushid) {
+                        // The device is already stored.
+                        isStored = true;
+                    } else {
+                        // The version or pushid has changed.
+                        versionOrPushChanged = true;
+                    }
+                }
+            });
+
+            if (isStored) {
+                // The device has already been registered, no need to register it again.
+                return {
+                    register: false,
+                    unregister: false
+                };
+            } else if (versionOrPushChanged) {
+                // This data can be updated by calling register WS, no need to call unregister.
+                return {
+                    register: true,
+                    unregister: false
+                };
+            } else {
+                return {
+                    register: true,
+                    unregister: true
+                };
+            }
+        });
+    }
 }
diff --git a/src/addon/pushnotifications/providers/register-cron-handler.ts b/src/addon/pushnotifications/providers/register-cron-handler.ts
new file mode 100644
index 000000000..fd3ea87ff
--- /dev/null
+++ b/src/addon/pushnotifications/providers/register-cron-handler.ts
@@ -0,0 +1,71 @@
+// (C) Copyright 2015 Martin Dougiamas
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import { Injectable } from '@angular/core';
+import { CoreCronHandler } from '@providers/cron';
+import { AddonPushNotificationsProvider } from './pushnotifications';
+
+/**
+ * Cron handler to force a register on a Moodle site when a site is manually synchronized.
+ */
+@Injectable()
+export class AddonPushNotificationsRegisterCronHandler implements CoreCronHandler {
+    name = 'AddonPushNotificationsRegisterCronHandler';
+
+    constructor(private pushNotificationsProvider: AddonPushNotificationsProvider) {}
+
+    /**
+     * Check whether the sync can be executed manually. Call isSync if not defined.
+     *
+     * @return {boolean} Whether the sync can be executed manually.
+     */
+    canManualSync(): boolean {
+        return true; // Execute the handler when the site is manually synchronized.
+    }
+
+    /**
+     * Execute the process.
+     * Receives the ID of the site affected, undefined for all sites.
+     *
+     * @param  {string} [siteId] ID of the site affected, undefined for all sites.
+     * @return {Promise<any>}         Promise resolved when done, rejected if failure.
+     */
+    execute(siteId?: string): Promise<any> {
+        if (!siteId) {
+            // It's not a specific site, don't do anything.
+            return Promise.resolve();
+        }
+
+        // Register the device again.
+        return this.pushNotificationsProvider.registerDeviceOnMoodle(siteId, true);
+    }
+
+    /**
+     * Get the time between consecutive executions.
+     *
+     * @return {number} Time between consecutive executions (in ms).
+     */
+    getInterval(): number {
+        return 86400000; // 1 day. We won't do anything with automatic execution, so use a big number.
+    }
+
+    /**
+     * Check whether it's a synchronization process or not. True if not defined.
+     *
+     * @return {boolean} Whether it's a synchronization process or not.
+     */
+    isSync(): boolean {
+        return false;
+    }
+}
diff --git a/src/addon/pushnotifications/providers/unregister-cron-handler.ts b/src/addon/pushnotifications/providers/unregister-cron-handler.ts
new file mode 100644
index 000000000..548d44bd0
--- /dev/null
+++ b/src/addon/pushnotifications/providers/unregister-cron-handler.ts
@@ -0,0 +1,47 @@
+// (C) Copyright 2015 Martin Dougiamas
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import { Injectable } from '@angular/core';
+import { CoreCronHandler } from '@providers/cron';
+import { AddonPushNotificationsProvider } from './pushnotifications';
+
+/**
+ * Cron handler to retry pending unregisters.
+ */
+@Injectable()
+export class AddonPushNotificationsUnregisterCronHandler implements CoreCronHandler {
+    name = 'AddonPushNotificationsUnregisterCronHandler';
+
+    constructor(private pushNotificationsProvider: AddonPushNotificationsProvider) {}
+
+    /**
+     * Execute the process.
+     * Receives the ID of the site affected, undefined for all sites.
+     *
+     * @param  {string} [siteId] ID of the site affected, undefined for all sites.
+     * @return {Promise<any>} Promise resolved when done, rejected if failure.
+     */
+    execute(siteId?: string): Promise<any> {
+        return this.pushNotificationsProvider.retryUnregisters(siteId);
+    }
+
+    /**
+     * Get the time between consecutive executions.
+     *
+     * @return {number} Time between consecutive executions (in ms).
+     */
+    getInterval(): number {
+        return 300000;
+    }
+}
diff --git a/src/addon/pushnotifications/pushnotifications.module.ts b/src/addon/pushnotifications/pushnotifications.module.ts
index 6de574ecc..d36a0ce43 100644
--- a/src/addon/pushnotifications/pushnotifications.module.ts
+++ b/src/addon/pushnotifications/pushnotifications.module.ts
@@ -16,6 +16,9 @@ import { NgModule } from '@angular/core';
 import { Platform } from 'ionic-angular';
 import { AddonPushNotificationsProvider } from './providers/pushnotifications';
 import { AddonPushNotificationsDelegate } from './providers/delegate';
+import { AddonPushNotificationsRegisterCronHandler } from './providers/register-cron-handler';
+import { AddonPushNotificationsUnregisterCronHandler } from './providers/unregister-cron-handler';
+import { CoreCronDelegate } from '@providers/cron';
 import { CoreEventsProvider } from '@providers/events';
 import { CoreLoggerProvider } from '@providers/logger';
 import { CoreLocalNotificationsProvider } from '@providers/local-notifications';
@@ -34,16 +37,24 @@ export const ADDON_PUSHNOTIFICATIONS_PROVIDERS: any[] = [
     ],
     providers: [
         AddonPushNotificationsProvider,
-        AddonPushNotificationsDelegate
+        AddonPushNotificationsDelegate,
+        AddonPushNotificationsRegisterCronHandler,
+        AddonPushNotificationsUnregisterCronHandler
     ]
 })
 export class AddonPushNotificationsModule {
     constructor(platform: Platform, pushNotificationsProvider: AddonPushNotificationsProvider, eventsProvider: CoreEventsProvider,
             localNotificationsProvider: CoreLocalNotificationsProvider, loggerProvider: CoreLoggerProvider,
-            updateManager: CoreUpdateManagerProvider) {
+            updateManager: CoreUpdateManagerProvider, cronDelegate: CoreCronDelegate,
+            registerCronHandler: AddonPushNotificationsRegisterCronHandler,
+            unregisterCronHandler: AddonPushNotificationsUnregisterCronHandler) {
 
         const logger = loggerProvider.getInstance('AddonPushNotificationsModule');
 
+        // Register the handlers.
+        cronDelegate.register(registerCronHandler);
+        cronDelegate.register(unregisterCronHandler);
+
         // Register device on GCM or APNS server.
         platform.ready().then(() => {
             pushNotificationsProvider.registerDevice();
diff --git a/src/assets/lang/en.json b/src/assets/lang/en.json
index 80ea77457..59cf7b125 100644
--- a/src/assets/lang/en.json
+++ b/src/assets/lang/en.json
@@ -68,6 +68,7 @@
     "addon.blog.siteblogheading": "Site blog",
     "addon.calendar.calendar": "Calendar",
     "addon.calendar.calendarevents": "Calendar events",
+    "addon.calendar.calendarreminders": "Calendar reminders",
     "addon.calendar.defaultnotificationtime": "Default notification time",
     "addon.calendar.errorloadevent": "Error loading event.",
     "addon.calendar.errorloadevents": "Error loading events.",
@@ -1508,6 +1509,7 @@
     "core.maxsizeandattachments": "Maximum size for new files: {{$a.size}}, maximum attachments: {{$a.attachments}}",
     "core.min": "min",
     "core.mins": "mins",
+    "core.misc": "Miscellaneous",
     "core.mod_assign": "Assignment",
     "core.mod_assignment": "Assignment 2.2 (Disabled)",
     "core.mod_book": "Book",
@@ -1660,6 +1662,7 @@
     "core.settings.navigatoruseragent": "Navigator userAgent",
     "core.settings.networkstatus": "Internet connection status",
     "core.settings.privacypolicy": "Privacy policy",
+    "core.settings.pushid": "Push notifications ID",
     "core.settings.reportinbackground": "Report errors automatically",
     "core.settings.settings": "Settings",
     "core.settings.showdownloadoptions": "Show download options",
diff --git a/src/config.json b/src/config.json
index 56244a5a5..331a72b6d 100644
--- a/src/config.json
+++ b/src/config.json
@@ -64,7 +64,6 @@
             "password": "moodle"
         }
     },
-    "gcmpn": "694767596569",
     "customurlscheme": "moodlemobile",
     "siteurl": "",
     "multisitesdisplay": "",
diff --git a/src/core/emulator/providers/local-notifications.ts b/src/core/emulator/providers/local-notifications.ts
index f8e4f0f65..bcf07ca6b 100644
--- a/src/core/emulator/providers/local-notifications.ts
+++ b/src/core/emulator/providers/local-notifications.ts
@@ -939,6 +939,8 @@ export class LocalNotificationsMock extends LocalNotifications {
 
     /**
      * Schedules or updates a single or multiple notifications.
+     * We only support using the "at" property to trigger the notification. Other properties like "in" or "every"
+     * aren't supported yet.
      *
      * @param {ILocalNotification | Array<ILocalNotification>} [options] Notification or notifications.
      * @param {string} [eventName] Name of the event: schedule or update.
@@ -978,15 +980,6 @@ export class LocalNotificationsMock extends LocalNotifications {
 
                     // Launch the trigger event.
                     this.fireEvent('trigger', notification);
-
-                    if (notification.trigger.every && this.scheduled[notification.id] &&
-                            !this.scheduled[notification.id].interval) {
-
-                        const interval = this.parseInterval(notification.trigger.every);
-                        if (interval > 0) {
-                            this.scheduled[notification.id].interval = setInterval(trigger, interval);
-                        }
-                    }
                 };
 
             this.scheduled[notification.id].timeout = setTimeout(trigger, toTriggerTime);
diff --git a/src/core/settings/lang/en.json b/src/core/settings/lang/en.json
index 2b95b657e..a960ccf02 100644
--- a/src/core/settings/lang/en.json
+++ b/src/core/settings/lang/en.json
@@ -40,6 +40,7 @@
     "navigatoruseragent": "Navigator userAgent",
     "networkstatus": "Internet connection status",
     "privacypolicy": "Privacy policy",
+    "pushid": "Push notifications ID",
     "reportinbackground": "Report errors automatically",
     "settings": "Settings",
     "showdownloadoptions": "Show download options",
diff --git a/src/core/settings/pages/about/about.html b/src/core/settings/pages/about/about.html
index 8efcfaa14..65dd36145 100644
--- a/src/core/settings/pages/about/about.html
+++ b/src/core/settings/pages/about/about.html
@@ -106,6 +106,10 @@
             <h2>{{ 'core.settings.cordovadeviceuuid' | translate}}</h2>
             <p>{{ device.uuid }}</p>
         </ion-item>
+        <ion-item text-wrap *ngIf="pushId">
+            <h2>{{ 'core.settings.pushid' | translate}}</h2>
+            <p>{{ pushId }}</p>
+        </ion-item>
         <ion-item text-wrap *ngIf="localNotifAvailable">
             <h2>{{ 'core.settings.localnotifavailable' | translate}}</h2>
             <p>{{ localNotifAvailable | translate }}</p>
diff --git a/src/core/settings/pages/about/about.ts b/src/core/settings/pages/about/about.ts
index 3bdebc52b..3c6497f49 100644
--- a/src/core/settings/pages/about/about.ts
+++ b/src/core/settings/pages/about/about.ts
@@ -22,6 +22,7 @@ import { CoreLangProvider } from '@providers/lang';
 import { CoreLocalNotificationsProvider } from '@providers/local-notifications';
 import { CoreSitesProvider } from '@providers/sites';
 import { CoreConfigConstants } from '../../../../configconstants';
+import { AddonPushNotificationsProvider } from '@addon/pushnotifications/providers/pushnotifications';
 
 /**
  * Page that displays the about settings.
@@ -53,10 +54,11 @@ export class CoreSettingsAboutPage {
     fsClickable: boolean;
     storageType: string;
     localNotifAvailable: string;
+    pushId: string;
 
     constructor(platform: Platform, device: Device, appProvider: CoreAppProvider, fileProvider: CoreFileProvider,
             initDelegate: CoreInitDelegate, langProvider: CoreLangProvider, sitesProvider: CoreSitesProvider,
-            localNotificationsProvider: CoreLocalNotificationsProvider) {
+            localNotificationsProvider: CoreLocalNotificationsProvider, pushNotificationsProvider: AddonPushNotificationsProvider) {
 
         const currentSite = sitesProvider.getCurrentSite();
 
@@ -111,5 +113,6 @@ export class CoreSettingsAboutPage {
         }
 
         this.localNotifAvailable = localNotificationsProvider.isAvailable() ? 'core.yes' : 'core.no';
+        this.pushId = pushNotificationsProvider.getPushId();
     }
 }
diff --git a/src/lang/en.json b/src/lang/en.json
index 65c423bd1..7b7086f67 100644
--- a/src/lang/en.json
+++ b/src/lang/en.json
@@ -126,6 +126,7 @@
     "maxsizeandattachments": "Maximum size for new files: {{$a.size}}, maximum attachments: {{$a.attachments}}",
     "min": "min",
     "mins": "mins",
+    "misc": "Miscellaneous",
     "mod_assign": "Assignment",
     "mod_assignment": "Assignment 2.2 (Disabled)",
     "mod_book": "Book",
diff --git a/src/providers/local-notifications.ts b/src/providers/local-notifications.ts
index 40cfc3926..6c6b7df7c 100644
--- a/src/providers/local-notifications.ts
+++ b/src/providers/local-notifications.ts
@@ -15,6 +15,7 @@
 import { Injectable } from '@angular/core';
 import { Platform, Alert, AlertController } from 'ionic-angular';
 import { LocalNotifications, ILocalNotification } from '@ionic-native/local-notifications';
+import { Push } from '@ionic-native/push';
 import { TranslateService } from '@ngx-translate/core';
 import { CoreAppProvider } from './app';
 import { CoreConfigProvider } from './config';
@@ -104,7 +105,7 @@ export class CoreLocalNotificationsProvider {
     constructor(logger: CoreLoggerProvider, private localNotifications: LocalNotifications, private platform: Platform,
             private appProvider: CoreAppProvider, private utils: CoreUtilsProvider, private configProvider: CoreConfigProvider,
             private textUtils: CoreTextUtilsProvider, private translate: TranslateService, private alertCtrl: AlertController,
-            eventsProvider: CoreEventsProvider) {
+            eventsProvider: CoreEventsProvider, private push: Push) {
 
         this.logger = logger.getInstance('CoreLocalNotificationsProvider');
         this.appDB = appProvider.getDB();
@@ -122,6 +123,14 @@ export class CoreLocalNotificationsProvider {
                     this.notifyClick(notification.data);
                 }
             });
+
+            // Create the default channel for local notifications.
+            this.createDefaultChannel();
+
+            translate.onLangChange.subscribe((event: any) => {
+                // Update the channel name.
+                this.createDefaultChannel();
+            });
         });
 
         eventsProvider.on(CoreEventsProvider.SITE_DELETED, (site) => {
@@ -176,6 +185,25 @@ export class CoreLocalNotificationsProvider {
         });
     }
 
+    /**
+     * Create the default channel. It is used to change the name.
+     *
+     * @return {Promise<any>} Promise resolved when done.
+     */
+    protected createDefaultChannel(): Promise<any> {
+        if (!this.platform.is('android')) {
+            return Promise.resolve();
+        }
+
+        return this.push.createChannel({
+            id: 'default-channel-id',
+            description: this.translate.instant('addon.calendar.calendarreminders'),
+            importance: 4
+        }).catch((error) => {
+            this.logger.error('Error changing channel name', error);
+        });
+    }
+
     /**
      * Get a code to create unique notifications. If there's no code assigned, create a new one.
      *
@@ -269,7 +297,8 @@ export class CoreLocalNotificationsProvider {
     isAvailable(): boolean {
         const win = <any> window;
 
-        return this.appProvider.isDesktop() || !!(win.plugin && win.plugin.notification && win.plugin.notification.local);
+        return this.appProvider.isDesktop() || !!(win.cordova && win.cordova.plugins && win.cordova.plugins.notification &&
+                win.cordova.plugins.notification.local);
     }
 
     /**
@@ -482,6 +511,8 @@ export class CoreLocalNotificationsProvider {
                             delete notification.sound; // Use default value.
                         }
 
+                        notification.foreground = true;
+
                         // Remove from triggered, since the notification could be in there with a different time.
                         this.removeTriggered(notification.id);
                         this.localNotifications.schedule(notification);