Pass values from webpage to application

warwound

Expert
Licensed User
Hi all.

I'm new to Basic4Android and am writing my first application - a store finder - and this is my first (rather long) post on the forum :).

I have three activities in my application:

The first activity gets the user's location using GPS and queries a database for nearest stores to the user location.
The activity parses the XML response and stores it as a process global variable.

The second activity creates a list view of these stores and a click on a list view item saves that store data as a process global and opens the third activity.

The third activity contains a WebView that loads a local HTML file with a query string generated from the location of the selected store - it gets the values from the second activitys process global.
The HTML file creates a Google Map displaying directions from the user location to the selected store.

All works perfectly so far.

Now when the third activity is paused - the device orientation changes - and is then resumed, the map displays exactly as it's displayed when initially viewed.
That is, if the user changes the map center, zoom level or map type and then changes their device orientation then when the third activity is resumed the map doesn't retain the view set by the user.

I can add event listeners to my web page and store (as javascript variables) the map center, zoom level and map type whenever any of these values change.
But how can i get these javascript values from my web page back to the third activitys Resume method, where i can add them to the query string and the map can restore the state of the map before the activity was paused?

My only solution so far is:

Whenever the user changes the map center, zoom level or map type to set the javascript location.href property to a new URL with the current map center, zoom level and/or map type in the new URL query string.
For example:

B4X:
google.maps.event.addListener(map, 'center_changed', function(){
   location.href='file:///android_asset/store_detail.htm?newcenter='+map.getCenter().toUrlValue();
});
Then in my application listen for the WebView OverrideUrl event.
If this is the first time that the WebView URL has changed then do not consume the event otherwise consume the event - parsing out new map center, zoom level and/or map type values to the third activity process global:

Activity #3 code:
B4X:
'Activity module
Sub Process_Globals
   'These global variables will be declared once when the application starts.
   'These variables can be accessed from all modules.
   Type State (Lat As Float, Lng As Float, Zoom As Int, MapType As String)
   Dim mapState As State
End Sub

Sub Globals
   'These global variables will be redeclared each time the activity is created.
   'These variables can only be accessed from this module.
   Dim handleUrls As Boolean
   Dim storeDetailWebView As WebView
End Sub

Sub Activity_Create(FirstTime As Boolean)
   If FirstTime=True Then
      ProgressDialogShow("Creating map view")
      mapState.Lat=0
      mapState.Lng=0
      mapState.Zoom=0
      mapState.MapType="ROADMAP"
      handleUrls=False
   End If
End Sub

Sub Activity_Resume
   Activity.LoadLayout("lytStoreDetail")
   storeDetailWebView.Width=100%x
   storeDetailWebView.Height=100%y
   
   Dim mapUrl As StringBuilder
   mapUrl.Initialize
   
   mapUrl.Append("file:///android_asset/store_detail.htm?saddr=")
   mapUrl.Append(Main.userLocation.Latitude).Append(",").Append(Main.userLocation.Longitude)
   mapUrl.Append("&daddr=").Append(actStoreList.selectedStore.Lat).Append(",").Append(actStoreList.selectedStore.Lng)
   
   storeDetailWebView.LoadUrl(mapUrl.ToString)
   
End Sub

Sub Activity_Pause (UserClosed As Boolean)
End Sub

Sub storeDetailWebView_PageFinished (url As String)
   Log("debug1: "&url)
   ' consume the OverrideUrl event now that the initial page view URL has loaded
   handleUrls=True
   ProgressDialogHide
End Sub

Sub storeDetailWebView_OverrideUrl (url As String) As Boolean
   Log("debug2: "&url)
   If handleUrls Then 
      '   parse map state from url and save to a process global
   End If
   Return handleUrls
End Sub
This solution so far doesn't work :(.

All the logic seems to be fine BUT OverrideUrl event does not fire when the map javascript sets the location.href property.
Instead the page reloads - losing the original directions and other map state.
PageFinished event fires when the page is first loaded and then each time the map javascript changes the location.href property BUT OverrideUrl event nevers fires if the page is reloaded by setting the location.href property within the page javascript.

The IDE reports the 'debug1' messages but no 'debug2' messages.

Now every Google Map has a link bottom corner - i gave it a click and 'debug2' message appeared in the IDE and OverrideUrl event has been called!

So i have two questions:

1) Should the OverrideUrl event be expected to fire when javascript (within a page being displayed in a WebView) changes the DOM location.href property?

2) Can anyone suggest any other methods that i can use to get values from my web page javascript into an activity where they can be saved as process globals?

Thanks a lot.

Martin.
 

Erel

Administrator
Staff member
Licensed User
Should the OverrideUrl event be expected to fire when javascript (within a page being displayed in a WebView) changes the DOM location.href property?
I do not know. You will need to create a small test to check it.

If handling orientation changes is difficult, you can consider preventing them by locking the orientation.
 

warwound

Expert
Licensed User
Hi.

Thanks for the reply.

I put together a simple program to test if OverrideUrl is being fired when a WebView URL is changed and the OverrideUrl event fires when the WebView URL is changed using javascript and the location.href property!

I've looked through my original code and can see nothing different that would explain why OverrideUrl is not being fired.

I did think that cookies would be an ideal solution but it seems that cookie support is variable when pages are loaded using the file:// protocol.
Session cookies may work but not cookies that will survive the activity being paused and then restarted.

Maybe i'll lock the application orientation as an easy solution...

I am busy for the rest of the day but will spend more time on it over the weekend and update this thread.

Thanks.

Martin.
 
Top