📜 ⬆️ ⬇️

Using HTML5 and JavaScript to develop applications for Windows Phone


Today I want to talk about what additional opportunities for developing applications for Windows Phone are those who own HTML5 and JavaScript.

First of all, let's deal with how this is possible. All the features associated with HTML5 + JS development for Windows Phone are related to the presence of Internet Explorer onboard, which is similar in functionality to desktop Internet Explorer 9. And this is understandable because they have a common code base. Below are the main (but not all) features supported by the browser.

The presence of a mobile browser with such support already provides the basic possibility of being present on a mobile platform: creating a rich mobile site. But we wanted to write applications! Developing applications is enabled by the WebBrowser control available to developers:
<phone:WebBrowser Grid.Row="1" Name="MyBrowser" IsGeolocationEnabled="True" IsScriptEnabled="True" Background="{StaticResource PhoneBackgroundBrush}"/> 

The presence of a fully-functional mobile site and the ability to insert a WebBrowes control into your application leads us to the first type of HTML5 applications for Windows Phone: applications hosted by the mobile website in the WebBrowser control and add additional service capabilities related to the platform, for example, Push Notification .

Let's write an example of such an application. We will host the Yandex mobile site. For simplicity, we will not invent additional services, but add the ApplicationBar and a few buttons that will provide access to the functionality most in demand.

As usual, we start by creating an application based on the Windows Phone Application template. Using NuGet, add the Silverlight for Windows Phone Toolkit package to the application. After that, add a WebBrowser control and a PerformanceProgressBar control to the main page of the MainPaige.xaml application to show the page loading process. As a result, the XAML code will look like this:
 <toolkit:PerformanceProgressBar Name="Progress" Height="10" IsIndeterminate="False" Background="{StaticResource PhoneBackgroundBrush}"/> <phone:WebBrowser Grid.Row="1" Name="Yandex" IsGeolocationEnabled="True" IsScriptEnabled="True" Background="{StaticResource PhoneBackgroundBrush}"/> 

Don't forget to add a namespace link to use controls from Silverlight for Windows Phone Toolkit:
  xmlns:toolkit="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit" 

To make an application in the style of Windows Phone and add buttons to it, I uncommented ApplicationBar, and used the information from the article Where do I get icons for Windows Phone applications ? To find the icons that my application needs. I also immediately added event handlers to the buttons on the ApplicationBar. As a result, the XAML code of my MainPage.xaml page of my application began to look like this:
 <phone:PhoneApplicationPage x:Class="MyYandexWithBJ.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone" xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:toolkit="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit" mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="696" FontFamily="{StaticResource PhoneFontFamilyNormal}" FontSize="{StaticResource PhoneFontSizeNormal}" Foreground="{StaticResource PhoneForegroundBrush}" SupportedOrientations="Portrait" Orientation="Portrait" shell:SystemTray.IsVisible="True"> <!--LayoutRoot is the root grid where all page content is placed--> <Grid x:Name="LayoutRoot" Background="Transparent"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <toolkit:PerformanceProgressBar Name="Progress" Height="10" IsIndeterminate="False" Background="{StaticResource PhoneBackgroundBrush}"/> <phone:WebBrowser Grid.Row="1" Name="Yandex" IsGeolocationEnabled="True" IsScriptEnabled="True" Background="{StaticResource PhoneBackgroundBrush}"/> </Grid> <!--Sample code showing usage of ApplicationBar--> <phone:PhoneApplicationPage.ApplicationBar> <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True"> <shell:ApplicationBarIconButton IconUri="/icons/appbar.back.rest.png" Text="" lick="ApplicationBarBackButton_Click"/> <shell:ApplicationBarIconButton IconUri="/icons/appbar.home.png" Text="" Click="ApplicationBarHomeButton_Click"/> <shell:ApplicationBarIconButton IconUri="/icons/appbar.plane.rotated.45.png" Text="" Click="ApplicationBarFlightsButton_Click"/> <shell:ApplicationBarIconButton IconUri="/icons/appbar.next.rest.png" Text="" Click="ApplicationBarForwardButton_Click"/> </shell:ApplicationBar> </phone:PhoneApplicationPage.ApplicationBar> </phone:PhoneApplicationPage> 

Icons were added to the icons folder in the project, the content type is set to Content, Copy to Output to Copy if newer. The application itself at startup now looks like this:

Add a code that, when downloading an application, opens the Yandex mobile page, by pressing the button with the house, opens it, and when clicking on the plane, opens the mobile page with the aircraft schedule.
 // Constructor public MainPage() { InitializeComponent(); Loaded += new RoutedEventHandler(MainPage_Loaded); } void MainPage_Loaded(object sender, RoutedEventArgs e) { Yandex.Navigate(new Uri("http://m.yandex.ru")); } private void ApplicationBarHomeButton_Click(object sender, EventArgs e) { Yandex.Navigate(new Uri("http://m.yandex.ru")); } private void ApplicationBarFlightsButton_Click(object sender, EventArgs e) { Yandex.Navigate(new Uri("http://m.rasp.yandex.ru/station?plane=1")); } 

Now the application opens the Yandex mobile page when it starts up, and when you click on the button with the plane, it opens the mobile page with the schedule of the aircraft:

It remains to add the processing of buttons forward / backward and the display of the ProgressBar when navigating to the page. In order to add a ProgressBar mapping, add the Navigating and Navigated WebBrowser control to the Navigating event:
 void MainPage_Loaded(object sender, RoutedEventArgs e) { Yandex.Navigated += new EventHandler<System.Windows.Navigation.NavigationEventArgs>(Yandex_Navigated); Yandex.Navigating += new EventHandler<NavigatingEventArgs>(Yandex_Navigating); Yandex.Navigate(new Uri(http://m.yandex.ru)); } void Yandex_Navigating(object sender, NavigatingEventArgs e) { Progress.IsIndeterminate = true; } void Yandex_Navigated(object sender, System.Windows.Navigation.NavigationEventArgs e) { Progress.IsIndeterminate = false; } 

To process the push of buttons forwards and backwards, we use the possibilities of JavaScript and the history object, along with the ability to call it from the application code:
 private void ApplicationBarBackButton_Click(object sender, EventArgs e) { Yandex.InvokeScript("eval", "history.go(-1)"); } private void ApplicationBarForwardButton_Click(object sender, EventArgs e) { Yandex.InvokeScript("eval", "history.go(1)"); } 

Now we have our own mobile Yandex application with a home button and an airplane schedule. A good completion of the exercise is the addition of defining the ability to navigate back / forward buttons, in order to have them active only if the transition can actually be completed.
')
This application uses remote HTML5 + JS content, the logical next step will be the second type of HTML5 applications for Windows Phone, which uses local content on the phone, without going, or at least going beyond, the WebBrowser control .

Let's write an example of such an application. This will be a local HTML5 page, the active content of which will be generated by JS. To simplify development, we will use the jQuery library.

As usual, we start by creating an application based on the Windows Phone Application template. In order not to write an HTML5 application myself, I took an SVG example from Kostya Kichinsky ’s report on TechEd Russia 2011 .

In the project, create a content folder and add the svgdemo.htm and jquery-1.7.min.js files to it. In the svgdemo.html file, change the path to the jquery-1.7.min.js script so that the current script looks like this:
 <script src="jquery-1.7.min.js" type="text/javascript"></script> 

You also need to set the files svgdemo.htm and jquery-1.7.min.js Build Action in Content and Copy to Output in Copy if newer.

Now, add the WebBrowser control to the main page of the application so that it fills the entire space. As a result, the XAML code will look like this:
 <phone:PhoneApplicationPage x:Class="IE9HTML.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone" xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768" FontFamily="{StaticResource PhoneFontFamilyNormal}" FontSize="{StaticResource PhoneFontSizeNormal}" Foreground="{StaticResource PhoneForegroundBrush}" SupportedOrientations="Portrait" Orientation="Portrait" shell:SystemTray.IsVisible="True"> <!--LayoutRoot is the root grid where all page content is placed--> <Grid x:Name="LayoutRoot" Background="Transparent"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <!--ContentPanel - place additional content here--> <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <phone:WebBrowser Name="myBrowser" IsScriptEnabled="True" /> </Grid> </Grid> </phone:PhoneApplicationPage> 

At first glance, in fact, the development is complete (taking into account the fact that we took the finished HTML5 application), but there is still one subtle point. The point is that our HTML file and JS file will not be accessible to the WebBrowser control after the application is deployed, since they will not be located in Isolated Storage. Therefore, when launching the application, we need to deploy our HTML5 application in Isolated Storage. For this we will use the sample code from MSDN, changing in it the set of files to our own:
 private void SaveFilesToIsoStore() { //These files must match what is included in the application package, //or BinaryStream.Dispose below will throw an exception. string[] files = { "content/svgdemo.htm", "content/jquery-1.7.min.js" }; IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForApplication(); if (false == isoStore.FileExists(files[0])) { foreach (string f in files) { StreamResourceInfo sr = Application.GetResourceStream(new Uri(f, UriKind.Relative)); using (BinaryReader br = new BinaryReader(sr.Stream)) { byte[] data = br.ReadBytes((int)sr.Stream.Length); SaveToIsoStore(f, data); } } } } private void SaveToIsoStore(string fileName, byte[] data) { string strBaseDir = string.Empty; string delimStr = "/"; char[] delimiter = delimStr.ToCharArray(); string[] dirsPath = fileName.Split(delimiter); //Get the IsoStore. IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForApplication(); //Re-create the directory structure. for (int i = 0; i < dirsPath.Length - 1; i++) { strBaseDir = System.IO.Path.Combine(strBaseDir, dirsPath[i]); isoStore.CreateDirectory(strBaseDir); } //Remove the existing file. if (isoStore.FileExists(fileName)) { isoStore.DeleteFile(fileName); } //Write the file. using (BinaryWriter bw = new BinaryWriter(isoStore.CreateFile(fileName))) { bw.Write(data); bw.Close(); } } 

The SaveFilesToIsoStore () method verifies that the specified files are not in Isolated Storage and copies them using the SaveToIsoStore helper method, preserving the directory hierarchy.

Now everything is ready to write code that will complete the initialization of our HTML5 application:
 // Constructor public MainPage() { InitializeComponent(); this.Loaded += new RoutedEventHandler(MainPage_Loaded); } void MainPage_Loaded(object sender, RoutedEventArgs e) { SaveFilesToIsoStore(); myBrowser.Navigate(new Uri("content/svgdemo.htm", UriKind.Relative)); } 

Save the files to IsolatedStorage and display the main HTML5 file in the WebBrowser control. A running application looks like this:

It seems to me that this is a great example. Thanks for him Kostya ( kichik ).

If we have a little pure HTML5 + JS and we want to go beyond the browser control, we can talk about the third type of HTML5 applications for Windows Phone, which not only uses local content on the phone, but also go beyond the limits of the WebBrowser control, using platforms (eg accelerometer) . We can make such an application “from scratch” on our own, using the ability to notify the platform about what is happening (window.external.notify / ScriptNotify) or call the JS script from C # code (WebBrowser.InvokeScript). But it is better to use the existing solution - PhoneGap.

At the time of writing, version 1.3 was available. You can download it on the website phonegap.com , there is also documentation. After downloading, unzip the archive and from the Windows Phone folder copy the PhoneGapCustom.zip and PhoneGapStarter.zip files to the Visual Studio 2010 \ Templates \ folder, unload all running versions of Visual Studio. After launching Visual Studio, a new project type will appear:

Create a project based on PhoneGapStarter. We look at the composition of the project:

Actually, PhoneGap itself is the phonegap-1.3.0.js JS file and the WP7GapClassLib .NET CF library that responds to it. In addition, instead of the built-in WebBrowser, a PGView control is used, which is located in the same WP7GapClassLib.

The auxiliary file ManifestProcessor.js is used to update the GapSourceDictionary.xml file, which contains the list of content files (the www project directory), which, as we already know from the previous example, will need to be deployed to Isolated Storage before building the application.

We write a simple application that will read the accelerometer data and display it on the page. To do this, replace the contents of the index.html file tag with the following:
 <h1>Accelerometer sample</h1> <div id="valueX"></div> <div id="valueY"></div> <div id="valueZ"></div> 

Now you need to replace the script on this page with your own, which works with the accelerometer (the code is taken from the article David Rousset, Tutorial: how to create HTML5 applications on Windows Phone thanks to PhoneGap) :
 <script type="text/javascript"> document.addEventListener("deviceready", onDeviceReady, false); // variable to output the current x, y & z values of the accelerometer var valueX; var valueY; var valueZ; // when PhoneGap tells us everything is ready, start watching the accelerometer function onDeviceReady() { valueX = document.getElementById("valueX"); valueY = document.getElementById("valueY"); valueZ = document.getElementById("valueZ"); startWatch(); } // start monitoring the state of the accelerometer function startWatch() { var options = { frequency: 500 }; navigator.accelerometer.watchAcceleration(onSuccess, onError, options); } // if the z-axis has moved outside of our sensitivity threshold, move the aarvark's head in the appropriate direction function onSuccess(acceleration) { valueX.innerHTML = "X: " + acceleration.x; valueY.innerHTML = "Y: " + acceleration.y; valueZ.innerHTML = "Z: " + acceleration.z; } function onError() { alert('onError!'); } </script> 

Of course, the only thing that needs explanation is the navigator object, which allowed us to connect to the accelerometer. This is actually part of PhoneGap. Learn more about the PhoneGap API at phonegap.com .

It remains only to start the application and make sure that it works:

As an example of the capabilities of the platform, I want to give a screenshot of the game on HTML5, from the same article by David Rousset:


Projects examples :
Myyandex
Svg demo
Phonegap Accelerometr Sample

Useful links:
Live Tiles and Background Agents
Windows Phone Development Center on MSDN (Windows Phone course)
Windows Phone SDK 7.1
Forums on development for Windows Phone in Russian

Source: https://habr.com/ru/post/136158/


All Articles