Android WebView - First click / touch is ignored after activity started - javascript

We are building an hybrid Razor HTML5/Xamarin Android application. The rendering of the views in an Android.Webkit.WebView itself works pretty well and we got many forms designed properly, but we got a problem with the performance of the javascript execution in the single views.
I'll try to describe what's happening. We call the webview, generate the razor html template with the view specific model. After that we call the view with "LoadDataWithBaseUrl" which works. The view gets loaded by the webview control. Now I'll try to use buttons which are implemented in the view. The onclick handlers of the buttons are implemented in the views header section script tag in javascript. Example implementation:
...
function ClearInput() {
var input = document.getElementById('page-text-input');
input.value = "";
}
...
<input type="button" class="numeric-input-function" onclick="ClearInput();"/>
The problem that occurs is that we aren't able to use the button directly after the view has been rendered by the webview control. It seems like the javascript isn't directly available. There is no click event thrown for the first button click in the process. The second click and following ones work.
As a result of this misbehavior we have restricted usability.
To clarify: The user sees the view but isn't able to operate properly because the click event for the first click isn't recognized.
Does anybody else have the same kind of issue or a solution for that problem?
Edit:
We tried to disable the forms with a loading screen while it isn't fully loaded but that wasn't the solution were looking for. The problem still remains.
It seems like the webview isn't focused on start and the first click is needed to setup the focus.
Edit 2:
I made some more tests and recognized that the input channel is destroyed right after its constructed everytime I call the webview. The corresponding debug output looks as follows:
08-16 16:50:01.583 D/InputTransport(31313): Input channel constructed: fd=144
08-16 16:50:01.583 D/InputTransport(31313): Input channel destroyed: fd=132
08-16 16:50:03.813 D/Mono (31313): GC_BRIDGE waiting for bridge processing to finish
08-16 16:50:03.856 I/art (31313): Starting a blocking GC Explicit
08-16 16:50:03.894 I/art (31313): Explicit concurrent mark sweep GC freed 18081(2MB) AllocSpace objects, 87(4MB) LOS objects, 14% free, 91MB/107MB, paused 559us total 38.349ms
08-16 16:50:03.927 D/Mono (31313): GC_TAR_BRIDGE bridges 6498 objects 8686 opaque 242 colors 6492 colors-bridged 6479 colors-visible 6479 xref 101 cache-hit 0 cache-semihit 0 cache-miss 13 setup 0.72ms tarjan 7.96ms scc-setup 2.09ms gather-xref 0.36ms xref-setup 0.07ms cleanup 0.76ms
08-16 16:50:03.927 D/Mono (31313): GC_BRIDGE: Complete, was running for 114.00ms
08-16 16:50:03.927 D/Mono (31313): GC_MAJOR: (LOS overflow) time 102.71ms, stw 104.75ms los size: 27552K in use: 23334K
08-16 16:50:03.927 D/Mono (31313): GC_MAJOR_SWEEP: major size: 10240K in use: 8427K
08-16 16:50:07.126 D/ViewRootImpl#22ae52[CoordinatorActivity](31313): Relayout returned: oldFrame=[0,0][2048,1536] newFrame=[0,0][2048,1536] result=0x1 surface={isValid=true -913786880} surfaceGenerationChanged=false
08-16 16:50:08.112 D/ViewRootImpl#22ae52[CoordinatorActivity](31313): ViewPostImeInputStage processPointer 0
08-16 16:50:08.215 D/ViewRootImpl#22ae52[CoordinatorActivity](31313): ViewPostImeInputStage processPointer 1
08-16 16:50:08.732 D/ViewRootImpl#22ae52[CoordinatorActivity](31313): ViewPostImeInputStage processPointer 0
08-16 16:50:08.800 D/ViewRootImpl#22ae52[CoordinatorActivity](31313): ViewPostImeInputStage processPointer 1
08-16 16:50:08.818 D/InputMethodManager(31313): HSI from window - flag : 0 Pid : 31313
08-16 16:50:08.824 D/InputMethodManager(31313): HSI from window - flag : 0 Pid : 31313
08-16 16:50:08.828 D/InputMethodManager(31313): HSI from window - flag : 0 Pid : 31313
08-16 16:50:08.831 D/InputMethodManager(31313): HSI from window - flag : 0 Pid : 31313
Edit 3:
I tried different flags, settings for focusable and focusableInTouchMode and ontouch / onfocuschanged event handlers but nothing seems to work. Nobody got an idea about how to fix that problem?

I've found the solution. The reason was that "system_ui_flag_hide_navigation" was set. I don't know why that side effect occured, but after I removed the line, it worked. Just in case somebody else also runs into that problem.

Related

Delete USB history (regedit) with script

I have a javascript and Powershell script allowing to detect a usb plug, and which shows me a pop up. Indeed, my script only detects new usb keys that have not yet been plugged into the system. That's why I would like to delete the usb key history from my computer, like USB OBLIVION does, in order to have as a new connection to each usb plug.
I don't see what I need to add to my script... I have already tried deleting the content of:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USBSTOR
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\DeviceClasses\
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USB
Thanks
You could try these, but don't forget to wipe the from them other 3 paths as well
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\SWD\WPDBUSENUM
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Portable Devices\Devices\
You could also consider using WMI Event subscriptions, this works whatever the usb key is already known or not, but do not clear the registry :
to detect usb plug :
Register-CIMIndicationEvent –Query `
"Select * From __InstanceCreationEvent Within 1 Where TargetInstance IsA 'Win32_LogicalDisk'" `
–SourceIdentifier "WMIInsert" –Action { Write-Host `
"$($Event.SourceEventArgs.NewEvent.TargetInstance.Name) plugged!`n" }
to detect usb ejection :
Register-CIMIndicationEvent –Query `
"Select * From __InstanceDeletionEvent Within 1 Where TargetInstance IsA 'Win32_LogicalDisk'" `
–SourceIdentifier "WMIEject" –Action { Write-Host `
"$($Event.SourceEventArgs.NewEvent.TargetInstance.Name) ejected!`n" }
Within 1 means to detect every one second. Depending on your needs, you can configure Within 30 for example to look it for every 30 seconds (every plug or ejection in the meantime are captured as well).
the -Action parameter let you do whatever you want since this is a scriptblock (In the example I provided the event is only displayed to the console).
And do not forget that StackOverflow is not a free coding service, so next time, please share the piece of code where you have got a problem or a bug.

Why does jquery return different values than the values submitted?

Update:
Please see the answer noted below as, ultimately, the problem had nothing to do with jsquery.
=============
Issue:
I submit an object to jquery to convert into a serialized string that will become part of a "POST" request to a server, and the data returned from the serialization request is different than the data sent on many occasions.
An example:
The JavaScript code that implements the server POST request:
function send_data(gpg_data) {
var query_string;
query_string = '?' + $.param(gpg_data, traditional = true);
console.log('gpg_data =', gpg_data)
console.log('query_string =', query_string);
$.post(server_address + query_string);
return;
}
This is the structure sent to the jquery param() function.
(copied from the browser console in developer mode.)
gpg_data =
{controller_status: 'Connected', motion_state: 'Stopped', angle_dir: 'Stopped', time_stamp: 21442, x_axis: 0, …}
angle_dir: "Stopped"
controller_status: "Connected"
force: 0
head_enable: 0
head_x_axis: 0
head_y_axis: 0
motion_state: "Stopped"
time_stamp: 21490
trigger_1: 0
trigger_2: 0
x_axis: 0
y_axis: "0.00"
. . . and the returned "query string" was:
query_string = ?controller_status=Connected&motion_state=Stopped&angle_dir=Stopped&time_stamp=21282&x_axis=0&y_axis=0.00&head_x_axis=0&head_y_axis=0&force=0&trigger_1=1&trigger_2=1&head_enable=0
The data received by the server is:
ImmutableMultiDict([('controller_status', 'Connected'), ('motion_state', 'Stopped'), ('angle_dir', 'Stopped'), ('time_stamp', '21282'), ('x_axis', '0'), ('y_axis', '0.00'), ('head_x_axis', '0'), ('head_y_axis', '0'), ('force', '0'), ('trigger_1', '1'), ('trigger_2', '1'), ('head_enable', '0')])
For example, note that "trigger_1" returns 1 when the data sent to it is a zero.
I have tried setting the query to "traditional = true" to revert to an earlier style of query handling as some articles suggested - which did not work.  I tried this with jquery 3.2 and 3.6.
I am not sure exactly how jquery manages to munge the data so I have no idea where to look.
I have looked at my script and at the unpacked jquery code, and I can make no sense out of why or how it does what it does.
Any help understanding this would be appreciated.
P.S.
web searches on "troubleshooting jquery" returned very complex replies that had more to do with editing e-commerce web pages with fancy buttons and logins than with simply serializing data.
P.P.S.
I am tempted to just chuck the jquery and write my own serialization routine. (grrrr!)
===================
Update:
As requested, a link to the browser-side context.
To run: unpack the zip file in a folder somewhere and attach an analog joystick/gamepad to any USB port, then launch index.html in a local browser.  Note that a purely digital gamepad - with buttons only or with a joystick that acts like four buttons - won't work.
You will want to try moving joystick axes 1 and 2, (programmatically axes 0 and 1) and use the first (0th) trigger button.
You will get a zillion CORS errors and it will complain bitterly that it cannot reach the server, but the server side context requires a GoPiGo-3 robot running GoPiGo O/S 3.0.1, so I did not include it.
Note: This does not work in Firefox as Firefox absolutely requires a "secure context" to use the Gamepad API.  It does work in the current version of Chrome, (Version 97.0.4692.99 (Official Build) (64-bit)), but throws warnings about requiring a secure context.
Please also note that I have made every attempt I know how to try to troubleshoot the offending JavaScript, but trying to debug code that depends on real-time event handling in a browser is something I have not figured out how to do - despite continuous searching and efforts.  Any advice on how to do this would be appreciated!
======================
Update:
Researching debugging JavaScript in Chrome disclosed an interesting tidbit:
Including the line // #ts-check as the first line in the JavaScript code turns on additional "linting" (?) or other checks that, (mostly) were a question of adding "var" to the beginning of variable declarations.
However. . . .
There was one comment it made:
gopigo3_joystick.x_axis = Number.parseFloat((jsdata.axes[0]).toFixed(2));
gopigo3_joystick.y_axis = Number.parseFloat(jsdata.axes[1]).toFixed(2);
I could not assign gopigo3_joystick.y_axis to a string object, (or something like that), and I was scratching my head - that was one of the pesky problems I was trying to solve!
If you look closely at that second line, you will notice I forgot a pair of parenthesis, and that second line should look like this:
gopigo3_joystick.y_axis = Number.parseFloat((jsdata.axes[1]).toFixed(2));
Problem solved - at least with respect to that problem.
I figured it out and it had nothing to do with jquery.
Apparently two things are true:
The state of the gpg_data object's structure is "computed", (snapshot taken), the first time the JavaScript engine sees the structure and that is the state that is saved, (even though the value may change later on). In other words, that value is likely totally bogus.
Note: This may only be true for Chrome. Previous experiments with Firefox showed that these structures were updated each time they were encountered and the values seen in the console were valid. Since Firefox now absolutely requires a secure context to use the gamepad API, I could not use Firefox for debugging.
I was trying to be "too clever". Given the following code snippet:
function is_something_happening(old_time, gopigo3_joystick) {
if (gopigo3_joystick.trigger_1 == 1 || gopigo3_joystick.head_enable == 1) {
if (old_time != Number.parseFloat((gopigo3_joystick.time_stamp).toFixed(0))) {
send_data(gopigo3_joystick)
old_time = gopigo3_joystick.time_stamp
}
}
return;
}
The idea behind this particular construction was to determine if "something interesting" is happening, where "something interesting" is defined as:
A keypress, (handled separately)
A joystick movement if either the primary trigger or the pinky trigger is pressed.
Movement without any trigger pressed is ignored so that if the user accidentally bumps against the joystick, the robot doesn't go running around.
Therefore the joystick data only gets updated if the trigger is pressed. In other words, trigger "release" events - the trigger is now = 0 - are not recorded.
The combination of these two events - Chrome taking a "snapshot" of object variables once and once only, (or not keeping them current) - and the trigger value persisting, lead me to believe that jquery was the problem since the values appeared to be different on each side of the jquery call.

How can I execute Javascript methods with AutoHotkey?

I am writing an AutoHotkey script to enter data into an Oracle PeopleSoft application. Rather than trying to locate specific elements on the page, I want to try execute JavaScript commands directly instead.
So instead of using a hardcoded MouseClick, left, 205, 281 to click the "Add New Values" button, I want to directly run submitAction_win0(document.win0,'#ICSwitchMode')
I've tried entering commands directly into the address bar, but this doesn't seem to have any effect.
#k::
jsCommand = javascript:submitAction_win0(document.win0,'#ICSwitchMode');
Send, !d ; places cursor in URL field
Send, %jsCommand%{Enter} ; submit JS command (doesn't work)
Return
According to this AHK thread, it should be possible to accomplish this using a ScriptControl object, but I'm a bit unsure how to use them.
How can I execute JavaScript commands using AutoHotkey?
Per an example I used in a previous question's answer for controlling IE, walking the DOM, etc:
F3::
wb := ComObjCreate("InternetExplorer.Application") ; Create a IE instance
wb.Visible := True
wb.Navigate("http://google.com")
Sleep, 5000
SendInput, This is test.{Enter}
Sleep, 5000
wb.document.getElementById("lst-ib").value := "This is another test."
wb.document.getElementById("_fZl").click()
return

What should be the metrics returned from protractor-perf getStats method?

I've got protractor-perf working in my tests, and when I log the full set of metrics out, it seems to be missing some of the ones I'd expect from the Chrome timeline (and what browser perf says it collects here: https://github.com/axemclion/browser-perf/wiki/Metrics)
Specifically, I'm looking for FunctionCall, and Layout - but they seem to be missing.
Also, there are metrics for Styles and Javascripts but they're returning 0 values (I know there's a tonne of both on the page - am I misunderstanding these values?).
I'm running this on the latest protractor-perf with Chrome 48 and chromedriver 2.21, and all looks to be working as far as I can tell.
These are the metrics I get results for (it's a pretty long list):
Styles
Javascript
fetchStart
domComplete
redirectEnd
LoadEventStart
navigationStart
requestStart
responseEnd
secureConnectionStart
domLoading
domInteractive
domainLookupEnd
domContentLoadedEventStart
loadEventEnd
connectEnd
responseStart
unloadEventStart
domContentLoadedEventEnd
connectStart
firstPaint
unloadEventEnd
domainLookupStart
loadTime
domReadyTime
readyStart
redirectTime
appcacheTime
unloadEventTime
domainLookupTime
connectTime
requestTime
initDomTreeTime
loadEventTime
NetworkJs
NetworkJs_avg
NetworkJs_max
NetworkJs_count
NetworkOther
NetworkOther_avg
NetworkOther_max
NetworkOther_count
NetworkImage
NetworkImage_avg
NetworkImage_max
NetworkImage_count
NetworkIframe
NetworkIframe_avg
NetworkIframe_max
NetworkIframe_count
NetworkCSS
NetworkCSS_avg
NetworkCSS_max
NetworkCSS_count

How to increase number of Call Stack entries in Google Chrome Developer Tools (or Firefox)?

How to increase number of Call Stack entries in Google Chrome Developer Tools (or Firefox Firebug)? I am getting a Javascript error in a third party control's Javascript. All the calls in the Call Stack window do not belong to my own code. I want to know which line in my code triggered the sequence of events. The Call Stack is not large enough to display something from my own code.
Chrome solution
https://v8.dev/docs/stack-trace-api
can set via commandline on startup --js-flags="--stack-trace-limit <value>"
or at runtime at loading a page: Error.stackTraceLimit=undefined //unlimited stack trace
In Chrome (also in node), you can type this in the js console:
Error.stackTraceLimit = Infinity;
Alternatively see this page for Chrome command line flags: https://v8.dev/docs/stack-trace-api (need to restart Chrome):
$ google-chrome --js-flags="--stack-trace-limit 10000"
I don't think there's a limit on call stack size*). Usually a stack trace that seems to come out of nowhere results from either
an event listener
a timeout (window.setTimeout)
an interval (window.setInterval)
some script loading after page has loaded (possibly iframe)
*) Of course, technically there certainly is some limit, but I gues it's practically irrelevant. Probably longint or something.
edit: From Firebug source code:
if (trace.frames.length > 100) // TODO in the loop above
{
var originalLength = trace.frames.length;
trace.frames.splice(50, originalLength - 100);
var excuse = "(eliding "+(originalLength - 100)+" frames)";
trace.frames[50] = new StackFrame.StackFrame({href: excuse}, 0, excuse,
[], null, null, context);
}
So Firebug will always show the first 50 and the last 50 items ("frames") of the call stack.

Categories

Resources