Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

WPWidgetLibrary HTML5 Widget for Windows Phone 7 Mango

0.00/5 (No votes)
14 Nov 2011 1  
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:

/// <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:

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. 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. 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.

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 has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here