65.9K
CodeProject 正在变化。 阅读更多。
Home

WPWidgetLibrary Windows Phone 7 Mango 的 HTML5 小部件

starIconstarIconstarIconstarIconstarIcon

5.00/5 (4投票s)

2011年11月14日

MIT

3分钟阅读

viewsIcon

38346

downloadIcon

912

在 Windows Phone 7 Mango 上以离线模式实现 HTML5 Widget 应用。

Article.png

引言

Windows Phone 7 Mango 中的浏览器几乎与 IE 9 桌面版使用的版本相同。 这意味着 WP7+ 能够渲染 HTML5 内容并运行 HTML5 应用程序。 与 Chrome 相比,它支持的 HTML5 元素较少,但地理位置和 canvas 等一些重要功能运行良好。 如果你想以离线模式打开一个 HTML 应用,你可能会遇到一些问题。 目前,WP 7 Mango 中的 WebBrowserControl 无法像 Android 和 iOS 等其他竞争对手支持的那样,导航到位于手机文件系统中的 HTML 文件。 这意味着你被限制在 WP7 上开发经典的 HTML5 Widget 应用。 使用 WPWidgetLibrary,你可以构建一个 HTML 5 Widget 应用作为原生 WP7 应用。 之后,你可以将其发布到 Windows Phone Marketplace 并轻松地更新该应用。 该库的工作方式是,第一次安装时,它通过模拟真实的硬盘将 HTML5 内容安装在独立存储中,包括 HTML 页面、脚本、图像等的路径。这个项目的灵感来自于 Windows Mobile 6.5 Widget Apps 的伟大想法。

实现

WPWidgetLibrary 包含一个类,该类实现了离线运行 HTML5 应用背后的全部逻辑。 以下代码展示了 WPWidgetLibrary 类的结构

/// <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();
}

这个类背后的主要思想是公共方法 InstalHTMLContent(string htmlFolder, string[] htmlDirs);。 让我们看看这个方法的实现

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.");
            }
        }
    }
}

HTML 内容必须作为嵌入式资源包含在项目中。 上面的方法根据输入参数 htmlDirs 提取独立存储中的资源内容。 在提取过程中,文件和文件夹结构必须与原始结构相同,以便链接和路径有效。

请注意,此方法仅在应用程序第一次运行时调用,这对于在使用 HTML5 应用时 localDataStorage 和持久对象非常重要。

使用代码

通过使用 WPWidgetLibrary,你只需几个步骤即可制作功能齐全的混合 Windows Phone 7 应用程序。 该库仅在 Windows Phone 7.1 中运行,因此你必须安装适用于 Visual Studio 2010 的 Windows Phone 7.1 Developer Tool。

  1. 在你的 WP7.1 项目中引用 WPWidgetLibrary DLL。
  2. 将你的 HTML (App) 复制到某个项目文件夹,并将构建操作中的所有文件标记为 EmbeddedResource
  3. 从工具箱中,拖动 WebBrowser 控件,并在 PageLoaded 事件中,导航到所需的网页。(参见 XAML 文件中的红色矩形。)
  4. MainPage 构造函数中,附加以下代码。 此代码将在应用程序启动时,将所有 HTML 相关内容复制到独立存储。 字符串数组(InstallHTMLContent 的第二个参数)应包含必须也复制到独立存储的项目的全部子文件夹。 如果你的应用非常简单,所有文件都在一个文件夹中,则不需要此参数。
  5. 在你的 MainPage xaml.cs 的构造函数中,放入以下代码
  6. var wdgt = new WPWidgetLibrary();            
    wdgt.InstalHTMLContent("HTML", new string[]
                   { "js/jQueryMobile/images",
                   "SubContent/SubSubContent",
                  });
  7. 从代码隐藏中的 MainPage Loaded 事件将初始页面设置为 WebBrowser 控件。 以下代码是常见的 WebBrowser 代码,用于开始浏览页面。 请注意,导航页面 (StartPage.htm) 不是托管在网上的页面。 它是独立存储中的页面。
  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. 编译并运行该应用程序,你正在查看一个功能齐全的 HTML Widget 应用程序。
  10. Article2.png

库的自定义

默认情况下,WPWIdgetLibrary 仅支持有限数量的文件格式,这些格式可能是 HTML5 应用的一部分。 例如,如果你想向你的 HTML5 应用添加一个 AVI 文件,你需要创建一个从基类派生的新实现类。 以下代码显示了一个支持 AVI 文件格式的示例。

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);
  }
}

我们在这里所做的是重写 IsWebExtension 方法,并实现对 AVI 文件格式的支持。 类似的逻辑可以应用于任何其他格式。

历史

  • 1.0.1 2011 年 10 月 - 第一个发布版本。
© . All rights reserved.