Page 1 of 1

ProfoundUI Mobile Client

Posted: Tue Apr 19, 2016 4:42 am
by robhathome2
Hi

We encountered a problem using the mobile client with Android 5.0.2 in our DC. When communication is momentarily lost with one of the access points, the mobile app takes approx. 18 minutes to realise that it has lost communication. On a tablet with 4.4.4 the issue is not seen and we receive notification within seconds that communication has been lost. I suppose it could be the particular devices but given the issues with Lollipop I'd probably lean towards that being the issue.

In an attempt to circumvent the issue I've implemented a web worker (all very new to me!) process for true multi-threading that performs an ajax call into the system. I'm able to detect if it has fed nothing back within 3 seconds and provide direction to the screen that there is a comms issue, directing the user to try again. However, it doesn't seem to work within the mobile app but it does work within Chrome on the device.

I've been unable to find technical specs for the mobile app but should web workers work? And do you have any thoughts on the timeout of 18 minutes with Android 5.0.2?

Thanks for reading

Rob.

Re: ProfoundUI Mobile Client

Posted: Tue Apr 19, 2016 7:41 pm
by Scott Klement
I have no idea why it'd take 18 minutes. Can you tell me more about the situation? Does it happen when you submit a screen that it sits and waits for 18 minutes to try to submit the screen before finally timing out and failing? Or does this happen when the screen is waiting for the user to input something, and so the timeout doesn't occur until later?

How are timeouts configured for your setup? Are you using client-side timeout? What values are set for the timeout interval?

I've never tried using web workers on Android. From some quick Google searches, they do seem to be available. You could try using the JavaScript setInterval() API instead of a web worker and see if that works better?

Re: ProfoundUI Mobile Client

Posted: Wed Apr 20, 2016 10:26 am
by robhathome2
Hi Scott

This has been a rapid learning curve so if I miss anything out then please ask away.

Primarily, it happens on an ajax call. Just to clarify, it works fine on a 4.4.4 tablet but not on a different tablet that is 5.0.2. It may actually be the tablet but it's tough to find out as there isn't a kitkat I can root it with. Even using setTimeout wouldn't work (for reasons I now understand - see the links). It just hangs whilst attempting the ajax for approx. 18 minutes whilst trying to resolve itself.

Even using a timeout on the ajax doesn't work as that timeout only commences once the ajax call has been triggered. This is the tablet struggling to even get that far. From the multitudes of pages I've read on wifi-related lollipop issues it could well be something associated with the DNS stack etc.

So to get round this I need something to run multi-threaded because if it doesn't come back and leave a marker for me within a defined timeframe then I can pretty much assume it is having this problem. The web worker seems to work on Chrome on the tablet but not in the Profound App. I would much rather stay within the profound app if at all possible.

If I over simplify then please accept my apologies but I feel it's better to have more than not enough.

Also, I have discovered (to my dismay) that javascript execution is single threaded, (irrespective of sync or async) even with event handlers. I found a great site (for those interested) http://javascript.info/tutorial/events-and-timing-depth that details how events, setTimeout etc. are actually processed and why you can't just loop around in your javascript (as nothing else will run until your javascript ends). This led me to http://www.html5rocks.com/en/tutorials/workers/basics/ and true multi-threading.

So here's how I implemented it when I wanted to check I could reach our server:

1. In the on-click I have

Code: Select all

function f_btn_GoQty() {
  if (doLocationStuff()) {
    if (doSKUStuff()) {
        submitUpdate('Btn_GoQty.click()');
        makeReady();
    }
  }
}  

function makeReady() {
  $('#btn_GoQty').prop('disabled', false);
  $('#pleaseWaitLabel').fadeTo('fast', 0);
}


if (validQty(get('txtQty'), get("txtOrigQty"))) {
  preCheckAjax(f_btn_GoQty);
}  
else {
  makeReady();
}
2. preCheckAjax which initiates the worker thread, creates the listener for comms from the worker, and starts the worker ("Wakey" is just my poor attempt at humour):

Code: Select all

function preCheckAjax(callback) {
	pui.set("pingResult","");
	var worker = new Worker('/profoundui/userdata/js/pingCheckWorker.js');
	
	worker.addEventListener('message', function(e) {
		pui.set("pingResult",e.data);
	});
	
	worker.postMessage('Wakey');
	
	setTimeout(function(){preCheckAjax1(1, callback)}, 200);
	
}
3. We can't stay in any js function or else the event listener we created never gets to run. So we use setTimeout to resubmit the same routine until we iterate 11 times:

Code: Select all

function preCheckAjax1(iteration, callback){

	pingResult = get("pingResult");
	
	if (pingResult == "1") {
		callback();
	} else {
		if (iteration < 12 && pingResult != "2") {
			iteration++;
			setTimeout(function(){preCheckAjax1(iteration, callback)}, 250);
		}
		else {
			commsError();
		}
	}
}
3. Here's the web worker source, pingCheckWorker.js (a web worker does not have access to many things so can't easily use pui's ajax):

Code: Select all

self.addEventListener('message', function(e) {

  var data = e.data;
  var result = false;
  
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (xhttp.readyState == 4 && xhttp.status == 200) {
     result = xhttp.responseText;
    }
  };
  xhttp.open("POST", "/profoundui/universal/pickValidation", false);
  xhttp.send("REQTYP=HELLO");
  
  if (result == 'HELLO') {
	self.postMessage('1');
  }
  else {
	self.postMessage('2');
  }
}, false);

Re: ProfoundUI Mobile Client

Posted: Thu Apr 21, 2016 2:42 am
by Scott Klement
Rob,

I have no clue why you'd ever have an 18 minute delay -- and it's even worse if it is actually blocking the JavaScript event loop! Wow! I do not have any ideas what would cause that, and have not run across it myself.

The Profound UI Mobile app is just a JavaScript program that is embedded inside an app using Apache Cordova (aka "PhoneGap"). So there's nothing too fancy about it. We didn't write a special browser or anything like that, it uses the one built in to your device. You can do a Google search on Web Workers in Cordova -- and I think you'll find that they are supported and work fine. I have never used Web Workers in the app, but I did do some searches myself, and they seem to be fully supported.

But, I think I see why your code isn't working!

You are using relative URLs such as "/profoundui/userdata/js/pingCheckWorker.js" and "/profoundui/universal/pickValidation". These will not work in in the Mobile App!! Relative URLs use the same server/port as the main HTML page that they are running under, and in this case, the HTML page is NOT coming from your server, rather it is an HTML page that has been embedded inside the Profound UI app that is installed on your device. Therefore, when you use /profoundui/userdata/etc/etc, it is trying to find that file ALSO embedded inside the app that's installed on your device, and of course, it is not there.

A quick soluion might be to try using fully-qualified URLs like http://your-server:your-port/profoundui/userdata/etc/etc -- adding the http:// and server/port to the start of the URL will make it clear that it needs to download the JS file from your server rather than finding it embedded in the app. Likewise, when you do your XHR call from the Web Worker, you'll need to do the same thing.

I would try adding the http:// and server/port to both URLs you are using (the one in new Worker() and the one in the XHR call) and see if that solves the problem for you.

If it does solve it, Profound UI does provide an API for this so you don't have to hard-code the server name. it is pui.normalizeURL(), and is documented here:
http://www.profoundlogic.com/docs/pages ... Id=7602181

With that URL, you should be able to change your code to work as follows:

Code: Select all

var worker = new Worker(pui.normalizeURL('/profoundui/userdata/js/pingCheckWorker.js'));
Unfortunately, I don't think you'll be able to call this pui.normalizeURL() routine for your XHR call inside the web worker. Workers are limited in what resources they can access (as you mentioned) so you won't be able to call the API. One workaround might be to call the API from the preCheckAjax routine like this:

Code: Select all

var myURL = pui.normalizeURL("/profoundui/universal/pickValidation");
 . . .
 worker.postMessage("myURL = " + myURL);
The idea is to get the value in the preCheckAjax() routine where it's possible to call PUI APIs, and then use postMessage to send the value to the worker. And of course, you'd then have to modify the worker to receive the value and use it in the XHR call. This might be a little tricky, but possibly better than hard-coding the server name?

Re: ProfoundUI Mobile Client

Posted: Fri Apr 29, 2016 10:44 am
by robhathome2
Hi Scott

Thanks - Normalization did the trick. I normalize the path to the worker and pass pui.serverURL through to the worker. I get the whole normalization now after reading your reply on another thread to my former colleague Mark. I've also included code to make the worker self close.

And yes, it is very strange. In fact, from the outer js worker.terminate just hangs in the same way despite it supposedly just terminating the WW. We are using ASUS ZenPad 7.0 tablets and the issue only occurs when you momentarily drop the wireless signal. We are able to replicate simply by disconnecting before attempting a return trip to the i.

One good thing to come out of all of this is I've now got a basic handle on web workers. I'm sure there will be uses in the future.

Thanks again for your help.

Rob.

(if anyone wants the code then reply and I'll put it up here).