I have created an authentication service based on Jason Watmore's example, and it works fine in the Ripple emulator for Android, logs in, saves the token to jStorage, and uses it to access other web services.
It was also working in the actual Android phone till yesterday.
I have tested to see if jStorage is working in my Android phone (it is), and I have tried removing all the app's data using the Settings.
Any idea why the Android phone is not fetching the token from the Moodle server (but the emulator is fetching it)?
Here's my service:
myApp.factory('AuthenticationService',
['$http', '$cookies', '$rootScope', '$timeout', '$log',
function ($http, $cookies, $rootScope, $timeout, $log) {
var service = {};
service.Login = function (username, password, callback) {
//$log.info('Login function called');
if ((username.length && password.length) && (username !== '' && password != '')) {
var loginUrl = 'https://my.moodle.url/local/token.php';
// use $.param jQuery function to serialize data from JSON
var data = $.param({
username: username,
password: password,
service: 'brookesid_ws'
});
//$log.info(data);
var config = {
headers: {
'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8;'
}
}
$http.post(loginUrl, data, config)
.success(function (data, status, headers, config) {
$log.info(data);
myToken = data.token;
dataString = JSON.stringify(data);
if (dataString.indexOf('error') > 0) {
$rootScope.className = 'error';
$rootScope.PostDataResponse = 'Invalid user credentials, please try again';
$rootScope.isAuthenticated = false;
$rootScope.dataLoading = false;
}
else {
$.jStorage.set('session', myToken, { TTL: 28800000 });
//$cookies.put('session', myToken);
}
$rootScope.isAuthenticated = true;
// $log.info('isAuthenticated = true');
callback(dataString);
})
.error(function (data, status, header, config) {
$rootScope.isAuthenticated = false;
$rootScope.ResponseDetails = "data: " + data +
"<br />status: " + status +
"<br />headers: " + header +
"<br />config: " + config;
responsedata = JSON.stringify(data);
callback(responsedata);
$log.info('error: '+responsedata);
});
} else {
$rootScope.className = 'error';
$rootScope.isAuthenticated = false;
$rootScope.PostDataResponse = 'Please enter a username and password';
}
};
service.SetCredentials = function (sessionToken) {
var JSONObject = JSON.parse(sessionToken);
var key = 'token';
myToken = JSONObject[key];
$log.info('session Token: ' + sessionToken);
$log.info('myToken: ' + myToken);
$rootScope.globals = {
currentUser: {
token: myToken
}
};
$http.defaults.headers.common['Authorization'] = 'Basic ' + sessionToken; // jshint ignore:line
//retrieve last login date and then update it
$rootScope.lastLogin = $.jStorage.get('lastLogin', '');
var today = new Date();
epochToday = Math.round(today.getTime() / 1000);
$.jStorage.set('lastLogin', epochToday, { TTL: 28800000 });
//$log.info('Rootscope Last Login: '+$rootScope.lastLogin);
$.jStorage.set('globals', $rootScope.globals, { TTL: 28800000 });
$.jStorage.set('session', myToken, { TTL: 28800000 });
$.jStorage.set('loginStatus', 'logged in', { TTL: 28800000 });
$log.info('Token (jStorage) ' + $.jStorage.get('session', ''));
//$log.info('Last login (jStorage) ' + $.jStorage.get('lastLogin', ''));
//$log.info('Login status (jStorage) ' + $.jStorage.get('loginStatus', ''));
};
service.ClearCredentials = function () {
$rootScope.globals = {};
//$cookies.remove('globals');
//$cookies.remove('session');
$.jStorage.deleteKey('globals');
$.jStorage.deleteKey('session');
$http.defaults.headers.common.Authorization = 'Basic ';
};
return service;
}])
Here is my login Controller:
.controller('loginCtrl',
['$scope', '$rootScope', '$location', 'AuthenticationService', '$routeParams', '$http',
function ($scope, $rootScope, $location, AuthenticationService, $routeParams, $http) {
$scope.login = function () {
$scope.dataLoading = true;
AuthenticationService.Login($scope.username, $scope.password, function (response) {
responsedata = JSON.stringify(response);
/* error handling*/
if (responsedata.indexOf('error') > 0 || responsedata.indexOf('invalid') > 0) {
$scope.error = response.message;
$rootScope.className = 'error';
$rootScope.dataLoading = false;
} else {
AuthenticationService.SetCredentials(response);
console.log('response: '+response);
$location.path('/home');
};
});
};
$scope.logout = function () {
$rootScope.dataLoading = false;
$rootScope.hideMe = true;
$rootScope.PostDataResponse = '';
$rootScope.ResponseDetails = '';
//alert('logging out');
AuthenticationService.ClearCredentials();
};
$scope.showMenuPanel = function () {
$scope.hideMenuPanel = false;
};
$scope.doHideMenuPanel = function () {
$scope.hideMenuPanel = true;
$rootScope.PostDataResponse = '';
};
}])
It was actually the Cordova app's URL whitelisting settings that were causing the problem.
Related
While i trying refresh my token with interceptors, its always looping. I dont know why. Firstly i want to show my code;
class ApiService {
final Dio _dio = Dio();
final Dio tokenDio = Dio();
int tryCount = 0;
String? accessToken;
String? refreshToken;
final _storage = const FlutterSecureStorage();
ApiService() {
_dio.options.baseUrl = ApiConstants.baseUrl;
tokenDio.options = _dio.options;
_storage.read(key: "token").then((value) => accessToken = value);
_storage.read(key: "refreshToken").then((value) => refreshToken = value);
_dio.interceptors.add(
QueuedInterceptorsWrapper(
onError: (DioError error, ErrorInterceptorHandler handler) async {
if (error.response?.statusCode == 401) {
log("Hata Aldık! ${error.requestOptions.path}");
RequestOptions options = error.response!.requestOptions;
if ("Bearer $accessToken" != options.headers[HttpHeaders.authorizationHeader]) {
log("token farklıydı! $accessToken / ${options.headers[HttpHeaders.authorizationHeader]} ");
options.headers[HttpHeaders.authorizationHeader] = "Bearer $accessToken";
_dio.fetch(options).then(
(value) => handler.resolve(value),
onError: (e) {
log("error on resolve");
handler.reject(e);
},
);
return;
}
_dio
.get("/Auth/RefreshTokenLogin?refreshToken=${Uri.encodeQueryComponent(refreshToken!)}")
.then((response) async {
log("Token Refreshlendi!");
if (response.statusCode == 200) {
final RefreshTokenResponseModel? model = RefreshTokenResponseModel.fromJson(response.data);
_storage.write(key: "token", value: model!.data!.token);
_storage.write(key: "refreshToken", value: model.data!.refreshToken);
refreshToken = model.data!.refreshToken;
accessToken = model.data!.token;
options.headers[HttpHeaders.authorizationHeader] = "Bearer ${model.data!.token}";
tokenDio.options.headers = options.headers;
// await UserSecureStorage.setField("token", model!.data!.token);
// await UserSecureStorage.setField("refreshToken", model.data!.refreshToken);
// final AuthService _authService = AuthService();
// await _authService.registerDevice();
if (model.data != null && model.data!.contractsToBeApproved!.isNotEmpty) {
final AuthController authController = Get.Get.find();
authController.contractsToBeApproved.value = model.data!.contractsToBeApproved!;
}
_dio.fetch(options).then(
(value) => handler.resolve(value),
onError: (e) {
handler.reject(e);
},
);
return;
}
return;
});
}
return handler.next(error);
},
onRequest: (RequestOptions options, RequestInterceptorHandler handler) {
log("istek atıldı. ${options.path}");
if (accessToken == null) {
_storage.read(key: "token").then((value) {
log("storage readed $value");
accessToken = value;
options.headers[HttpHeaders.authorizationHeader] = "Bearer $value";
tokenDio.options.headers = options.headers;
handler.next(options);
});
} else {
options.headers[HttpHeaders.authorizationHeader] = "Bearer $accessToken";
return handler.next(options);
}
},
),
);
}
Its my ApiService. And my goal is refreshing token. It might have multiple request in same time so I used "QueuedInterceptorsWrapper". After token expire, Its entering to error handler function and logging "Token Refreslendi" after token refresh api call.But after that if i click something for api call its looping infinitely. Whats wrong with my code ? Thanks for help :)
I am trying to integrate paytm payment gateway in my flutter application by following all in one sdk developer documentation but getting the error on UI (Access Denied you don't have permission to access https://securegw-stage.paytm.in/theia/api/v1/showPaymentPage?mid=MID&orderId=ORDER_ID on this server)
Here is my payment config class code
import 'dart:convert';
import 'package:flutter/services.dart';
import 'package:http/http.dart' as http;
import 'package:paytm_allinonesdk/paytm_allinonesdk.dart';
class PaytmConfig {
final String _mid = MID;
final String _mKey = MKEY;
final String _website = "WEBSTAGING";
final String _url =
'http://flutter-paytm-backend.great-site.net/generateTxnToken'; //testing server
String get mid => _mid;
String get mKey => _mKey;
String get website => _website;
String get url => _url;
String getMap(double amount, String callbackUrl, String orderId) {
return json.encode({
"mid": mid,
"key_secret": mKey,
"website": website,
"orderId": orderId,
"amount": amount.toString(),
"callbackUrl": callbackUrl,
"custId": "9204473819624814",
});
}
Future<void> generateTxnToken(double amount, String orderId) async {
final callBackUrl =
'https://securegw-stage.paytm.in/theia/paytmCallback?ORDER_ID=$orderId';
final body = getMap(amount, callBackUrl, orderId);
try {
final response = await http.post(
Uri.parse(url),
body: body,
headers: {'Content-type': "application/json"},
);
String txnToken = response.body;
await initiateTransaction(orderId, amount, txnToken, callBackUrl);
} catch (e) {
print(e);
}
}
Future<void> initiateTransaction(String orderId, double amount,
String txnToken, String callBackUrl) async {
String result = '';
try {
var response = AllInOneSdk.startTransaction(
mid,
orderId,
amount.toString(),
txnToken,
callBackUrl,
true,
false,
);
response.then((value) {
// Transaction successfull
print(value);
}).catchError((onError) {
if (onError is PlatformException) {
result = onError.message! + " \n " + onError.details.toString();
print(result);
} else {
result = onError.toString();
print(result);
}
});
} catch (err) {
// Transaction failed
result = err.toString();
print(result);
}
}
}
Calling the function to initiate the transaction when the button is pressed
ElevatedButton(
onPressed: () async => {
if (_formKey.currentState!.validate())
{
await PaytmConfig().generateTxnToken(
double.parse(priceController.text.toString()),
ORDER_ID),
}
},
child: Text('Pay'),
)
And here is my app.js class code in backend
var express = require('express');
var port = process.env.PORT || 3000;
var app = express();
const https = require('https');
const checksum_lib = require('./checksum');
app.use(express.json());
app.use(express.urlencoded());
app.get('/', function(req, res) {
console.log(req);
res.send(JSON.stringify({ Hello: 'World' }));
});
app.post('/generateTxnToken', function(request, res) {
console.log(request.body);
var paytmParams = {};
var MID = request.body.mid;
var orderId = request.body.orderId;
var amount = parseFloat(String(request.body.amount));
var custId = request.body.custId;
var key_secret = request.body.key_secret;
var callbackUrl = request.body.callbackUrl;
var mode = request.body.mode;
var website = request.body.website;
var testing = String(request.body.testing);
console.log(callbackUrl);
console.log(mode);
paytmParams.body = {
/* for custom checkout value is 'Payment' and for intelligent router is 'UNI_PAY' */
"requestType": "Payment",
/* Find your MID in your Paytm Dashboard at https://dashboard.paytm.com/next/apikeys */
"mid": MID,
/* Find your Website Name in your Paytm Dashboard at https://dashboard.paytm.com/next/apikeys */
"websiteName": website == undefined ? "DEFAULT" : website,
/* Enter your unique order id */
"orderId": orderId,
/* on completion of transaction, we will send you the response on this URL */
// "callbackUrl": "https://mrdishant.com",
"callbackUrl": callbackUrl,
/* Order Transaction Amount here */
"txnAmount": {
/* Transaction Amount Value */
"value": amount,
/* Transaction Amount Currency */
"currency": "INR",
},
/* Customer Infomation here */
"userInfo": {
/* unique id that belongs to your customer */
"custId": custId,
},
};
console.log("Mode");
console.log(mode);
if (mode == "1") {
console.log("Mode 1 So Net Banking");
paytmParams.body[
"enablePaymentMode"] = [{
"mode": "NET_BANKING",
}]
} else if (mode == "0") {
console.log("Mode 0 So BALANCE");
paytmParams.body[
"enablePaymentMode"] = [{
"mode": "BALANCE",
}]
} else if (mode == "2") {
console.log("Mode 2 So UPI");
paytmParams.body[
"enablePaymentMode"] = [{
"mode": "UPI",
}]
} else if (mode == "3") {
console.log("Mode 3 So CC");
paytmParams.body[
"enablePaymentMode"] = [{
"mode": "CREDIT_CARD"
}]
}
console.log(JSON.stringify(paytmParams));
/**
* Generate checksum by parameters we have in body
* Find your Merchant Key in your Paytm Dashboard at https://dashboard.paytm.com/next/apikeys
*/
checksum_lib.genchecksumbystring(JSON.stringify(paytmParams.body), key_secret, (err, checksum) => {
if (err) {
return;
}
/* head parameters */
paytmParams.head = {
/* put generated checksum value here */
"signature": checksum
};
/* prepare JSON string for request */
var post_data = JSON.stringify(paytmParams);
var options = {
/* for Staging */
/* for Production */
hostname: testing == "0" ? 'securegw-stage.paytm.in' : 'securegw.paytm.in',
port: 443,
path: '/theia/api/v1/initiateTransaction?mid=' + MID + '&orderId=' + orderId,
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': post_data.length
}
};
// Set up the request
var response = "";
var post_req = https.request(options, (post_res) => {
post_res.on('data', (chunk) => {
response += chunk;
});
post_res.on('end', () => {
console.log(orderId);
console.log(MID);
console.log('Response: ', response);
response = JSON.parse(response);
res.send(response.body.txnToken);
return 0;
});
});
// post the data
post_req.write(post_data);
post_req.end();
});
});
app.listen(port, function() {
console.log(`Example app listening on port !`);
});
I am Developing an Ionic Application that Upload, downloads, and delete attachments
Here I use the File Plugin inside the platform. ready() and build APK. when I run the APK on an android device the code inside the Platform.ready is not getting fired what is the problem???
import { Platform } from '#ionic/angular';
import { File } from '#ionic-native/file/ngx';
constructor(private cFile: File,private platform: Platform){}
DownloadAttachment()
{
var buffer = pFilebytearray.replace(/\"/g, "");
var byteCharacters = atob(buffer);
var byteNumbers = new Array(byteCharacters.length);
for (var i = 0; i < byteCharacters.length; i++) {
byteNumbers[i] = byteCharacters.charCodeAt(i);
}
this.cFile.dataDirectory
var byteArray = new Uint8Array(byteNumbers);
let aType: any = "";
let aMimeTypeJson = {} as any;
aMimeTypeJson = this.GetMimeType(pAttachmentType.toLowerCase())
aType = aMimeTypeJson.MimeType;
var blob1 = new Blob([byteArray], { type: aType });
alert("completed the Name Seperation and Blob Creation")
this.platform.ready().then(() => {
alert("Download Starts...");
let result = this.cFile.createDir(this.cFile.externalDataDirectory, "Documents", true).then(data => {
let dirpath = data.toURL();
alert("Dir created at" + dirpath);
this.cFile.writeFile(dirpath, pAttachmentName, blob1, { replace: true })
.then((Result) => {
this.MessageDialog("Message", "Attachment downloaded " + dirpath, false, true);
}, (error) => {
this.MessageDialog("Message", "Attachment not downloaded", false, true);
});
}).catch(error => {
alert("error" + error);
});
})
}
The Error Solved for me after using Async, await. This makes the code wait till the platform gets ready
async AttachmentDownload(pFilebytearray, pAttachmentType, pAttachmentName): Promise<void> {
alert("entering AttachmentDownload")
var buffer = pFilebytearray.replace(/\"/g, "");
var byteCharacters = atob(buffer);
var byteNumbers = new Array(byteCharacters.length);
for (var i = 0; i < byteCharacters.length; i++) {
byteNumbers[i] = byteCharacters.charCodeAt(i);
}
this.cFile.dataDirectory
var byteArray = new Uint8Array(byteNumbers);
let aType: any = "";
let aMimeTypeJson = {} as any;
aMimeTypeJson = this.GetMimeType(pAttachmentType.toLowerCase())
aType = aMimeTypeJson.MimeType;
var blob1 = new Blob([byteArray], { type: aType });
alert("completed the Name Seperation and Blob Creation")
await this.platform.ready().then(() => {
alert("Download Starts...");
let result = this.cFile.createDir(this.cFile.externalDataDirectory, "Documents", true).then(data => {
let dirpath = data.toURL();
alert("Dir created at" + dirpath);
this.cFile.writeFile(dirpath, pAttachmentName, blob1, { replace: true })
.then((Result) => {
this.MessageDialog("Message", "Attachment downloaded " + dirpath, false, true);
}, (error) => {
this.MessageDialog("Message", "Attachment not downloaded", false, true);
});
}).catch(error => {
alert("error" + error);
});
})
}
Via flutter app, I need to send periodic local notifications with callback--where callback is called for each period/interval before sending notification.
So far I have tried Timer to schedule periodic local notifications, but it does not work in background i.e. when app is closed. I have also tried flutterLocalNotificationsPlugin.periodicallyShow, but this one does not have callback, which is called before sending notification. Lastly, I have tried Firebase, but it needs notifications to be set in firebase console. how to get callback notification with completed and pending reports after changes in database.
Please advice a solution for the above given problem.
This is my code :
import 'package:eclarity/pages/radiologist.dart';
import 'package:eclarity/pages/technici.dart';
import 'package:flutter/material.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:intl/intl.dart';
import 'package:android_alarm_manager/android_alarm_manager.dart';
import 'package:flutter/cupertino.dart';
import 'dart:isolate';
import 'dart:math';
import 'dart:ui';
// import 'dart:ui';
import 'package:eclarity/pages/local_notifications.dart' as notify;
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State {
FlutterLocalNotificationsPlugin fltrNotification;
String _selectedParam;
String task;
String task1;
int task2;
String duration;
String numCompleted;
String numCompleted1;
String numPending;
String numPending1;
String role;
Timer timer;
TextEditingController timeController;
TextEditingController timeController1 = TextEditingController();
int val;
var url = "http://";
var data;
// Future<Radiologist> _future;
//Future<Radiologist> fetchReportStatus() async {
fetchReportStatus() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
int userPk = prefs?.getInt("userPk");
String startDate2 = prefs?.getString("notifyDateTime");
String startDate = prefs?.getString("loginDateTime");
var currentTime =
DateFormat('yyyy-MM-dd hh:mm:ss a').format(DateTime.now());
String role = prefs?.getString("role");
bool userIsTechnician = true;
if (role == "ROLE_RADIOLOGIST") {
userIsTechnician = false;
}
//userIsTechnician
Map data1 = {
'authUserPk': userPk,
"startDate": startDate,
"endDate": currentTime,
"userIsTechnician": userIsTechnician
};
String body1 = json.encode(data1);
final response = await http.post(url,
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8'
},
body: body1);
if (response.statusCode == 200) {
// If the server did return a 200 OK response,
// then parse the JSON.
if (userIsTechnician) {
Technici r = Technici.fromJson(json.decode(response.body));
this.numCompleted = r.numCompleted;
this.numPending = r.numPending;
print("tech===============" + response.body);
} else {
Radiologist r = Radiologist.fromJson(json.decode(response.body));
this.numCompleted = r.numCompleted;
this.numPending = r.numPending;
print("rad===============" + response.body);
}
//return Radiologist.fromJson(json.decode(response.body));
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
throw Exception('Failed to load report count');
}
}
/// The name associated with the UI isolate's [SendPort].
String isolateName = 'isolate';
// /// A port used to communicate from a background isolate to the UI isolate.
final ReceivePort port = ReceivePort();
static SendPort uiSendPort;
Future<void> showNotification(data) async {
print(data);
var rand = Random();
var hash = rand.nextInt(100);
DateTime now = DateTime.now().toUtc().add(Duration(seconds: 1));
await notify.singleNotification(
now,
"Hello $hash",
"This is hello message",
hash,
);
}
// The callback for our alarm
Future<void> callback() async {
print('Alarm fired!');
// // This will be null if we're running in the background.
uiSendPort ??= IsolateNameServer.lookupPortByName(isolateName);
uiSendPort?.send("hi");
}
#override
void initState() {
super.initState();
// _future =
// fetchReportStatus();
// repeatNotification();
//_showNotification();
port.listen((data) async => await showNotification(data));
runAlarm();
WidgetsBinding.instance.addPostFrameCallback((_) async {
timeController1.text = await getPrefForTimer3();
});
getPrefForTimer2().then((s) {
task1 = s.toString();
});
getPrefForDuration().then((s) {
_selectedParam = s;
});
var androidInitilize = new AndroidInitializationSettings('app_icon');
var iOSinitilize = new IOSInitializationSettings();
var initilizationsSettings = new InitializationSettings(
android: androidInitilize, iOS: iOSinitilize);
fltrNotification = new FlutterLocalNotificationsPlugin();
fltrNotification.initialize(initilizationsSettings,
onSelectNotification: notificationSelected);
setDurationAndShowNotification();
// timerNotification(false);
}
void runAlarm() async {
await AndroidAlarmManager.periodic(
Duration(seconds: 1),
0,
callback,
rescheduleOnReboot: true,
exact: true,
wakeup: true,
);
print("OK");
}
Future<String> getPrefForTimer3() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
int taskInt = prefs.getInt("task") ?? 30;
this.task1 = taskInt.toString();
return this.task1;
}
Future<int> getPrefForTimer1() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
int taskInt = prefs.getInt("task") ?? 30;
this.task1 = taskInt.toString();
return taskInt;
}
Future<int> getPrefForTimer2() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
int taskInt = prefs.getInt("task") ?? 30;
task1 = taskInt.toString();
return taskInt;
}
setPrefForTimer1(int val) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
// setState(() {
prefs.setInt("task", val);
// });
}
Future<String> getPrefForDuration() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
setState(() {
duration = prefs.getString("duration").toString() ?? "Minutes";
});
return duration;
}
setPrefForDuration(String val) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
//setState(() {
prefs.setString("duration", val);
// });
}
getPrefForNumPending() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
this.numPending1 = prefs.getInt("numPending").toString() ?? "-1";
}
setPrefForNumPending(String val) async {
if (val == null) {return;}
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setInt("numPending", int.parse(val));
}
getPrefForNumCompleted() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
this.numCompleted1 = prefs.getInt("numCompleted").toString() ?? "0";
}
setPrefForNumCompleted(String val) async {
if (val == null) {return;}
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setInt("numCompleted", int.parse(val));
}
Future<bool> getUserIsTechnician() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
String role = prefs?.getString("role");
bool userIsTechnician = true;
if (role == "ROLE_RADIOLOGIST") {
userIsTechnician = false;
}
return userIsTechnician;
}
timerNotificationRestart() {
if (this.task1 != null) {
setPrefForTimer1(int.parse(this.task1));
}
//timerNotification(true);
}
timerNotification1(bool stop) {
if (stop && this.timer != null) {
this.timer.cancel();
}
//getPrefForTimer1();
if (this.task1 == null) {
this.task2 = 30;
} else {
this.task2 = int.parse(task1);
}
Duration duration;
if (_selectedParam == "Hour") {
duration = Duration(hours: this.task2);
} else {
duration = Duration(minutes: this.task2);
}
bool isStopped = false;
this.timer = Timer.periodic(duration, (timer1) async {
// Make a local notification
if (isStopped) {
timer1.cancel();
}
var androidPlatformChannelSpecifics = AndroidNotificationDetails(
'your channel id', 'your channel name', 'your channel description',
importance: Importance.max,
priority: Priority.high,
ticker: 'ticker');
var iOSPlatformChannelSpecifics = IOSNotificationDetails();
var platformChannelSpecifics = NotificationDetails(
android: androidPlatformChannelSpecifics,
iOS: iOSPlatformChannelSpecifics);
await fetchReportStatus();
var value = await getUserIsTechnician();
if (!value) {
getPrefForNumPending();
bool sendNotification = false;
if (this.numPending1 != null && this.numPending != null
&& this.numPending != this.numPending1) {
sendNotification = true;
} else if (this.numPending1 == null) {
sendNotification = true;
}
setPrefForNumPending(this.numPending);
if (sendNotification) {
await fltrNotification.show(
0, "",
// "# Report Completed :" +
// this.numCompleted +
// "\n",
"# Report Pending : " +
this.numPending, platformChannelSpecifics,
payload: 'item x');
}
} else {
getPrefForNumCompleted();
bool sendNotification = false;
if (this.numCompleted1 != null && this.numCompleted != null
&& this.numCompleted != this.numCompleted1) {
sendNotification = true;
} else if (this.numCompleted1 == null) {
sendNotification = true;
}
setPrefForNumCompleted(this.numCompleted);
if (sendNotification) {
await fltrNotification.show(
0, "",
// "# Report Completed :" +
// this.numCompleted +
// "\n",
"# Report Completed : " +
this.numCompleted, platformChannelSpecifics,
payload: 'item x');
}
}
});
}
setDurationAndShowNotification() async {
await fltrNotification.cancelAll();
//await fltrNotification.cancel(1);
showNotification1();
}
showNotification1() async {
// var scheduledNotificationDateTime =
// new DateTime.now().add(new Duration(seconds: 5));
// Show a notification every minute with the first appearance happening a minute after invoking the method
var androidPlatformChannelSpecifics =
new AndroidNotificationDetails('repeating channel id 1',
'repeating channel name 1', 'repeating description 1');
var iOSPlatformChannelSpecifics =
new IOSNotificationDetails();
var platformChannelSpecifics = new NotificationDetails(
android: androidPlatformChannelSpecifics, iOS: iOSPlatformChannelSpecifics);
await fetchReportStatus();
var value = await getUserIsTechnician();
var interval;
if (_selectedParam == "Hour") {
interval = RepeatInterval.hourly;
} else {
interval = RepeatInterval.everyMinute;
}
if (!value) {
await getPrefForNumPending();
bool sendNotification = false;
if (this.numPending1 != null && this.numPending != null
&& this.numPending != this.numPending1) {
sendNotification = true;
} else if (this.numPending1 == null) {
sendNotification = true;
}
print("=========== About to send Rad Notification");
print("num pending ===== " + this.numPending);
print("num pending1 ===== " + this.numPending1);
print("sendNotification ===== " + sendNotification.toString());
setPrefForNumPending(this.numPending);
if (sendNotification) {
await fltrNotification.periodicallyShow(
0, "eClarity Reprot Status",
// "# Report Completed :" +
// this.numCompleted +
// "\n",
"# Report Pending : " + this.numPending,
interval, platformChannelSpecifics,
);
}
} else {
getPrefForNumCompleted();
bool sendNotification = false;
if (this.numCompleted1 != null && this.numCompleted != null
&& this.numCompleted != this.numCompleted1) {
sendNotification = true;
} else if (this.numCompleted1 == null) {
sendNotification = true;
}
print("=========== About to send Rad Notification");
print("num completed ===== " + this.numCompleted.toString());
print("num completed1 ===== " + this.numCompleted1.toString());
print("sendNotification ===== " + sendNotification.toString());
setPrefForNumCompleted(this.numCompleted);
if (sendNotification) {
await fltrNotification.periodicallyShow(
0, "eClarity Reprot Status",
// "# Report Completed :" +
// this.numCompleted +
// "\n",
"# Report Completed : " +
this.numCompleted, interval, platformChannelSpecifics,
);
}
}
}```
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