×
Namespaces

Variants
Actions

混合 - 移动设备应用

From Nokia Developer Wiki
Jump to: navigation, search
WP Metro Icon Porting.png
SignpostIcon WP7 70px.png
Article Metadata

兼容于
文章
翻译:
WS_YiLunLuo
最后由 hamishwillee 在 27 Jun 2013 编辑

本文翻译自:Hybrid - Applications for Mobile 在这篇文章中,我们将会学习如何使用HTML5、jQuery和CSS来跨平台/混合应用程序。

Contents

简介

在这篇文章中,我们将会学习如何为多个移动平台(如Symbian、Windows Phone 7、iOS和BlackBarry等等)开发一个混合应用程序。在这篇文章中,我将针对Nokia的Lumia Windows Phone 7平台开发一个混合应用程序。混合应用程序基本上使用 HTML5、JavaScript和CSS、本地API实现 跨平台(应用程序)。

一般情况

在开发混合项目之前让我们介绍一下混合移动应用程序开发的基本混合架构。

002 hybrid design architecture.png

混合架构:-混合架构允许开发者在一个单一的应用程序中使用混合技术,例如HTML5、CSS3、JavaScript和本地移动平台功能(结合本地组件和Web组件)。这就叫做混合移动应用程序。移动平台混合架构最核心的优势是RAD(Rapid Application Development,快速应用开发),代码的重复利用;多个移动平台的一致性UX(User Experience,用户体验),使用唯一代码库;最重要的是代码可以跨多个移动平台重复利用和共享。优良的设备本地服务集成,支持在线/离线操作。

003 - hybrid design architecture.png

  • HTML5:- HTML 5表示超文本标记语言,HTML 5是通过Web显示内容的核心技术。HTML 5是HTML最新版本。
  • CSS3:- CSS表示层叠样式表,提供了网页格式化指令。CSS3是它的最新版本。
  • JavaScript:-JavaScript是一种解释性语言,用来编写智能(代码)在客户端浏览器中显示动态控件,弹出警告对话框等等。
  • SPA: - SPA表示(Single Page Application,单页面应用程序);SPA是一种为移动浏览器开发Web应用程序的方法。它允许好的UX(用户体验),快速UI(User Interface,用户界面)导航,它会在第一次请求中下载所有的请求数据到客户端,然后将之存储在浏览器缓存中。

基线

这里我们将要涉及集成HTML5到移动本机应用程序,嵌入HTML5到Windows Phone应用程序。下面是将要涉及到的功能:-

  • 相机
  • 单页面应用程序
  • Canvas,画板
  • 地理位置
  • 加速器

使用移动jQuery框架(HTML5、jQuery和CSS)为移动设备开发/设计web页面时,需要记住的重点:

1. <!DOCTYPE>声明必须在<html>标签之前。<!DOCTYPE html>

2. 使用meta标签控制小型设备的屏幕。

<meta name="viewport" content="width=device-width, initial-scale=1" />

这里view port 是一个可以控制网页大小和缩放的虚拟窗口。

3. 需要拥有相同版本的jQuery和CSS。

在此应用程序中,嵌入一些html页面,然后在Windows Phone 7本机应用程序中使用。

步骤1:使用传统方式创建Windows Phone 应用程序

创建Windows Phone 应用程序,使用传统方式。文件 -> 新建项目 -> 选择Silverlight for Windows Phone7模板,选择“Windows Phone应用程序”

004 HMA vs project.png

步骤2:创建一个目录

  • apphtml – 此目录将会保存所有的HTML5页面
  • apphtml/jsAndcss - 此目录将会保存此项目中JavaScript和CSS

005 HMA vs solution.png

步骤3: 添加一个手机WebBrowser控件至Mainpage.xaml

在grid的根元素中添加一个WebBrowser控件,渲染所有的HTML页面至手机WebBrowser控件。

请看以下Xaml页面代码,添加手机WebBrowser控件,设置必须的属性和事件。例如IsGeolocationEnabled= true,IsScriptEnabled = true和ScriptNotify事件。IsGeolocationEnabled属性允许获取当前地理位置(经度和纬度),IsScriptEnabled属性允许在手机WebBrowser控件执行JavaScript,默认的它是被禁用的,ScriptNotify事件在Javascript调用之后被触发。

XAML代码片段:

<Grid x:Name="LayoutRoot" Background="Transparent">
<phone:WebBrowser IsGeolocationEnabled="True"
Source="apphtml/myPage.html"
IsScriptEnabled="True"
ScriptNotify=" webBrowser1_ScriptNotify"
Name="webBrowser1"
Height="auto" Width="auto" />
</Grid>

设计视图中的用户界面

006 HMA design view.png

步骤4: 使用jQuery Mobile和CSS创建HTML5页面。在这个项目中我们为每个功能点编写以下HTML页面。使用以下目录结构,将所有的HTML页面保存至/apphtml目录,所有的Javascript和CSS保存至/apphtml/jsAndcss路径。

/apphtml

  • Default.html
  • MobileCamera.html
  • Two.html
  • Canvas.html
  • GeoLocation.html
  • Accelerometer.html

/apphtml/jsAndcss

  • jquery-1.6.4.min.js
  • jquery.mobile-1.0.min.css
  • jquery.mobile-1.0.min.js
  • MobileAppStyles.css
这里是所有的jQuery mobile文件

- Default.html

<!DOCTYPE html>
<html class="ui-mobile">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Hybrid App</title>
<!-- Js -->
<link rel="stylesheet" href="jsAndcss/jquery.mobile-1.0.min.css" />
<script type="text/javascript" src="jsAndcss/jquery-1.6.4.min.js"></script>
<script type="text/javascript" src="jsAndcss/jquery.mobile-1.0.min.js"></script>
</head>
<body class="ui-mobile-viewport">
<!-- first page: one -->
<div data-role="page" id="one" data-url="one" tabindex="0" class="ui-page ui-body-c ui-page-active"
style="min-height: 200px;">
<!-- start page header section -->
<div data-role="header" class="ui-header ui-bar-a" role="banner">
<h1 class="ui-title" tabindex="0" role="heading" aria-level="1">
Main Menu</h1>
</div>
<!-- end page header section -->
<!-- start page content section -->
<div data-role="content" class="ui-content" role="main">
<h2>
HTML 5</h2>
<p>
<a href="MobileCamera.html" rel="external" data-role="button" data-theme="c" class="ui-btn ui-btn-corner-all ui-shadow ui-btn-up-c">
<span class="ui-btn-inner ui-btn-corner-all"><span class="ui-btn-text">Camera</span></span></a></p>
<p>
<a href="two.html" rel="external" data-role="button" data-theme="c" class="ui-btn ui-btn-corner-all ui-shadow ui-btn-up-c">
<span class="ui-btn-inner ui-btn-corner-all" aria-hidden="true"><span class="ui-btn-text">
Single page</span></span></a>
</p>
<p>
<a href="GeoLocation.html" rel="external" data-role="button" data-theme="c" class="ui-btn ui-btn-corner-all ui-shadow ui-btn-up-c">
<span class="ui-btn-inner ui-btn-corner-all" aria-hidden="true"><span class="ui-btn-text">
Geo-Location</span></span></a>
</p>
<p>
<a href="Canvas.html" rel="external" data-role="button" data-theme="c" class="ui-btn ui-btn-corner-all ui-shadow ui-btn-up-c">
<span class="ui-btn-inner ui-btn-corner-all" aria-hidden="true"><span class="ui-btn-text">
Canvas</span></span></a></p>
<p>
<a href="Accelerometer.html" rel="external" data-role="button" data-theme="c" class="ui-btn ui-btn-corner-all ui-shadow ui-btn-up-c">
<span class="ui-btn-inner ui-btn-corner-all" aria-hidden="true"><span class="ui-btn-text">
Accelerometer</span></span></a></p>
</div>
<!-- end page content section -->
<!-- start page footer section -->
<div data-role="footer" data-theme="a" class="ui-footer ui-bar-d" role="contentinfo">
<h4 class="ui-title" tabindex="0" role="heading" aria-level="1">
@WmDev</h4>
</div>
<!-- end page footer section -->
</div>
</body>
</html>

- MobileCamera.html

<!DOCTYPE html>
<html class="ui-mobile">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<title>Hybrid App</title>
<!-- -->
<link rel="stylesheet" href="jsAndcss/jquery.mobile-1.0.min.css" />
<script type="text/javascript" src="jsAndcss/jquery-1.6.4.min.js"></script>
<script type="text/javascript" src="jsAndcss/jquery.mobile-1.0.min.js"></script>
<script type="text/javascript">
function capturePicture() {
window.external.notify("capturePicture");
}
 
function captureImageCallback(src) {
//window.external.notify("Log: capturePicture(" + src + ")");
document.getElementById("imgPic").src = src;
}
</script>
</head>
<body onload="onLoad()">
<div data-role="page" id="one" data-url="one" tabindex="0" class="ui-page ui-body-c ui-page-active"
style="min-height: 200px;">
<!-- start header -->
<div data-role="header" class="ui-header ui-bar-a" role="banner">
<h1 class="ui-title" tabindex="0" role="heading" aria-level="1">
Mobile Camera</h1>
</div>
<!-- end header -->
<!-- start content -->
<div data-role="content" class="ui-content" role="main">
<h2>
HTML 5</h2>
<p>
<a href="#" data-role="button" onclick="capturePicture()" data-theme="c" class="ui-btn ui-btn-corner-all ui-shadow ui-btn-up-c">
<span class="ui-btn-inner ui-btn-corner-all"><span class="ui-btn-text">Camera</span></span></a></p>
<p>
<img alt="capture picture" id="imgPic" width="300px" height="240px" />
</p>
</div>
<!-- end content -->
<!-- start footer -->
<div data-role="footer" data-theme="d" class="ui-footer ui-bar-d" role="contentinfo">
<h4 class="ui-title" tabindex="0" role="heading" aria-level="1">
@WmDev</h4>
</div>
<!-- end footer -->
</div>
</body>
</html>

-Two.html

<!DOCTYPE html>
<html class="ui-mobile">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<title>Single Page App</title>
<!-- -->
<link rel="stylesheet" href="jsAndcss/jquery.mobile-1.0.min.css">
<script src="jsAndcss/jquery-1.6.4.min.js"></script>
<script src="jsAndcss/jquery.mobile-1.0.min.js"></script>
</head>
<body class="ui-mobile-viewport">
<!-- Start of first page: #one -->
<div data-role="page" id="one" data-url="one" tabindex="0" class="ui-page ui-body-c ui-page-active"
style="min-height: 624px;">
<div data-role="header" class="ui-header ui-bar-a" role="banner">
<h1 class="ui-title" tabindex="0" role="heading" aria-level="1">
Multi-page</h1>
</div>
<!-- /header -->
<div data-role="content" class="ui-content" role="main">
<p>
<a href="Default.html" rel="external" data-role="button" data-theme="c" class="ui-btn ui-btn-corner-all ui-shadow ui-btn-up-c">
<span class="ui-btn-inner ui-btn-corner-all" aria-hidden="true"><span class="ui-btn-text">
Page "two"</span></span></a>
</p>
<p>
<a href="Default.html" rel="external" data-role="button" data-theme="c" class="ui-btn ui-btn-corner-all ui-shadow ui-btn-up-c">
<span class="ui-btn-inner ui-btn-corner-all" aria-hidden="true"><span class="ui-btn-text">
Back</span></span></a></p>
</div>
<!-- /content -->
<div data-role="footer" data-theme="d" class="ui-footer ui-bar-d" role="contentinfo">
<h4 class="ui-title" tabindex="0" role="heading" aria-level="1">
Page Footer</h4>
</div>
<!-- /footer -->
</div>
<!-- /page one -->
</body>
</html>

-Canvas.html

<!DOCTYPE html>
<html class="ui-mobile">
<head>
<meta name="MobileOptimized" content="width" />
<meta name="HandheldFriendly" content="true" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Hybrid App</title>
<link rel="stylesheet" href="jsAndcss/jquery.mobile-1.0.min.css" />
<script src="jsAndcss/jquery-1.6.4.min.js"></script>
<script src="jsAndcss/jquery.mobile-1.0.min.js"></script>
</head>
<body>
<div id="container">
<div data-role="header" class="ui-header ui-bar-a" role="banner">
<h1 class="ui-title" tabindex="0" role="heading" aria-level="1">
Canvas</h1>
</div>
<div>
<canvas id="appCanvas" width="400" height="350" style="border: 2px solid #c3c3c3;">
Your browser does not support the canvas element.
</canvas>
<p>
<a href="Default.html" rel="external" data-role="button" data-theme="c" class="ui-btn ui-btn-corner-all ui-shadow ui-btn-up-c">
<span class="ui-btn-inner ui-btn-corner-all" aria-hidden="true"><span class="ui-btn-text">
Back</span></span></a>
</p>
</div>
<div data-role="footer" data-theme="d" class="ui-footer ui-bar-d" role="contentinfo">
<h4 class="ui-title" tabindex="0" role="heading" aria-level="1">
Page Footer</h4>
</div>
<!-- /footer -->
<script type="text/javascript">
// --------------- Rectangle -----------------------
var objCanvas = document.getElementById("appCanvas");
var context = objCanvas.getContext("2d");
context.fillStyle = "#FF00EE";
context.fillRect(75, 37, 150, 75);
 
// --------------- Circle -----------------------
context.fillStyle = "#FF0000";
context.beginPath();
context.arc(275, 80, 15, 0, Math.PI * 2, true);
context.closePath();
context.fill();
 
// --------------- Triangle -----------------------
var width = 125; // Triangle Width
var height = 105; // Triangle Height
var padding = 20;
// Draw a path
context.beginPath();
context.moveTo(padding + width / 2, padding); // Top Corner
context.lineTo(padding + width, height + padding); // Bottom Right
context.lineTo(padding, height + padding); // Bottom Left
context.closePath();
// Fill the path
context.fillStyle = "#BBAACC";
context.fill();
 
 
// --------------- Text -----------------------
var context = objCanvas.getContext("2d");
 
var lineHeight = 25;
var x = (objCanvas.width - 300) / 2;
var y = 200;
var text = "Hello this Hybrid Application";
context.font = "16pt Calibri";
context.fillStyle = "#333";
context.fillText(text, x, y);
 
// --------------- Image -----------------------
 
var imageObj = new Image();
 
imageObj.onload = function () {
context.drawImage(imageObj, 69, 220);
};
imageObj.src = "http://www.developer.nokia.com/dynamic/profile/photo.html?size=78&username=pavan.pareta&status=private";
</script>
</body>
</html>

-GeoLocation.html

<!DOCTYPE html>
<html>
<head>
<title>Geo Location</title>
<meta name="viewport" content="width=device-width, height=device-height initial-scale=1, user-scalable=yes" />
<!-- <meta name="viewport" content="width=480, height=800, user-scalable=yes" />-->
<meta name="MobileOptimized" content="width" />
<meta name="HandheldFriendly" content="true" />
<link href="jsAndcss/MobileAppStyles.css" rel="Stylesheet" />
<script type="text/javascript">
function getLocation() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(showPosition);
navigator.geolocation.watchPosition(showPosition);
}
}
 
function showPosition(position) {
var latlon = position.coords.latitude + "," + position.coords.longitude;
var img = new Image();
img.width = 300;
img.height = 500;
img.src = "http://maps.googleapis.com/maps/api/staticmap?center=" + latlon + "&zoom=16&size=300x500&scale=2&markers=color:green%7CLabel:A%7C" + latlon + "&sensor=false";
img.onload = function () {
var ctx = document.getElementById("geocanvas").getContext("2d");
ctx.drawImage(img, 0, 0, 300, 500);
};
}
</script>
</head>
<body id="background" onload="getLocation()">
<div id="container">
<div id="mapholder">
<canvas id="geocanvas" height="800" width="480">
</canvas>
</div>
</div>
</body>
</html>

-Accelerometer.html

<!DOCTYPE html>
<html class="ui-mobile">
<head>
<meta name="MobileOptimized" content="width" />
<meta name="HandheldFriendly" content="true" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<title>Hybrid App</title>
<link rel="stylesheet" href="jsAndcss/jquery.mobile-1.0.min.css" />
<script src="jsAndcss/jquery-1.6.4.min.js"></script>
<script src="jsAndcss/jquery.mobile-1.0.min.js"></script>
</head>
<body id="background" onload="onLoad()">
<div id="container">
<h3>
Accelerometer</h3>
<input id="sensorX" type="text" value="0" />
<input id="sensorY" type="text" value="0" />
<input id="sensorZ" type="text" value="0" />
</div>
<script type="text/javascript">
function onLoad() {
window.external.notify("StartAccelerometer");
}
var sensorX = document.getElementById("sensorX");
var sensorY = document.getElementById("sensorY");
var sensorZ = document.getElementById("sensorZ");
 
function CallbackAccelerometer(x, y, z) {
sensorX.value = x;
sensorY.value = y;
sensorZ.value = z;
}
</script>
</body>
</html>

MobileCamera.html的HTML页面代码解释:在此HTML中我们使用Javascript调用移动设备的相机。有一个工作流通过Javascript来调用本地功能。

步骤5: 应用程序和Javascript之间交流

下面是三个核心方法和事件,他们通过Javascript让HTML和Silverlight沟通。 1. 在HTML文件中的window.external.notify(“<data>”) 2. Silverlight应用程序中的WebBrowser.ScriptNotify 3. Silverlight应用程序中的WebBrowser.InvokeScript()

Web browser通过window.external.notify(“<data>”)异步调用应用程序,无论何时,在Silverlight应用程序中触发的WebBrowser.ScriptNotify事件控制和执行本地操作,而且通过WebBrowser.InvokeScript()事件请求返回结果。这个方法一般有一个JavaScript方法名作为参数,允许你使用WebBrowser.InvokeScript()在应用程序和JavaScript的回传之间通信。当OnScriptNotify 事件发生时这是一个相反的通信过程。在我们的例子中,我们使用WebBrowser.InvokeScript("javascript方法名", "string类型参数列表");.

插件架构 007 HMA javascriptfllowdiagram.png

MainPage.cs

private void browser_ScriptNotify(object sender, NotifyEventArgs e)
{
try
{
var request = JavascriptRequestHandler.Create(e.Value);
var command = BrowserInteropCommandFactory.Create(request);
command.Invoke(webBrowser1);
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
}

在C#代码中实现ScriptNotify以回传(这里是从JavaScript的window.external.notify()接收一个请求),NotifyEventArgs保存有一个请求,在以下代码片段中我们有一个java请求控制类来解析请求并传给BrowserInteropCommandFactory类,然后命令工厂和browser.InvokeScript()调用各自的方法。

MainPage.cs

private void browser_ScriptNotify(object sender, NotifyEventArgs e)
{
try
{
var request = JavascriptRequestHandler.Create(e.Value);
var command = BrowserInteropCommandFactory.Create(request);
command.Invoke(webBrowser1);
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
}

JavascriptRequestHandler.cs

public class JavascriptRequestHandler
{
public string MethodName { get; set; }
public IList<object> Arguments { get; set; }
 
public static JavascriptRequestHandler Create(string javascriptArgumentString)
{
var parameters = javascriptArgumentString.Split('|');
var javascriptArgument = new JavascriptRequestHandler { MethodName = parameters[0] };
 
if (parameters.Length == 1)
return javascriptArgument;
 
javascriptArgument.Arguments = new List<object>(parameters.Length - 2);
for (var i = 1; i < parameters.Length; i++)
javascriptArgument.Arguments.Add(parameters[i]);
 
return javascriptArgument;
}
}

BrowserInteropCommandFactory.cs

public static class BrowserInteropCommandFactory
{
public static BrowserInteropCommand Create(JavascriptRequestHandler request)
{
switch (request.MethodName.ToUpperInvariant())
{
case "CAPTUREPICTURE":
return new CameraCommand(request);
case "STARTACCELEROMETER":
return new AccelerometerCommand(request);
 
default:
throw new NotImplementedException("The method request by the browser component is not implemented");
}
}
}

CameraCommand.cs

public class CameraCommand : BrowserInteropCommand
{
public CameraCommand(JavascriptRequestHandler jsRequest) : base(jsRequest){ }
 
 
public override void Invoke(WebBrowser browser)
{
var photoCameraCapture = new CameraCaptureTask();
photoCameraCapture.Completed += (sender, result) =>
{
if (result.TaskResult != TaskResult.OK)
return;
SaveToIsolatedStorage(result.ChosenPhoto, "apphtml\\capture.jpg");
browser.InvokeScript("captureImageCallback", "capture.jpg");
};
photoCameraCapture.Show();
}
 
private void SaveToIsolatedStorage(Stream imageStream, string fileName)
{
using (var store = IsolatedStorageFile.GetUserStoreForApplication())
{
if (store.FileExists(fileName))
store.DeleteFile(fileName);
 
using (var fileStream = store.CreateFile(fileName))
{
var bitmap = new BitmapImage();
bitmap.SetSource(imageStream);
 
var wb = new WriteableBitmap(bitmap);
wb.SaveJpeg(fileStream, wb.PixelWidth, wb.PixelHeight, 0, 100);
}
}
}
}

步骤6: 在本机应用程序中装载HTML、JS和CSS文件到应用程序Isolated存储区。

在本机应用程序域中,复制所有HTML、JS和CSS文件到各自目录再到Isolated存储,这很重要。在这个示例应用程序中使用到的这些HTML页面都是嵌入的。

重要的是,在解决方案资源管理器中选择所有的HTML页面,按下F4键,设置Build Action - Embedded Resource,Copy to output directory – Copy always ,同时设置所有的javascript和CSS文件Build Action – Content

008 HMA page-property.png

现在在MainPage构造方法中,使用C#代码添加加载事件,实现复制所有HTML、JavaScript和CSS文件的代码。

// Constructor
public MainPage()
{
InitializeComponent();
Loaded += new RoutedEventHandler(MainPage_Loaded);
}
 
 
// Loaded event
void MainPage_Loaded(object sender, RoutedEventArgs e)
{
using (var store = IsolatedStorageFile.GetUserStoreForApplication())
{
//-----------------------------------------------------------
// Must copy all html, css and js files in the ISO
//-----------------------------------------------------------
if (!store.DirectoryExists("apphtml")) store.CreateDirectory("apphtml");
CopyToIsolatedStorage("apphtml\\myPage.html", store);
CopyToIsolatedStorage("apphtml\\two.html", store);
CopyToIsolatedStorage("apphtml\\GeoLocation.html", store);
CopyToIsolatedStorage("apphtml\\MobileCamera.html", store);
CopyToIsolatedStorage("apphtml\\Accelerometer.html", store);
CopyToIsolatedStorage("apphtml\\Canvas.html", store);
CopyToIsolatedStorage("apphtml\\Pages-Multi.html", store);
 
if (!store.DirectoryExists("apphtml\\jsAndcss")) store.CreateDirectory("apphtml\\jsAndcss");
CopyToIsolatedStorage("apphtml\\jsAndcss\\jquery-1.6.4.min.js", store);
CopyToIsolatedStorage("apphtml\\jsAndcss\\jquery.mobile-1.0.min.js", store);
CopyToIsolatedStorage("apphtml\\jsAndcss\\jquery.mobile-1.0.min.css", store);
CopyToIsolatedStorage("apphtml\\jsAndcss\\MobileAppStyles.css", store);
 
}
}
 
private static void CopyToIsolatedStorage(string file, IsolatedStorageFile store, bool overwrite = true)
{
if (store.FileExists(file) && !overwrite)
return;
 
using (var resourceStream = Application.GetResourceStream(new Uri(file, UriKind.Relative)).Stream)
using (var 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);
}
}

步骤6: 按下F5键或者菜单选项 调试-> 开始调试。

输出屏幕 Hma-wmdev.gif

This page was last modified on 27 June 2013, at 08:19.
172 page views in the last 30 days.