MOBILE-2831 push: Unregister before register if needed
This commit is contained in:
		
							parent
							
								
									75a2732141
								
							
						
					
					
						commit
						a9e4e0c528
					
				| @ -21,7 +21,7 @@ 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 { AddonPushNotificationsDelegate } from './delegate'; | ||||
| import { CoreLocalNotificationsProvider } from '@providers/local-notifications'; | ||||
| import { CoreUtilsProvider } from '@providers/utils/utils'; | ||||
| @ -31,6 +31,54 @@ import { CoreConstants } from '@core/constants'; | ||||
| import { CoreConfigConstants } from '../../../configconstants'; | ||||
| import { ILocalNotification } from '@ionic-native/local-notifications'; | ||||
| import { 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. | ||||
| @ -44,7 +92,8 @@ export class AddonPushNotificationsProvider { | ||||
| 
 | ||||
|     // Variables for database.
 | ||||
|     static BADGE_TABLE = 'addon_pushnotifications_badge'; | ||||
|     protected tablesSchema: SQLiteDBTableSchema[] = [ | ||||
|     static REGISTERED_DEVICES_TABLE = 'addon_pushnotifications_registered_devices'; | ||||
|     protected appTablesSchema: SQLiteDBTableSchema[] = [ | ||||
|         { | ||||
|             name: AddonPushNotificationsProvider.BADGE_TABLE, | ||||
|             columns: [ | ||||
| @ -64,6 +113,46 @@ export class AddonPushNotificationsProvider { | ||||
|             primaryKeys: ['siteid', 'addon'] | ||||
|         } | ||||
|     ]; | ||||
|     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, | ||||
| @ -73,7 +162,8 @@ export class AddonPushNotificationsProvider { | ||||
|             private translate: TranslateService, private platform: Platform) { | ||||
|         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.
 | ||||
| @ -150,6 +240,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. | ||||
|      * | ||||
| @ -227,10 +334,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); | ||||
|         } | ||||
| @ -246,6 +353,12 @@ export class AddonPushNotificationsProvider { | ||||
|             if (!response || !response.removed) { | ||||
|                 return Promise.reject(null); | ||||
|             } | ||||
| 
 | ||||
|             // Remove the device from the local DB.
 | ||||
|             return site.getDb().deleteRecords(AddonPushNotificationsProvider.REGISTERED_DEVICES_TABLE, this.getRegisterData()) | ||||
|                     .catch(() => { | ||||
|                 // Ignore errors.
 | ||||
|             }); | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
| @ -388,28 +501,54 @@ 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 + '-fcm', | ||||
|             version:    this.device.version, | ||||
|             pushid:     this.pushID, | ||||
|             uuid:       this.device.uuid | ||||
|         }; | ||||
|         const data = this.getRegisterData(); | ||||
|         let result, | ||||
|             site: CoreSite; | ||||
| 
 | ||||
|         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.
 | ||||
|                     }); | ||||
|                 }); | ||||
|             } | ||||
|         }); | ||||
| 
 | ||||
|         return this.sitesProvider.getCurrentSite().write('core_user_add_user_device', data); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -448,4 +587,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 | ||||
|                 }; | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -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; | ||||
|     } | ||||
| } | ||||
| @ -16,6 +16,8 @@ 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 { CoreCronDelegate } from '@providers/cron'; | ||||
| import { CoreEventsProvider } from '@providers/events'; | ||||
| import { CoreLoggerProvider } from '@providers/logger'; | ||||
| import { CoreLocalNotificationsProvider } from '@providers/local-notifications'; | ||||
| @ -34,16 +36,21 @@ export const ADDON_PUSHNOTIFICATIONS_PROVIDERS: any[] = [ | ||||
|     ], | ||||
|     providers: [ | ||||
|         AddonPushNotificationsProvider, | ||||
|         AddonPushNotificationsDelegate | ||||
|         AddonPushNotificationsDelegate, | ||||
|         AddonPushNotificationsRegisterCronHandler | ||||
|     ] | ||||
| }) | ||||
| export class AddonPushNotificationsModule { | ||||
|     constructor(platform: Platform, pushNotificationsProvider: AddonPushNotificationsProvider, eventsProvider: CoreEventsProvider, | ||||
|             localNotificationsProvider: CoreLocalNotificationsProvider, loggerProvider: CoreLoggerProvider, | ||||
|             updateManager: CoreUpdateManagerProvider) { | ||||
|             updateManager: CoreUpdateManagerProvider, cronDelegate: CoreCronDelegate, | ||||
|             registerCronHandler: AddonPushNotificationsRegisterCronHandler) { | ||||
| 
 | ||||
|         const logger = loggerProvider.getInstance('AddonPushNotificationsModule'); | ||||
| 
 | ||||
|         // Register the handlers.
 | ||||
|         cronDelegate.register(registerCronHandler); | ||||
| 
 | ||||
|         // Register device on GCM or APNS server.
 | ||||
|         platform.ready().then(() => { | ||||
|             pushNotificationsProvider.registerDevice(); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user