Click here to Skip to main content
15,880,796 members
Articles / Mobile Apps / Windows Phone 7

WPWidgetLibrary HTML5 Widget for Windows Phone 7 Mango

Rate me:
Please Sign up or sign in to vote.
5.00/5 (4 votes)
14 Nov 2011MIT3 min read 36.6K   878   17   10
Imlementation of HTML5 Widget apps in offline mode on Windows Phone 7 Mango.

Article.png

Introduction

The browser in Windows Phone 7 Mango is almost the same version used for the IE 9 desktop edition. This means WP7+ is able to render HTML5 content and run HTML5 apps. In comparison to Chrome, it supports less HTML5 elements, but some of the important features like geo-location and canvas work well. If you want to open an HTML app in offline mode, you will have a little problem. Currently, there is no way for WebBrowserControl in WP 7 Mango to navigate to an HTML file which is located somewhere in the file system at the phone as supported by other competitors, e.g., Android and iOS. This means you are constrained to develop a classic HTML5 Widget app on WP7. With WPWidgetLibrary, you can build an HTML 5 Widget app as a native WP7 app. Afterwards you can publish it on the Windows Phone Marketplace and easily make updates for the app. The library works so that the first time it installs HTML5 content in Isolated Storage by simulating the real hard disk, and paths of the HTML pages, scripts, images, etc. We have been inspired in this project by the great idea of Windows Mobile 6.5 Widget Apps.

Implementation

WPWidgetLibrary contains a class which implements the whole logic behind offline running HTML5 apps. The following code presents the WPWidgetLibrary class structure:

C#
/// <summary>
/// Class is used to extract HTML content from the application resource 
/// and use as regular HTML Widget app
/// </summary>
public class WidgetLibrary
{
    /// <summary>
    /// list of folder structure of the HTML app
    /// </summary>
    private List<string> m_Subfolders = new List<string>();

    /// <summary>
    /// Extract all HTML5 app from the resource
    /// and create file system in Isolated Storage.
    /// </summary>
    /// <param name="htmlFolder"></param>
    public void InstalHTMLContent(string htmlFolder, string[] htmlDirs);

    /// <summary>
    /// Check is file is in corect file format
    /// </summary>
    /// <param name="webResource"></param>
    /// <returns></returns>
    private bool iswebResource(string webResource);

    /// <summary>
    /// We can restrict file to be part of HTML app.
    /// </summary>
    /// <param name="ext"></param>
    /// <returns></returns>
    protected virtual bool isWebExtension(string ext);

    /// <summary>
    /// Small helper to xtract name from full resource W7 name.
    /// </summary>
    /// <param name="assemblyReplacement"></param>
    /// <param name="webResource"></param>
    /// <returns></returns>
    private string getFileNameFromResourceName(string assemblyReplacement, 
                   string webResource);

    /// <summary>
    /// This is copying files from installed to isolatedstorage target location 
    /// </summary>
    /// <param name="isoFile"></param>
    /// <param name="webResourceFileName"></param>
    /// <param name="webResourceStream"></param>
    private void copyFile(IsolatedStorageFile isoFile, 
            string webResourceFileName, Stream webResourceStream);
        
    /// <summary>
    /// Creates the list of all subfolders from specified array.
    /// Creates from "aa/bb/cc following entries in m_Subfolders:
    /// aa
    /// aa/bb
    /// aa/bb/cc 
    /// </summary>
    /// <param name="directories">
    /// </param>
    private void resolveSubfolders(string[] directories);
        
    /// <summary>
    /// Create folder structure of our web site with all folders. 
    /// HTML folder must be in root app folder
    /// </summary>
    /// <param name="isolatedStorageFile"></param>
    /// <param name="webResourceFileName"></param>
    /// <returns></returns>
    private string createRequiredDirectory(IsolatedStorageFile 
            isolatedStorageFile,string webResourceFileName);

    /// <summary>
    /// Delete directory of previous version before
    /// you install current version is recomended.
    /// We need to go throught all folders and subfolder in order to delete every file.
    /// </summary>
    /// <param name="isolatedStorageFile"></param>
    /// <param name="root"></param>
    private void deleteDirectory(IsolatedStorageFile isolatedStorageFile,string root);

    /// <summary>
    /// Check if the app is running for the first time.
    /// </summary>
    /// <returns></returns>
    private bool IsFirstTimeRun();
}

The main idea behind this class is the public method InstalHTMLContent(string htmlFolder, string[] htmlDirs);. Let us see the implementation of the method:

C#
public void InstalHTMLContent(string htmlFolder, string[] htmlDirs)
{
    if (htmlDirs == null)
        throw new Exception("No html folder structure passed!");

    //Load HTML content first time App is running
    if (!IsFirstTimeRun())
        return;

    Debug.WriteLine("Application runs for the first time!");

    //Resolve folder structure of HTML app
    resolveSubfolders(htmlDirs);

    var asm = Assembly.GetCallingAssembly();

    using (IsolatedStorageFile isolatedStorageFile = 
             IsolatedStorageFile.GetUserStoreForApplication())
    {
        deleteDirectory(isolatedStorageFile, String.Empty);

        foreach (var webResource in asm.GetManifestResourceNames())
        {
            if (iswebResource(webResource))
            {
                var pos = webResource.ToLower().IndexOf(htmlFolder.ToLower());
                if (pos > 0)
                    copyFile(isolatedStorageFile, getFileNameFromResourceName(
                      webResource.Substring(0, pos + htmlFolder.Length + 1), 
                      webResource), asm.GetManifestResourceStream(webResource));
                else
                    throw new InvalidOperationException("invalid resource name.");
            }
        }
    }
}

The HTML content has to be included in the project as an Embedded Resource. The method above extracts the resource content on Isolated Storage based on the input argument htmlDirs. During extracting, the file and folder structure must be the same as the original so that the links and paths are valid.

Note that this method is called only the first time the application is running, which is important for localDataStorage and persistent objects while using HTML5 apps.

Using the code

By using WPWidgetLibrary, you can make fully functional hybrid Windows Phone 7 applications in only a few steps. The library runs only in Windows Phone 7.1 so you have to install Windows Phone 7.1 Developer Tool for Visual Studio 2010.

  1. Reference the WPWidgetLibrary DLL in your WP7.1 project.
  2. Copy your HTML (App) to some project folder and mark all files in build action as EmbeddedResource.
  3. From the Toolbox, drag the WebBrowser control, and in the PageLoaded event, navigate to the desired webpage. (See the red rectangle in the XAML file.)
  4. In the MainPage constructor, append the following code. This code will, on the start of the application, copy all HTML related content to Isolated Storage. The string array (second argument of InstallHTMLContent) should contain all subfolders of your project which have to be copied to Isolated Storage too. If you have a very simple app with all files in one folder, then this argument is not required.
  5. In the constructor of your MainPage xaml.cs, put the following code:
  6. C#
    var wdgt = new WPWidgetLibrary();            
    wdgt.InstalHTMLContent("HTML", new string[]
                   { "js/jQueryMobile/images",
                   "SubContent/SubSubContent",
                  });
  7. Set the initial page to the WebBrowser control from the MainPage Loaded event in code-behind. The following code is a common WebBrowser code, which starts browsing the page. Please note that the navigating page (StartPage.htm) is not the page hosted online. It is the page in Isolated Storage.
  8. C#
    void MainPage_Loaded(object sender, RoutedEventArgs e)
    {
        //Navigate to initial page of the HTML app
         webBrowser1.Navigate(new Uri("StartPage.htm", UriKind.Relative));
    }
  9. Compile and run the application, and you are looking at a full featured HTML Widget application.
  10. Article2.png

Customization of the library

By default, WPWIdgetLibrary only supports a limited number of file formats which can be part of the HTML5 app. For example, if you want to add an AVI file to your HTML5 app, you need to make a new implementation class derived from the base class. The following code shows an example of supporting the AVI file format.

C#
public class MyWPWidgetLibrary: WPWidgetLibrary{

protected override bool IsWebExtension(string ext){
   bool res = false;
   switch (ext.ToLower())
   {
       case "avi":
           return true;
           //break;
   }
   return base.IsWebExtension(ext);
  }
}

What we have done here is overridden the IsWebExtension method and implement support for the AVI file format. Similar logic can be applied for any other format.

History

  • 1.0.1 October 2011 - First release version.

License

This article, along with any associated source code and files, is licensed under The MIT License


Written By
Software Developer (Senior)
Bosnia and Herzegovina Bosnia and Herzegovina
Bahrudin Hrnjica holds a Ph.D. degree in Technical Science/Engineering from University in Bihać.
Besides teaching at University, he is in the software industry for more than two decades, focusing on development technologies e.g. .NET, Visual Studio, Desktop/Web/Cloud solutions.

He works on the development and application of different ML algorithms. In the development of ML-oriented solutions and modeling, he has more than 10 years of experience. His field of interest is also the development of predictive models with the ML.NET and Keras, but also actively develop two ML-based .NET open source projects: GPdotNET-genetic programming tool and ANNdotNET - deep learning tool on .NET platform. He works in multidisciplinary teams with the mission of optimizing and selecting the ML algorithms to build ML models.

He is the author of several books, and many online articles, writes a blog at http://bhrnjica.net, regularly holds lectures at local and regional conferences, User groups and Code Camp gatherings, and is also the founder of the Bihac Developer Meetup Group. Microsoft recognizes his work and awarded him with the prestigious Microsoft MVP title for the first time in 2011, which he still holds today.

Comments and Discussions

 
GeneralMy vote of 5 Pin
Kanasz Robert21-Sep-12 0:48
professionalKanasz Robert21-Sep-12 0:48 
Question??how this works Pin
SteveMintz24x719-Dec-11 12:27
SteveMintz24x719-Dec-11 12:27 
AnswerRe: ??how this works Pin
Bahrudin Hrnjica22-Dec-11 6:40
professionalBahrudin Hrnjica22-Dec-11 6:40 
GeneralRe: ??how this works Pin
SteveMintz24x722-Dec-11 18:07
SteveMintz24x722-Dec-11 18:07 
GeneralAmazing effort :) Pin
Espen Harlinn14-Nov-11 21:54
professionalEspen Harlinn14-Nov-11 21:54 
This is an amazing effort. A few more detailed articles would help to underscore this, as the library certainly deserves all the attention it can get Smile | :)

Not that this is a large library, just a very neat trick underscoring the value of keeping things simple - while still providing something useful.
Espen Harlinn
Senior Architect, Software - Goodtech Projects & Services


modified 15-Nov-11 4:04am.

GeneralRe: Amazing effort :) Pin
Bahrudin Hrnjica17-Nov-11 11:26
professionalBahrudin Hrnjica17-Nov-11 11:26 
QuestionIntersting Solution Pin
halida14-Nov-11 10:24
halida14-Nov-11 10:24 
AnswerRe: Intersting Solution Pin
Bahrudin Hrnjica17-Nov-11 11:29
professionalBahrudin Hrnjica17-Nov-11 11:29 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.