MOBILE-2831 push: Unregister before register if needed
parent
75a2732141
commit
a9e4e0c528
|
@ -21,7 +21,7 @@ import { TranslateService } from '@ngx-translate/core';
|
||||||
import { CoreAppProvider } from '@providers/app';
|
import { CoreAppProvider } from '@providers/app';
|
||||||
import { CoreInitDelegate } from '@providers/init';
|
import { CoreInitDelegate } from '@providers/init';
|
||||||
import { CoreLoggerProvider } from '@providers/logger';
|
import { CoreLoggerProvider } from '@providers/logger';
|
||||||
import { CoreSitesProvider } from '@providers/sites';
|
import { CoreSitesProvider, CoreSiteSchema } from '@providers/sites';
|
||||||
import { AddonPushNotificationsDelegate } from './delegate';
|
import { AddonPushNotificationsDelegate } from './delegate';
|
||||||
import { CoreLocalNotificationsProvider } from '@providers/local-notifications';
|
import { CoreLocalNotificationsProvider } from '@providers/local-notifications';
|
||||||
import { CoreUtilsProvider } from '@providers/utils/utils';
|
import { CoreUtilsProvider } from '@providers/utils/utils';
|
||||||
|
@ -31,6 +31,54 @@ import { CoreConstants } from '@core/constants';
|
||||||
import { CoreConfigConstants } from '../../../configconstants';
|
import { CoreConfigConstants } from '../../../configconstants';
|
||||||
import { ILocalNotification } from '@ionic-native/local-notifications';
|
import { ILocalNotification } from '@ionic-native/local-notifications';
|
||||||
import { SQLiteDBTableSchema } from '@classes/sqlitedb';
|
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.
|
* Service to handle push notifications.
|
||||||
|
@ -44,7 +92,8 @@ export class AddonPushNotificationsProvider {
|
||||||
|
|
||||||
// Variables for database.
|
// Variables for database.
|
||||||
static BADGE_TABLE = 'addon_pushnotifications_badge';
|
static BADGE_TABLE = 'addon_pushnotifications_badge';
|
||||||
protected tablesSchema: SQLiteDBTableSchema[] = [
|
static REGISTERED_DEVICES_TABLE = 'addon_pushnotifications_registered_devices';
|
||||||
|
protected appTablesSchema: SQLiteDBTableSchema[] = [
|
||||||
{
|
{
|
||||||
name: AddonPushNotificationsProvider.BADGE_TABLE,
|
name: AddonPushNotificationsProvider.BADGE_TABLE,
|
||||||
columns: [
|
columns: [
|
||||||
|
@ -64,6 +113,46 @@ export class AddonPushNotificationsProvider {
|
||||||
primaryKeys: ['siteid', 'addon']
|
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,
|
constructor(logger: CoreLoggerProvider, protected appProvider: CoreAppProvider, private initDelegate: CoreInitDelegate,
|
||||||
protected pushNotificationsDelegate: AddonPushNotificationsDelegate, protected sitesProvider: CoreSitesProvider,
|
protected pushNotificationsDelegate: AddonPushNotificationsDelegate, protected sitesProvider: CoreSitesProvider,
|
||||||
|
@ -73,7 +162,8 @@ export class AddonPushNotificationsProvider {
|
||||||
private translate: TranslateService, private platform: Platform) {
|
private translate: TranslateService, private platform: Platform) {
|
||||||
this.logger = logger.getInstance('AddonPushNotificationsProvider');
|
this.logger = logger.getInstance('AddonPushNotificationsProvider');
|
||||||
this.appDB = appProvider.getDB();
|
this.appDB = appProvider.getDB();
|
||||||
this.appDB.createTablesFromSchema(this.tablesSchema);
|
this.appDB.createTablesFromSchema(this.appTablesSchema);
|
||||||
|
this.sitesProvider.registerSiteSchema(this.siteSchema);
|
||||||
|
|
||||||
platform.ready().then(() => {
|
platform.ready().then(() => {
|
||||||
// Create the default channel.
|
// Create the default channel.
|
||||||
|
@ -150,6 +240,23 @@ export class AddonPushNotificationsProvider {
|
||||||
return this.pushID;
|
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.
|
* Get Sitebadge counter from the database.
|
||||||
*
|
*
|
||||||
|
@ -227,10 +334,10 @@ export class AddonPushNotificationsProvider {
|
||||||
/**
|
/**
|
||||||
* Unregisters a device from a certain Moodle site.
|
* Unregisters a device from a certain Moodle site.
|
||||||
*
|
*
|
||||||
* @param {any} site Site to unregister from.
|
* @param {CoreSite} site Site to unregister from.
|
||||||
* @return {Promise<any>} Promise resolved when device is unregistered.
|
* @return {Promise<any>} Promise resolved when device is unregistered.
|
||||||
*/
|
*/
|
||||||
unregisterDeviceOnMoodle(site: any): Promise<any> {
|
unregisterDeviceOnMoodle(site: CoreSite): Promise<any> {
|
||||||
if (!site || !this.appProvider.isMobile()) {
|
if (!site || !this.appProvider.isMobile()) {
|
||||||
return Promise.reject(null);
|
return Promise.reject(null);
|
||||||
}
|
}
|
||||||
|
@ -246,6 +353,12 @@ export class AddonPushNotificationsProvider {
|
||||||
if (!response || !response.removed) {
|
if (!response || !response.removed) {
|
||||||
return Promise.reject(null);
|
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.
|
||||||
*
|
*
|
||||||
|
* @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.
|
* @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.');
|
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);
|
return Promise.reject(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = {
|
const data = this.getRegisterData();
|
||||||
appid: CoreConfigConstants.app_id,
|
let result,
|
||||||
name: this.device.manufacturer || '',
|
site: CoreSite;
|
||||||
model: this.device.model,
|
|
||||||
platform: this.device.platform + '-fcm',
|
return this.sitesProvider.getSite(siteId).then((s) => {
|
||||||
version: this.device.version,
|
site = s;
|
||||||
pushid: this.pushID,
|
|
||||||
uuid: this.device.uuid
|
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;
|
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 { Platform } from 'ionic-angular';
|
||||||
import { AddonPushNotificationsProvider } from './providers/pushnotifications';
|
import { AddonPushNotificationsProvider } from './providers/pushnotifications';
|
||||||
import { AddonPushNotificationsDelegate } from './providers/delegate';
|
import { AddonPushNotificationsDelegate } from './providers/delegate';
|
||||||
|
import { AddonPushNotificationsRegisterCronHandler } from './providers/register-cron-handler';
|
||||||
|
import { CoreCronDelegate } from '@providers/cron';
|
||||||
import { CoreEventsProvider } from '@providers/events';
|
import { CoreEventsProvider } from '@providers/events';
|
||||||
import { CoreLoggerProvider } from '@providers/logger';
|
import { CoreLoggerProvider } from '@providers/logger';
|
||||||
import { CoreLocalNotificationsProvider } from '@providers/local-notifications';
|
import { CoreLocalNotificationsProvider } from '@providers/local-notifications';
|
||||||
|
@ -34,16 +36,21 @@ export const ADDON_PUSHNOTIFICATIONS_PROVIDERS: any[] = [
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
AddonPushNotificationsProvider,
|
AddonPushNotificationsProvider,
|
||||||
AddonPushNotificationsDelegate
|
AddonPushNotificationsDelegate,
|
||||||
|
AddonPushNotificationsRegisterCronHandler
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class AddonPushNotificationsModule {
|
export class AddonPushNotificationsModule {
|
||||||
constructor(platform: Platform, pushNotificationsProvider: AddonPushNotificationsProvider, eventsProvider: CoreEventsProvider,
|
constructor(platform: Platform, pushNotificationsProvider: AddonPushNotificationsProvider, eventsProvider: CoreEventsProvider,
|
||||||
localNotificationsProvider: CoreLocalNotificationsProvider, loggerProvider: CoreLoggerProvider,
|
localNotificationsProvider: CoreLocalNotificationsProvider, loggerProvider: CoreLoggerProvider,
|
||||||
updateManager: CoreUpdateManagerProvider) {
|
updateManager: CoreUpdateManagerProvider, cronDelegate: CoreCronDelegate,
|
||||||
|
registerCronHandler: AddonPushNotificationsRegisterCronHandler) {
|
||||||
|
|
||||||
const logger = loggerProvider.getInstance('AddonPushNotificationsModule');
|
const logger = loggerProvider.getInstance('AddonPushNotificationsModule');
|
||||||
|
|
||||||
|
// Register the handlers.
|
||||||
|
cronDelegate.register(registerCronHandler);
|
||||||
|
|
||||||
// Register device on GCM or APNS server.
|
// Register device on GCM or APNS server.
|
||||||
platform.ready().then(() => {
|
platform.ready().then(() => {
|
||||||
pushNotificationsProvider.registerDevice();
|
pushNotificationsProvider.registerDevice();
|
||||||
|
|
Loading…
Reference in New Issue