adobe air模拟器
Whoever said that the desktop was dead? Large sites such as eBay make available desktop applications for their web services due to the fact that they’re often more stable, more lightweight, and provide a smoother user experience.
谁说台式机坏了? 大型站点(例如eBay)通常可以更稳定,更轻巧,并提供更流畅的用户体验,因此可为Web服务提供桌面应用程序。
One of the big features of Adobe AIR is the rethink of Ajax – in particular, the cross-domain security restrictions. Before AIR, a web application could only make Ajax requests to the same domain from which it originated, with some exceptions. To fetch data from another domain, a server-side proxy script was needed to relay the request. In AIR, Adobe has enabled cross-domain Ajax requests to support the wide variety of potential uses of AIR applications that consume web services and interact with server-side applications. This opens the door for all sorts of handy mashups that operate entirely on the client side.
Adobe AIR的一大功能是对Ajax的重新思考-特别是跨域安全性限制。 在AIR之前,除了某些例外,Web应用程序只能向其起源的同一域发出Ajax请求。 要从另一个域获取数据,需要服务器端代理脚本来中继请求。 在AIR中,Adobe已启用跨域Ajax请求,以支持使用Web服务并与服务器端应用程序进行交互的AIR应用程序的各种潜在用途。 这为完全在客户端上运行的各种方便的混搭打开了大门。
In this article, we’re going to look at consuming web services from a simple PHP application – we’ll work with login mechanisms, file uploads, and reading an RSS news feed. We’ll be building a simple interface to enable a firm’s clients to log in and submit files, as well as browse internal notices from the newsfeed.
在本文中,我们将研究从简单PHP应用程序中使用Web服务的情况–我们将使用登录机制,文件上传以及阅读RSS新闻提要。 我们将构建一个简单的界面,使公司的客户可以登录并提交文件,以及浏览新闻源中的内部通知。
Continuing our recent theme, there’ll be a quiz at the end, to test you on what you’ve learned. The first 100 people to undergo the quiz will receive, free-of-charge, the Adobe AIR For JavaScript Developers pocket guide in the post. Remember, the book can be downloaded free as a PDF, so get cracking!
延续我们最近的主题,最后将进行测验 ,以测试您所学的内容。 帖子中的前100人将免费获得Adobe AIR For JavaScript Developers袖珍指南。 请记住,这本书可以PDF格式免费下载 ,所以快来破解吧!
NOTE: Background Knowledge To gain the most from this tutorial, I suggest you read through my introductory HTML/Ajax AIR articles, Build a Customer Management App and Build a Note Storage App, or are at least comfortable with AIR and jQuery. We’ll be using the AIR SDK again, along with Aptana and jQuery. If you haven’t set these up already, I cover this process in my first article, under the section A Powerful Tool for Building AIR Apps. For the purposes of this example, you’ll also need access to a PHP-enabled web server. Alternatively, you can rewrite the trivial PHP routines in your server-side language of choice.
注意:背景知识为了充分利用本教程,建议您通读我HTML / Ajax AIR入门文章, 构建客户管理应用程序和构建Note存储应用程序 ,或者至少对AIR和jQuery感到满意。 我们将再次使用AIR SDK ,以及Aptana和jQuery。 如果您尚未进行设置,那么我将在第一篇文章“构建AIR应用程序的强大工具”下介绍该过程。 就本示例而言,您还需要访问启用PHP的Web服务器。 另外,您可以用您选择的服务器端语言重写琐碎PHP例程。
To get ready to build the application, download the baseline project files. You’ll find a single HTML file with separate div elements for the key sections of the application interface – we’ll use jQuery to show and hide the relevant sections as needed. Open Aptana, and create a new project in the same directory that you extracted the baseline files, or use the “Existing Folder as New Project” in the File > Import dialog.
要准备构建该应用程序,请下载基准项目文件 。 您会在应用程序界面的关键部分找到一个带有单独的div元素HTML文件–我们将根据需要使用jQuery显示和隐藏相关部分。 打开Aptana,并在提取基准文件的目录中创建一个新项目,或者在“文件” >“导入”对话框中使用“现有文件夹作为新项目”。
The archive also includes a folder named serverfiles – you’ll need to upload these files to a PHP-enabled web server if you want to modify and experiment with the backend. Alternatively, you can create your own with the instructions in this tutorial. For now, we’ll use a hosted demonstration copy of these files.
该归档文件还包含一个名为serverfiles的文件夹-如果要修改和尝试后端,则需要将这些文件上传到启用PHP的Web服务器。 或者,您可以按照本教程中的说明创建自己的教程。 现在,我们将使用这些文件的托管演示副本。
Within our new project, all the action happens within the index.html file. Here’s a screenshot of the file with all the sections revealed.
在我们的新项目中,所有操作都在index.html文件中进行。 这是该文件的屏幕截图,其中显示了所有部分。
We’ll store all our behavior logic in the behavior.js JavaScript file.
我们将所有行为逻辑存储在behavior.js JavaScript文件中。
Now that we’ve got our AIR project ready and our interface in place, let’s start adding functionality with the APIs.
现在我们已经准备好AIR项目并准备好接口,让我们开始使用API添加功能。
Authentication
认证方式
The front line of our application is the authentication dialog. Creating our client-side login system is quite similar to creating a server-side login system, with a couple of exceptions: the authentication API is accessed over HTTP, and we have to take an extra level of care regarding sensitive data.
我们应用程序的第一行是身份验证对话框。 创建客户端登录系统与创建服务器登录系统非常相似,但有一些例外:身份验证API是通过HTTP访问的,我们必须特别注意敏感数据。
Here’s the HTML for our login form as it stands:
这是我们登录表单HTML:
<div class="form"> <div class="input"> <label for="username">Username</label> <input type="text" id="username"/> </div> <div class="input"> <label for="password">Password</label> <input type="password" id="password"/> </div> <div class="input"> <input type="submit" value="Login" id="loginbtn" /> </div> </div>Let’s open the behavior.js file and add some JavaScript. The file is currently empty, except for a $(document).ready() function with some basic interface management code. We’ll use this to bind to the form’s submit event, so that we can catch the user clicking that Login button. Inside the $(document).ready() function, add the following:
让我们打开behavior.js文件并添加一些JavaScript。 该文件当前为空,除了带有基本接口管理代码的$(document).ready()函数外。 我们将使用它来绑定到表单的submit事件,以便我们可以捕获单击“ 登录”按钮的用户。 在$(document).ready()函数内,添加以下内容:
server = 'http://bitmeta.org/air/'; $("#loginbtn").click(function(){ params = 'username='+$("#username").val()+'&password='+$("#password").val(); request = new air.URLRequest(server + 'loginService.php'); request.data = params; request.method = air.URLRequestMethod.POST; loader = new air.URLLoader(); loader.addEventListener(air.Event.COMPLETE, loginComplete); try { loader.load(request); } catch (error) { alert("Error connecting to login server."); } });We start by using jQuery to bind to the click event of our Login button (from the HTML snippet above). Here, we’re using two key AIR APIs: URLRequest, and URLLoader. URLRequest manages the request information – in our case, the URL to load, request method to use, parameters to pass and so on – while URLLoader handles the actual HTTP transfer and deals with the results. The request object has a data property that takes variables in name=value&name=value format, just like any POST request body. We really shouldn’t transmit the password in plaintext either, even though we do above – consider using HTTPS, client-side hashing, or both.
我们首先使用jQuery绑定到“ 登录”按钮的click事件(来自上面HTML代码段)。 在这里,我们使用两个关键的AIR API: URLRequest和URLLoader 。 URLRequest管理请求信息(在我们的示例中是要加载的URL,要使用的请求方法,要传递的参数等),而URLLoader处理实际的HTTP传输并处理结果。 与任何POST请求正文一样, request对象具有一个data属性,该属性接受name=value&name=value格式的变量。 即使我们如上所述,我们也确实不应该以纯文本形式传输密码-考虑使用HTTPS, 客户端哈希或两者都使用。
The loader object has a number of events, including request progress, identification of response status code, and IO error – see here for a full list. At present, we’re only interested in the completion of the request, and so we use the generic air.Event.COMPLETE to catch this, with the callback function: loginComplete.
加载程序对象有许多事件,包括请求进度,标识响应状态代码和IO错误-请参见此处以获取完整列表。 目前,我们只对请求的完成感兴趣,因此我们使用通用的air.Event.COMPLETE和回调函数air.Event.COMPLETE来捕获此loginComplete 。
We’ll receive an XML document from the web service, which we’ll handle with jQuery in a moment. For now, we’ll define our callback handler – insert this right after the previous block:
我们将从Web服务接收XML文档,稍后我们将使用jQuery处理该XML文档。 现在,我们将定义回调处理程序–将其插入到上一个代码块之后:
function loginComplete(event) { handleLogin(event.target.data); }With this line, we pass the XML response to our handleLogin function, and away we go!
在这一行中,我们将XML响应传递给handleLogin函数,然后我们就走了!
It’s time to start thinking about our server backend – our demonstration server runs at bitmeta.org/air/ with the username and password “test”.
现在是时候开始考虑我们的服务器后端了–我们的演示服务器以用户名和密码“ test”运行在bitmeta.org/air/上。
We referenced our callback function loginComplete, which is passed a single argument – an Event object. This has a target property, referring to the “target” of the event – the URLLoader – which in turn will always place the response body in its data property. Now, loginService.php will give us an XML response like this:
我们引用了回调函数loginComplete ,该函数传递了一个参数– Event对象。 它具有target属性,它是指事件的“ target ”( URLLoader ), URLLoader总是将响应主体置于其data属性中。 现在, loginService.php将给我们这样的XML响应:
<?xml version="1.0" encoding="utf-8"?> <response xmlns="https://www.sitepoint.com/air/a3/login"> <login code="LOGIN_PASS">4d0vncb4j41mpu...</login> <latestNews> <item> <heading>New Service: Data Migration</heading> <content>Understanding that our clients...</content> <guid>http://example.com/rss/article/1</guid> </item> <item> <heading>Security Breach!</heading> <content>On 1/1/1 we were made aware of a...</content> <guid>http://example.com/rss/article/2</guid> </item> </latestNews> </response>Within the login element is our session token; this is unique for each successful login. A login failure response looks like this:
在登录元素中是我们的会话令牌; 这对于每次成功登录都是唯一的。 登录失败响应如下所示:
<?xml version="1.0" encoding="utf-8"?> <response xmlns="https://www.sitepoint.com/air/a3/login"> <login code="LOGIN_FAIL"/> </response>All we need now is a handleLogin function to process this response. We’ll rely on jQuery to handle the tricky XML traversing and DOM manipulation here. Copy this into the very end of your behavior.js file:
现在我们需要的是一个handleLogin函数来处理此响应。 在这里,我们将依靠jQuery处理棘手的XML遍历和DOM操作。 将其复制到您的behavior.js文件的最后:
function handleLogin(data) { if ($("login", data).attr("code") == 'LOGIN_PASS') { air.trace('Our session token is '+$("#login", data).text()); $("#latestnews").empty(); $("latestNews item", data).each(function(i) { item = $("latestNews item", data).get(i); story = $('<div class="rssitem"></div>') .append('<span>'+$("heading",item).text()+'</span>'+ '<p>'+$("content",item).text()+'</p>'+ '<a href="'+$("guid",item).text()+'">Read More...</a>') .appendTo('#latestnews' }); $(".rssitem a").click(function(){ air.navigateToURL(new air.URLRequest(this.href)); return false; }) $("#login").hide(); $("#main").show(); } else { alert('Login Failed: Please Try Again.'); } }We first check whether the code="LOGIN_PASS" attribute value is present in the login element; if so, we record the session token we received on the console. We then empty the <div id="latestnews"> element on our main page and start filling it with the faux RSS entries included in the response. (Parsing a real RSS feed is similarly trivial.) At this point, we could also use Javascript’s usual DOM traversal functions – the data variable holds a perfectly normal XML document. To launch a URL in the default web browser (and not inside our AIR application), we need to call air.navigateToURL(new air.URLRequest(url)) – in this snippet, we use the hyperlink of the current object, as we’re binding to all the links in the news section.
我们首先检查login元素中是否存在code="LOGIN_PASS"属性值; 如果是这样,我们记录在控制台上收到的会话令牌。 然后,我们在主页上清空<div id="latestnews">元素,并开始使用响应中包含的伪RSS条目进行填充。 (解析一个真正的RSS feed同样很简单。)在这一点上,我们还可以使用Javascript常用的DOM遍历功能- data变量保存一个完全正常的XML文档。 要在默认的Web浏览器中(而不是在AIR应用程序中)启动URL,我们需要调用air.navigateToURL(new air.URLRequest(url)) –在此代码段中,我们将使用当前对象的超链接,绑定到新闻部分中的所有链接。
We use a lot of CSS selectors here – remember that the jQuery selector syntax, $("css selector", domdocument) will try to select elements matching the selector within the provided DOM document, defaulting to the current document. We specify our XML response document to set the context of the operation.
我们在这里使用了许多CSS选择器–请记住,jQuery选择器语法$ ( "css selector" , domdocument )将尝试在提供的DOM文档中选择与选择器匹配的元素,默认为当前文档。 我们指定XML响应文档来设置操作的上下文。
NOTE: Maintaining a Session In our login routine, we’re loading the authentication information as well as the latest news in one go. Often, however, you’ll need to make further HTTP requests after authentication. In our server script here, loginService.php includes a session ID of sorts. In our case it’s generated by PHP’s session extension, but it could just as well have been any login token. To persist with this in an AIR application, it’s quite feasible to store it in a variable upon receipt, and if needed, a cookie as well. Any JavaScript code in your application can then make use of this token by including it in future requests. Of course, if you use a cookie-based session mechanism, your application could leave the entire process to PHP, thus avoiding the need to store a session token; on the client side, the URL request libraries will automatically handle cookies for you.
注意:维护会话在我们的登录例程中,我们一次性加载了身份验证信息和最新消息。 但是,通常,在身份验证之后,您将需要发出更多的HTTP请求。 在此处的服务器脚本中, loginService.php包含各种会话ID。 在我们的例子中,它是由PHP的会话扩展生成的,但也可能是任何登录令牌。 为了在AIR应用程序中坚持下去,将其存储在接收到的变量中也是非常可行的,如果需要,还可以将其存储在cookie中。 然后,您的应用程序中的任何JavaScript代码都可以通过在以后的请求中包含此令牌来使用此令牌。 当然,如果您使用基于cookie的会话机制,则您的应用程序可以将整个过程留给PHP,从而避免了存储会话令牌的麻烦; 在客户端,URL请求库将自动为您处理Cookie。
Now that we’ve authenticated the user and displayed the latest news, all that’s left for us to do is enable the file upload feature. The typical and most convenient approach we can take is to use a plain old form. Just as we can use Ajax file uploads on a typical web page within Safari, we can do likewise in AIR. Unfortunately, it’s not quite that simple – an Ajax file upload doesn’t actually exist; the JavaScript XMLHttpRequest object can’t handle files. Most implementations of the concept involve redirecting the form to an iframe, and as AIR places security restrictions on remote content, this isn’t a reliable option for us.
现在我们已经验证了用户身份并显示了最新消息,剩下要做的就是启用文件上传功能。 我们可以采用的典型且最方便的方法是使用简单的旧表格。 正如我们可以在Safari的典型网页上使用Ajax文件上传一样,我们也可以在AIR中进行同样的操作。 不幸的是,它并不是那么简单–实际上不存在Ajax文件上传; JavaScript XMLHttpRequest对象无法处理文件。 该概念的大多数实现都涉及将表单重定向到iframe ,并且由于AIR对远程内容施加了安全限制,因此这对我们来说不是一个可靠的选择。
Instead, AIR provides an upload method within every File object. Given a reference to a file, we can upload with just a URLRequest object and the name of the faux form field of which the file should pretend to be a part. It will then make an HTTP request, as per the URLRequest data; the only real limitation is that we can’t handle the response – we have to make a second request to list our files after the upload.
而是,AIR在每个File对象中提供一个上载方法。 给定对文件的引用,我们可以仅上传一个URLRequest对象以及该文件应假装为其中的人造表单字段的名称。 然后,它将根据URLRequest数据发出一个HTTP请求; 唯一真正的限制是我们无法处理响应-上传后,我们必须再次提出请求以列出文件。
Here’s how our form appears at this point:
此时,我们的表单显示如下:
<div class="form"> <div class="input"> <input type="file" name="file" id="file" /> <input type="submit" value="Upload" id="uploadbtn" /> </div> </div>To implement Ajax for the file upload, we just work out when that upload button is clicked, construct a File object, construct a URLRequest object, and then upload the File object to the URLRequest. Just inside the end of the $(document).ready block in the behavior.js file, add the following:
为了实现文件上传的Ajax,我们只需计算一下单击该上传按钮的时间,构造一个File对象,构造一个URLRequest对象,然后将File对象上传到URLRequest 。 在behavior.js文件中$(document).ready块的末尾,添加以下内容:
$("#uploadbtn").click(function(){ filePath = $("#file").val(); file = air.File.userDirectory.resolvePath(filePath); request = new air.URLRequest(server + 'uploadService.php'); request.method = air.URLRequestMethod.POST; request.data = "token="+sid; file.addEventListener(air.Event.COMPLETE, uploadComplete); file.upload(request, "AIRfile"); });The form field with the id “file” has a value corresponding to the appropriate file path. The first two lines in this block calculate that file path, and give us an air.File object (in the variable: file) pointing to the file the user has chosen; it’s this File object that will manage the upload. We then construct our request variable, pointing it to our upload web service and passing in our session ID stored in sid. Finally, we bind the uploadComplete function as a callback to the air.Event.COMPLETE event and then upload the file.
id “ file”的表单字段的值对应于相应的文件路径。 该块的前两行计算该文件路径,并为我们提供air.File对象(在变量: file ),该对象指向用户选择的文件; 正是这个File对象将管理上传。 然后,我们构造请求变量,将其指向我们的上载Web服务,并传递存储在sid中的会话ID。 最后,我们将uploadComplete函数作为回调绑定到air.Event.COMPLETE事件,然后上传文件。
Our server-side upload script
我们的服务器端上传脚本
Let’s have a look at the upload service in serverfiles/uploadService.php. Here’s the PHP code:
让我们看看serverfiles/uploadService.php中的上载服务。 这是PHP代码:
<?php session_start(); if (empty($_FILES['AIRfile']) && !empty($_SESSION['latestfile'])) { echo "<li>$_SESSION[latestfile]</li>n"; } if (!empty($_FILES['AIRfile'])) { $_SESSION['latestfile'] = $_FILES['AIRfile']['name'] . ' - ' . $_FILES['AIRfile']['size']; exit; } ?> <li><?php print_r($_REQUEST); ?></li> <li><a href="http://bitmeta.org/air/dump/example.txt">example.txt</a></li> <li>Your session token is <?=$_REQUEST['token']?></li>This script first initializes the session handler, and checks to see if a “latestfile” variable has been stored for the current user. If so, we output it. Next, we check if any files are being uploaded – here, we don’t upload any files, as this is a demonstration server. If a file is being uploaded, we set that latestfile session variable, so that it will be visible the next time we check back; we then end the script there. If the script continues past this point:
该脚本首先初始化会话处理程序,然后检查是否为当前用户存储了“ latestfile ”变量。 如果是这样,我们将其输出。 接下来,我们检查是否有任何文件正在上传–在这里, 我们没有上传任何文件 ,因为这是一个演示服务器。 如果文件正在上传,我们将设置该latestfile会话变量,以便下次我们再次查看时可以看到该变量; 然后,我们在此处结束脚本。 如果脚本继续到这一点:
exit; }We know that we’re not currently uploading a file, but are instead checking back after uploading a file. We then proceed to output some sample information for the end user.
我们知道我们当前不上传文件,而是在上传文件后进行检查。 然后,我们为最终用户输出一些样本信息。
Checking back after the upload
上传后再检查
Now that we’ve uploaded the file, we need to check back to grab the current list of files from the server. We used a callback function in behavior.js here:
现在,我们已经上传了文件,我们需要返回查看以从服务器获取当前文件列表。 我们在这里的behavior.js使用了回调函数:
file.addEventListener(air.Event.COMPLETE, uploadComplete);We now need to write that uploadComplete function. Add the following code inside the $("#uploadbtn").click(function(){ block:
现在,我们需要编写该uploadComplete函数。 在$("#uploadbtn").click(function(){块内)中添加以下代码:
function uploadComplete(event) { request = new air.URLRequest(server + 'uploadService.php'); request.data = "token="+sid; loader = new air.URLLoader(); loader.addEventListener(air.Event.COMPLETE, statusComplete); try { loader.load(request) } catch (error) { air.trace("Could not retrieve file list."); } function statusComplete(event) { $("#filelist").html(event.target.data); } }This makes another call to uploadService.php, passing in the session ID – only this time we use a URLLoader object as we want to read the response. The uploadService.php script will output a series of <li> tags for our list, so we use the html jQuery function to take the response body – in loader.data, or event.target.data inside the callback – and place it straight into our <ul id="filelist"> on the page. When we run this script with a sample robots.txt file, the result appears as expected.
这再次调用了uploadService.php ,并传入了会话ID –仅在这一次,我们使用URLLoader对象来读取响应。 uploadService.php脚本将为列表输出一系列<li>标记,因此我们使用html jQuery函数获取响应主体(在loader.data或回调中的event.target.data并将其直接放置进入页面上的<ul id="filelist"> 。 当我们使用示例robots.txt文件运行此脚本时,结果将按预期显示。
And we’re done! You can download our completed behavior.js file from the code archive.
我们完成了! 您可以从代码档案下载我们完整的behavior.js文件。
Now that we’ve completed a simple web-enabled AIR application, you’re ready to take your web applications and services beyond the browser. You might find these handy references useful in further exploring the topics we’ve covered:
现在,我们已经完成了一个简单的,支持Web的AIR应用程序,您可以将Web应用程序和服务带到浏览器之外。 您可能会发现这些方便的参考资料对进一步探讨我们涵盖的主题很有用:
Working with external data
处理外部数据
Using the URL Request class
使用URL Request类
Working with File objects
使用File对象
Language reference – URLLoader samples
语言参考– URLLoader示例
Available events on async URLLoader loads
async URLLoader上的可用事件加载
You can test your comprehension of this tutorial with a short quiz, and stand to receive a FREE copy of the pocket guide, Adobe AIR For JavaScript Developers, for your efforts. The guide will be delivered FREE, courtesy of Adobe Systems, but this offer is only available to the first 100 people, so get in quick! (If you do miss out, you can still download the book in PDF format for free.)
您可以通过简短的测验来测试您对本教程的理解,并为您的努力免费获得袖珍指南Adobe AIR For JavaScript Developers的副本。 该指南将免费提供(由Adobe Systems提供),但是此优惠仅适用于前100人,因此请尽快入手! (如果您错过了,您仍然可以免费下载PDF格式的书。)
Take the quiz!
参加测验!
翻译自: https://www.sitepoint.com/learn-adobe-air-part-3/
adobe air模拟器
相关资源:adobeAir开发工具