App uses to much memory as time increases - android

My app takes too much memory; 1GB and increases by time. If my app stays open for two days it crashes. Two possible causes:
utils-decorators used to cache data from an API:
import { memoizeAsync, Cache, memoize } from 'utils-decorators';
#memoizeAsync({
expirationTimeMs: 1000 * 60 * 60,
cache: serviceTempData.HttpClientCache
})
async getHtml(url: string, isImage?: boolean): Promise<HTMLElement>{
....
}
The custom cache :
export default class CustomCache implements Cache<any> {
private loadedFiles = new Map<string, any>();
private maxItems: number;
private clearSize: number;
constructor(maxItems?: number, clearSize?: number) {
this.maxItems = maxItems ?? 1000;
this.clearSize = clearSize ?? 500;
}
keys(){
var result = [] as string[];
for(var x of this.loadedFiles.keys())
result.push(x);
return result;
}
clearAll() {
this.loadedFiles.clear();
}
validate() {
var counter = this.clearSize;
if (this.loadedFiles.size > this.maxItems)
for (var key of this.loadedFiles.keys()) {
counter--;
this.loadedFiles.delete(key);
if (counter <= 0)
break;
}
}
set = (key: string, parameter: any) => {
this.validate();
this.loadedFiles.set(key, parameter);
}
get = (key: string) => {
return this.loadedFiles.get(key);
}
delete = (key: string) => {
if (this.loadedFiles.has(key))
this.loadedFiles.delete(key)
}
has = (key: string) => {
return this.loadedFiles.has(key)
}
}
Using expo.sqlight. I build and ORM expo-sqlite-wrapper around expo-sqlight.
I also have a background service running:
while (BackgroundService.isRunning()) {
const dData = [...downloads.filter(x => serviceOperations.DownloadTasks[x.novel] === undefined)]
if (dData.length > 0) {
await dData.asyncForeach(async x => {
console.log("Downloading" + x.novel);
serviceOperations.DownloadTasks[x.novel] = x;
var parser = BackGroundOperator.includedParser.find(f => x.parserName == f.name);
if (parser) {
var novel = await parser.getNovel(x.novel)
parser.downloadNovel(novel, () => {
if (BackGroundOperator.onDownloadStart && BackGroundOperator.onDownloadStart[x.novel] != undefined) {
BackGroundOperator.onDownloadStart[x.novel]();
delete BackGroundOperator.onDownloadStart[x.novel];
}
});
}
});
}
if (!workingOnMessages)
validateMessages();
if (!BackGroundOperator.serviceData && data) {
console.log("Playing")
BackGroundOperator.serviceData = data;
AudioService.task(BackGroundOperator.includedParser);
} else if (!data)
BackGroundOperator.serviceData = undefined;
if (!isWorking)
checkRemovableFiles();
if (!workingOnSessionProgress)
validateSession();
if (__DEV__ && pinger % 100 === 0) {
console.log("Service is still alive")
pinger = 0;
}
await HttpClient.wait(4000);
if (__DEV__)
pinger++
}

Related

ArgumentError (Invalid argument(s): Illegal argument in isolate message: (object extends NativeWrapper - Library:'dart:ui' Class: Paragraph))

I am trying to implement isolate in my flutter project. I got the error
"ArgumentError (Invalid argument(s): Illegal argument in isolate
message: (object extends NativeWrapper - Library:'dart:ui' Class:
Paragraph))"
.suggest me what I am doing wrong
Here is my code
entryPoint(
SendPort sendPort,
) async =>
await CommonService()
.fetchWithoutzip(catId, contactPage, contactSize)
.then((value) {
sendPort.send(value as List);
});
Future fetchWithoutZipcode() async {
userStatus = await getPreferenceStorage('status');
defaultZip = await getPreferenceStorage('defaultZip');
contactPermission = await getPreferenceStorage('contactPermission');
catId = await getPreferenceStorage('selectedIndustryId');
if ((userStatus == 'new' || userStatus == 'active') &&
contactPermission == 'true') {
if (isContactLoading) return;
isContactLoading = true;
hasMoreContact = false;
ReceivePort recievePort =
ReceivePort(); //creating new port to listen data
await Isolate.spawn(entryPoint,
recievePort.sendPort); //spawing/creating new thread as isolates.
return recievePort.listen(
(contactMessage) async {
withoutZipResponse = contactMessage['vouchInfoSearchResults'];
if (withoutZipResponse.isNotEmpty) {
await filterContacts(withoutZipResponse);
}
setState(() {
isContactLoading = false;
if (!contactMessage['last']) {
hasMoreContact = true;
contactPage++;
entryPoint(recievePort.sendPort);
} else {
isContactLoading = true;
}
});
},
);
} else {
return true;
}
}
Thanks in advance

Why I got : Unhandled Exception: 'package:flutter/src/material/scaffold.dart

I'm new with flutter and I want to connect devices with bluetooth. Actually the scan is workin very well but for connecting devices an exception was occured.
The exception is :
Unhandled Exception: 'package:flutter/src/material/scaffold.dart': Failed assertion: line 269 pos 7: '_scaffolds.isNotEmpty': ScaffoldMessenger.showSnackBar was called, but there are currently no descendant Scaffolds to present to.
E/flutter ( 3688): #0 _AssertionErr
this is the code:
// Method to connect to bluetooth
void _connect() async {
setState(() {
_isButtonUnavailable = true;
});
if (_device == null) {
show('No device selected');
} else {
if (!isConnected) {
await BluetoothConnection.toAddress(_device.address)
.then((_connection) {
print('Connected to the device');
connection = _connection;
setState(() {
_connected = true;
});
connection.input.listen(null).onDone(() {
if (isDisconnecting) {
print('Disconnecting locally!');
} else {
print('Disconnected remotely!');
}
if (this.mounted) {
setState(() {});
}
});
}).catchError((error) {
print('Cannot connect, exception occurred');
print(error);
});
show('Device connected');
setState(() => _isButtonUnavailable = false);
}
}
}
void onDataReceived(Uint8List data) {
// // Allocate buffer for parsed data
int backspacesCounter = 0;
data.forEach((byte) {
if (byte == 8 || byte == 127) {
backspacesCounter++;
}
});
Uint8List buffer = Uint8List(data.length - backspacesCounter);
int bufferIndex = buffer.length;
// Apply backspace control character
backspacesCounter = 0;
for (int i = data.length - 1; i >= 0; i--) {
if (data[i] == 8 || data[i] == 127) {
backspacesCounter++;
} else {
if (backspacesCounter > 0) {
backspacesCounter--;
} else {
buffer[--bufferIndex] = data[i];
}
}
}
}
// Method to disconnect bluetooth
void _disconnect() async {
setState(() {
_isButtonUnavailable = true;
_deviceState = 0;
});
await connection.close();
show('Device disconnected');
if (!connection.isConnected) {
setState(() {
_connected = false;
_isButtonUnavailable = false;
});
}
}
// Method to send message,
// for turning the Bluetooth device on
void _sendOnMessageToBluetooth() async {
connection.output.add(utf8.encode("1" + "\r\n"));
await connection.output.allSent;
show('Device Turned On');
setState(() {
_deviceState = 1; // device on
});
}
// Method to send message,
// for turning the Bluetooth device off
void _sendOffMessageToBluetooth() async {
connection.output.add(utf8.encode("0" + "\r\n"));
await connection.output.allSent;
show('Device Turned Off');
setState(() {
_deviceState = -1; // device off
});
}
// Method to show a Snackbar,
// taking message as the text
Future show(
String message, {
Duration duration: const Duration(seconds: 3),
}) async {
await new Future.delayed(new Duration(milliseconds: 100));
ScaffoldMessenger.of(context).showSnackBar(
new SnackBar(
content: new Text(
message,
),
duration: duration,
),
);
}
}
I would be very thankful if you help me.
Issue is with your Scafold You can copy and paste run the full code below
You can use ScaffoldMessenger, you can change from
return Scaffold(
key: scaffoldMessengerKey,
To
return ScaffoldMessenger(
key: scaffoldMessengerKey,
child: Scaffold(
i have check show('Device Turned Off');its working fine

How to keep the user logged in even after closing the app in ionic/angular project?

I am new to angular/ionic and I am assigned with a project where the user supposed to be logged in even after he close the application unless logging out. can anyone suggest me how to modify the following code?
login.page.ts
import { AuthenticationService } from '../../services/authentication/authentication.service';
import {
ToastController,
AlertController,
NavController,
ModalController,
Platform,
} from '#ionic/angular';
import { FormBuilder, Validators, FormGroup } from '#angular/forms';
import { ApiService } from '../../services/api/api.service';
import { Router } from '#angular/router';
import { crm, environment } from '../../../environments/environment';
import { DataService } from '../../services/data/data.service';
import { ToastService } from '../../services/toast/toast.service';
import { AlertService } from '../../services/alert/alert.service';
import { ForgotPasswordModalPage } from '../forgot-password-modal/forgot-password-modal.page';
import { Device } from '#ionic-native/device/ngx';
import { FcmService } from '../../services/fcm/fcm.service';
import { SplashScreen } from '#ionic-native/splash-screen/ngx';
import { LoadingService } from 'src/app/services/loading/loading.service';
import { ServerService } from 'src/app/services/server/server.service';
import * as moment from 'moment';
import { AppComponent } from '../../app.component';
#Component({
selector: 'app-login',
templateUrl: './login.page.html',
styleUrls: ['./login.page.scss'],
})
export class LoginPage implements OnInit {
loginForm: FormGroup;
development: boolean;
counts: number = 0;
platformName: string;
settings: any;
constructor(
private authService: AuthenticationService,
public formBuilder: FormBuilder,
private api: ApiService,
private router: Router,
private alert: AlertService,
private dataService: DataService,
private toast: ToastService,
private navCtrl: NavController,
private modalCtrl: ModalController,
private device: Device,
private fcmService: FcmService,
private splashScreen: SplashScreen,
private loadingService: LoadingService,
private server: ServerService,
private alertCtrl: AlertController,
private platform: Platform,
private app: AppComponent,
) {
this.initForm();
}
ngOnInit(): void {
this.setupServerUrl();
}
async setSettings() {
console.log('settings called in appcomp');
// check if in storage get it from storage
this.dataService.getStorageData('settings').then((data) => {
if (data != null) {
this.settings = JSON.parse(data);
console.log('seetings from storage:', this.settings);
// this.dataService.setData('settings', this.settings)
} else {
// not found in storage get from api
this.getSettingsApi();
}
});
}
async getSettingsApi() {
// this.loadingService.loading();
let mainLogos = document.getElementsByClassName('logo');
for (let i = 0; i < mainLogos.length; i++) {
mainLogos[i].setAttribute('src', 'assets/img/spinner.gif');
}
await this.api.get(crm.SETTINGS).subscribe((res) => {
console.log('the api is ', this.api.url);
// Note the api I supposed to get
console.log('setting from appcomp api: ', res);
if (res['code'] === '000') {
this.settings = res;
// this.dataService.setData('settings', this.settings)
console.log('settings from appcomp done');
this.dataService.setStorageData('settings', res);
for (let i = 0; i < mainLogos.length; i++) {
mainLogos[i].setAttribute('src', this.settings.image_id.src);
}
// this.loadingService.dismissLoading();
}
});
}
// async setSettings() {
// console.log('settings from login')
// await this.dataService.getStorageData('settings').then( data => {
// console.log('seetings from storage: ', data)
// if (data != null) {
// this.settings = JSON.parse(data);
// this.dataService.setData('settings', this.settings)
// }else { // not found in storage get from api
// this.api.get(crm.SETTINGS).subscribe(res => {
// if (res['code'] === '000') {
//
// this.settings = res
// this.dataService.setData('settings', this.settings)
// this.dataService.setStorageData('settings', res);
// // this.settingsService.data = this.settings
//
// // toolbar logo
// // let mainLogos = document.getElementsByClassName('logo')
// // for (let i = 0; i < mainLogos.length; i++) {
// // mainLogos[i].setAttribute('src', this.settings.image_id.src)
// // }
// }
// })
// }
// })
// }
// Note : server set up and function coming from server.service
setupServerUrl() {
this.dataService.getStorageData('url').then((res) => {
if (res) {
this.server.url = JSON.parse(res);
console.log('server', res);
console.log('server result123: ', this.server.url);
console.log('login result123: ', this.server.login_url);
this.server.login_url = JSON.parse(res);
console.log('login', res);
// console.log('have result serve url:', this.server.url);
// console.log('have result login url:', this.server.login_url);
this.getApiDomain('https://oasis.api.app360.my/');
} else {
console.log('empty result url:', this.server.url);
this.getApiDomain('oasis.member.app360.my');
}
});
}
ionViewDidEnter() {
if (this.server.login_url === this.server.login_dev) {
this.development = true;
}
if (this.server.login_url === this.server.login_prod) {
this.development = false;
}
// this.setup()
// this.development = true;
// break;
// case this.server.prod:
// this.server.url = this.server.prod // added by me
// this.development = false;
// break;
// }
// })
}
initForm() {
this.loginForm = this.formBuilder.group({
email: [
'',
Validators.compose([
Validators.pattern('.+#.+\\..+'),
Validators.required,
]),
],
password: ['', Validators.required],
});
}
async getApiDomain(urlDomain: String) {
console.log('beforeeee', this.server.url);
await this.api
.getBeforeLogin(crm.API_DOMAIN, '', '?url=' + urlDomain)
.subscribe((res) => {
if (res['code'] === '000') {
// console.log('resulttt',res['domain'])
this.server.url = 'https://' + res['domain'] + '/';
this.server.prod = 'https://' + res['domain'] + '/';
this.server.secret = res['api_key'];
// this.server.url = "http://oasis.api.app360.my/"
console.log('afterrrr', this.server.url);
// console.log('afterrrr', this.server.secret);
this.getSettingsApi();
this.setHome();
this.checkToken();
}
});
}
// resolveSettings() {
// console.log('settings from login')
// this.api.get(crm.SETTINGS).subscribe(res => {
// if (res['code'] === '000') {
//
// this.settings = res
// this.dataService.setData('settings', this.settings)
// // this.settingsService.data = this.settings
//
// // toolbar logo
// let mainLogos = document.getElementsByClassName('logo')
// for (let i = 0; i < mainLogos.length; i++) {
// mainLogos[i].setAttribute('src', this.settings.image_id.src)
// }
//
//
// }
// })
// }
setup() {
console.log('testttt', this.settings);
// set toolbar color
let toolbars = document.getElementsByTagName('ion-toolbar');
for (let i = 0; i < toolbars.length; i++) {
toolbars[i].setAttribute(
'style',
`--background: ${this.settings.colours.colour_menu_background}`,
);
}
// toolbar logo
let mainLogos = document.getElementsByClassName('logo');
for (let i = 0; i < mainLogos.length; i++) {
mainLogos[i].setAttribute('src', this.settings.image_id.src);
console.log('wahaha', this.settings.image_id.src);
}
let button = document.getElementsByClassName('login-btn')[0];
button.setAttribute(
'style',
`--background: ${this.settings.colours.colour_button1};
--color: ${this.settings.colours.colour_menu_font}`,
);
console.log('endend');
}
async login(form) {
await this.loadingService.loading();
form.platform = this.device.platform;
form.device_type = this.device.model;
form.platform_token = this.device.uuid;
form.push_token = this.fcmService.pushToken;
console.log('form', form);
await this.api.post(crm.LOGIN, form).subscribe((res) => {
this.loadingService.dismissLoading();
console.log('login', res);
if (res.code === '000') {
console.log('code', res.code);
this.toast.showToast('Login Successful');
//proceed with auth
this.doAuth(res);
} else {
// let message = res.status+':'+res.statusText+'<br/>'+res.error.code+':'+res.error.message
this.alert.showAlert({
header: 'Error: ' + res.error.code,
message: res.error.message,
});
console.log('error', res);
}
});
}
async forgotPassword() {
console.log('do forgot password');
let modal = await this.modalCtrl.create({
component: ForgotPasswordModalPage,
cssClass: 'forgot-password',
});
return await modal.present();
}
doAuth(data) {
console.log('from do auth: ', data);
this.authService.login(data).then((res) => {
if (res) {
this.navCtrl.navigateRoot('/tabs/tabs/home');
console.log('doauth', data);
}
});
}
counter() {
this.counts++;
console.log(this.counts);
if (this.counts >= 8) this.presentPrompt(); //TODO: change to 8
}
async presentPrompt() {
this.counts = 0;
const alert = await this.alertCtrl.create({
header: ' ',
inputs: [
{
name: 'passcode',
placeholder: 'Passcode',
type: 'password',
},
],
buttons: [
{
text: 'Cancel',
role: 'cancel',
handler: (data) => {
console.log('Cancel clicked');
},
},
{
text: 'Ok',
handler: (data) => {
this.api
.getBeforeLogin(crm.SWITCH, null, `?passcode=${data.passcode}`)
.subscribe((res) => {
if (res['code'] == '000') {
this.changeServer();
console.log('Switched');
this.toast.showToast('Switched');
// this.loadingService.dismissLoading();
} else {
this.alert.showAlert({
header: 'Error: ' + res['code'],
message: res['error'],
});
console.log('error', res);
}
});
},
},
],
cssClass: 'alertCustomCss',
backdropDismiss: false,
});
await alert.present();
}
changeServer() {
this.server.switchURL();
switch (this.server.login_url) {
case this.server.login_prod:
this.development = false;
// this.api.url = this.server.prod;
this.server.login_url = this.server.login_prod;
console.log('api url', this.server.login_url);
break;
case this.server.login_dev:
this.development = true;
this.server.login_url = this.server.login_dev;
console.log('api url', this.server.login_url);
break;
}
this.checkDownload();
// Note :
this.getApiDomain('https://oasis.api.app360.my/');
// this.getApiDomain('com.apppay.cohibacustomer');
}
async checkDownload() {
await this.dataService.getStorageData('stats_for_dev').then((res) => {
if (!res) {
let params = {};
if (this.platform.is('android')) {
this.platformName = 'android';
} else if (this.platform.is('ios')) {
this.platformName = 'ios';
} else {
this.platformName = 'web';
}
params['refno'] = moment().format('YYYYMMDDHHmm');
params['data'] = [
{
action_cd: 'install',
user_id: null,
item_id: this.platformName[0], // a for android, i for ios
cnt: 1,
created_ts: moment().format('YYYY-M-D'),
},
];
} else {
console.log('have stats', JSON.parse(res));
}
});
}
async setHome() {
await this.api.get(crm.HOME).subscribe((res) => {
console.log('home>>>>>>>>>>>>>>>>>>>>>>>>> ', res);
this.dataService.setStorageData('home', res);
this.dataService.setData('home', res);
return res;
});
}
async checkToken() {
await this.dataService.getStorageData('member').then((res) => {
if (res != null) {
let token = res ? JSON.parse(res) : null;
token = token['secret'] ? token['secret'] : null;
if (token) {
this.authService.authenticationState.next(true);
if (this.server.url != this.server.check_url) {
this.navCtrl.navigateRoot('/tabs/tabs/home');
}
} else {
this.authService.authenticationState.next(false);
this.navCtrl.navigateRoot('');
}
}
});
}
}
authentication.service.ts
import { Platform, NavController } from "#ionic/angular";
import { Injectable } from "#angular/core";
import { Storage } from "#ionic/storage";
import { BehaviorSubject } from "rxjs";
import { DataService } from "../data/data.service";
import { ObservablesService } from "../observable/observables.service";
import { SplashScreen } from "#ionic-native/splash-screen/ngx";
import { Badge } from "#ionic-native/badge/ngx";
import { ServerService } from "../server/server.service";
const TOKEN_KEY = "auth-token";
export interface OcOAuth {
success: number;
error: any;
data: {
access_token: string;
expire_in: number;
token_type: string;
};
}
#Injectable({
providedIn: "root",
})
export class AuthenticationService {
authenticationState = new BehaviorSubject(false);
constructor(
private storage: Storage,
private plt: Platform,
private dataService: DataService,
private observable: ObservablesService,
private splashScreen: SplashScreen,
private navCtrl: NavController,
private badge: Badge,
private server: ServerService
) {
this.plt.ready().then(() => {
this.checkToken();
});
this.observable.unread().subscribe((res) => {
this.badge.set(res);
console.log("observed unread", res);
});
}
async checkToken() {
await this.storage.get("member").then((res) => {
if (res != null) {
let token = res ? JSON.parse(res) : null;
token = token["secret"] ? token["secret"] : null;
if (token) {
this.authenticationState.next(true);
if (this.server.url != this.server.check_url) {
this.navCtrl.navigateRoot("/tabs/tabs/home");
}
// console.log('server url: ', this.server.url);
//
} else {
this.authenticationState.next(false);
this.navCtrl.navigateRoot("");
}
}
});
}
login(data) {
return this.storage.set(TOKEN_KEY, "Bearer 1234").then(() => {
console.log("auth login", TOKEN_KEY);
this.dataService.setStorageData("member", data);
this.dataService.setData("member", data);
// this.dataService.setStorageData('profile', data.user)
this.observable.user.next(data.user);
this.authenticationState.next(true);
return true;
});
}
logout() {
return this.storage.remove("member").then(() => {
this.badge.clear();
this.authenticationState.next(false);
});
}
isAuthenticated() {
return this.authenticationState.value;
}
}
Firstly your code is so long that can not help with that but i can explain what u must do the concept is when you logged in successfully u must get a token and store that.
After at app openning you must check that stored token. If that token still available u can navigate to main screen. Else u must navigate to ur login page.
login() {
const attempt = login(username,pw)
if(attempt.status === 200) {
//if username and pw is correct web service must be return token
this.storage.set("token", attempt.token)
navigate("where u want")
} else {
//Error when username or pw wrong.
}
If u using ionic u must check ur token in app.component.ts
const token = await this.storage.get("token")
const checkTokenIsAvailable = await checkToken(token)
if(checkTokenIsAvailable) {
navigate("where u want")
//Token is still available
} else {
navigate("login screen")
}
That's all.
In your app.component.ts after platform is ready, add
if(this.authenticationService.isAuthenticated())
{
//Navigate to Home Page
}
else{
//Navigate to Login Page
}
so I was able to solve the issue with the subscribe() method. Inside platfrom.ready I called this
this.authService.authenticationState.subscribe((state) => {
if (state) {
this.navCtrl.navigateRoot("/tabs/tabs/home");
} else {
this.navCtrl.navigateRoot("");
}
});

How to use trasaction method inside a then() method firebase cloud function?

I want to run a transaction operation in the second then() method that is like
return admin.database().ref(/Posts).child(oldPostKey).transaction();
Is it correct to do this as shown in the code? There is no error in the Firebase console function log when I execute it, but it does return anything to the next then() method. admin.database().ref(/Posts).child(oldPostKey) has more than one child. Now in the next then() method I want to get all the values of the child for further processing. Can anyone help me?
exports.newIdGenerator = functions.database.ref('/User/{fixedId}').onCreate((shot, context) => {
const fixedId = context.params.fixedId;
const totalLikeRef = admin.database().ref(`/TotalLike`).child(fixedId);
var totalAmount;
return totalLikeRef.transaction((totalLike) => {
if (totalLike !== null) {
console.log("totalLike: " + totalLike);
totalAmount = totalLike;
return totalAmount;
} else {
throw totalAmount;
}
})
.then((totalAmount) => {
return admin.database().ref(`/OldNewKey`).child(fixedId).once('value');
})
.then((oldPostKeyShot) => {
if (!oldPostKeyShot.exists()) {
oldPostKey = fixedId;
} else {
oldPostKey = oldPostKeyShot.val();
}
return admin.database().ref(`/Posts`).child(oldPostKey).transaction();
})
.then((postRefShot) => {
if (postRefShot === null) {
return null;
} else {
return postRefShot;
}
})
.catch((error) => {
return admin.database().ref().child('Send').child(fixedId).set(null);
});
)
}

Client registration failed

I have developped an ibm mobile first application with adapter authorization and challenged handler.I have added an android environment and want to test it against production server, so I deployed the apk on my dev tablet.
I've seen that when trying to invoke a remote adapater worklight tries to get ClientInstanceId by executing a cordova method "WLAuthorizationManagerPlugingetClientInstanceIdHeader". This request results always in a timeout and I can see in console one new entru: "Uncaught (in promise) adapter-communication-error". The method exits with "WL.Logger.debug('Client registration failed with error: ' + JSON.stringify(error));"
Edited: Login flow:
Login implementation:
import {UserModel} from 'app-user';
import {UserService} from 'app-user-service';
import {AppSettingsService} from 'app-settings';
import {AppMasterDataService} from "../master-data/app-master-data-service";
import jsSha from 'js-sha';
import {UserRepository} from "user-repository";
import {NetworkInformation} from ../../infrastructure/phonegap/plugins/network-information';
export class LoggedInUser{
public static inject = [UserService, AppSettingsService, AppMasterDataService, UserRepository];
public info: UserModel;
public isLoggedIn: boolean;
private singleStepAuthRealmChallengeHandler: any;
private _getUserInfoPromise: Promise<UserModel>;
private _listeners: Array<(success: boolean, error: string) => void> = [];
private lastCredentials: any;
constructor(private _userService: UserService, private _settingsService: AppSettingsService, private _masterDataService: AppMasterDataService, private _userRepo: UserRepository){
if(typeof WL != "undefined"){
this.singleStepAuthRealmChallengeHandler = WL.Client.createChallengeHandler('GicarAuthRealm');
this.singleStepAuthRealmChallengeHandler.isCustomResponse = this.isCustomResponse.bind(this);
this.singleStepAuthRealmChallengeHandler.handleChallenge = this.handleChallenge.bind(this);
}
}
public async initializeUserInfo(): Promise<void>{
return this.executeLogOut(null, null);
}
public addLoginEventListener(callback: (success: boolean, error: string) => void){
if(!this._listeners.some(x => x === callback)){
this._listeners.push(callback);
}
}
public removeLoginEventListener(callback: (success: boolean, error: string) => void){
let index = this._listeners.indexOf(callback);
if(index >= 0){
this._listeners.splice(index, 1);
}
}
private raiseLoginEvent(success: boolean, error?: string){
for (var listener of this._listeners){
try {
listener(success, error);
}catch (e){
this.removeLoginEventListener(listener);
}
}
}
public prepareLogin(){
if(NetworkInformation.connected())
this._getUserInfoPromise = this._userService.getUserInfo();
}
public async executeLogIn(userName: string, password: string){//: Promise<boolean>{
await this.executeLogOut(userName, password);
if(this.singleStepAuthRealmChallengeHandler){
if(NetworkInformation.connected()){
var userNameSha = new jsSha("SHA-512", "TEXT");
userNameSha.update(userName);
var userNameHash = userNameSha.getHash("B64");
var passwordSha = new jsSha("SHA-512", "TEXT");
passwordSha.update(password);
var passwordHash = passwordSha.getHash("B64");
this.lastCredentials = {
userName: userNameHash,
password: passwordHash
};
var invocationData = {
adapter : "GicarAuthAdapter",
procedure : "submitAuthentication",
parameters : [ userName, window.btoa(userName + ':' + password) ]
};
this.singleStepAuthRealmChallengeHandler.submitAdapterAuthentication(invocationData);
}else {
this.doDisconnectedLogin(userName, password);
}
}
else{
this._userService.logIn(userName, password)
.then(info =>{
this.info = info;
this.isLoggedIn = typeof info !== 'undefined' && info != null;
this.raiseLoginEvent(this.isLoggedIn);
}).catch(e =>{
this.isLoggedIn = false;
this.info = null;
this.raiseLoginEvent(false, e.message ? e.message : e.toString())
});
}
}
private async doDisconnectedLogin(userName: string, password: string){
var userNameSha = new jsSha("SHA-512", "TEXT");
userNameSha.update(userName);
var userNameHash = userNameSha.getHash("B64");
var passwordSha = new jsSha("SHA-512", "TEXT");
passwordSha.update(password);
var passwordHash = passwordSha.getHash("B64");
var persisted = await this._userRepo.findUserByUserName(userNameHash);
let success = persisted && persisted.password == passwordHash;
this.info = persisted;
this.isLoggedIn = success;
this.raiseLoginEvent(success, success ? null : 'user-invalid-credentials');
}
public executeLogOut(userName: string, password: string): Promise<void>{
this.lastCredentials = null;
if(NetworkInformation.connected()){
return this._userService.logOut(this.info).then(() =>{
this.isLoggedIn = false;
this.info = null;
});
}
else
return Promise.resolve();
}
private isCustomResponse(response: any): boolean{
if (!response || !response.responseJSON || response.responseText === null) {
return false;
}
if (typeof(response.responseJSON.authRequired) !== 'undefined'){
return true;
} else {
return false;
}
}
private async handleChallenge(response: JQueryXHR){
var authRequired = response.responseJSON.authRequired;
if(authRequired == true){
this.info == null;
this.raiseLoginEvent(false, response.responseJSON.errorMessage);
}else {
try {
if(this.info == null){
this.singleStepAuthRealmChallengeHandler.submitSuccess();
this.info = await this._getUserInfoPromise;
await this._masterDataService.initializeMasterData(false);
if(this.lastCredentials){
await this._userRepo.saveUser({
entityId: this.lastCredentials.userName,
firstName: this.info.firstName,
lastName: this.info.lastName,
fullName: this.info.fullName,
email: this.info.email,
nif: this.info.nif,
address: this.info.address,
userName: this.lastCredentials.userName,
password: this.lastCredentials.password
});
}
this.isLoggedIn = true;
this.raiseLoginEvent(true);
}
}catch (error){
this.raiseLoginEvent(false, error.message ? error.message : error.toString());
}
}
}
}
I think I found the issue.
In order to support several environment, including desktopbrowser's one, I'm calling MFP adapter using the "old" method:`
WL.Client.invokeProcedure({
adapter: "UserServiceAdapter",
procedure: 'getUserInfo'
parameters: [],
compressResponse: false
},{
timeout:30000,
onSuccess: handleSuccess,
onFailure: handleFailure
});
If I replace above code by:
var resourceRequest = new WLResourceRequest("/adapters/UserServiceAdapter/getUserInfo", WLResourceRequest.GET, 30000);
resourceRequest.send().then(
handleSuccess,
handleFailure
);
It's working fine on Android.
It seems I have to check the environment in order to decide the adapter invocation method

Categories

Resources