Android Question [Solved] How to get a javascript variable from a webview

Mark Read

Well-Known Member
Licensed User
Longtime User
I am using a webview (with webviewextras) and can control the website as needed with javascript. To get the final information for my app I need to build a URL string which contains the javascript variable "uuid" stored in the website.

How can I get the value of this variable? It will be a string and is then used to build the url:

webpageurl/results.cgi?uuid=a99a27d04a6fe5d4be756e14beafd569

I then need to download the resulting text file accordingly.
Many thanks.
 

DonManfred

Expert
Licensed User
Longtime User
Use webviewextras, add a javascriptinterface, inject some javascript which gets the value you need to get and call a sub in your app using the javascriptinterface.
 
Upvote 0

Mark Read

Well-Known Member
Licensed User
Longtime User
Thank you for your reply Manfred. Maybe I was not clear in my question.
Use webviewextras
- Done that,

add a javascriptinterface
- Done that,

inject some javascript which gets the value you need to get
- Here is the problem!,

call a sub in your app using the javascriptinterface
- can't do this without the value.

This was my attempt:
B4X:
WebViewExtras1.executeJavascript(WebView1, "B4A.CallSub('JavascriptCallback', true, document.getElementById('uuid'))")

but nothing happens, no error, nothing. I am not good with javascript so I probably got it all wrong.
 
Upvote 0

DonManfred

Expert
Licensed User
Longtime User
which contains the javascript variable "uuid" stored in the website
This, @mark35at , does not match your trying
B4X:
WebViewExtras1.executeJavascript(WebView1, "B4A.CallSub('JavascriptCallback', true, document.getElementById('uuid'))")

As far as i can see (please note that i´m not a javascript profi) you are getting a reference to an OBJECT inside your html code which must have the ID set to uuid.

B4X:
<div id="uuid">
                <div class="row">
                    <div class="col-md-7 col-sm-6 col-xs-10">File</div>
                    <div class="col-md-2 col-sm-2 col-xs-2 text-right">Size</div>
                    <div class="col-md-3 col-sm-4 hidden-xs text-right">Last Modified</div>
                </div>
            </div>

With your call you would getting the object of your html holding this outer DIV (including it´s childs).
Ok, now we know; wrong way... Let´s try something other...

the javascript variable "uuid"

That´w the point. You said "javascript variable". So i guess you have seen it - while inspecting the html - as $uuid inside the javascriptcode....

Try to use
B4X:
WebViewExtras1.executeJavascript(WebView1, "B4A.CallSub('JavascriptCallback', true, $uuid)")

This will use the VARIABLE $uuid instead of getting a reference to an specific object.

Please note that you should use this executeJavascript call after the page has finished loading!
B4X:
Sub www_PageFinished (Url As String)

Hope it helps ;)
 
Last edited:
Upvote 0

Mark Read

Well-Known Member
Licensed User
Longtime User
Hello Manfred,

yes you are correct. The variable is a javascript variable. In the html code, 3 javascript files are loaded and I can see the variable here. This is what I require.

I will try your code shortly.
 
Upvote 0

Mark Read

Well-Known Member
Licensed User
Longtime User
I get this error:

Uncaught ReferenceError: $uuid is not defined in null (Line: 1)

which tells me nothing????
 
Upvote 0

Mark Read

Well-Known Member
Licensed User
Longtime User
Here is an extract from the javascript file

B4X:
link=document.getElementById(routing_type + "_html");
link.href="results.cgi?uuid=" + uuid + ";type=" + routing_type + ";format=html";

link=document.getElementById(routing_type + "_gpx_track");
link.href="results.cgi?uuid=" + uuid + ";type=" + routing_type + ";format=gpx-track";

link=document.getElementById(routing_type + "_gpx_route");
link.href="results.cgi?uuid=" + uuid + ";type=" + routing_type + ";format=gpx-route";

link=document.getElementById(routing_type + "_text_all");
link.href="results.cgi?uuid=" + uuid + ";type=" + routing_type + ";format=text-all";

link=document.getElementById(routing_type + "_text");
link.href="results.cgi?uuid=" + uuid + ";type=" + routing_type + ";format=text";

links=document.getElementById(routing_type + "_links").style.display = "";

"routing_type" I know already, I can see it in the webview but not the "uuid". This changes on every run.
 
Upvote 0

Mark Read

Well-Known Member
Licensed User
Longtime User
Here is the project to date. Its very rough as I have only just begun.
Btn_Sendurl has no function as yet.

Start the app, wait for the webpage to completely load (see log), press run. In the results page there are 5 popups all called with the same function and using the variable "uuid". I want to get the text file for now.

Thanks
 

Attachments

  • waterway.zip
    10.4 KB · Views: 330
Upvote 0

DonManfred

Expert
Licensed User
Longtime User
Thanks.
Ok, i tried to use the url in my browser

in b4a you are "using" the "button" to get the shortest track
in webview you got some results then (all of them uses your named uuid as i can see here now)
Looking into the used javascripts inside this webpage i found the place where the uuid is used to build thos urls you can use

I found this
//
// Success in running router.
//

function runRouterSuccess(response)
{
var lines=response.responseText.split('\n');

var uuid=lines[0];
var success=lines[1];

var link;

// Update the status message

if(success=="ERROR")
{
displayStatus("result","error");
hideshow_show('help_route');

link=document.getElementById("router_log_error");
link.href="results.cgi?uuid=" + uuid + ";type=router;format=log";

return;
}
else
{
displayStatus("result","complete");
hideshow_hide('help_route');

link=document.getElementById("router_log_complete");
link.href="results.cgi?uuid=" + uuid + ";type=router;format=log";
}

// Update the routing result message

link=document.getElementById(routing_type + "_html");
link.href="results.cgi?uuid=" + uuid + ";type=" + routing_type + ";format=html";

link=document.getElementById(routing_type + "_gpx_track");
link.href="results.cgi?uuid=" + uuid + ";type=" + routing_type + ";format=gpx-track";

link=document.getElementById(routing_type + "_gpx_route");
link.href="results.cgi?uuid=" + uuid + ";type=" + routing_type + ";format=gpx-route";

link=document.getElementById(routing_type + "_text_all");
link.href="results.cgi?uuid=" + uuid + ";type=" + routing_type + ";format=text-all";

link=document.getElementById(routing_type + "_text");
link.href="results.cgi?uuid=" + uuid + ";type=" + routing_type + ";format=text";

links=document.getElementById(routing_type + "_links").style.display = "";

// Add a GPX layer

var url="results.cgi?uuid=" + uuid + ";type=" + routing_type + ";format=gpx-track";

layerGPX[routing_type] = new OpenLayers.Layer.Vector("GPX (" + routing_type + ")",
{
protocol: new OpenLayers.Protocol.HTTP({url: url, format: new OpenLayers.Format.GPX()}),
strategies: [new OpenLayers.Strategy.Fixed()],
style: gpx_style[routing_type],
projection: map.displayProjection
});

map.addLayer(layerGPX[routing_type]);

hideshow_show(routing_type);

displayResult(routing_type,uuid);
}
inside this javascript.

May i ask if you have control over the webpage? I mean; you could change something in source. In this case it would b easy.
But i guess it is not yours and you want to grap them programatically..

Your problem is, that this uuid variable is used inside a function which is the result of an httpcalls. Like JobDone in b4a.
All variables inside side sub are private and only accessible inside the function.

So your tryings could not work as the variable is not a global one.

BUT you now know that it is not private and it i update a part of the html (the ones where the popup link resides).
I suggest to use jquery as it is implemented in the webpage. So you can use jquerycalls inside the executejavascript.
You need to know the right jquery query to get access to the urls defined here in the route.js
// Update the routing result message

link=document.getElementById(routing_type + "_html");
link.href="results.cgi?uuid=" + uuid + ";type=" + routing_type + ";format=html";

That´s what i would try. But as i already said i´m not a profi with javascript. i just have basic knowledge.
 
Upvote 0

Mark Read

Well-Known Member
Licensed User
Longtime User
Thanks for your help Manfred, I will keep trying.
 
Upvote 0

Mark Read

Well-Known Member
Licensed User
Longtime User
Sorry, to answer your question, I have no control over the page. I discovered it by accident. There is an API available but I cannot make a wrapper for B4A. I am sure I am not the only one who would be interested in this. I will fight on.
 
Upvote 0

Mark Read

Well-Known Member
Licensed User
Longtime User
Working all day on this and have now got the route data in the B4A log.

The new code for the "btn_GetTextRoute"

B4X:
Sub btn_GetTextRoute_Click
       
    Dim Javascript As String="B4A.CallSub('GetVarFromWebview', true, document.getElementById('shortest_text').getAttribute('href'))"
   
    WebViewExtras1.executeJavascript(WebView1, Javascript)
   
    'This works!!
    'WebView1.LoadUrl("javascript:alert(document.getElementById('shortest_text').getAttribute('href'));")
   
    'or this
   
'    Dim Javascript As String="javascript:alert(document.getElementById('shortest_text').getAttribute('href'));"
'   WebViewExtras1.executeJavascript(WebView1, Javascript)
       
#Region   
'    <tr><td>HTML directions:<td><a id="shortest_html"      target="shortest_html"      href="#">Open Popup</a>
'   <tr><td>GPX track File: <td><a id="shortest_gpx_track" target="shortest_gpx_track" href="#">Open Popup</a>
'   <tr><td>GPX route File: <td><a id="shortest_gpx_route" target="shortest_gpx_route" href="#">Open Popup</a>
'   <tr><td>Full text File: <td><a id="shortest_text_all"  target="shortest_text_all"  href="#">Open Popup</a>
'   <tr><td>Text File:      <td><a id="shortest_text"      target="shortest_text"      href="#">Open Popup</a>
#End Region

End Sub

Two new subs are also required

B4X:
Sub GetVarFromWebview(WebVar As String)
    TextURL="http://routino.grade.de/" & WebVar   
    Log(TextURL)
    HttpUtils.Download("Job1", TextURL)
End Sub

Sub JobDone (Job As String)
    Select Job
        Case "Job1"
            If HttpUtils.IsSuccess(TextURL) Then
                Log(HttpUtils.GetString(TextURL))
            End If
    End Select
           
    HttpUtils.Complete = False 'Turn off the complete flag so we won't handle it again if the activity is resumed.
End Sub

and of course, the result!

** Activity (main) Create, isFirst = true **
** Activity (main) Resume **
URL has finished loading ...
http://routino.grade.de/results.cgi?uuid=43bb3e4964246943c8910a5a8b80e0c5;type=shortest;format=text
Starting Job: Job1
** Service (httputilsservice) Create **
** Service (httputilsservice) Start **
# Creator : Routino - http://www.routino.org/
# Source : Based on OpenStreetMap data from http://www.openstreetmap.org/
# License : http://www.openstreetmap.org/copyright
#
#Latitude Longitude Section Section Total Total Point Turn Bearing Highway
# Distance Duration Distance Duration Type
53.279818 12.984015 0.000 km 0.0 min 0.0 km 0 min Waypt -4 Havel
53.254604 13.026962 4.105 km 61.6 min 4.1 km 62 min Junct +0 +3 CEMT=VII
53.254604 13.026962 0.000 km 0.0 min 4.1 km 62 min Junct +0 +3 Havel
53.248081 13.028815 0.770 km 11.6 min 4.9 km 73 min Junct +0 -4 Wildhofbrücke
53.248081 13.028815 0.000 km 0.0 min 4.9 km 73 min Junct +0 -4 Havel
53.219405 13.033510 4.750 km 71.2 min 9.6 km 144 min Junct +0 -4 Brücke Priepert
53.219405 13.033510 0.000 km 0.0 min 9.6 km 144 min Junct +0 -4 Havel
53.214277 13.030169 0.640 km 9.6 min 10.3 km 154 min Junct +0 +3 Havel
53.194282 13.081767 5.825 km 87.4 min 16.1 km 241 min Junct +0 +3 Steinhavel
53.188611 13.090667 0.878 km 13.2 min 17.0 km 255 min Junct +0 +3 Brücke Steinförde
53.188611 13.090667 0.000 km 0.0 min 17.0 km 255 min Junct +0 +3 Steinhavel
53.183515 13.137106 4.310 km 64.7 min 21.3 km 319 min Junct +0 +2 Eisenbahnbrücke
53.183515 13.137106 0.000 km 0.0 min 21.3 km 319 min Junct +0 +2 Havel
53.182237 13.142282 0.381 km 5.7 min 21.7 km 325 min Junct +1 +3 Havel
53.181441 13.144421 0.169 km 2.5 min 21.8 km 327 min Junct +0 +2 Straßenbrücke
53.181441 13.144421 0.000 km 0.0 min 21.8 km 327 min Junct +0 +2 Havel
53.184764 13.151810 0.664 km 10.0 min 22.5 km 337 min Junct +0 +1 Überdachte Fußgängerbrücke
53.184764 13.151810 0.000 km 0.0 min 22.5 km 337 min Junct +0 +1 Havel
53.185110 13.152190 0.045 km 0.7 min 22.5 km 338 min Junct +0 +1 Havel
53.173316 13.218033 4.939 km 74.1 min 27.5 km 412 min Junct +0 +2 CEMT=I
53.173323 13.227186 0.623 km 9.3 min 28.1 km 421 min Waypt
** Service (httputilsservice) Destroy **
** Activity (main) Pause, UserClosed = false **
** Activity (main) Resume **

Now I am off to celebrate with a glass of wine!!

For other users, this is a routing program for waterways. The gpx file is very good and quite accurate in google maps. The only drawback is the online requirement.
I will still add it as a feature in my OSM-Canoe app.
 
Upvote 0
Top