WPWidgetLibrary Windows Phone 7 Mango 的 HTML5 小部件





5.00/5 (4投票s)
在 Windows Phone 7 Mango 上以离线模式实现 HTML5 Widget 应用。
引言
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。
- 在你的 WP7.1 项目中引用 WPWidgetLibrary DLL。
- 将你的 HTML (App) 复制到某个项目文件夹,并将构建操作中的所有文件标记为
EmbeddedResource
。 - 从工具箱中,拖动
WebBrowser
控件,并在PageLoaded
事件中,导航到所需的网页。(参见 XAML 文件中的红色矩形。) - 在
MainPage
构造函数中,附加以下代码。 此代码将在应用程序启动时,将所有 HTML 相关内容复制到独立存储。 字符串数组(InstallHTMLContent
的第二个参数)应包含必须也复制到独立存储的项目的全部子文件夹。 如果你的应用非常简单,所有文件都在一个文件夹中,则不需要此参数。 - 在你的
MainPage
xaml.cs 的构造函数中,放入以下代码 - 从代码隐藏中的
MainPage
Loaded
事件将初始页面设置为WebBrowser
控件。 以下代码是常见的WebBrowser
代码,用于开始浏览页面。 请注意,导航页面 (StartPage.htm) 不是托管在网上的页面。 它是独立存储中的页面。 - 编译并运行该应用程序,你正在查看一个功能齐全的 HTML Widget 应用程序。
var wdgt = new WPWidgetLibrary();
wdgt.InstalHTMLContent("HTML", new string[]
{ "js/jQueryMobile/images",
"SubContent/SubSubContent",
});
void MainPage_Loaded(object sender, RoutedEventArgs e)
{
//Navigate to initial page of the HTML app
webBrowser1.Navigate(new Uri("StartPage.htm", UriKind.Relative));
}
库的自定义
默认情况下,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 月 - 第一个发布版本。