Javascript, the Back Button, and Windows Phone 8 Development

Published on Feb 18, 2013 by Jamie Munro

I recently had the opportunity to begin exploring and toying around with Windows Phone 8 development.

Why you ask?  Why not really, but mostly because I was giving a free phone and it’s an untapped market when it comes to apps.  At this stage it’s not over diluted like the Android and iPhone stores are.  That and of course there is an option to create apps using HTML, Javascript, and CSS – technologies I’ve used and mastered for years!

I actually submitted my first app last weekend – and sadly – it got rejected :(  I was given two reasons; firstly I did set a default application icon, whoops my bad.  Secondly, I didn’t properly handle the back button since there are “multiple pages” in my application.

It took me several hours to finally found the answer so I thought I would share it.  Please note, this feels like a bit of a hack, but I wasn’t able to get the “suggested” solutions working…




Of course now that I have the solution, it feels quite simple, still hacky, but simple.  It also opened my eyes up to a lot of future potential – specifically the way I am about to demonstrate sending data between C# and Javascript!

The end solution involves two key functions; the C# piece:


Browser.InvokeScript("MyJavascriptFunction");


And the Javascript piece:


window.external.notify(myJavascriptVariable);


I explain how to solve the issue in more detail in a second, but wanted to firstly present the key functions and their use.

The C# function does exactly what the name says, it invokes a script.  Now here is the part that feels hacky.  According to the MSDN documentation: http://msdn.microsoft.com/en-us/library/ee652559(v=vs.95).aspx the function is supposed to return an object that contains the results of the Javascript execution.  I tried for the life of me to get this to work, but my result was always empty.

So please, if you know what I did wrong here I would love to know as the following part goes on to explain my hacked together solution “to get the job done” as they say.

The second key function is a Javascript call that – once again – does exactly what it says, it notifies an external device with the data I passed in.

On to the final solution…

Your xaml file that contains your web embedded web browser requires a few updates – typically this is your MainPage.xaml.  When you create a new project, Visual Studio will probably generate XML quite similar to this:


<!--LayoutRoot is the root grid where all page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent">
<phone:WebBrowser x:Name="Browser"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Loaded="Browser_Loaded"
NavigationFailed="Browser_NavigationFailed"/>
</Grid>


Two additional variables are required to be added and set after the NavigationFailed variable:


<!--LayoutRoot is the root grid where all page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent">
<phone:WebBrowser x:Name="Browser"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Loaded="Browser_Loaded"
NavigationFailed="Browser_NavigationFailed"
IsScriptEnabled="True"
ScriptNotify="ScriptNotifyHandler"/>
</Grid>


The two variables are IsScriptEnabled and ScriptNotify.  The first function ensures Javascript execution is allowed and the second variable defines a function that must be added in your MainPage.xaml.cs file that will be called whenever you execute a call with window.external.notify.

Once these variables are added, let’s add the new function in our MainPage.xaml.cs file:


private void ScriptNotifyHandler(object sender, NotifyEventArgs e)
{
// e.Value contains the contents of our Javascript call, so do something with it
}


With the key places all in place, here is the full solution that I implemented.  Once again in our MainPage.xaml.cs file, we need to capture the back button press:


protected override void OnBackKeyPress(System.ComponentModel.CancelEventArgs e)
{
Browser.InvokeScript("checkClose");
e.Cancel = true;
}


This function does two important things.  It invokes a Javascript function checkClose and it sets e.Cancel to true.  This will cause the application to not exit when the user presses the back button.

Now here is the Javascript checkClose function:


var state;

function checkClose() {
if ($startScreen.is(":visible")) {
state = "home";
} else {
state = "game";
}

try {
window.external.notify(state);
} catch(err) {
alert(err);
}
}


This will require some customization by you to get it working in your example…

In my example above, the goal of this function is to set and send a value for the global state variable.  If the user is on the “start screen” of my application I set state to home; otherwise, I set it to game.  This data is then passed to C#.

Two more things before this is a finished solution, we go back to the MainPage.xaml.cs file and fill in the blanks to our ScriptNotifyHandler function:


private void ScriptNotifyHandler(object sender, NotifyEventArgs e)
{
// If in game, go to start screen; otherwise, close
if (e.Value == "game")
{
Browser.InvokeScript("GoHome");
}
else
{
Application.Current.Terminate();
}
}


If the value sent contains the word “game” I once again invoke another Javascript function; otherwise, I terminate the application because the user is on the start screen.

The final piece is creating the Javascript function GoHome.  This function should be created by you to bring the user back to your start screen – or – if you do not always want to send the user directly back to the start page, you can invoke any other Javascript to bring the user back to their previous spot.

I hope this helps you and if someone can help me make this solution feel less hacky, that would be cool too.

On a side/final note, I resubmitted my app this past weekend, so hopefully it will get accepted this time :)

Tags: Javascript | ASP.NET | c# | JavaScript | Windows Phone | wp8 | windows phone 8

Related Posts

blog comments powered by Disqus