跳转到内容


在 Windows Phone 中集成 HTML5 以及 JavaScript

Windows Phone HTML5 Javascript

  • 您无法回复此主题
No replies to this topic

#1 冰力

    Administrator

  • 总版主
  • 1261 帖子数:

发表于 2012/03/30 13:15:51

这年头,到处都在讨论HTML5,我自己也在 Danish Developer Conference 2012 on Windows Phone and HTML5 大会上提到了它。我们也看到了 HTML5 的能力与优点。但是对于移动应用来说,HTML5 对此依然没有做好完全的准备。我一般是用原生开发模式来做一个能够充分使用手机平台特点的移动应用,而不是一个基于浏览器插件的 Web 应用程序。我认为开发者也应该更加热衷基于原生手机平台的开发。

今天这篇文章,我主要解释下如何在 Windows Phone 应用程序里集成 HTML5 + JavaScript 以及展示如何将 JavaScript 以及 .NET 进行互相调用。

所以,我们的学习步骤如下:
1,创建一个 Windows Phone Silverlight 程序。
2,在 MainPage 添加一个 WebBrowser 控件。
3,设置 WebBrowser 控件的 IsScriptEnabled 属性为 True
4,为 WebBrowser 控件的 ScriptNotify 事件添加处理方式。
5,创建一个名为 HTML 的文件夹,然后添加 HTML, JavaScript 以及 css 文件到这个文件夹中。
6,编写代码来将 HTML 的所有附属文件装载到 IsolatedStorage 中(独立存储)
7,设置 WebBrowser 的 Source 属性为主要 HTML 页

很简单。不是吗?

原理:
上面的这些步骤虽然看上去非常的简单。对于 JavaScript 来说,我们能用 window.external.notify() 方法来调用装载 WebBrowser 控件。window.external.notify() 方法传递一条包含描述你要浏览器控件来干什么的元数据字符串。
那么与之相反, .NET 来调用 JavaScript 代码时,我们可以使用 WebBrowser 控件的 InvokeScript() 方法。
InvokeScript() 方法将传递一条字符串参数给 Javascript, 用来描述 JavaScript 将如何执行, 以及一个字符串集合参数用来表示 JavaScript 将执行的方法使用的参数。如果你希望调用的 JavaScript 方法不是运行在UI线程上时(即想运行在后台线程时),最好的做法就是使用 InvokeScript("eval", "methodName(args1,args2,args3)") 而不是把第一个参数写成JavaScript 方法名称。

以下图表就是我在 DDC 2012 年展示刚才整个过程的示意图。
附加文件  DDC 2012 年展示刚才整个过程的示意图.jpg   70.27K   0 下载次数

对于下面这个示例,我们将创建一个使用浏览器控件加载HTML5页面的应用程序,用它来显示当前手机的内存信息(如图)。
附加文件  手机的内存信息.png   84.79K   0 下载次数

以下就是我们需要的代码:
Default.html (HTML5 + JavaScript)
以下代码就是本地的 html 文件,这个文件将被拷贝到独立存储中,我们需要将它放入到最开始创建的 HTML 文件夹中。



	<meta name="viewport" content="width=480, height=800, user-scalable=no">
	<meta name="MobileOptimized" content="width">
	<meta name="HandheldFriendly" content="true">
	<title>HTML5 and Windows Phone 7</title>
	<style>
		body
		{
			color: White;
			background-color: Black;
			font-family: 'Segoe WP Semibold';
			text-align: left;
		}
		h3
		{
			font-size: 20pt;
		}
		input
		{
			color: #ffffff;
			background-color: #000000;
			border: 2px solid white;
			vertical-align: baseline;
			font-size: 17pt;
			min-width: 40px;
			min-height: 40px;
			margin: 5;
		}
	</style>


	<div>
		<h3>
			Current memory usage:</h3>
		<input id="memoryUsage" value="0" type="text">
		<h3>
			Memory usage limit:</h3>
		<input id="memoryUsageLimit" value="0" type="text">
		<h3>
			Peak memory usage:</h3>
		<input id="peakMemoryUsage" value="0" type="text">
		<h3>
			Total memory:</h3>
		<input id="totalMemory" value="0" type="text">
	</div>
	


MainPage.xaml

<phone:phoneapplicationpage x:class="PhoneApp.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" loaded="PhoneApplicationPage_Loaded">

	<grid x:name="LayoutRoot" background="Transparent">
		<phone:webbrowser name="browser" isscriptenabled="True" source="HTML/Default.html" scriptnotify="browser_ScriptNotify">
	</phone:webbrowser></grid>

</phone:phoneapplicationpage>

MainPage.xaml.cs

[CODE]public partial class MainPage : PhoneApplicationPage
{
	public MainPage()
	{
		InitializeComponent();
	}

	private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
	{
		using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
		{
			if (!store.DirectoryExists("HTML")) store.CreateDirectory("HTML");
			CopyToIsolatedStorage("HTML\\Default.html", store);
		}
	}

	private static void CopyToIsolatedStorage(string file, IsolatedStorageFile store, bool overwrite = true)
	{
		if (store.FileExists(file) && !overwrite)
			return;

		using (Stream resourceStream = Application.GetResourceStream(new Uri(file, UriKind.Relative)).Stream)
		using (IsolatedStorageFileStream fileStream = store.OpenFile(file, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite))
		{
			int bytesRead;
			var buffer = new byte[resourceStream.Length];
			while ((bytesRead = resourceStream.Read(buffer, 0, buffer.Length)) > 0)
				fileStream.Write(buffer, 0, bytesRead);
		}
	}

	private void browser_ScriptNotify(object sender, NotifyEventArgs e)
	{
		var response = new object[]
					   {
						   DeviceStatus.ApplicationCurrentMemoryUsage,
						   DeviceStatus.ApplicationMemoryUsageLimit,
						   DeviceStatus.ApplicationPeakMemoryUsage,
						   DeviceStatus.DeviceTotalMemory
					   };
		browser.InvokeScript("getMemoryUsageCallback", response.Select(c => c.ToString()).ToArray());
	}
}

首先,MainPage 被加载,然后 html 文件夹的所有内容被拷贝到独立存储中,接着在 WebBrowser 控件中加载。当 ScriptNotify 事件被触发时,Silverlight 应用程序使用 DeviceStatus 类 检测硬件内存信息,最后在 WebBrowser 控件使用 InvokeScript() 方法来调用 getMemoryUsageCallback() 方法来显示内存信息。


好了,虽然上面这个示例非常简单基础,但是它展示了我们可以使用这个方法来完成很多意想不到的功能。我希望这对大家都有用。

以下就是完整的代码示例:
https://skydrive.live.com/redir.aspx?cid=ca531e7fb4762c70&resid=CA531E7FB4762C70!846&parid=CA531E7FB4762C70!172&authkey=!AIlgEO7SWk3fIeY