IntroductionWelcome| 00:00 | Welcome, I'm really glad you are here for this series and whether
you're just curious about AIR or if you've already built an application,
| | 00:07 | I really believe you can get a lot out of this series.
| | 00:10 | AIR provides so much new functionality for Flash developers.
And I am really excited to see the kind of applications that
| | 00:16 | will be coming out over the next year.
| | 00:18 | Now you maybe wondering, how am I connected with AIR? Well,
I am an AIR, Flash and Flex developer from Savannah, Georgia
| | 00:24 | and I have been working with AIR since its
early days when it was still called the Apollo.
| | 00:28 | I'm also a writer at insideria.com where I blog about AIR and
its affect on rich internet application landscape. I'm also a
| | 00:35 | contributor to the Adobe AIR Developer Center as well as
maintaining my own blog at davidtucker.net, where I focus on AIR
| | 00:41 | related projects. Now I hope that you are as
excited about the possibilities with AIR as I am.
| | Collapse this transcript |
| Using the example files| 00:01 | Just a quick word about the exercise files that we'll be using.
| | 00:04 | If you're a premium member of the lynda.com Online Training Library
| | 00:08 | or if you're watching this tutorial on a disc, you have
access to the exercise files used throughout the title.
| | 00:13 | In the Exercise Files folder, I have collected some assets for
you as well as some graphics and some pre-compiled applications
| | 00:20 | that you can use that actually go
along with what we will be learning.
| | 00:23 | Now I have copied this folder onto the desktop,
but you can put yours wherever you would like.
| | 00:27 | Now if you're a monthly or annual subscriber to lynda.com,
you don't have access to the exercise files, but you can
| | 00:33 | easily follow along and use your own assets
inside of the applications that you will create.
| | 00:37 | Let's get started.
| | Collapse this transcript |
|
|
1. Getting Started with AIRIntroduction to AIR| 00:00 | As we begin this series, I wanted to give you a little bit of
information about some things that you can expect. We're going to be
| | 00:05 | developing several applications throughout this series including
a web browser built entirely in Flash CS3, an image viewer
| | 00:12 | that allows you to pull images off
of your local hard drive to view them,
| | 00:15 | an online-offline contact manager application and even an
application that analyzes the current monitor setup that you have.
| | 00:22 | Now all of this is great and I really hope that you are excited
about it, but also there are a few things that you'll need
| | 00:27 | to know as we get into this. First,
we're already making some assumptions.
| | 00:32 | We assume that you're a little bit competent with ActionScript
3.0 as well as have a good understanding of how to work
| | 00:37 | with the Flash IDE.
| | 00:38 | If you don't, no worries.
| | 00:40 | There are some other great series here at lynda.com that you
can view to actually get up to speed on some of these issues.
| | 00:49 | Just as an example, here in the Image Loader, we are actually
dynamically grabbing some XML and then we are actually parsing
| | 00:55 | through that to create some objects. If that seems kind of
strange to you, again no worries, but I probably would take a
| | 01:01 | chance to go look at some of the other tutorials on Flash CS3
and ActionScript 3.0 before you decide to jump into this course,
| | 01:08 | but if you're ready for it, we're going to create some really great
applications using Adobe AIR powered by Flash CS3 Professional.
| | Collapse this transcript |
| Getting started with AIR| 00:01 | The AIR Essential Training series here at lynda.com covered
many of the details on how to get Flash CS3 ready for
| | 00:06 | creating AIR applications.
| | 00:08 | Let's review those steps. First, you'll need to be sure that
you have the latest version of Flash CS3 Professional installed.
| | 00:15 | Now this can be accomplished by going under Help,
| | 00:18 | and then Updates under the File menu. If you do need to update
your installation, just complete the on-screen prompts before
| | 00:24 | moving onto the next step.
| | 00:26 | Next you'll need to download the Adobe
AIR update for Flash CS3 Professional.
| | 00:30 | This update can be found at the URL
| | 00:33 | adobe.com/support/flash/downloads.html.
| | 00:40 | When you scroll down the page you should see the option
for the Adobe AIR Update for Flash CS3 Professional.
| | 00:46 | Download the version that is correct for your system
| | 00:48 | and save it on your hard drive. You will need to
close Flash and any open browsers before continuing.
| | 00:53 | Then install the update for Flash CS3.
| | 00:56 | You'll know that the update installed correctly when you see
the Create New Flash File Adobe AIR option on the welcome screen.
| | 01:04 | Once you have installed this update, you'll be ready to create all
of the applications that we will be working with in this series.
| | Collapse this transcript |
|
|
2. Using the AIR Extension for Flash CS3Understanding the AIR application workflow| 00:00 | So you want to develop full desktop applications.
| | 00:04 | Well the AIR update for Flash CS3 gives
Flash developers the ability to create,
| | 00:09 | test and package AIR applications using
tools that they are already familiar with.
| | 00:14 | While the tools are similar, the process for working
| | 00:17 | with AIR applications inside of Flash is a bit
different from the normal Flash development.
| | 00:22 | You will need to review a few old
items and learn a few new ones.
| | 00:25 | In addition, I will walk you through the entire
workflow for a Flash CS3 AIR application.
| | 00:30 | Now there are a few helpful terms that you are
going to need to know as you work with AIR.
| | 00:35 | First, of course you will need to know AIR, and
AIR is short for the Adobe Integrated Runtime
| | 00:40 | and it is the base on which each AIR application runs.
| | 00:44 | Now what this means for you is that you can't
run your AIR application on any computer
| | 00:48 | that does not have the Adobe Integrated Runtime installed.
| | 00:52 | ADL is the short for the AIR Debug Launcher. It allows
for an application to be previewed without installing it
| | 00:58 | onto the computer and this is very important for you
the developer, because you don't want to have to package
| | 01:03 | and install an application every time
you want to test one small change.
| | 01:08 | When an AIR application is distributed,
it is distributed as an .air file.
| | 01:13 | Now this file allows an application
to be installed on a computer.
| | 01:16 | Now of course as we said it earlier,
this computer has to have AIR installed
| | 01:20 | for the .air file to be recognized as an actual AIR file.
| | 01:24 | And finally a secure certificate
is required to create an .air file
| | 01:30 | and it verifies the publisher and application integrity.
| | 01:33 | Now because AIR applications are so much
more powerful than traditional Flash movies,
| | 01:38 | AIR applications can work with the local file system.
| | 01:40 | AIR applications have an embedded
database and so these additional pieces
| | 01:44 | of functionality require that an
extra security measure be taken.
| | 01:49 | So let's look at the workflow inside
of Flash CS3 for AIR applications.
| | 01:53 | First, you are going to need to create.
Application are built with the same graphical tools
| | 01:58 | as with a standard Flash movie, so you can use
those same tools from the palette just as you did
| | 02:04 | within Flash CS3 for traditional Flash movies.
| | 02:07 | However, applications can choose to take advantage of the
new classes and service monitoring components within AIR,
| | 02:13 | so there is additional functionality.
So not only can you use the same tools
| | 02:16 | but you can expand on that and offer even more.
| | 02:19 | Now debugging an AIR application is very much
like debugging a traditional Flash movie.
| | 02:24 | Applications can utilize the ActionScript
3 Debugger that's in Flash CS3.
| | 02:28 | So all the power of that debugger isn't lost in AIR; rather
you can use it to its full functionality inside of AIR.
| | 02:35 | Second, applications are still run with
the Test Movie and Debug Movie commands,
| | 02:40 | and for those of you that use keyboard shortcuts,
| | 02:43 | the keyboard shortcuts for those
commands still work within AIR as well.
| | 02:47 | The difference however, is that applications are handled
by ADL, the AIR Debug Launcher instead of the Flash player.
| | 02:54 | Finally, packaging and sending out your application.
| | 02:57 | Applications are not published with
the traditional Publish command,
| | 03:01 | so the way the Flash CS3 movies
were published is not the same.
| | 03:06 | In Flash CS3, a movie was generated with an HTML file and
other things that could easily be embedded on a web page,
| | 03:12 | but rather with AIR, you create a .air file.
| | 03:15 | The applications with AIR must be
packaged using the Create AIR File command.
| | 03:20 | This is found under the Command menu and it was one of the
options added by the AIR update for Flash CS3 Professional.
| | 03:26 | And finally as we stated earlier, applications
must be signed with a secure certificate.
| | 03:32 | This is important because it adds another security measure
so that people can know who the application is coming from.
| | 03:38 | Now while there are many techniques used in crafting
AIR applications that I will cover in this series,
| | 03:42 | the core workflow of creating, debugging and
packaging an application will mostly remain the same.
| | 03:48 | Once you understand how this process works in Flash
with a simple AIR application, you can apply this to any
| | 03:54 | of the complex applications that
you will be creating in the future.
| | Collapse this transcript |
| Modifying the Application and Installer settings| 00:00 | At this point you are probably ready
to create your first AIR application,
| | 00:03 | but you might be wondering, how do I make my application
behave like other desktop applications I have seen?
| | 00:08 | What's important to know that the desktop opens
up many new possibilities for the developer
| | 00:13 | for how the application will both look and function.
| | 00:16 | Now to learn how these settings can affect an
application, let's just go ahead and create one.
| | 00:20 | So anytime you want to create a new AIR application
inside of Flash CS3 you are going to want to go
| | 00:25 | under the Create New Flash File Adobe AIR option.
| | 00:28 | And when we create the new application it's
going to look a lot like a normal Flash movie.
| | 00:33 | There are a few things we are going to need to do first.
| | 00:36 | First if we go under File and then Publish Settings,
we are going to need to uncheck the HTML option.
| | 00:42 | We don't need the generic HTML that's generated for a
Flash movie because again this isn't going to be running
| | 00:47 | in the browser, this is going to be a
desktop application. Then we can click OK.
| | 00:52 | Next we are going to want to go ahead and save our movie.
| | 00:55 | Flash is going to require that you actually save a
movie before you can edit the Application Settings.
| | 01:00 | So let's go to File, Save and I am going
to call this one Sample Application.
| | 01:06 | And I am going to save it under the
Chapter 2 folder of the exercise files
| | 01:11 | but you can save it wherever you
would like on your hard drive.
| | 01:14 | After our application has been saved we can
go ahead and start adding things to the Stage.
| | 01:19 | First I am just going to go ahead and add some text to the
Stage, to show that again just by using the normal tools
| | 01:24 | that you are used to working with inside of
Flash you can add items to a desktop application.
| | 01:28 | Next I want to bring an image in that's going
to serve as the footer for our application.
| | 01:36 | So I am going to go to File and then
Import and then Import to Stage.
| | 01:42 | Now if you look under the exercise files
folder in the Chapter 2 folder inside
| | 01:47 | of the Images folder you will see an image called Footer.
| | 01:50 | Let's open that image.
| | 01:52 | Now that's brought it into the Stage but I
want this to be positioned at the bottom.
| | 01:56 | And again just as in Flash I can go to the Align panel.
| | 01:59 | If you don't see the Align panel you can get
there by going under Window and then Align.
| | 02:04 | Now if we select the image and we go
over here To Align and be sure that the
| | 02:08 | To Stage option is checked we can then
just hit the Align to Bottom button.
| | 02:13 | That will align our footer to the bottom of the application.
| | 02:18 | Now we have added some basic items to the
Stage, we can now test our application.
| | 02:22 | Now to test your application you simply
need to go to Control, Test Movie.
| | 02:26 | Now this is going to look like a lot of the very
basic desktop applications that you have seen.
| | 02:33 | It's got the normal what we call chrome
around it like most other desktop applications.
| | 02:38 | And it also can be moved around and has options for
closing, for maximizing and for minimizing the application.
| | 02:44 | But there are a few things on this
application that aren't ideal.
| | 02:47 | First, if we move to the bottom right
corner of the application we can see
| | 02:51 | that we are given the option to resize the window.
| | 02:53 | And if we start resizing our application we notice
that our application really wasn't made to be resized.
| | 02:59 | The image at the bottom of the
application is becoming very pixelated.
| | 03:02 | It doesn't look very good.
| | 03:04 | In addition if we go to the Maximize option and click
it, our application takes up the whole screen but
| | 03:10 | yet again the image at the bottom is pixelated because
our application really wasn't made to be maximized.
| | 03:15 | So wouldn't it would be great if there was a way
to turn some of these items off so that users
| | 03:19 | of your application could only
do what you wanted them to do?
| | 03:22 | Well these are just a few other things that
you can change by changing the settings
| | 03:26 | in the application descriptor file for an AIR application.
| | 03:29 | Now the great thing is inside of Flash there is an easy
way to edit the application descriptor file by going
| | 03:35 | under Commands and then AIR
Application and Installer Settings.
| | 03:39 | If we click on that it brings up a dialog
box with the lot of different form fields.
| | 03:44 | Now a few of these are very important and
are going to be need to be changed for each
| | 03:48 | and every AIR application that you create.
| | 03:51 | First I want to go ahead and give it a name. You can
see that's already been given a name, Sample Application.
| | 03:56 | And I am going to put a space in between
that should call it Sample Application.
| | 04:00 | Same thing for name we will give
it the name, Sample Application.
| | 04:03 | Now these items can't be left at their
default values and it would be okay.
| | 04:08 | But an item that needs to be changed for each and every
AIR application that you create is the Application ID.
| | 04:14 | This is how AIR distinguishes one
AIR application from another.
| | 04:17 | And when many people create an ID for their application
they use something called Reverse DNS Format.
| | 04:23 | And basically what this means is you take a domain that you
own or associate it with and you flip it around backwards
| | 04:30 | and then add the name of your application.
| | 04:31 | For example, if I wanted to use the domain
lynda.com, I could type in com.lynda and then add
| | 04:41 | in the name of my application, Sample Application.
| | 04:46 | You need to be sure that you go in and edit the
application ID for every AIR application that you create.
| | 04:51 | Now we are not going to worry about these other
settings at the moment but we did want to stop people
| | 04:55 | from resizing and maximizing our application.
| | 04:58 | To accomplish this we are going to
need to go to the advanced settings.
| | 05:02 | If we click on the Settings button another dialog
box will open and you will see that there are options
| | 05:07 | and checkboxes next to Maximizable,
Minimizable, Resizable and Visible.
| | 05:12 | We are going to uncheck the Resizable and
Maximizable options and then click OK.
| | 05:17 | And if we click OK one more time these settings
are going to be applied to our application.
| | 05:22 | And now if we go to Control, Test Movie, our application will
launch but now someone goes to the corner of our application
| | 05:29 | they're not going to be given the
option to resize the window.
| | 05:32 | In addition if they go to the Maximize
button, it's been disabled
| | 05:36 | and even if they click it it's not
going to maximize the application.
| | 05:40 | Now these are just a few of the settings that you
can change inside of the application descriptor file.
| | 05:44 | Now to review, anytime you want to edit
any of the application settings that are
| | 05:48 | in the application descriptor file you will need to use
the Application and Installer Settings dialog box.
| | 05:54 | Every time you create an AIR application you
will need to at least edit the application ID.
| | 05:58 | Now this will be a core task that you will use for any
AIR application that you create and since you know how
| | 06:04 | to create your application with custom settings and how
to test it with the AIR Debug Launcher you are now ready
| | 06:09 | to package you AIR application for installation.
| | Collapse this transcript |
| Signing your AIR application| 00:01 | The application is complete and now you need to be able
to distribute the application to anyone and everyone.
| | 00:07 | Since AIR applications are true desktop applications,
| | 00:11 | the way in which they are published is quite a
bit different from a traditional Flash movie.
| | 00:15 | When AIR applications are published, they are
packaged into an .air file that then can be installed
| | 00:21 | on any computer that has AIR already installed.
| | 00:23 | Since AIR applications have access to the user's computer,
| | 00:26 | security is even a greater concern
than with the traditional Flash movie.
| | 00:30 | Because of this, the packaging
requires a few additional steps.
| | 00:33 | The first step is to create a secure
certificate to package your AIR application with.
| | 00:39 | We will start by opening the sample application.
| | 00:41 | Let me go under File and then Open
and then select Sample Application,
| | 00:46 | which can be found under the Exercise
files in the Chapter 2 folder.
| | 00:50 | Now when the application is launched, we are going to need
to go to the Application and Installer Settings dialog box,
| | 00:56 | which can be found under Commands,
Application and Installer Settings.
| | 01:00 | Now to create a certificate, we are going
to go down to the installer settings.
| | 01:04 | You will see that there is an option that
says Digital Signature and next to it says,
| | 01:08 | "Select a certificate to sign the AIR file."
| | 01:10 | Well we don't have one yet, so we
are going to need to create one.
| | 01:13 | So we need to click the Set button, which will
allow us to then create a new certificate.
| | 01:18 | And to create one, we can click the Create
button and it will bring up another dialog box.
| | 01:22 | Now you are going to have to fill in each of the items
here, so for Publisher Name, I am just going to say,
| | 01:28 | David Tucker and for the Organizational Unit, part
of the organization that develops AIR applications
| | 01:35 | and then for the Organization Name, we will say lynda.com.
| | 01:39 | So we have created these basic items for our
certificate, now the publisher name will actually appear
| | 01:44 | in the installer, if you use a commercially signed
certificate, not if you use a self-signed certificate.
| | 01:49 | So now we are going to go and enter a
password for our secure certificate.
| | 01:53 | We are going to enter just 12345
for my certificate, hopefully,
| | 01:58 | you will pick a much better password for your certificate.
| | 02:01 | Then we need to select where we will save our certificate.
| | 02:05 | So if you click the Browse button, it allows you
to select a directory to save the certificate in.
| | 02:09 | For this example, I am going to
save the certificate on the desktop.
| | 02:13 | So if we select desktop and then
hit OK, we can see that it is going
| | 02:16 | to name the certificate, mycert.p12,
and that's what we want.
| | 02:19 | We will just click OK and it will take the
application in a second as it creates the file.
| | 02:24 | Then it will inform us that the
self-signed certificate has been created.
| | 02:27 | We will click OK.
| | 02:29 | Now we have created our certificate and it will
automatically populate that into the certificate field.
| | 02:34 | Now we need to enter in our password.
| | 02:36 | I am going to enter in the extremely difficult
password of 12345 and I am also going to select for it
| | 02:43 | to remember the password for this session.
| | 02:45 | This way each time we package the AIR
application as long as we keep Flash open,
| | 02:49 | we won't have to enter this password
again, then we click OK.
| | 02:53 | Now we have actually gone through the
first step of packaging our application.
| | 02:57 | Next, we will actually have to go through
the process of creating an .air file as well
| | 03:02 | as adding a custom icon to our application.
| | Collapse this transcript |
| Packaging your AIR application | 00:00 | Now that you have signed your AIR application, you now
can create an .air file that then can be distributed
| | 00:06 | to anyone who is running AIR on their computer.
| | 00:09 | In addition to doing that, we are also
going to customize the Application icon
| | 00:13 | to give your application a customized look
and feel that people can then recognize.
| | 00:18 | So the first thing we are going to do is open up our sample
application, so I am going to go to File and then Open
| | 00:23 | and then I am going to select sampleApplication02 which
is in the Chapter 02 folder of the exercise files.
| | 00:30 | Now that I have loaded up my application, I am
going to go under Commands and then AIR application
| | 00:36 | and installer settings, and that's going to bring up
the application and installer settings dialog box.
| | 00:40 | Now we have worked with many of the items in here, but we
have not yet worked with configuring the Application icon
| | 00:46 | and the reason is that this value
cannot actually be previewed
| | 00:49 | until you actually package and
then install your application.
| | 00:52 | So I am going to hit the Select icon
images button and it's going to open up
| | 00:55 | and it's going to show us 4 different sizes of icons.
| | 00:58 | Now the reason that these icons are of different
sizes is that different operating systems use them
| | 01:03 | at different places at different
sizes, so this way we can be sure
| | 01:07 | that our application icon will appear
properly for each of these sizes.
| | 01:10 | So I have created some icons and placed them in the Icons
folder inside of the Chapter 2 folder in the exercise files
| | 01:16 | and we are going to replace these values with those.
| | 01:19 | We are going start off here with the one that's 128 x 128.
| | 01:23 | I am going to hit the Folder icon.
| | 01:24 | I am going to go into the Icons folder and select
Icon-128, and then I will do the same for 48,
| | 01:32 | and then I will do the same for 32 and finally, 16.
| | 01:38 | Now I have added all of my custom icons, and I can hit OK.
| | 01:42 | Now I am just going to check and be sure
that our signature has been signed correctly,
| | 01:47 | and yes we can see that it has the
correct certificate and we can hit OK.
| | 01:53 | Now we are ready to actually package the application.
| | 01:56 | So now I am going to save the file and then I am
going to go to Commands and then Create AIR File.
| | 02:01 | And then it will tell us the AIR file has been created.
| | 02:05 | So I will click OK and I am going to open up the
Chapter 2 folder and we will now see inside of there,
| | 02:10 | a sampleApplication_02 that's an
.air file, it's in installer package.
| | 02:17 | So now we actually can double click
on this and install our application.
| | 02:20 | It will walk us through the process, again
because we have used a self-signed certificate,
| | 02:26 | it will tell us that the publisher is unknown, but then
we can hit Install, we can leave the default settings here
| | 02:32 | and just hit Continue, and it will actually
install our application and there we go.
| | 02:37 | We have actually installed and run our application.
| | 02:40 | If we go to the desktop, we can see now that our Sample
Application icon has been populated there as well
| | 02:47 | as when we run the application, we can see
that our icon has been populated at the top
| | 02:52 | of the application as well in the native window.
| | 02:55 | So now that you have learnt how to use the workflow to
not only create, test and now package in your application,
| | 03:01 | you now can move on to actually creating
AIR applications that utilize some
| | 03:04 | of the AIR specific classes that
are available within Flash CS3.
| | Collapse this transcript |
|
|
3. Using the ClipboardIntroducing the Clipboard| 00:01 | As we begin to look at the clipboard support inside
of AIR, we are going to be using a sample application
| | 00:06 | that I have already created. So to see how this works
just go ahead and look at the sample application
| | 00:11 | without any of the AIR functionality in it.
| | 00:15 | So we go to File and then Open.
| | 00:17 | Then I am going to open ImageViewer01, which is
in the Chapter 3 folder of the exercise files.
| | 00:23 | Once the application is loaded, I am just going to go
to Control and then Test Movie to see the functionality.
| | 00:32 | Now what's happening is the application is loading
an XML file that contains a listing of images
| | 00:37 | with their thumbnails and if you click on
any of these smaller items in the list below,
| | 00:42 | it will bring the larger image to display above it.
| | 00:46 | Now this is using 2 components, this
is using a UI Loader for the top area
| | 00:51 | and it is using a Tile List for the bottom list area.
| | 00:54 | Let's look and see how we implemented
that inside of ActionScript.
| | 00:57 | So I am going to select my Actions layer,
and then I am going to go to Windows
| | 01:03 | and then Actions or again we can press the F9 key.
| | 01:07 | Now immediately, you will notice that we have brought
in some classes that we are going to be using,
| | 01:12 | URLLoader, URLRequest and then the UILoader class.
| | 01:15 | And if you look down, you will
see why we used the first two.
| | 01:18 | We are going to load in the XML using an URLLoader
and it's just going to load in slides.xml.
| | 01:23 | Now this is going to work the same way in
an AIR application as it did in the browser,
| | 01:28 | it's going to look in the exact same directory,
it's going to find slides.xml and load it in.
| | 01:33 | When that's complete, it's going
to call the onXMLLoad method.
| | 01:37 | And if we go and look at that method, it actually takes
the loader, the data that's returned by the loader
| | 01:43 | and then creates a new XML object and then here it uses that
data to create an object for each of the different items
| | 01:52 | that are found in the list: one for the thumb,
one for the full size image, one for the caption.
| | 01:57 | And then when it's done, it actually takes
and adds it to the TileList component.
| | 02:02 | Now some of this XML work might look a little bit confusing.
If you haven't seen this before you might want to look
| | 02:07 | at Todd Perkins' series ActionScript 3,
Working with XML here on lynda.com.
| | 02:14 | Now after we have added that, we are
going to actually configure our TileList.
| | 02:17 | So we have actually set a TileList on the Stage, we have set
its size, its column width, its row height, its label field
| | 02:24 | and then we also have added an event
listener to it that is called onImageSelect,
| | 02:28 | that gets called every time the
item is changed within the TileList.
| | 02:31 | So if we go and look at onImageSelect, it's going to set
the imageLoader.Source equal to the data of the object
| | 02:40 | that we set up here, which is the full size image.
| | 02:43 | So it uses the data property to then set
the image that will be displayed full size.
| | 02:49 | So this simple application just uses roughly 39 lines
of ActionScript code to create an application that loads
| | 02:56 | in data from an XML file and then displays a
list of images and then allows you to click
| | 03:01 | on those images and view the images full screen.
| | 03:03 | But there will be a lot of things that we would
like to do with this application with some
| | 03:06 | of the AIR specific functionality, so over the course of the
next few sessions, we are going to be adding different items
| | 03:11 | to this application to give it increased functionality.
| | Collapse this transcript |
| Understanding the Clipboard| 00:00 | Most modern operating systems use a clipboard
to share data between different applications.
| | 00:06 | This can be simple data such as copied text, bitmap
data from an image or a list of files from the desktop.
| | 00:12 | Every time you copy and paste between
applications, you are using the clipboard.
| | 00:17 | Now before you begin working with the
operating system clipboard inside of AIR,
| | 00:21 | I wanted to demonstrate some key
characteristics of the clipboard.
| | 00:25 | So to do that, the first thing I am
going to do is open up Internet Explorer.
| | 00:28 | Now I have loaded up the lynda.com
homepage, and I will go scroll down
| | 00:33 | and I am going to find this one paragraph of text.
| | 00:35 | I am going to highlight the paragraph and I am going
to right-click or Control-click on Mac and select Copy.
| | 00:41 | At this point, you will probably assume
that this has just copied just the text,
| | 00:46 | but as we will learn there are many
different kinds of text within the clipboard.
| | 00:50 | To illustrate this, I have loaded up Microsoft Word 2007.
| | 00:54 | Let me go to the Paste option and I am going to go down
to the Paste Special and it's going to show us a list
| | 01:01 | of every type of data that's currently on the clipboard.
| | 01:04 | We can see right here from this one item that we have
highlighted and copied that there is unformatted text
| | 01:10 | as we might expect, there is also HTML Formatted Text, there
is Unformatted Unicode Text and there is Formatted Text RTF.
| | 01:18 | So simply by highlighting one paragraph and copying it,
we get 4 different data types added to the clipboard.
| | 01:24 | But it's not just with text.
| | 01:26 | If I clear all the items off the clipboard and I go back to
the web page, I can unselect this text and move to the top
| | 01:34 | of the page and right-click on the logo and select Copy.
| | 01:38 | If I go back to Microsoft Word
and go to Paste and Paste Special,
| | 01:42 | you are going to see that there are also different
types of data on the clipboard with an image.
| | 01:46 | There is device-independent bitmap data, which
is the actual bitmap data inside of the image.
| | 01:51 | There is HTML Format Data, which includes the image
tag and the reference to the actual image file itself
| | 01:56 | and then an actual file's object that actually
contains a reference to this specific file.
| | 02:02 | So just again with copying one image,
we get 3 different data formats.
| | 02:06 | So there are several things that we need to learn about
the clipboard, but one of the main items to understand
| | 02:10 | as we move forward and look at AIR support for the
clipboard is that clipboard can contain many different types
| | 02:16 | of data even at the same time, even
from a single originating piece of data.
| | 02:22 | So we are going to move on and look at how AIR
supports the clipboard and we will be working
| | 02:26 | with the Image Loader application that we viewed earlier.
| | 02:29 | AIR supports almost every function
of the clipboard and it allows
| | 02:32 | to greatly enhance the functionality of this application.
| | Collapse this transcript |
| Adding data to the Clipboard| 00:00 | One of the main goals of clipboard support is to make
your data available and accessible to other applications,
| | 00:07 | to do that you place the data on the clipboard.
| | 00:10 | In the beginning of this chapter we
looked at an Image Viewer application.
| | 00:14 | Now this application is what we are
going to use to add this functionality.
| | 00:18 | So I am going to go ahead and open
up the Image Viewer application.
| | 00:22 | So I want to go to File and then open and then in
the Chapter 3 folder of the exercise files I am going
| | 00:29 | to go ImageViewer01 and then I am going to run
the application by going to Control, Test Movie.
| | 00:39 | If you remember when we click on an image you
will see the larger image displayed above.
| | 00:44 | To go for this video will be to take the larger
image displayed above and add it to the clipboard
| | 00:50 | so that other applications can access it.
| | 00:53 | To do that we are first going to need to add a button
to the Stage that will trigger our copy functionality.
| | 01:00 | So the first thing we need to do is create a new layer.
| | 01:02 | I am just going to call it Button
because that's where we place our button.
| | 01:07 | Then I am going to open the Components window, this
can be done by going under Window and then Components
| | 01:14 | and then I am going to drag out an instance of
the button to the bottom right of the Stage.
| | 01:19 | I can then go under the Parameters tab and
change the label on this button to be copied.
| | 01:27 | And we are going to give this one
an instance name of copyButton.
| | 01:32 | Now that we have set up our Stage we can
now begin working with the ActionScript.
| | 01:39 | I am going to highlight the Actions layer and
I am going to go to Window and then Actions.
| | 01:44 | Now the first thing we are going to need to do is
we are going to need to import two specific classes.
| | 01:51 | The first class that we are going to
need to import is the Clipboard class.
| | 01:54 | If we don't import this class we are not going
to have the ability to add data to the Clipboard.
| | 01:59 | To import that we simply need to
say import flash.desktop.Clipboard.
| | 02:09 | In addition there is also a class
inside of AIR that defines what type
| | 02:15 | of clipboard data formats AIR supports,
that class is called ClipboardFormats.
| | 02:22 | The clipboard formats that are supported by
AIR are Text_Format, which holds raw text data,
| | 02:29 | URL_Format that holds URL, formatted items, HTML_
Format which has html tags and text, Bitmap_Format,
| | 02:37 | which contains image data, and File_List_Format,
which contains data from a group of files.
| | 02:44 | Now to use this inside of AIR you have to
first import the ClipboardFormats class.
| | 02:49 | And there are many instances where you have to tell
the Clipboard either what type of data you want to set
| | 02:55 | or what type of data you want to retrieve.
| | 02:57 | So to import the Clipboard Formats class we need
to say import flash.desktop.ClipboardFormats.
| | 03:07 | Now that we have imported those we can begin to wire
the Clipboard functionality into our Copy button.
| | 03:16 | So I am going to go under where I can figure the TileList,
I am going to create a new small little subsection.
| | 03:23 | We will call it Add Event Listeners.
| | 03:25 | And this is just a comment that
helps keep our code organized.
| | 03:30 | Now I want to say copyButton.addEventListener
and then we are going to need
| | 03:37 | to tell it what event we are listening for.
| | 03:39 | In this case we are going to listen for MouseEvent.CLICK.
| | 03:43 | And what we are going to want to do is we are
going to want to call a method called onCopyClick.
| | 03:56 | So now we can head down to the
event handler section of our code.
| | 04:00 | And we can create a function called onCopyClick; it
will receive an event that will be a Mouse Event.
| | 04:10 | And it is not going to return anything.
| | 04:13 | Now what we are going to want to do in
this method is actually add the data
| | 04:18 | to the Clipboard inside of this method.
| | 04:21 | But what we want to do is we also want to add a very
specific kind of data, we want to add the image data.
| | 04:27 | Now to add image data we are going to be
using the ClipboardFormats.Bitmap_Format
| | 04:32 | of the formats for the clipboard.
| | 04:35 | So to do this we are going to want to have a function
that basically takes the current image that's
| | 04:40 | in the UIloader and returns all the bitmap data for it.
| | 04:45 | So we are going to add a new subsection.
| | 04:48 | And this section is just going to be called
Methods because these are the methods
| | 04:53 | that are going to respond to any specific event.
| | 05:00 | And then we are going to want to create a method
called renderBitmapData and it's not going
| | 05:10 | to take any arguments but it's going to return bitmap data.
| | 05:14 | The first thing we are going to need to do inside
of our renderBitmapData function is we are going
| | 05:21 | to create a new instance of the BitmapData class, but
to do that, we are actually going to have to go back
| | 05:26 | and also import the BitmapData class so let's go
back up to the top of our ActionScript and directly
| | 05:32 | under where we imported the ClipboardFormats
we are going to import flash.display.bitmapdata.
| | 05:44 | If we scroll down to where we have our renderBitmapData
function the first thing we are going to do is we are going
| | 05:49 | to create a variable BD which will be BitmapData and
we are going to set that equal to new BitmapData.
| | 06:00 | Now when you create a new BitmapData you are going to need
to tell the width and the height that you want it to be.
| | 06:05 | Now the great thing is our UI loader actually tells us
what it's currently displaying and its width and height
| | 06:12 | so we can use that as the basis for this BitmapData.
| | 06:16 | So we can say imgLoader, which is our UI loader, .content.
| | 06:22 | Now this is the reference to the actual image
that is being displayed and we will say width
| | 06:27 | and then we will say imgLoader.content.height.
| | 06:33 | So now we have created our BitmapData object.
| | 06:40 | And now what we are going to want to do is we are going
to want to fill it with all of the data from the image
| | 06:44 | that is not currently being displayed in the UI loader.
| | 06:47 | Now the BitmapData class has a method called
Draw that will take an object on the Stage
| | 06:53 | and then draw its data out in BitmapData.
| | 06:55 | So we can say bd.draw and then pass in
a reference to the imgLoader.content.
| | 07:09 | By doing this we now have created a new instance of the
BitmapData class, we have set its specific width and height
| | 07:17 | and now we have actually added the bitmap data from the
current image in the UI loader into the BitmapData object.
| | 07:24 | The last thing we need to do is
actually return our bitmap data.
| | 07:29 | Now that we have rendered our bitmap data we
can go back up to where onCopyClick method
| | 07:34 | and we can actually add this data to the Clipboard.
| | 07:38 | So to get to the operating system Clipboard we say
Clipboard.generalClipboard and this is a reference
| | 07:47 | to the normal operating system
Clipboard and then to actually add data
| | 07:51 | to the Clipboard we are going to call the setData method.
| | 07:56 | Then within this method the first thing we are going
to want to tell is what type of data we are passing in.
| | 08:01 | And this is where we use the ClipboardFormats class.
| | 08:03 | We will say ClipboardFormats.
| | 08:07 | And then we will say Bitmap_Format
and this will be the image data.
| | 08:12 | And then we will need to tell it
what data that we wanted to pass in.
| | 08:15 | So what we want to do first is we want to go back and create
another instance of the BitmapData class and set it equal
| | 08:24 | to renderBitmapData, the method that we just created.
| | 08:29 | Then we can go to our setData call and
we can pass in BD for the bitmap data.
| | 08:37 | Now we can save our application and we can test it.
| | 08:41 | So to test it we are going to go to Control,
Test Movie and we are going to select an image.
| | 08:50 | Let us select this image of Bourbon Street.
| | 08:52 | Now we should be able to go and hit our Copy button
and then I am going to bring up Microsoft Paint.
| | 08:59 | And I should be able inside of Microsoft Paint to go Edit
and then Paste and there is our image it's been brought
| | 09:05 | in from our AIR application through the clipboard.
| | 09:08 | By being able to add data to the clipboard you can
create applications that have two way communications
| | 09:15 | with other applications on the user's operating
system. But AIR clipboard support does not end there.
| | 09:21 | AIR also gives you access to retrieve data from the
clipboard as well as using some advanced functions
| | 09:27 | to control when an item is actually
pasted onto the clipboard.
| | 09:31 | Now that you have learned how to add
data to the clipboard you can began
| | 09:34 | to explore these other options that
are available to you within AIR.
| | Collapse this transcript |
| Getting data from the Clipboard| 00:01 | Another vital area of clipboard
support is being able to get data
| | 00:05 | from the operating system clipboard into your application.
| | 00:08 | A lot of times this is just summed up by saying paste
so we want to paste data that somebody else has copied
| | 00:14 | in from a different application into our application so
that we can use it and manipulate it however we would like.
| | 00:20 | We are going to add this functionality
to the Image Viewer application.
| | 00:24 | This application can be found if we go to File
and Open and look under the Chapter 3 folder
| | 00:30 | of the exercise files and go to ImageViewer02.
| | 00:36 | The first thing we are going to need to
do is add another button to our Stage.
| | 00:40 | We have a Copy button but we are
going to need a Paste button.
| | 00:42 | I am going to go ahead and lock
all the layers except the top one.
| | 00:45 | I am going to change it from button to buttons you
don't have to but if you are going to put two buttons
| | 00:50 | on a layer it probably needs to be plural.
| | 00:52 | The next thing you want to do is going to
window and then components then we are going
| | 00:57 | to drag another instance of the button onto the Stage.
| | 01:00 | We are going to change its label by going to
parameters and changing the label to Paste.
| | 01:06 | We are also going to give it an
instance name of pasteButton.
| | 01:13 | Now we can close the Components window we can kind
of position our Paste button where we would like it
| | 01:18 | and then we can highlight both of it and our
Copy button and be sure they are lined to center.
| | 01:23 | Now we can go into the ActionScript and
actually add the Paste functionality.
| | 01:28 | So I am going to highlight the Actions layer then
I am going to go under Window and then Actions.
| | 01:33 | Now we have already imported the
ClipboardFormats and BitmapData classes
| | 01:38 | so adding this will only require two steps.
| | 01:41 | First we need to create an event
listener for a Paste button.
| | 01:46 | We will say pasteButton.addEventListener
and we are going to listen
| | 01:54 | for the MouseEvent.Click and we
are going to say onPasteClick.
| | 02:02 | Now we are going to need to go and create the onPasteClick
method in the event handler section of our code.
| | 02:12 | So we are going to create a function onPasteClick.
| | 02:19 | It is going to receive an event, which will be a
mouse event, and it's not going to return anything.
| | 02:31 | Now what we are going to want to do inside
of this method is we are going to want
| | 02:36 | to take any bitmap data that's currently on the clipboard
and we are going to want to display it in our UI loader.
| | 02:42 | So we are going to be using a method
of the Clipboard class called getData.
| | 02:47 | But the first thing we are going to is we are
going to create a new instance of the Bitmap class.
| | 02:52 | So we are going to say var bm and this will be just
of type Bitmap and a Bitmap is related to BitmapData.
| | 03:04 | But BitmapData is actually contained
within a Bitmap so the UI loader is going
| | 03:09 | to accept a Bitmap as the actual image that's on the Stage.
| | 03:13 | So when we want to actually replace that image within image
| | 03:15 | from the clipboard we are going
to need to use the Bitmap class.
| | 03:18 | We are going to say Bitmap=new Bitmap and now we are going
to actually want to get the bitmap data off of the clipboard
| | 03:29 | so we can say Clipboard.generalClipboard, which again is
the reference to the operating system clipboard, .getData
| | 03:38 | and then we are going to need to tell
up what kind of data we wanted to get.
| | 03:43 | So we are going to use the ClipboardFormats
class and we are going to use Bitmap_Format.
| | 03:54 | Then we can close this call.
| | 03:56 | Now what we are going to want to
do is we are actually going to want
| | 03:59 | to set the image loader's source property to that bitmap.
| | 04:06 | Now when we write everything we
are going to receive an error.
| | 04:09 | I will show you. It's going to saying here
that we have an implicit coercion of a value
| | 04:18 | and basically what it's saying
is, is you are passing us a value
| | 04:22 | and we don't know what it is. You are assuming it's bitmap
data but there is no way to know. So what we are going
| | 04:26 | to do is we are going to tell it that
the value that's going to be returned
| | 04:29 | by the getData call is going to be bitmap data.
| | 04:33 | And that's something called Casting, so we can
say we want this to be returned as bitmap data.
| | 04:40 | Now this won't convert any data into a different format
| | 04:44 | but rather it will just tell the Flash player
expect bitmap data coming back from this function.
| | 04:49 | If it doesn't end up returning a different
type of data then it will throw an error.
| | 04:53 | We can now test our application and see
indeed that the error has gone away.
| | 05:02 | We now if we wanted to can go back to Microsoft
Paint and load it up, we can now take an image,
| | 05:12 | for instance this image of Alcatraz
Island we can add it to the clipboard.
| | 05:17 | We can now drop it into Microsoft Paint by pasting.
| | 05:21 | If we wanted to we could grab the Airbrush tool and
this will go all over Alcatraz Island and then just say
| | 05:29 | that we want to copy our image and then if we go back over
to our Image Viewer and say paste there is our version
| | 05:37 | that we have edited with our own artistic flair.
| | 05:41 | So by not only being able to add data
to a clipboard but also receiving data
| | 05:46 | from the clipboard we have truly implemented two-way
communication between our application and other applications
| | 05:52 | that are running on the operating system.
| | Collapse this transcript |
| Using deferred rendering| 00:00 | What if you created an application that gave up to the second
stock values for the New York Stock Exchange and you wanted
| | 00:07 | users to be able to copy stock values from your application
into a spreadsheet application. Chances are that between
| | 00:13 | the time they copied the information and then pasted
it in their spreadsheet, the data would have changed.
| | 00:18 | Deferred rendering inside of AIR allows you to define the
data for the clipboard, not when it was copied, but rather when
| | 00:25 | it was pasted. In this way the user of the stock prices
application could ensure that the data that is passed would at least
| | 00:32 | be to the second accurate. Deferred rendering inside of AIR
is accomplished by using the setDataHandler method of the
| | 00:39 | Clipboard class.
| | 00:40 | Now we can also apply this to our Image Viewer application.
| | 00:44 | If we go to File
| | 00:45 | and then Open,
| | 00:47 | we're going to open the ImageViewer03 application that's
found in the Chapter 3 folder in the exercise files.
| | 00:54 | To illustrate this functionality
I am going to test the application.
| | 00:57 | If we go to Control and then Test Movie,
| | 01:03 | and we select Alcatraz Island
| | 01:05 | and we hit Copy,
| | 01:06 | and we then select Big Ben
| | 01:09 | and we bring out Microsoft Paint,
| | 01:11 | and we paste
| | 01:12 | you'll notice that Alcatraz Island is the one that was added
to the clipboard. And even though it's not the one currently
| | 01:18 | selected, it's the one that was added when
the setData method of the clipboard was called.
| | 01:24 | So I'm going to go ahead and delete this from Microsoft Paint.
| | 01:28 | Then I am going to minimize that for
the moment. We are going to go in now
| | 01:32 | and we are going to add one more button
to our Stage. So we can go to the Window
| | 01:36 | and then go to Components
| | 01:38 | and then we are going to add one more button.
| | 01:41 | And we are going to give this one
| | 01:42 | a label
| | 01:43 | of Copy Later.
| | 01:47 | And again,
| | 01:48 | labels can be accessed under the Parameters tab,
| | 01:52 | and we are going to give this one an instance of copyLaterButton.
| | 01:58 | We now can bring it a little closer
| | 02:00 | to our other buttons we're going to select all three buttons. We're going
to align them in the center and then we're going to space them evenly.
| | 02:07 | You can now close the Components window.
| | 02:09 | Now that we have created our Copy Later button and have given
it an instance name we can now move to our ActionScript.
| | 02:16 | So I am going to select the Actions layer
| | 02:18 | and then go to Window
| | 02:20 | and then Actions.
| | 02:22 | Now the first thing we're going to need to do is we're going
to need to add an Event Listener for the Copy Later button.
| | 02:27 | So under our other addEventListeners we are
going to say copyLaterButton.addEventListener
| | 02:36 | and we are going to listen for a MouseEvent.Click
| | 02:39 | and we are going to create a method called OnCopy
| | 02:44 | LaterClick.
| | 02:47 | Now we are going to go below all our other event
handlers and we are going to create this method.
| | 02:55 | onCopyLaterClick and it's going to receive an event that
will be a mouse event but it's not going to return anything.
| | 03:08 | So we can set the return type equal to void. Now as I
stated at the beginning of this video the setDataHandler
| | 03:14 | method of the Clipboard class allows us to do
deferred rendering. So we are going to say Clipboard
| | 03:20 | .generalClipboard, which returns a
reference to the operating system clipboard,
| | 03:25 | and then we are going to call the setDataHander method.
| | 03:30 | And the first parameter that it's going to want is it's
going to want to know what format this data is going to be in.
| | 03:36 | And we are going to use ClipboardFormats
| | 03:39 | .Bitmap_Format
| | 03:43 | and notice it's going to want a function that's going to actually
return the bitmap data of the currently selected item in the tile list.
| | 03:51 | Well the convenient thing for us is we actually have
already created that method. The method that we created in a
| | 03:57 | previous video was renderBitmapData. It took the
currently selected item from the UILoader and returned
| | 04:04 | the bitmap data.
| | 04:06 | So we actually can pass that in as
the second parameter, renderBitmapData,
| | 04:14 | and that we can close that call,
we can save our application
| | 04:18 | and now we can test it.
| | 04:19 | If we close our Actions window and
we go to Control and then Test Movie
| | 04:27 | and we select Alcatraz Island
| | 04:29 | and we hit Copy Later. And then we open up Microsoft Paint.
| | 04:34 | We select Big Ben and then we paste.
| | 04:37 | We'll notice that now Big Ben has been copied as opposed
to Alcatraz Island. Even though Alcatraz Island was selected
| | 04:44 | when the Copy Later button was clicked,
| | 04:46 | the renderBitmapData method is not called until the data
is actually pasted. And this is what enables us to give
| | 04:53 | accurate bitmap data of the item that's currently selected.
| | 04:58 | Now there are many different uses of deferred rendering but it
can be especially useful when the data that you are placing on
| | 05:03 | the clipboard needs to be calculated and could utilize a lot of
system resources. In this way your application wouldn't need to do
| | 05:10 | the difficult work until the data is needed.
| | 05:13 | So just to review, we have been able to not only set data on
the clipboard, get data from the clipboard, but also use deferred
| | 05:21 | rendering to work with clipboard data inside of AIR.
| | Collapse this transcript |
|
|
4. Supporting Drag-and-Drop FunctionalityUnderstanding drag-and-drop operations| 00:00 | Another level of operating system integration provided by
Adobe AIR is the ability to support drag-and-drop gestures
| | 00:06 | into and out of your application.
| | 00:08 | Just as with the clipboard, data that is dragged
out of an application exists in different formats.
| | 00:13 | Applications can be configured to accept
| | 00:15 | or reject a drag-in gesture based on the data format.
| | 00:18 | To illustrate this, I have a folder.
| | 00:20 | Inside of it are different images.
| | 00:22 | I'm going to also open up a copy of Microsoft Word.
| | 00:26 | Now, from my folder of the images, I can take one of
my images and actually drag it onto Microsoft Word.
| | 00:32 | You can see if the cursor changes and this change
indicates that it will accept this drag-in data.
| | 00:37 | I can then let go the mouse.
| | 00:39 | You can see that the image has been
added to the document in Microsoft Word.
| | 00:43 | Now, from here, I can also drag this
data out to another application.
| | 00:47 | I've opened up Internet Explorer,
| | 00:49 | and we can see that if I try to drag this,
| | 00:52 | it says it will not let us drag this data in.
| | 00:55 | So, an application can also be configured
to not accept certain kinds of data.
| | 00:59 | But I also have WordPad open and I can choose now if I wanted
to drag and you can see that the cursor will change indicating
| | 01:05 | that yes, this application will accept this drag-in data.
| | 01:09 | Now, you can see that there are many similarities between
clipboard support and drag-and-drop support inside of AIR.
| | 01:13 | Actually, they both use the Clipboard class to accomplish this.
| | 01:17 | Now, if you can leverage drag-and-drop, you can create a user
experience that is very similar to a traditional desktop application.
| | Collapse this transcript |
| Supporting a drag operation| 00:00 | Now, what we are going to want to do is we are going to want to take
an existing application and actually let it share its data with other
| | 00:05 | applications by using a drag-out gesture.
| | 00:08 | Anytime you want to do a drag-in or drag-out gesture, you're going
to be working with one class within AIR, the NativeDragManager,
| | 00:15 | and specifically to begin a drag operation, you are going
to use the doDrag method of this class and any interactive
| | 00:21 | object on this Stage can be used as a drag object.
| | 00:24 | We are going to go ahead and add this to an existing application.
| | 00:27 | So, if we go under File and then Open,
| | 00:29 | I'm going to open the Image Viewer 01 file which
is in the Chapter 4 folder of the exercise files.
| | 00:35 | Now, I am going to go ahead and test this movie.
| | 00:37 | If we go to Control and Test Movie,
| | 00:40 | we'll then see that our application has been loaded
| | 00:42 | and we can see that if we click on any of these
smaller items, it brings up the full size image above.
| | 00:47 | Now, what we want to be able to do is actually grab this
image and be able to drag it into other applications.
| | 00:53 | So to accomplish that, we are going to be
using the NativeDragManager.dodrag method.
| | 00:58 | So, let's open the Actions panel.
| | 01:00 | I'm going to highlight the Actions layer
| | 01:01 | and then go to Window
| | 01:03 | and then Actions.
| | 01:04 | Now, the first thing we'll need to do is
actually import the NativeDragManager class.
| | 01:08 | This can be accomplished by going import flash.,
| | 01:12 | and then we are going to go to desktop.NativeDragManager.
| | 01:17 | Now that we have imported that class,
| | 01:19 | we need to add an event listener to our
UI Loader that loads the full size image.
| | 01:23 | So, go down to where we have the event
listeners and we are just going to add a new one.
| | 01:27 | Now, the instance name of the UI Loader is image loader,
| | 01:30 | IMG Loader.
| | 01:31 | So we will say imgLoader.addEventListener
| | 01:35 | and it's going to listen for the MouseEvent.mouseDown
| | 01:40 | because we wanted to actually register when a user pushes the
mouse down on the item so that we can actually drag it from
| | 01:46 | that point on. And we will call the
response method onLoaderMouseDown.
| | 01:52 | Now, we are going to go ahead and add that method. So we scroll
down to our EventHandler section and just add in one more method.
| | 01:58 | function onLoader mouseDown.
| | 02:03 | and it's going to receive an event which will be of type Mouse Event,
| | 02:07 | return type on this is going to be void,
| | 02:09 | because the method's not going to return anything.
| | 02:12 | Now, the first item that we are going
to want to accomplish within this method
| | 02:15 | is we are actually going to create
a new instance of the Clipboard class.
| | 02:18 | No, we haven't done this previously because we've been working
with the operating system clipboard which can be found in
| | 02:23 | Clipboard.generalClipboard.
| | 02:25 | In this case, we are actually going to pass an
instance of the Clipboard class to the doDrag method.
| | 02:30 | So we will say var clipboard
| | 02:32 | will be of type Clipboard
| | 02:35 | is equal to a new Clipboard.
| | 02:38 | Now, we're also going to want to get the bitmap data of the
current image that's actually inside of the image loader.
| | 02:44 | Now, we have already created a method to do this.
This is actually created in a previous video,
| | 02:48 | and you can see the function renderBitmapData
| | 02:51 | and this is just going to return the bitmap data
of the currently selected image in the UI Loader.
| | 02:55 | So we are going to say var
| | 02:57 | BitmapData
| | 03:00 | and that's going to be equal to the function
| | 03:02 | renderBitmapData.
| | 03:06 | So now we've retrieved the bitmap data as well.
| | 03:08 | We're actually going to add that bitmap data
to the clipboard. So we'll say clipboard.
| | 03:12 | Notice in this instance, I am using a lower case 'c' for clipboard
because I am referring here to a clipboard variable that we
| | 03:17 | created at the beginning of this function.
| | 03:19 | And we will say clipboard.setData
| | 03:23 | and then we will use the ClipboardFormats
| | 03:26 | and we'll useBitmap_Format
| | 03:29 | and then we will actually pass in the bitmap data.
| | 03:32 | Now that we've added to this instance of
the Clipboard class that we have created,
| | 03:36 | we now can pass it into the NativeDragManager.doDrag method.
| | 03:42 | Now, notice here that we didn't have to create
an instance of the NativeDragManager class.
| | 03:45 | The NativeManager.doDrag method is a static method which
means it can be called without instantiating the class.
| | 03:52 | The first thing we are going to need to pass in is the Drag
Initiator. In this case, that's going to be our image loader.
| | 03:58 | Then, we'll need to actually pass in the clipboard
that was created. Ours is just named clipboard.
| | 04:03 | And finally, for us, we are going to need to pass the bitmap data
that we wanted to render when the user begins the drag method and we
| | 04:09 | have already created that with the BitmapData.
| | 04:12 | Now, we have finished our method and we can actually go and test
our application to see if it functions the way that we'd like.
| | 04:17 | I'm going to close the Actions panel
| | 04:18 | and I am going to go under Control and then Test Movie.
| | 04:22 | Now, to test this, I am also going to open up
a copy of Microsoft Word to run in the background.
| | 04:28 | I am going to load up an image,
| | 04:30 | such as Alcatraz Island,
| | 04:31 | and then I am going to grab our image and actually drag
and you can see the bitmap data that it's using as we drag.
| | 04:37 | We can see here also that the cursor has changed saying that
we can't drop this data here because we have not actually
| | 04:43 | configured our application to receive dropped data,
| | 04:46 | but if we drag it over to Word, you can see that the icon
changes on the cursor and we can now drop the image in, and we've
| | 04:52 | actually dragged the data out of our application.
| | 04:54 | The NativeDragManager gives you quite
a bit of power within your application.
| | 04:58 | By using the doDrag method, you can now take data that's
in your application and make it easily accessible to other
| | 05:04 | applications simply by dragging
the data from one application to another.
| | Collapse this transcript |
| Accepting dropped data| 00:00 | Now, that you have created an application that can
actually drag out data to be used in other application,
| | 00:05 | you are probably going to want to create an
application that allows you to drag data into it,
| | 00:09 | but there is one thing to understand first:
most applications deal with specific types of data.
| | 00:14 | For example, in the Image Viewer, the application deals with
bitmap and file data. It doesn't deal with text or URL data.
| | 00:21 | Because of this you will want to limit what
data can be dragged into the application.
| | 00:26 | This can be accomplished by responding to the
NativedragEnter and NativedragOver events.
| | 00:31 | Once the application decides that
a piece of data is appropriate,
| | 00:34 | you can call the NativeDragManager.acceptDragDrop method.
| | 00:38 | So, let's actually implement this.
| | 00:40 | I am going to go to File and then Open and I
am going to open the ImageViewerO2 file inside
| | 00:45 | of the Chapter 4 folder for the exercise files.
| | 00:49 | Now to implement this, we are going to go to the Actions
layer, so click on the Actions layer and then I am going
| | 00:53 | to go to Window and then Actions and the first thing we
are going to need to do is we are going to actually need
| | 00:58 | to import two new classes that we haven't used before.
| | 01:01 | The first of these is going to be
flash.desktop.ClipboardTransferMode
| | 01:09 | and we will discuss what this particular
class is and how it's used in a moment.
| | 01:13 | We are also going to need to import
the flash.filesystem.File class.
| | 01:18 | So, now that we have imported our classes, we
actually can add our event listeners to your UILoader.
| | 01:24 | So if we scroll down to where the event listeners
are, we are going to actually add two new ones.
| | 01:29 | First we are going to want to response
to the NativeDragEvent.
| | 01:36 | and we are going to look for NativeDragEnter.
| | 01:40 | Now, this is the event that's going to be dispatched
whenever someone drags data over the application
| | 01:45 | and the method that we are going to use to
respond to that is going to be onDragEnter.
| | 01:50 | Now, we are going to add one more. This one is
going to be for NativeDragEvent.NativeDragDrop
| | 02:05 | and then we are going to respond to
that with the method onDragDrop.
| | 02:08 | So, now that we have added these two event
listeners, we actually can implement these methods.
| | 02:13 | So, if we go to the Event Handler section of
the code and scroll down below the others,
| | 02:18 | we are going to create our two new methods.
| | 02:19 | First, we are going to create the first method,
onDragEnter, and that's going to receive an event,
| | 02:27 | which will be a NativeDragEvent and
it's not going to return anything,
| | 02:32 | so we can set the return type equal to v oid.
| | 02:35 | And inside of here, we are actually going to
want to detect if this is the kind of data
| | 02:39 | that we want our application to deal with.
| | 02:41 | So we are going to want to use a method called
hasFormat of the Clipboard class and the great thing
| | 02:45 | about the NativeDragEvent is that it actually
contains a reference to the current clipboard
| | 02:49 | of the data that's being dragged over our application.
| | 02:52 | So, we can say if event.clipboard.hasFormat and
then we can pass in the format that we want.
| | 03:00 | In this case, we are going want a new format that we
haven't dealt with before, ClipboardFormats.File_List_Format
| | 03:07 | and then say okay, if it has the data that we want, we will
actually accept this drag operation and the way that we do
| | 03:12 | that is to say NativeDragManager.acceptDragDrop.
| | 03:17 | Now, we are going to need to pass in one
parameter to this method and that's going
| | 03:21 | to be the object that's actually
allowed to accept the DragDrop.
| | 03:24 | In this case, that's going to be Image Loader.
| | 03:28 | Now, we have created this one method that actually looks
at the data and accepts only the kind of data that we want.
| | 03:33 | If any other type of data is passed over, the
application will not allow it to be dropped.
| | 03:37 | Now, we are going to create our onDragDrop event
and it's also going to receive a NativeDragEvent.
| | 03:48 | Now, what we are going to want to do inside of this method
is we are actually going to want to extract the data
| | 03:53 | from the clipboard and the file list format
is going to return an array of files.
| | 03:58 | So, we are going to create an array, we will just call
it A and we are going to set that equal to event.clipboard
| | 04:05 | because again this is a reference to the
current clipboard of what's being dragged.
| | 04:08 | And then we are going to want to get data.
| | 04:11 | Now, we are going to want to tell it what format.
| | 04:13 | In this case, we are going to use ClipboardsFormats.
file_list_format and then we are going to need
| | 04:19 | to pass one more item and this item tells the
application that's sending us the data if we want a copy
| | 04:24 | of the data or if we want the original thing.
| | 04:27 | In this case, we are just going to want a copy, so
we are going to use the class ClipboardTransferMode
| | 04:32 | and we are going to want to use a clone only.
| | 04:36 | So, now that we have actually grabbed the data, we
actually can now make it into the type that it needs to be.
| | 04:42 | If we would have run this code right now, it would throw
an error saying, "You are trying to make this clipboard data
| | 04:47 | into an array, but we don't know that that's an array."
| | 04:49 | So, we actually can cast this data and say it's
going to return an array, so that the compiler knows.
| | 04:55 | Now, the next thing that we are going to need to
do is we are going to want to create a new file.
| | 04:59 | Now, we haven't yet dealt with the File class inside of AIR.
| | 05:02 | The important thing to know is that an instance of the
File class can represent either a file or a directory.
| | 05:07 | In this case, it's going to reference a file.
| | 05:09 | Since the file list returns an array of files, we are just
going to take the first item off the list and we are going
| | 05:14 | to tell the compiler that it's going to return a file,
because arrays can contain many different types of data.
| | 05:19 | This way our application knows exactly
what type of data is in the array.
| | 05:22 | Now, the last item that we will
need to implement this is we want
| | 05:26 | to set the Image Loader Source property
equal to a property of our file object.
| | 05:30 | Now, each file object contains a property called URL, which
is a URL formatted reference to its path on the hard drive.
| | 05:37 | This way the Image Loader can know
where to go find the picture.
| | 05:40 | So, if we save our application, close the
Action panel, we can now test our movie.
| | 05:44 | So, if we go to Control and then Test Movie, you can
actually see that everything works as it did previously.
| | 05:50 | We also have the capability to drag data out, but in
addition I am going to open up a folder of some pictures.
| | 05:56 | And just the sample pictures that come with Microsoft
Vista, we now can go and drag any of these images
| | 06:03 | into our application and we now can see
it properly displayed on the screen.
| | 06:09 | So our application now has the ability, not only
to drag data out but also to drag specific files
| | 06:14 | into the application and have them previewed in
real time, truly creating two-way communication
| | 06:19 | between the operating system, other
applications and our application.
| | Collapse this transcript |
|
|
5. Using the File SystemIntroducing file system support| 00:00 | One of the main differences between AIR and a traditional
web-based Flash movie is the File System Support.
| | 00:05 | In a Flash movie, you can select a file from the user's
hard drive and upload it through the FileReference class.
| | 00:10 | In AIR, you have the capability to create, edit, move,
and copy files in directories on the user's hard drive.
| | 00:17 | There are three main classes that you
will use on a regular basis in AIR,
| | 00:20 | when you are working with the File System Support.
| | 00:23 | These classes are first, the File class.
| | 00:25 | Now, this contains a reference to an object in the
file system, so it can be either a file or directory.
| | 00:30 | It also contains static properties to
give information about the file system.
| | 00:34 | Now, this class will be used quite often whenever you
are working with the actual file system and again,
| | 00:39 | you will have an instance of this class for each
and every file reference that you are working with.
| | 00:43 | The next class is a FileMode class.
| | 00:44 | Now, it's going to define the different modes that can be
used for opening a file read, write, append, and update.
| | 00:50 | So, every time you open a file, you are going
to be opening it in one of these four modes.
| | 00:55 | The last class that you are going to be using
on a regular basis is the FileStream class.
| | 00:59 | Now, this class is able to open files,
read data from them and write data to them.
| | 01:03 | Now, within AIR, the File System Support enables you to do
a lot of these actions such as copy a file or directory,
| | 01:09 | delete a file or directory, send a file or
directory to the trash, move a file or directory,
| | 01:15 | as well as getting a list of files, within a directory.
| | 01:17 | So, you can see that any basic
file action that can be performed
| | 01:20 | within the operating system can be done within AIR as well.
| | 01:23 | The File class contains static references to specific
directories that work across different operating systems.
| | 01:29 | This is extremely important because one of the great
things about AIR is that it can work on multiple platforms,
| | 01:35 | it can work on Windows, it can work on Mac.
| | 01:37 | Now, if you hard code a directory such as
c:documentsandsettingdavidtucker that's not going to work
| | 01:44 | on a Mac, where it might work on Windows machine.
| | 01:47 | So the File class gives you the static references, so
that you can reference a directory by these names instead
| | 01:53 | of actually by their actual hard coded name.
| | 01:55 | First File.applicationDirectory,
now this directory is a directory
| | 02:00 | that actually houses the core bits of your application.
| | 02:02 | For example, the compiled SWF file for your AIR
application will actually reside in this directory.
| | 02:08 | The applicationStorageDirectory is a
directory that actually contains any extra assets
| | 02:12 | that you might have for your application.
| | 02:14 | Both of these contain shortcuts that
enable you when you are typing out the path
| | 02:18 | to actually get to the directory using less text.
| | 02:21 | The first uses app:/, the second one uses appstorage:/.
| | 02:27 | These options just give you a quicker and more
concise way to get to the specific directories,
| | 02:31 | wherever the user happens to install your application.
| | 02:34 | The next one is File.desktopDirectory, as well as
File.documentsDirectory and file.userDirectory.
| | 02:41 | These are operating system specific directories that
the user can use to store specific pieces of information
| | 02:46 | and now you can reference these painlessly and have
it work on every operating system that AIR can run on.
| | 02:52 | Finally a warning, unlike with the Flash movie,
you can perform real file system actions with AIR,
| | 02:58 | so you need to be very cautious when
working with the file system in AIR.
| | 03:01 | If you choose to delete a file, it's
really deleted, if you choose to move it
| | 03:04 | to the trash, it's really moved to the trash.
| | 03:06 | The same thing with moving files, so just be sure
and be cautious with this new power that you have
| | 03:11 | to develop powerful desktop applications.
| | Collapse this transcript |
| Working asynchronously vs. synchronously| 00:00 | AIR provides two different methods for interacting
with the file system, synchronous and asynchronous.
| | 00:05 | Now, these are also the same two different methods
that exist for working with the embedded SQL database
| | 00:10 | that will be covered later in the series.
| | 00:11 | Now, these two methods work very differently
and each method has its own place.
| | 00:15 | First, let's look at some examples to compare
synchronous and asynchronous programming.
| | 00:20 | In this first example, we are going to be
using the FileStream class to open a file
| | 00:24 | and while we haven't discussed this thoroughly, you can see
that we've created instance of the FileStream, we open it,
| | 00:29 | we extract data from it and then we close the FileStream.
| | 00:33 | So, in reality, in those four lines of code,
we have been able to accomplish all of that.
| | 00:37 | Now, let's look at the asynchronous example.
| | 00:40 | In the asynchronous, we created
a new instance of the FileStream.
| | 00:43 | We added an event listener for the Event.COMPLETE event.
| | 00:46 | Then we open the FileStream.
| | 00:48 | We actually respond to the Event.COMPLETE method and
then inside of that method, we actually read the data
| | 00:53 | out of the file and then close the FileStream.
| | 00:56 | Each of these different methods has pros and cons.
| | 00:59 | With synchronous, there is less code to accomplish file
operation, so you don't have to actually respond to events
| | 01:05 | so you will know that when you enter a command, it actually
will be completed before moving to the next command.
| | 01:09 | The problem is that it can negatively
impact the user experience.
| | 01:13 | For example, if you are loading in a really small text
file, nothing is going to happen, it will be fine,
| | 01:18 | it will load it in quick enough that
the user won't notice any problems.
| | 01:21 | However, if you are loading in a video file that's
2GB in size, the user is going to have to wait
| | 01:26 | and your application will be basically
frozen while this action is taken.
| | 01:30 | They won't be able to interact with your
application at all during this time.
| | 01:33 | And finally, it should only be used for smaller files
because as we stated, anytime you work with larger files,
| | 01:38 | you can negatively impact the user experience.
| | 01:40 | Asynchronous works different however.
| | 01:42 | First, it takes more code for basic file operations.
| | 01:45 | So now, instead of just opening a
FileStream, you have to add an event listener,
| | 01:49 | open the FileStream and then respond to that event.
| | 01:51 | It does not affect the experience of the end-user.
| | 01:55 | You open up the door for the user to
still interact with your application even
| | 01:58 | if a very intense file system action is taking place.
| | 02:02 | Finally, it can be used with files of any size.
| | 02:05 | Now, the truth is synchronous code
is very easy to read and understand.
| | 02:08 | And if you can learn to develop asynchronously,
developing synchronously in situations
| | 02:13 | where it can be useful will be very easy.
| | 02:15 | So, all of the code samples that we will be doing
for the series will be done in the asynchronous mode.
| | 02:20 | This way, you can develop your applications that
it won't negatively impact the user experience.
| | 02:25 | Synchronous programming certainly has its place.
| | 02:27 | If you need to develop an application
quickly for prototyping purposes,
| | 02:30 | synchronous programming can work very well.
| | 02:33 | Or if you are in a situation where you know that you
are only going to be dealing with very small files
| | 02:36 | and there is not even a remote possibility
you will be dealing with larger ones,
| | 02:40 | you can look at synchronous programming to save time.
| | 02:42 | However, in most situations, especially with applications
where the user can control what type of data is loaded
| | 02:47 | into the application, we'll probably want to use
asynchronous programming so you don't run into some
| | 02:52 | of the problems that I mentioned earlier.
| | Collapse this transcript |
| Browsing for files and directories| 00:00 | So up to this point, we have developed an application
that actually pulls in the names and locations of images
| | 00:05 | through an XML file, but ideally we would
like for the user to be able to select files
| | 00:10 | and directories off of their own hard drive to view.
| | 00:12 | Now the File class contains many methods that
allow the application to prompt the end user
| | 00:17 | to select a file or directory from their hard drive.
| | 00:21 | This would be needed when the user needed
to select the location to save a file,
| | 00:24 | to select a directory of pictures to
browse or to select files to open.
| | 00:27 | So let's go ahead and implement
that inside of our application.
| | 00:30 | First, we are going to go to File and then Open
and we are going to select the ImageViewer01 file
| | 00:37 | in the Chapter 05 folder of the exercise files.
| | 00:39 | Now that we have opened our application,
let's look at this Stage.
| | 00:42 | Since we are adding in a new piece of functionality,
we are going to need to add in another button.
| | 00:46 | In this case, we are going to want to create a button
that has a label of Browse that then the user can click
| | 00:51 | and that will be prompted for a directory of pictures.
| | 00:54 | So the first thing, we will need to do is unlock the Buttons
layer and then we are going to open the Components window.
| | 00:59 | We now can drag a button from the Components
window on to the Stage and we are going
| | 01:03 | to give it a label by going under parameters of Browse.
| | 01:06 | We are also going to give it an
instance name of browseButton.
| | 01:12 | Now we can select all of our buttons.
| | 01:14 | We will align them to the center and we
will be sure that they are evenly spaced.
| | 01:19 | Now we can relock the Buttons layer and we can
highlight our Actions layer and go under Window
| | 01:23 | and then Actions to open the Actions panel.
| | 01:26 | The first thing we are going to need to do is we are going
to need to add an event listener for our Browse button,
| | 01:30 | so we will say browseButton.addEventListener and we are
going to want it to listen for the MouseEvent.CLICK event.
| | 01:40 | And then we are going to have it
respond with the method onBrowseClick.
| | 01:47 | So now if we scroll down to our event
handler section and go to the end of it,
| | 01:51 | we are going to add one more event handler.
| | 01:53 | So we will set a function onBrowseClick, we will
receive an event of type MouseEvent and it's not going
| | 02:02 | to return anything so we can leave the return type as void.
| | 02:05 | Inside of this method, we are going to
want to do a few things specifically.
| | 02:08 | The first thing we are going to do is we are
going to create an instance of the File class.
| | 02:11 | So we will saay var file of type, File
is going to be equal to a new File.
| | 02:19 | The next thing we will need to do is we will
need to add an event listener for this file
| | 02:22 | because we are getting ready to
ask the user to select a directory.
| | 02:25 | When they do, it will actually dispatch a SELECT
event and then this will fire another method.
| | 02:30 | So in this case, we want to say file.addEventListener
and we are going to listen for the Event.SELECT event.
| | 02:37 | And then we will respond with the
onDirectorySelect method that we will create shortly.
| | 02:44 | Next we need to actually prompt the user, to accomplish
this we simply need to say file.browseForDirectory
| | 02:53 | and then we will tell the user we
just want them to select pictures.
| | 02:58 | Now if we save our application, if we attempted to run it
at this point, it would through an error because we have not
| | 03:03 | yet created our onDirectorySelect method.
| | 03:05 | So I am going to go ahead and create a shell of this
method that we actually will be implementing later.
| | 03:10 | So we will say function onDirectorySelect and then we
will say that it's going to receive an Event of type event.
| | 03:20 | It's not going to return anything, so we
can go ahead and leave the return type void.
| | 03:23 | And since we are not yet implementing this functionality,
I am going to leave myself a little to doonCopyClick note
| | 03:27 | to remind myself to go back and add this functionality.
| | 03:30 | So we will say ToDo Add Directory Listing.
| | 03:35 | So now we can save our application and if
we go under Control and then Test Movie,
| | 03:42 | we can see here that our application works as it has before
we can select a smaller image and see the larger image,
| | 03:47 | but now we also have the Browse button. If we click
the Browse button, it will prompt us for directory.
| | 03:52 | We then can go and select a directory that we
would like, but at this point when we click OK,
| | 03:56 | nothing is going to happen because we
haven't yet implemented this functionality.
| | 03:59 | However in the course of this lesson, you have
learned how to create an instance of the File class
| | 04:04 | and use that to then prompt the user to select a directory.
| | 04:07 | Now you are ready to actually respond to that event and
display a listing of all the files within a given directory.
| | Collapse this transcript |
| Listing the contents of a directory| 00:00 | Now that you have been able to prompt the user
to select a directory on their hard drive,
| | 00:04 | you are going to want to be able to respond to that
by actually taking that directory and learning how
| | 00:08 | to list all the files that are inside of it and also
learning how to look at each of those and determining
| | 00:13 | if it's a file, if it's a directory or even if it's
a certain file type that you want to work with.
| | 00:17 | So let's go ahead and implement
that inside of an application.
| | 00:20 | So I am going to go to File and then Open and then
I am going to open the ImageViewer02 file inside
| | 00:26 | of the Chapter 5 folder in the exercise files.
| | 00:29 | So if I test the movie, I have got the ability here to
select the Browse button, where we can select a directory
| | 00:36 | from the hard drive, but if we click OK, nothing
happens because we haven't yet implemented that method.
| | 00:41 | So let's go ahead and close the application.
| | 00:43 | Go to the Actions layer, go to
Window and then go down to Actions.
| | 00:47 | Now we are going to scroll down to the method
that we didn't fully implement previously.
| | 00:51 | Well now that we have gotten there,
because I add it a ToDo tag that reminds us
| | 00:54 | that we need to add the directory listing.
| | 00:56 | So I will just highlight that comment and delete it.
| | 00:58 | Now the first thing we are going to need to do is
because we are going to want do display our images
| | 01:03 | from this folder actually in the Tile List, we are going to
want to remove the current items that are in the Tile List.
| | 01:08 | So we will just say imgList.removeAll and
that will remove all of the current items.
| | 01:14 | Now we are going to want to get a reference to the
directory that the user selected from the prompt.
| | 01:19 | So we can say var and since this a file reference, we
will just call it fileRef and it's actually of type File
| | 01:26 | and we are going to actually set that equal to Event.TARGET.
| | 01:30 | Now this is another situation where
we are going to have to use casting.
| | 01:33 | Event.TARGET can contain a lot of different types of data,
| | 01:36 | we need to reassure the compiler
that we are passing it a file.
| | 01:39 | So we will say Event.TARGET as File.
| | 01:43 | Next we are going to need to actually get a
listing of all of the files within the directory.
| | 01:47 | It's going to return an array.
| | 01:48 | So let's go ahead and create an array to use.
| | 01:50 | We will say var dirListing, which is a short for
Directory Listing, of type Array. It's going to be equal to-
| | 01:58 | and this is a new method that we are going to use.
| | 01:59 | We are going to get the file reference and again this
is a reference to that directory that the user selected
| | 02:04 | and then we are going to use the method getDirectoryListing.
| | 02:10 | Now we actually have an array of each of these items.
| | 02:13 | Now we actually need to go in and create
a listing for each of these arrays.
| | 02:17 | So we also need to go in and take
a peek at each of these and be sure
| | 02:20 | that we are actually looking at an
image, which we want to look at.
| | 02:23 | So we are going to be using the for each statement.
| | 02:25 | We will say for each, and then we need to
say for each file, so we will say var file, in
| | 02:31 | and then we need to pass in our array, DirListing.
| | 02:36 | Now this way, this one statement, the for each statement
will loop over each item in the directory listing.
| | 02:41 | Inside of the for each statement, we can use the variable
file to refer to the current item as it's looping through.
| | 02:48 | Now if we want to add these to the Tile
List, the first thing we are going to need
| | 02:51 | to do is we are going to need to create a new object.
| | 02:54 | But before we can actually create
the object and give it the data,
| | 02:56 | we want to be sure that we are working with a real file.
| | 02:59 | So we need to actually examine it.
| | 03:01 | So we are going to create an if statement.
| | 03:02 | The first thing we are going to want
to do is that we want to be sure
| | 03:05 | that we are looking at a file and not a directory.
| | 03:07 | Now the instance of the File class
contains a property called isDirectory.
| | 03:12 | If this is a directory it will return true.
| | 03:14 | If it's not a directory, it will return false.
| | 03:17 | In this instance, we only want it to return true if
it's not a directory, so to do that we are just going
| | 03:23 | to put an exclamation point in front of it and
it will actually reverse whatever the result is.
| | 03:28 | So in this case, if the file is a directory, it will
return false, if it's not a directory, it will return true.
| | 03:34 | We also want to check and be sure it's not symbolic link.
| | 03:37 | Now some system support symbolic links and
basically that's just where there is a file inside
| | 03:42 | of the directory that's just a pointer to another file.
| | 03:45 | We want to be sure we are not looking
at any of those either.
| | 03:47 | So there also is a property file.isSymbolicLink.
| | 03:52 | Now we want to do the same thing here,
we don't want it to be a symbolic link,
| | 03:55 | so we want it to return true if it's not.
| | 03:58 | To accomplish this, we are going to put
another exclamation point in front of it.
| | 04:01 | So now we have ensured that this is a kind
of file that we want to be working with.
| | 04:05 | So now we are going to create an object
to actually insert into the Tile List.
| | 04:09 | We will say var O is of type Object
and that's equal to a new Object.
| | 04:14 | Then we are going to want to actually fill in the data
unlike with the XML where we had a separate image file
| | 04:20 | for the thumbnail as well as for the larger version, in
this case we are going to use the large image for both
| | 04:25 | and actually just have it scale down the
large image to fit into the thumbnail.
| | 04:28 | So our data and source properties
are both going to be the same.
| | 04:31 | So we will say o.data is equal to file.nativePath.
| | 04:36 | Now we haven't used this property before, but it actually
returns the path of the file on the local hard drive.
| | 04:42 | In the format, all files are expected
to be for that operating system.
| | 04:46 | We will actually look at this a little
bit more in depth in the next video.
| | 04:49 | But we are going to set o.data and
o.source equal to file.nativePath.
| | 04:55 | Now the last thing we are going to need to do
is actually add this object to the Tile List.
| | 05:01 | Since we have removed all the items that are in
there before we can just call the addItem method
| | 05:05 | and then we will add in our object.
| | 05:09 | Now we can hit Save.
| | 05:10 | So just to review, we have removed all the items from
the Tile List, we have created a file reference that's
| | 05:14 | of type file that points to the
directory that the user selected.
| | 05:17 | We have gotten all the files in the directory, in the
directory listing then we have looped through each of them
| | 05:22 | to ensure that they are not a directory or a symbolic link.
| | 05:24 | Now we can actually test on moving.
| | 05:26 | If we go to Control and then Test Movie, we
now can select Browse and I happen to know
| | 05:32 | that I have some pictures in my Pictures directory.
| | 05:34 | I am going to go to the Edinburgh directory and then hit OK.
| | 05:37 | Now it's going to throw an error, it's going
to say loaded file is an unknown type.
| | 05:42 | Now this actually is okay, because I
also know that there are one or two files
| | 05:45 | in this directory that aren't actually image files.
| | 05:48 | We want to ensure that we are looking at the right
kind of files, so let's go back to our application.
| | 05:53 | If we look here, we have already checked to see if the file
is a directory and a symbolic link, but now we want to check
| | 05:59 | and be sure that we are looking at a file
that has .jpg somewhere in the file name,
| | 06:03 | that way we can sure that we are
working with an actual JPEG file.
| | 06:06 | So we will say and we also want to check file.nativePath
because we said earlier it contains the native path
| | 06:14 | for that specific file in the operating
system and it's actually a string.
| | 06:18 | Now one of the methods that you can
use from the String class is Search.
| | 06:22 | You can tell this to search for
a string within the file name.
| | 06:25 | So we will say we want to search for .jpg.
| | 06:29 | Now if this actually finds .jpg in the
file name, it's going to return a number
| | 06:33 | that indicates where in the string this occurs.
| | 06:35 | If it doesn't find .jpg then it's
going to return negative one.
| | 06:40 | So we just want to say, we want to be sure
that this does not equal negative one.
| | 06:44 | So now we can actually close that section, save it,
now we can go back and launch our application again.
| | 06:51 | We will say Control, Test Movie,
now it brings back up our movie.
| | 06:56 | We can now browse and go back down to my pictures
directory and go to Edinburgh and click OK.
| | 07:02 | And now no errors have been thrown and we can be sure
| | 07:05 | that we are actually dealing with
JPEG images, which we want to do.
| | 07:08 | Now if you wanted to extend this application even further,
you could actually have it check for other file name formats
| | 07:13 | that you might want to support as well such
as PNGs which the Flash player can load file.
| | 07:17 | But in this case we have created an application
that prompts the user to select a directory.
| | 07:22 | We have then looped through all the files in that directory
using the getDirectoryListing method then we have checked
| | 07:27 | each of those files to be sure that it's
not a directory, it's not a symbolic link
| | 07:30 | and to be sure that it has .jpg in the file name.
| | 07:33 | We will continue putting a lot of these other methods
from the File class together to create an application
| | 07:37 | that truly has great support for the file system.
| | Collapse this transcript |
| Using the File class properties| 00:00 | Now that we are able to open a directory look at all
of its contents and look at each of the files contained
| | 00:05 | in that directory and determine
some information about them such as
| | 00:08 | if they are a directory or if they are a symbolic link.
| | 00:10 | We are going to look at some other properties of the file
class that will enable us to do some things more efficiently
| | 00:15 | than we did in the previous movies
as well as access some information
| | 00:18 | about the file that we haven't actually accessed yet.
| | 00:21 | So to accomplish this we are going
to need to open the application.
| | 00:24 | So if we go to File and we go to Open we are going to open
ImageViewer03 in the Chapter 5 folder of the exercise files.
| | 00:31 | Now we are going to go to the Actions panel so let's click
on the Actions later and then go to Window and then Actions
| | 00:37 | and we are going to place what's
called a breakpoint in our application.
| | 00:41 | This needs to be done at a very specific point for us to
be able to view the data that we need to view so scroll
| | 00:45 | down to the onDirectorySelect method and then we are going
| | 00:49 | to place a breakpoint directly here
to next to where it says var o Object.
| | 00:54 | Now what this will do is when we
launch our application in Debug mode
| | 00:58 | when the application reaches this point it will stop
| | 01:01 | and it will let us inspect the
current properties within this method.
| | 01:05 | We are going to take a closer look at the file class and
its properties so let's go to Debug and then Debug Movie.
| | 01:13 | It will take a second for our application to load but
once it does it will look just like it did before.
| | 01:17 | We are going to go to browse and then I am going
to go under David Tucker and then Pictures.
| | 01:22 | You can pick a directory that you
have on your system if you would
| | 01:24 | like to use another directory as
long as it contains some JPEGs.
| | 01:26 | Let's click on Edinburgh, click OK and you will
notice in the background things have kind of changed.
| | 01:32 | First the notification is telling us the Flash has
something it wants us to see so if we click on the taskbar
| | 01:37 | and go to Flash or if you are on Mac
you can actually click on the dock.
| | 01:41 | We are then going to move in and we are
going to look at this instance of file.
| | 01:44 | If we look at the code on the right this is were
we actually looping through each of the files.
| | 01:49 | And you can see for each file, so we are actually
looking at the first instance of the file.
| | 01:54 | So if we move this over and we go to the Variables window
we can look at this instance of File and see its properties.
| | 02:00 | If I press the plus sign next to it, it will
expand and show me all the information that it has.
| | 02:05 | There is a couple of things I want to note specifically,
| | 02:07 | if you look at the field named nativePath you can see the
native path of the application that begins with c:/users.
| | 02:15 | This is going to be the native path for that specific
operating system so sometimes when you are working
| | 02:20 | with other applications you are going
to need to be able to access this data.
| | 02:23 | In addition we also have a URL property
and if we look at that it starts
| | 02:28 | with a file:/// before it moves on to the native path .
| | 02:31 | But also in the place of a space between David
and Tucker it's replaced it with percent 20.
| | 02:36 | So this is basically a URL encoded version of a
file name that can be used also in communicating
| | 02:42 | with other applications or passing this information
through a component within your own application.
| | 02:46 | There are two other properties I want to
note. First if you look at Type you can see
| | 02:51 | that this is a JPEG file. It says .jpg.
We can use this in our application
| | 02:56 | so we don't have to use the Search method of the string.
| | 02:58 | This will shorten the code that we have to write.
| | 03:00 | In addition you can see that there
is also a Name property, 1.jpeg.
| | 03:04 | That we can then use for the captions
within our application.
| | 03:08 | By using these properties we can
decrease some code in some areas
| | 03:11 | and we also can gain some functionality
in others, so let's exit Debug mode.
| | 03:15 | To accomplish this we are going to
click the Red X in the Debug console.
| | 03:18 | Now that we are back to our application
we are going to first go and we are going
| | 03:23 | to add the name as the caption for each image.
| | 03:26 | So we will say o.caption = file.name.
| | 03:32 | In addition we are going to go to the section where
we were searching for jpeg and we are going to add
| | 03:37 | in an equality statement, we will say file.type = .Jpg
this way we can check to see if it is indeed a jpeg file
| | 03:48 | without having as much code as we had previously.
| | 03:52 | Now we can save our application we can take our
breakpoint off and we can go to Control and then Test Movie.
| | 04:00 | Now if we browse and just go to a directory of pictures
| | 04:03 | and then click OK we will notice
a couple of things have changed.
| | 04:07 | First of all it did indeed load only the jpegs.
| | 04:10 | We don't have error saying that there is a
file that isn't a jpeg within this directory.
| | 04:14 | In addition we can see that the names of our
images have been added as the captions below.
| | 04:18 | So in a lot of ways this is functioning
just like it did in the beginning
| | 04:21 | when we were loading all the images in from XML.
| | 04:24 | By using these file properties you can
learn how to better access your files
| | 04:27 | as well as how to obtain information about them.
| | 04:29 | There are many other properties that we won't be using
in this application and we can determine things such as
| | 04:34 | when the file is last modified and when it was
created and this information can prove very useful
| | 04:38 | as you are creating full featured applications
that utilize a file system support within AIR.
| | Collapse this transcript |
| Performing file system actions| 00:00 | Now that we have created an application
it allows us to look through a directory,
| | 00:03 | see all the files and even find properties of those files.
| | 00:07 | We now want to be able to perform
basic file actions on these files.
| | 00:10 | Now this can all be accomplished
with the file class inside of AIR
| | 00:13 | and gives you the developer the ability
to create very powerful applications.
| | 00:17 | So let's go ahead and add that
to our Image Viewer application.
| | 00:20 | First let's go under File and then
Open and then select ImageViewer04
| | 00:24 | in the Chapter 5 folder of the
exercise files and then hit Open.
| | 00:28 | We are going to stay on the Stage for a
second and add one more item to the Stage.
| | 00:32 | To do that we are also going to need to another
layer and we are going to call this layer ComboBox.
| | 00:38 | We are now going to go to the Components window under
Window and then Components and then we are going to drag
| | 00:43 | out an instance of, you guessed it the ComboBox.
| | 00:46 | We now can close the Components window.
| | 00:47 | I will move this around so it lands up on the Stage and
we will give window an instance name of fileActionBox.
| | 00:54 | Now we are also going to want to
adjust some of its parameters.
| | 00:57 | So if we hit the Parameters tab we are going to
want to be sure that the Editable Property is set
| | 01:02 | to False then we are going to select the
dataProvider property and then we are going
| | 01:05 | to hit the magnifying glass on the right.
| | 01:07 | Now we can actually add values to this ComboBox.
| | 01:10 | First we are going to give it a
default label of File Actions.
| | 01:15 | Then we are going to give the first
label the value of Copy file,
| | 01:20 | then we are going to add another one then we
are going to give it a value of move to trash.
| | 01:26 | Then we are going to add one more
and give it the label of Delete File.
| | 01:29 | Now we don't need to worry about the Data Properties
for any of these items then we will click OK.
| | 01:36 | Now we actually are ready to move in
and begin working with ActionScript
| | 01:39 | so let's lock our ComboBox layer then select the
Actions layer and go to Window and then Actions.
| | 01:45 | The first thing we are going to need to do is add an
event listener for our fileActionBox so if we scroll
| | 01:50 | down to our Event Listener section we can
then move to the end and add a new one
| | 01:54 | and it will be fileActionBox.addEventListener
and then in here it every time the value
| | 02:00 | of a ComboBox is changed it dispatches the changed event
so we will be looking for Event.CHANGE and we will respond
| | 02:06 | to that with the onFileActionBox method
so let's go ahead and add that method.
| | 02:13 | Let's scroll down to our Event
Handler section and we are going
| | 02:17 | to create a new function which will be onFileActionBox.
| | 02:22 | Let's go into receive an event of type
Event and it's not going to return anything
| | 02:26 | so we can leave the return type equal to void.
| | 02:29 | Now here inside of this method before we can perform
any file actions we are going to be need to be sure
| | 02:33 | that one thing is true if there is actually an item
selected on the Tile List so to accomplish that we will say
| | 02:40 | if imglist.selectedItem so if there is
a value in that then we will proceed
| | 02:47 | but if not we are just not going to do anything.
| | 02:50 | So now all of the logic that will exist for us moving our
file to the trash or deleting it or copying it is all going
| | 02:55 | to be contained inside of this if statement.
| | 02:57 | And we are going to determine which value is currently
selected on the ComboBox by using a switch statement.
| | 03:02 | So we will say switch and we will switch actually on the
statement fileActionBox.selectedItem.label so depending
| | 03:13 | on what this value is we actually do different things.
| | 03:16 | We can now setup our cases for each of the actions.
| | 03:19 | First we have Copy File and then we can go in
and just add a comment reminding us to come back
| | 03:26 | and implement the copy file functionality
then we can add a Break statement.
| | 03:30 | Now each of these will need to have a break statement.
| | 03:33 | If they don't you are on the possibility of trying
to commit multiple actions on a single file.
| | 03:38 | The next one will be case. Say Delete File, add the break
statement and then finally we will say Move to Trash.
| | 03:56 | And then we will add our break statement.
| | 03:59 | Now we are going to need one property to each of the items
in the tile list to make this possible so we will scroll
| | 04:05 | up to our onDirectorySelect method and we
will add the property file to the object.
| | 04:10 | Now we are just going to set this equal to the current file
so this property will contain an instance of the file class
| | 04:16 | for each of the images that's being displayed.
| | 04:19 | Now we can scroll down and actual begin working
with implementing these pieces of functionality.
| | 04:24 | So first we will actually look at implementing the copy
functionality so the first thing we are going to need to do
| | 04:29 | to copy our file is we are going to need to
create an instance of the File class and this is
| | 04:33 | because we are actually going to prompt the user
with where we want them to save this copied file.
| | 04:38 | So we will first say var f of type
File is equal to new File.
| | 04:43 | Now since we are going to actually prompt the user
we need to be sure that we add an event listener
| | 04:48 | which will be f.add ventListener
and when I select the location
| | 04:52 | to save this copied file it will actually
dispatch the select event so we want to listen
| | 04:56 | for Event.SELECT then we will respond
to it with the onCopySelect method.
| | 05:02 | Finally to actually ask the user where they want to save the
file we can call the f.browseForSave method then we need
| | 05:11 | to give it a name and in this case we will say Copy File To
| | 05:15 | that way the user will know why again they
are having to enter the name of the file.
| | 05:18 | Finally the last thing we are going to want to do is
actually set the fileActionBox back to its default value
| | 05:24 | so we will say fileActionBox.selectedIndex and we
will just set that equal to 0 and that will set it back
| | 05:33 | to the very first value in its data provider.
| | 05:36 | Now we need to create our onCopySelect
method now this method will receive an event
| | 05:45 | of type Event and the return type will be void.
| | 05:49 | Now inside of this method we are going to need to
actually pull the file reference out of the event
| | 05:54 | so we will say var file of type File will be equal
to and we are going to set it equal to Event.TARGET
| | 06:03 | and that will actually get the value of the file.
| | 06:05 | But again because the Event.Target can contain
a lot of different values we are going to want
| | 06:10 | to specifically tell the application
that it contains a file.
| | 06:13 | This is called casting.
| | 06:15 | Now the next thing we are going to
need to do is actually perform the copy
| | 06:18 | so in this case we will say imglist.selectedItem.file,
and then we will say Copy to Async.
| | 06:28 | Again we are going to be asynchronous methods.
| | 06:30 | Now if we actually needed anything to happen when this file
was done copying then we would need to add an event listener
| | 06:36 | but in this case we can actually just tell it to
copy and then the user can go back later if they want
| | 06:40 | to actually see the location where that file has been saved.
| | 06:43 | Then we also need to pass into this method
where we wanted to copy the file to.
| | 06:46 | We have already prompted the user for this
so we can just pass in the file reference
| | 06:50 | that was created when they actually selected the file.
| | 06:53 | Now we need to actually implement the delete and move
to trash options so let's move to the delete option.
| | 06:58 | We can go and highlight the comment and then delete it.
| | 07:01 | In this case we are going to need to respond to
the complete event of the deleteFileAsync method.
| | 07:07 | So we are going to first say
imglist.selecteditem.file.addEventListener.
| | 07:15 | This will actually let us listen for when the File
Delete command is been completed so we wanted to listen
| | 07:20 | for Event.COMPLETE and then we will
respond with onFileActionComplete.
| | 07:28 | Now we can actually delete our file
imglist.selectedItem.file again this is a reference
| | 07:36 | to the current file of the item that is
selected and then we will say deleteFileAsync.
| | 07:42 | We don't need to pass any parameters into it.
| | 07:44 | It will just delete the file that have references.
| | 07:46 | And the last thing that we need to do in this part of
the method is actually to set the fileActionBox back
| | 07:51 | to its default value that can be accomplished
by just copying and pasting that in.
| | 07:56 | Now we are going to need to actually write the
onFileActionComplete method so we will scroll
| | 08:01 | down below our onCopySelect method and create
onFileActionComplete and it will receive an event
| | 08:10 | of type Event that's not going to return
anything so we can leave the return type as void.
| | 08:14 | Now inside of here we are only going to need to do one
thing since we are actually deleting an item that's
| | 08:19 | in our tile list we are going to want to actually remove
that item from the list so we can say imglist.removeItem
| | 08:25 | and then from here we are going
to remove imgList.selectedItem.
| | 08:33 | Now we can scroll back up and implement our move to trash.
| | 08:36 | We actually can copy most of the code from the delete
file section and paste it in the move to trash section.
| | 08:43 | The only thing that we have to be changed is instead
of delete to file aysnc we are just going to say move
| | 08:49 | to trash async and everything else can remain the same, even
the same method can respond to the Event.COMPLETE event.
| | 08:58 | Now we have implemented all of the
functionality for our file action support
| | 09:01 | so now we can test our application and see if it works.
| | 09:04 | So I am going to close the Actions panel and
we are going to go to Control and Test Movie.
| | 09:08 | Now this isn't going to work with any of the items
that are loaded in by default through the XML.
| | 09:14 | We are actually going to have browse through a directory.
| | 09:16 | So we will say Browse and go to
David Tucker and then pictures
| | 09:20 | and then we will actually click on this event of folder.
| | 09:22 | You can choose any folder on your
hard drive that contains images.
| | 09:25 | Now here is a picture of a fountain in number 2 and let's
just say for some reason I just don't like this picture.
| | 09:30 | I actually can now go to File Actions
and move this file to the trash.
| | 09:34 | You can see that when that is completed it
actually has been removed from the list.
| | 09:37 | In the same way let's say I want to
save a copy of this particular picture.
| | 09:41 | Well I can easily go to File Actions and say Copy File.
| | 09:45 | It will then prompt me for where I want to
save it I will just call this one copy.jpg.
| | 09:50 | Once I hit Save it will actually perform the copy.
| | 09:53 | If I now go to the desktop I can see that indeed
it has copied over my file and I have a copy
| | 09:58 | of the original right here on my desktop so with
this functionality you can easily include some
| | 10:03 | of these core file actions within your application and now
you are ready to move on to actually working with writing
| | 10:08 | and receiving data from files on the local hard drive.
| | Collapse this transcript |
| Writing data to a file| 00:00 | There will be many times when you want to
actually store data on the user's local computer.
| | 00:04 | As we discussed earlier, one of
the ways that you can do that is
| | 00:07 | to actually store data inside of
a file on the user's computer.
| | 00:10 | Obviously, the File System Support
within there gives you this capability
| | 00:13 | and we are going to actually use this in our application.
| | 00:16 | We want to actually allow the user to set the
default directory that will actually be displayed
| | 00:21 | when they open up our Image Viewer application.
| | 00:23 | This way we can get rid of the old XML file that we
use to deal with, in this way it entirely is linked
| | 00:28 | to the user's file system and because of that it can
then be customized for each individual user's needs.
| | 00:34 | So, now let's go to the File menu
and open up our application.
| | 00:37 | We will go to Open and we will open up ImageViewer06,
in the Chapter 5 folder in the exercise files.
| | 00:44 | Now, if we look at the Stage, we
have 4 buttons at the bottom.
| | 00:48 | In this case, I am going to choose to
actually rename a Copy Layer button
| | 00:52 | and make it our Set Default button,
so let's unlock the Buttons layer.
| | 00:56 | We now can just select the Copy Layer button, we are going
to change the instance name to make it setDefaultButton,
| | 01:02 | we are also going to change the label to Set Default.
| | 01:07 | Now, because we changed the instance name, we are
going need to be sure that we delete any old references
| | 01:12 | to the Copy Layer button inside of our ActionScript,
so let's go ahead and lock the Buttons layer,
| | 01:16 | highlight the Actions layer and
then go to Window and then Actions.
| | 01:20 | Let's scroll down to the section, where we have
our event listeners, and you can see there,
| | 01:24 | there is one reference to our Copy Layer button,
we can highlight that and then delete it.
| | 01:28 | In addition, that means there is
also a method we won't need anymore,
| | 01:32 | the onCopyLayerClick method, we
can go ahead and delete that.
| | 01:36 | Now, we are ready to add the event
listener for our Set Default button.
| | 01:39 | So, we can say setDefaultButton.addEventListener and we
are going to be listening for the MouseEvent.CLICK event
| | 01:51 | and we are going to call the onSetDefault method.
| | 01:55 | Before we add that, we are going to need to add a
property that is accessible to the entire application
| | 02:01 | and we are going to actually store
the value of the current directory,
| | 02:04 | when the user selects a new directory
inside of that property.
| | 02:07 | So let's go to the top directly under our Import Statements
| | 02:11 | and we will just create a property
var currentDirectory of type File.
| | 02:18 | We will now need to update our onDirectorySelect method,
| | 02:21 | so that every time the user selects a new
directory it updates the currentDirectory property.
| | 02:26 | So, we will scroll down to our onDirectorySelect method and
inside of here, we can totally do away with the fileRef,
| | 02:33 | the variable that we created to hold the instance
of the file and instead assign currentDirectory.
| | 02:39 | We also will have to do it on the next line,
| | 02:41 | so instead of saying fileRef.getDirectoryListing
we can say currentDirectory.getDirectoryListing.
| | 02:48 | Now, we actually can begin updating our onSetDefault method.
| | 02:51 | So we will add a new event listener, method onSetDefault, it
will receive an event of type Mouse Event and it's not going
| | 03:02 | to return anything so can need the return type void.
| | 03:04 | The first thing we are going to need to do is
to create an instance of a FileStream class.
| | 03:09 | Now, the FileStream class is used anytime you need to stream
data to or stream data from a file on the user's hard drive.
| | 03:16 | So, in this case we will say var and we will just call
it fs, of type FileStream, is equal to a new FileStream.
| | 03:24 | Now, we have not yet imported the
FileStream class, so we will need to do that.
| | 03:28 | But in addition, we are also going to need the FileMode
class, so instead of actually having align for each
| | 03:33 | of those items, we can actually go
back up to our imports and we are going
| | 03:37 | to import everything in the flash.filesystem package.
| | 03:41 | Now, we can scroll back down to our onSetDefault method.
| | 03:44 | Now that we have created the instance of our
FileStream, we can go ahead and add an event listener.
| | 03:51 | Since, we will be working with
the FileStream asynchronously,
| | 03:54 | we want to listen for the Event.COMPLETE event, this
will tell us when it is actually completed writing data
| | 04:00 | to our file and we will respond to that
with the onFileStreamComplete method.
| | 04:05 | As I said, we are going to be opening an
asynchronous connection, so we will say fs.openAsync
| | 04:11 | and now we need to tell it what file we wanted to open.
| | 04:14 | Now, we are going to create a new reference
to a file, so we will say new File.
| | 04:19 | If we pass in a path that already
exists then we will use that file.
| | 04:24 | However, if we pass in a new file
name, that file name will be created.
| | 04:27 | As I stated in the beginning of this chapter,
we can use certain reference that will point
| | 04:32 | to specific directories for our application.
| | 04:34 | We are going to use one of these now.
| | 04:35 | We are going to say AppStorage, which is the
default storage directory for our application ":/"
| | 04:41 | and now we actually can put in the name of our file.
| | 04:45 | In our case, it will be prefs.xml and we will
use this to store application preferences.
| | 04:51 | Now, we can close that and we need to now tell the
FileStream what mode we want to open our file in.
| | 04:57 | In this case, we are going to open
our file in file in FileMode.WRITE.
| | 05:01 | Now, this will actually write data to the file, if
the file already contains data, it will overwrite it.
| | 05:07 | If we wanted to continue writing a file that
already existed, we will use the FileMode.APPEND.
| | 05:12 | If you are working with a file and you want to be able to
not only append data, but also go back and write data then
| | 05:18 | in those cases you are going to use the FileMode.UPDATE.
| | 05:21 | Now, that we have opened an asynchronous connection
to our file, we are going want to actually figure
| | 05:25 | out what data we are going to want
to store inside of our file.
| | 05:27 | So, we are going to create a variable,
fileData and that's going to be a string.
| | 05:33 | And in this case, we are going to actually make the
string contain some XML data, so we will actually want
| | 05:38 | to go ahead and put it our XML header first.
| | 05:40 | So, we will say XML version = 1.0, then
we want to say encoding equals UTF-8.
| | 05:50 | If you notice here, I used single quotes on the outside,
| | 05:54 | because I had to use double quotes
actually inside of the string.
| | 05:57 | Next, we are going to want to actually store the information
about our preferences, so we will say fileData +=,
| | 06:03 | which will continue what we already put inside a fileData.
| | 06:06 | We are going to want to now say prefs and that will
be our outer tag and then we will have an inner tag
| | 06:10 | that will be defaultDirectory and then we are going to
want to actually put in the value of our currentDirectory.
| | 06:18 | So, in this case we will say +currentDirectory
and we will just pass in the native path .
| | 06:25 | Now, we are going to want to add one more item,
our closing tags, so we will say fileData +=
| | 06:32 | and then we will close off our
defaultDirectory and then we will close the prefs.
| | 06:39 | Now, that we have actually added our file data that will
be stored in our file, we actually can begin the process
| | 06:45 | of writing it, so we will say fs.write and
whenever you are writing a string into a file,
| | 06:51 | you are going to use writeUTFBytes and then we
will just say that we want to write the fileData.
| | 06:57 | Now, since we opened it asynchronously,
anytime we read or write data to a file,
| | 07:02 | it will actually dispatch the Event.COMPLETE
whenever it is done actually writing that data,
| | 07:07 | so we actually need to create our one additional
method the onFileStreamComplete method
| | 07:16 | and that will receive an event of type Event.
| | 07:19 | And since, we don't need to return
anything; we can set the return type as void.
| | 07:23 | Now, inside of this method, we really
just need to close the FileStream,
| | 07:26 | so we will say var fs of type FileStream
is equal to Event.TARGET.
| | 07:33 | And as we have stated before, since the target
can contain many different types of data,
| | 07:37 | we need to actually tell the application that it's
going to be a FileStream, so we will say as FileStream.
| | 07:43 | Next, we can just say fs.close and that will
actually close the connection to our FileStream
| | 07:49 | and we would have written our data to the file.
| | 07:51 | So, let's go ahead and test our application.
| | 07:56 | We are going to first browse for a directory,
pick this event in directory and select Open,
| | 08:01 | but you can select any directory on a
computer's hard drive that has pictures.
| | 08:04 | We then can say, Set Default.
| | 08:06 | Now, we will notice here that nothing happens.
| | 08:08 | We haven't set anything yet that will actually be displayed
to the end user, however we are going to actually build
| | 08:13 | on the skill and now that you are able to
actually write data to a file on the hard drive,
| | 08:17 | we are now going to actually have the
application automatically read that data
| | 08:21 | in from the hard drive and update View accordingly.
| | Collapse this transcript |
| Reading files| 00:00 | Now that we've created an application that allows
us to store information on the user's hard drive,
| | 00:05 | we are now going to use that information
to update the application.
| | 00:07 | Originally, we loaded in an XML file that
had references to many different files in it.
| | 00:12 | Now, we are actually going to be able to do
away with that portion of the application.
| | 00:16 | Instead, we are going to actually use the
data that was stored on the user's hard drive
| | 00:19 | to have it automatically load data
whenever the application launches.
| | 00:23 | In this case, it will change to the
default directory that they have set
| | 00:26 | and then it will update the screen with the proper data.
| | 00:29 | So let's go ahead and open up the application.
| | 00:31 | We will go to File and then Open and then we
are going to scroll down to Image Viewer 07
| | 00:39 | in the Chapter 5 folder of the exercise files.
| | 00:42 | We are going to go ahead and go to the Actions panel,
| | 00:46 | so let's go to the Actions layer
and then Window and then Actions.
| | 00:49 | Now, the first thing we are going to do is we are
going to remove any references to the XML data.
| | 00:55 | So we will go ahead and highlight this
section here and we can just delete it.
| | 01:01 | We now can scroll down and also
delete the onXMLLoad method.
| | 01:09 | After that's deleted, we are now ready to begin the process
| | 01:12 | of retrieving data that's stored
on the user's local hard drive.
| | 01:16 | Now, to do this, the first thing we are going to need to do
is we are going to create a method called readPreferences.
| | 01:20 | So let's go down to our method section
because it's not responding to any events.
| | 01:26 | We will say function readPreferences,
and this isn't accepting any parameters
| | 01:34 | and it's also not returning anything.
| | 01:35 | Now, the first thing we are going to need to do
is create an instance of the FileStream class,
| | 01:41 | so we will say var fs of type FileStream
is equal to a new FileStream.
| | 01:49 | The next thing that we are going to
need to do is add an event listener.
| | 01:54 | Since we are going to be opening this action asynchronously,
we are going to need to listen for the Event.COMPLETE event.
| | 02:00 | So we'll say fs.addEventListener, Event.COMPLETE and then
we will respond with the onOpenPreferences method.
| | 02:10 | The next thing that we are going to
need to do is actually open the file.
| | 02:15 | So we will say fs.openAsync and then we are
going to need to pass in the file reference.
| | 02:20 | So we will create a new file reference and then
we'll pass in the name of the file that we referenced
| | 02:25 | when we actually wrote it to the hard drive.
| | 02:27 | I will copy that and then paste it below.
| | 02:31 | The next thing we are going to need to do is tell the
FileStream what mode we are going to open the file in.
| | 02:37 | In this case, we are going to open
the file in FileMode.READ.
| | 02:42 | Now, we can close our OpenAsync.
| | 02:48 | Now, everything else that happens is actually going
to be passed up to the onOpenPreferences method.
| | 02:52 | So let's go ahead and create that method.
| | 02:54 | We will go up to the end of our Event Handler section
and create the new method onOpenPreferences.
| | 03:04 | It's going to receive an event
of type Event and it's not going
| | 03:09 | to return anything so we can leave the return type void.
| | 03:13 | Now, inside of this method, we are going to
need to go ahead and grab the FileStream.
| | 03:17 | So we will say var fs of type FileStream
is going to be equal to event.target.
| | 03:25 | As we stated earlier, event.target can
contain many different types of data.
| | 03:30 | So we want to be sure and let the application
know that it's going to be a FileStream.
| | 03:33 | So we will say as FileStream.
| | 03:36 | That way, we have cast event.target as a FileStream.
| | 03:39 | The next item is we are going to need to go
ahead and extract the data out of the file.
| | 03:43 | So we will say var preferences and that's actually
going to be of type XML because we are actually going
| | 03:50 | to parse XML data out of the file we
saved on the user's hard drive, XML.
| | 03:55 | And now, we are actually going to read from the file.
| | 03:58 | So we will say fs.
| | 04:00 | And just as we used writeUTFBytes to write the data,
| | 04:03 | we are now going to use readUTFBytes
to read the data from the file.
| | 04:08 | It's going to ask us how many bytes we wanted
to read and we wanted to read all of them.
| | 04:14 | The good thing is our FileStream instance actually
contains the number of bytes that are available.
| | 04:18 | So we can say fs.bytesAvailable.
| | 04:21 | Now, we can close that line.
| | 04:24 | Now, the next thing we need to do is now that
we actually have the preferences XML is we need
| | 04:29 | to set the currentDirectory property to that actual value.
| | 04:33 | So we will say currentDirectory is going to be equal
to and then we are going to say new File reference,
| | 04:42 | and then we are going to pass in the name of the
directory that was saved on the user's hard drive.
| | 04:47 | We can get to that by saying preferences. That will be
the root tag and then we can say defaultDirectory.
| | 04:56 | Now, because the application doesn't know, in this
case, if there is more than one defaultDirectory tag
| | 05:01 | because it's an XML list, we actually
can just have it get the first one.
| | 05:05 | Now, the last thing we are going to need to do, we
are going to need to have a method that creates a list
| | 05:11 | of all the files and then adds them to the tile list.
| | 05:14 | Now, in this case, we have a method
that does something similar.
| | 05:16 | If we scroll up to our onDirectorySelect method, it
does all of that but it's actually tied to the event.
| | 05:23 | So it needs to be able to still get to the event.
| | 05:25 | So we are actually going to extract part of this
method and create a new method called listFiles.
| | 05:31 | So we will highlight everything from var dirListing down,
cut it and then we will move down to our method section
| | 05:40 | and create a new method function listFiles.
| | 05:44 | It's not going to return anything so
we can say the return type is void.
| | 05:50 | Now, we can just paste all of the data in.
| | 05:52 | Now, we need to go back up to our onDirectorySelect
method and put in a reference to the method listFiles.
| | 06:01 | That way, every time the user selects a directory, it
will still update all of the files within the application.
| | 06:07 | Now, we need to scroll down and we also
need to call this method inside of our
| | 06:10 | onOpenPreferences, so we will say listFiles.
| | 06:14 | Now, the last thing we need to do, we
want to use this readPreferences method
| | 06:19 | to actually load data once the application is launched.
| | 06:22 | So we can highlight the name and we can go up to the top
of the application where we used to load in the XML Data.
| | 06:28 | And we now can load preferences.
| | 06:32 | I will create a comment so I will know what I am doing.
| | 06:36 | Then, we will add in the readPreferences call.
| | 06:39 | Now, we should be able to save our application.
| | 06:41 | Let's test our movie.
| | 06:43 | Now, as you can see, we actually set a
value and it actually went and detected
| | 06:52 | that value when we launched the application.
| | 06:54 | Let's go ahead and try this again.
| | 06:55 | Let's go to Browse.
| | 06:57 | We will go to David Tucker pictures.
| | 06:59 | Again, you can pick any directory you want
on your hard drive that contains images.
| | 07:03 | I am going to go to the directory
Savannah, we will click OK.
| | 07:06 | Now, it will go through and load all of those
values, but now we will click Set Default.
| | 07:11 | Now, we will close the application and we
will go to Control and then Test Movie again,
| | 07:17 | and you will see that the application has been updated with
the new directory and automatically loads the new images.
| | 07:25 | Outside of that, it still functions with all
the functionality that we put into it earlier.
| | 07:29 | So now, you have been able to not only write data to
the user's local hard drive but also to read data back.
| | 07:35 | This can be a great way to store things such as
application preferences as well as application data.
| | Collapse this transcript |
| Using temporary files and directories| 00:00 | There might be some yimes while you are developing your applications
in working with the file system that you just want to create a
| | 00:05 | temporary file or directory to store data in for the length
of the application and then just delete it once you are done.
| | 00:10 | In those cases you can use two methods of the File class to help you.
| | 00:14 | Let's open up,
| | 00:15 | in the Chapter 5 folder of the exercise files, ImageViewer08.
| | 00:20 | Let's go to the Actions layer,
| | 00:21 | and then go under Window and then Actions.
| | 00:24 | If we scroll down
| | 00:27 | to the onSetDefault method,
| | 00:29 | let's pretend for a moment that instead of actually
storing this on the user's local hard drive,
| | 00:33 | we just wanted to create a temporary file that would exist
for as long as the application and then we could delete it.
| | 00:38 | In those cases we can actually just delete the reference to the
file and we could use a method that's included with the File class.
| | 00:44 | In those cases, we can then just say File.
| | 00:47 | createTempFile
| | 00:51 | and what this will do, this will actually create a temporary
file inside of the temporary file's folder for the application.
| | 00:57 | Now this will automatically create a unique file. So you will have
to check and see if the file exists. You can't even give it a name
| | 01:04 | but you can create a file which you know
is going to be unique for your application.
| | 01:08 | However, in these instances because you don't know the name
of the file, you can't really make this data accessible once
| | 01:13 | you restart the application.
| | 01:15 | So in these cases these files are made to
be used for a single use of the application.
| | 01:19 | You also can create a temporary directory.
| | 01:22 | However,
| | 01:23 | you still must be sure to go through and delete the file
when you're done with it because these files will not be
| | 01:27 | deleted automatically from the user's local hard drive.
| | 01:30 | By using this you can create temporary preferences or you
can dump temporary application data and this can be very
| | 01:35 | useful when developing your applications and it is just another
example of the file system support that AIR provides for you.
| | Collapse this transcript |
|
|
6. Using HTMLIntroducing HTML in AIR| 00:01 | One of the benefits of AIR that opens up new
possibilities to developers is the robust HTML support.
| | 00:07 | AIR includes the entire WebKit, HTML
rendering engine and JavaScript interpreter.
| | 00:11 | This is the same engine that powers
the Safari browser that comes with Mac
| | 00:15 | and is also available for Windows XP and Vista.
| | 00:18 | By leveraging this technology developers can create
entirely new experiences within Flash for the desktop.
| | 00:24 | However, Flash already supports some HTML, so what
is gained by the new HTML support inside of AIR?
| | 00:30 | In this session you will learn what the key differences
are between the standard HTML support inside of Flash
| | 00:35 | and the advanced HTML support inside of AIR.
| | 00:37 | You will also see the sample application
that will be created in this chapter.
| | 00:41 | So let's look closely at the differences
between the normal Flash support and AIR.
| | 00:45 | In a Flash movie it renders only
a small subset of HTML tags,
| | 00:49 | so you can basically have some tags
that modify the way the text looks.
| | 00:53 | In a Flash movie it also supports a limited set
of CSS properties, so you can set a few things
| | 00:59 | but you can't do nearly as much as you
can within CSS in a normal HTML page.
| | 01:03 | You are also limited to loading external
content on servers that allow it;
| | 01:07 | they have to have a cross-domain policy
file to allow you to work with their data.
| | 01:11 | In addition there's no JavaScript support in HTML.
| | 01:13 | Now you can talk to JavaScript functions through
the external interface but there is no direct way
| | 01:18 | to interpret JavaScript methods inside of Flash.
| | 01:21 | However with AIR, you can fully support all standard
HTML tags so anything that you can create with HTML
| | 01:28 | and view in a browser you now can view inside of AIR.
| | 01:30 | AIR fully supports standard CSS
as well as the WebKit extensions.
| | 01:34 | So not only can you do everything you
normally will be able to do in a browser
| | 01:37 | but with the WebKit extensions
you can do even a few more things.
| | 01:41 | AIR can load external content without a policy file.
| | 01:44 | So in these cases you are not limited
to just those servers that allow it.
| | 01:48 | Also, AIR contains the full JavaScript
Interpreter that comes with WebKit.
| | 01:52 | So now you have the capability to connect ActionScript
and JavaScript in a way never before thought possible.
| | 01:59 | In this chapter we will be creating a browser just with
AIR and Flash that uses the HTML support to load a URL,
| | 02:05 | it is going to have history support with a
forward and back control, you are going to be able
| | 02:09 | to access the JavaScript Document
Object Model, you are going to be able
| | 02:12 | to manipulate CSS data and scroll
HTML content, all within AIR.
| | 02:18 | Now with this power inside of AIR you can
now develop new and engaging experiences.
| | 02:21 | So you are now ready to create a web browser
with nothing but Flash CS3 and Adobe AIR.
| | Collapse this transcript |
| Using the HTMLLoader| 00:01 | In this session, you will learn how to use
the HTMLLoader class that comes with AIR.
| | 00:04 | Anytime you want to view HTML content
inside of an AIR application in Flash,
| | 00:08 | you are going to be using the HTMLLoader class.
| | 00:11 | By the end of this session, you will know
how to create an instance of the class,
| | 00:15 | place it on the Stage, position
it and then load a URL into it.
| | 00:18 | The first step in creating a browser application is
to create a new AIR application inside a Flash CS3.
| | 00:23 | Now we can do this by going under Create
New and then going to Flash File, Adobe AIR.
| | 00:29 | Now the first thing we are going to do
is we are going to save our application.
| | 00:33 | In this case, I am just going to save mine on the
desktop and we are just going to call it Browser.
| | 00:38 | You can choose to save yours wherever
you would like on your hard drive.
| | 00:42 | Now we need to adjust some of the settings.
| | 00:43 | First we will change the size we will
make this, 800 pixels x 600 pixels,
| | 00:49 | since browsers generally have a lot to display.
| | 00:52 | In addition, we will also go and adjust some
of the AIR Application and Installer Settings.
| | 00:56 | Now this can be accomplished by going under Commands
and then AIR Application and Installer Settings.
| | 01:01 | Note that you will actually have to save your
application before you actually can edit the settings.
| | 01:05 | Now we are going to give it a File Name, a Name and an ID
as we need to do for every AIR application that we create.
| | 01:12 | So we will call this Browser application
for both the File Name and the Name
| | 01:18 | and then we will need to actually give it an ID.
| | 01:22 | In most cases, people use the Reverse DNS Format,
so either a URL that you own or are associated with,
| | 01:28 | you can just flip around backwards and use that here.
| | 01:30 | In this case, I am going to use the
lynda.com domain, so I will say com.lynda
| | 01:34 | and then I will say it Browser Application,
which is the name of our application.
| | 01:39 | We are also going to need to adjust
a couple of the advanced settings,
| | 01:42 | so let's click on Settings next to the word Advanced.
| | 01:45 | We will uncheck the Maximizable and
Resizable options and then click OK.
| | 01:49 | We will click OK one more time and now
our settings have gone into effect.
| | 01:53 | Now we actually can create an Actions
layer and start working with it.
| | 01:56 | But first we are going to need to lay out
some of the UI Elements of our application.
| | 02:01 | So we are actually going to rename
this layer UI for the user interface.
| | 02:05 | Now we are going to go to Window and then go to Components.
| | 02:08 | Now we are going to actually need to drag two
components onto the Stage, first we will drag the button
| | 02:13 | and then we will drag one instance of the text input.
| | 02:16 | We can now close the Components window.
| | 02:18 | I am going to position the Text
Input in top left of the screen.
| | 02:21 | Then I am going to position the Label
on the top right of the application.
| | 02:26 | Now I am going to go ahead and select the Free Transform
tool, and I am going to choose the Text Input and I am going
| | 02:33 | to hold down the Alt key on PC or Option key on
Mac and I am going to stretch this to the right.
| | 02:38 | I want to stretch it, so that it is close to the button.
| | 02:41 | Now I am going to select both items and
I am going to go to the Align panel.
| | 02:48 | If yours is not open, you can go
under Window and then Align.
| | 02:51 | And then inside of the Align panel, I am going
to choose to align these up both in the center.
| | 02:55 | Now I am going to give the text input an
instance name of URLInput and I am going
| | 03:04 | to give the button an instance name of goButton.
| | 03:06 | And I am also going to change its label to be Go.
| | 03:10 | Now we can lock our UI layer, create
a new layer name it Actions.
| | 03:17 | At Preference I would like to keep all of my Actions layers
at the bottom and then I am going to lock that layer.
| | 03:24 | We now can be sure that it's selected and
we can go under Window and then Actions.
| | 03:28 | I would like to keep my code organized
by giving it sections.
| | 03:33 | In this section, we are going to be importing classes
so I will add an import comment so I know where I am at.
| | 03:38 | Now the first thing we are going to need to do is
we are going to need to import an entire package.
| | 03:42 | We are going to be using several classes from the
Flash.display package, so we will just import all those.
| | 03:49 | In addition, we are also going
to need to import the HTMLLoader.
| | 03:52 | So we will say importFlash.html.htmlloader.
| | 03:57 | We are also going to need the URLRequest class
because when we use the Load method of the HTMLLoader,
| | 04:04 | it's going to require that we pass
in the URLRequest to that method.
| | 04:07 | So we will say import flash.net.URLRequest.
| | 04:12 | Now we can actually set up our Stage.
| | 04:16 | In this case, we are going to need to actually set
a few properties, by default the HTMLLoader tries
| | 04:22 | to scale our content to the size
of the actual HTMLLoader container.
| | 04:26 | We don't want it to do that, so we are actually
going to set the stage scaleMode and the stageAlign.
| | 04:30 | So in these cases, we are going to say stage.scaleMode,
it is going to be equal to StageScaleMode.No_Scale.
| | 04:43 | We also need to set the Align property and that will
be stage.align it's going to be equal to StageAlign.
| | 04:53 | then we will say Top_Left.
| | 04:56 | Now that we have set up our Stage, we can begin
creating our properties and position them on the Stage.
| | 05:02 | In this case, we are first going to create the HTMLLoader.
| | 05:06 | So we will say var html Loader is of type
HTMLLoader is equal to a new HTMLLoader.
| | 05:16 | Now we are going to want to position our item on this
Stage, so we will say htmlLoader.x and we are going to set
| | 05:24 | that equal to 10 so that it doesn't go all
the way to the edge of the application.
| | 05:28 | Then we will the y property and we will set that
equal to 45, so this is far enough down off the top
| | 05:33 | that it won't run into our URL input and goButton.
| | 05:35 | Next we are going to need to actually set the width
and that is going to be equal to stage.stageWidth
| | 05:43 | and then we are going to subtract 40, so it
will reside in about the middle of the window.
| | 05:51 | Then we are going to need to set the height and
that's going to be equal to stage.stageHeight
| | 05:57 | and then we are going to subtract a 100 from that.
| | 06:03 | Now the next thing that we will need to do is actually add
our HTMLLoader to the Display List, this can be accomplished
| | 06:09 | by just saying addChild and then htmlLoader.
| | 06:13 | Now we are going to want to go ahead and
add an event listener for our goButton.
| | 06:19 | So we will say goButton.addEventListener and then we are
going to want to listen for the MouseEvent.CLICK event.
| | 06:27 | And we are going to pass it into an onGoClick method.
| | 06:36 | Now within this method, we are actually going
to retrieve the data that's in the URL Input
| | 06:40 | and then pass it at the HTMLLoader to load.
| | 06:43 | So we will go ahead and create this function but first
we will create our section for our event handlers.
| | 06:53 | Then we will say function onGoClick and
then we will want to pass in the event,
| | 07:00 | in this case it will be an event of type MouseEvent.
| | 07:03 | It's not going to return anything, so
we can leave the return type as void.
| | 07:07 | Now within here we are going to want to use the
HTMLLoader.load method, so we will say htmlLLoader.load
| | 07:15 | and here is where we actually need to create a URLRequest.
| | 07:17 | So we will say new URLRequest and we will
pass in the URL that we wanted to go to.
| | 07:23 | In this case we are going to use the URL input so we will
say urlInput.text and that will bring us back the text
| | 07:30 | that is actually contained in the text input on the Stage.
| | 07:33 | So that's all we need to do for our onGoClick method.
| | 07:37 | In most cases when you go to a web browser it
actually loads a page by default so when I go back
| | 07:42 | up under the addChild method and I am going to say
htmlLoader.load and then we are going to tell it
| | 07:48 | to load a new URLRequest and we will just put lynda.com.
| | 07:54 | In this way when the user opens the browser, it
will automatically navigate to a page for them.
| | 07:58 | So now let's save our application and then
we can go to control and then Test Movie
| | 08:03 | and now that we have tested our
movie, you will see it comes up
| | 08:06 | and it will take it a second but
then it loads the lynda.com page.
| | 08:10 | Now your application already has many of
the trappings of a complete web browser.
| | 08:14 | We can tell by even typing in a URL
such as www.google.com then we can go
| | 08:21 | to the goButton click and there
we go, we have loaded a page.
| | 08:25 | So you should now feel comfortable using the
HTMLLoader placing it on the Stage and using it
| | 08:30 | to load a URL all within Flash CS3 and AIR.
| | Collapse this transcript |
| Scrolling HTMLLoader content| 00:00 | In this session you will learn how to scroll
the content within the HTMLLoader container.
| | 00:04 | The HTMLLoader does not contain any scroll bars by default so
we will be using the ScrollBar control that's within Flash.
| | 00:10 | To begin we will open the FileBrowserApplication01 which
can be found in the Chapter 6 folder of the exercise files.
| | 00:16 | So we will click the File and then click Open.
| | 00:20 | The first thing we will need to do before we jump
| | 00:22 | into the Actions panel is we are going
to need to add an item to the library.
| | 00:25 | So if we go to Window and then Components
we are going to look for the UIScrollBar.
| | 00:31 | And we are going to add this into our library.
| | 00:33 | Now we are not actually going to
be using the UIScrollBar however,
| | 00:37 | the base class for the UIScrollBar is fl.controls.ScrollBar
and this is the class that we will be using.
| | 00:43 | So to ensure that it gets compiled into our application
we are just going to add that component to the library.
| | 00:48 | Now we will select our Actions layer and
we will go under Window and then Actions.
| | 00:52 | Now the first thing we will need to do is
create two scroll bars. So directly under the area
| | 00:57 | where we created our HTMLLoader and added it to
the Stage we are going to create a scroll bar.
| | 01:02 | We will start off with vScrollBar for Vertical.
| | 01:04 | It's going to be of type ScrollBar and
it's going to be equal to a new ScrollBar.
| | 01:09 | Now to ensure that we are able
to do this we are going to need
| | 01:12 | to import two classes first we are going
to need to import fl.controls.ScrollBar.
| | 01:20 | In addition we are also going to
need to import the fl.events.* package.
| | 01:28 | Some of the events that are dispatched
by the ScrollBar are in this package
| | 01:31 | and this way we can react to those events.
| | 01:34 | After we create the vScrollBar we are
going to need to position it on the Stage.
| | 01:38 | First we are going to need to set its direction.
| | 01:41 | This is the property of the ScrollBar that tells
it if it goes horizontal or if it goes vertical.
| | 01:46 | So we will set vScrollBar.direction=vertical.
| | 01:50 | Next we will need to set the x and
y properties of the vScrollBar.
| | 01:56 | In this case the x is going to be equal to htmlLoader.x and
then we are going to want to add in the htmlLoader.width.
| | 02:06 | This will position the vertical scroll bar directly
on the right side of the HTMLLoader container.
| | 02:12 | Next we will set the y property and that's going to be equal
to htmlLoader.y. This will position it even with the top
| | 02:22 | of the HTMLLoader container which is what we want.
| | 02:25 | Then we will set the height which will be vScrollBar.height
and that's going to be equal to htmlloader.height.
| | 02:34 | This way the scroll bar will run directly down the right side
| | 02:38 | of the HTMLLoader container for
the full height of the container.
| | 02:41 | Now the next thing we are going to need to do is we are
going to need to set a few of the specific properties
| | 02:45 | of the scroll bar. First we are going
to need to set line scroll size.
| | 02:49 | In this case we are going to tell it to scroll 15
lines every time they push scroll down or scroll up.
| | 02:57 | In addition we are going to need to set the page size.
| | 02:59 | Now we can set the page size just
simply equal to the htmlLoader.height.
| | 03:07 | This way when someone clicks the track of
the actual scroll bar it will note to move
| | 03:11 | down the full width of the HTMLLoader's content.
| | 03:15 | Now at this point redone setting up our
vScrollBar and we can add it to the Stage.
| | 03:19 | So we will say addChild vScrollBar.
| | 03:23 | Now we are ready to move on to creating a
horizontal scroll bar so we will say var hScrollBar
| | 03:29 | of type ScrollBar is going to be equal to a new ScrollBar.
| | 03:36 | Now we are going to set its direction and
that's going to be equal to horizontal.
| | 03:45 | Next we are going to need to set the x and y values we
are going to set the hScrollBar.x is going to be equal
| | 03:53 | to htmlLoader.x. This will position the scroll bar to
be even with the left side of the HTMLLoader container.
| | 04:01 | Then we will set the hScrollBar.y=htmlLoader.y but
then we are going to add in the htmlLoader.height.
| | 04:13 | This will position the horizontal scroll bar directly
below the HTML container and that's what we want.
| | 04:19 | Next we are going to need to configure the width.
| | 04:22 | So we will say hScrollBar.width is
going to be equal to htmlLoader.width.
| | 04:28 | This way it will reside directly below the HTMLLoader and
also will be just as wide as the HTMLLoader container.
| | 04:34 | Next we are going to need to also do the line scroll
size for the hScrollBar and we can set that equal to 15,
| | 04:42 | we also can set the pageSize=htmlLoader.width.
| | 04:52 | Next we are going to add our hScrollBar to the display list.
| | 05:01 | Now we are going to need to listen for two specific
events so we actually can scroll down and we can see
| | 05:08 | that we have a section here where we add event listeners.
| | 05:10 | So we will go ahead and create little
subsection that says Add Event Listeners.
| | 05:15 | And I will create an addEventListener
statement for each scroll bar.
| | 05:19 | First with the vScrollBar we will add an
Event Listener and we are going to want
| | 05:24 | to listen specifically for the ScrollEvent.SCROLL.
| | 05:30 | And for that we are going to create a method called
onVScroll and it will do the same thing for the hScrollBar
| | 05:41 | and we are also going to listen for the ScrollEvent.SCROLL
and we will respond to that with the onHScroll method.
| | 05:49 | Now that we have added our two event listeners we can
actually begin the process of configuring those methods.
| | 05:56 | So if we go down to the event handler section we
are going to first create a method and this is going
| | 06:02 | to be called onVScroll, it's going to receive an event
it's going to be a ScrollEvent and it is not going
| | 06:08 | to return anything so we can set
that return type equal to void.
| | 06:11 | Now we are going to use a property of
the HTMLLoader that's called scrollV.
| | 06:20 | Now basically what this does is this tells the
HTMLLoader how far to scroll down the content.
| | 06:26 | In this case we actually can take that
value from the event.position property.
| | 06:33 | Now position is a property that's actually
passed in by the ScrollEvent and we can use
| | 06:36 | that to tell the HTMLLoader where
to scroll the content vertically.
| | 06:40 | Now the same thing we can actually copy this
entire method and we will paste it below.
| | 06:44 | And we just need to update it with H instead of V.
| | 06:48 | So in this case we have got onHScroll
and scrollh is equal to event.position.
| | 06:53 | Now that we have added that we are going to
need to add one more method to our application.
| | 06:57 | If we left it this way, well our scroll bars would work they
would not be updated every time that we go to a new page.
| | 07:04 | We obviously want our scroll bars to work
with any page that we go to so because of
| | 07:07 | that we will create a method called updateScrollBars.
| | 07:11 | Since this is a method that won't
be called by an event we are going
| | 07:14 | to actually create a new section just for our methods.
| | 07:21 | So we will create the method called function and then
we will say updateScrollBars and it is not going
| | 07:28 | to receive any events and it's not going to return anything.
| | 07:31 | Now we are going to need to do some calculations
inside of here, first we are going to need to determine
| | 07:38 | if we need a horizontal or vertical
scroll bar for a given page.
| | 07:42 | So we are going to use two properties of the
HTMLLoader, contentWidth and contentHeight.
| | 07:47 | And that gives the actual width and height of the
HTMLLoader container's content so first we will determine
| | 07:53 | if we need the vScrollBar to be
enabled, if htmlLoader.contentHeight,
| | 08:00 | if that is actually greater then htmlLoader.Height then
we know that we are actually going to need our scroll bar.
| | 08:09 | That statement is basically saying if the
stuff inside of the HTMLLoader is taller
| | 08:13 | than the HTMLLoader itself then yes,
we are going to need the scroll bars.
| | 08:17 | We will go inside of the if statement here
and we will say vScrollBar.enabled=true.
| | 08:24 | On the other side we know that if it's the content height
is not greater than the height then we are not going
| | 08:30 | to need the scroll bars so we can say else
and we can say vScrollBar.enabled=false.
| | 08:39 | Now we also can put in the same logic for the hScrollBar
but before we do we are going to need to do the min
| | 08:45 | and max scroll positions for the vScrollBar so we will say
vScrollBar.minScrollPosition is going to be equal to 0
| | 08:56 | because we are always going to want the minimum to be 0
that way they could scroll all the way back to the top.
| | 09:00 | Next we are going to set the maxScrollPosition.
| | 09:06 | And here is where things are a little bit different.
| | 09:09 | To create the maximum scroll position we want
to take the content height but we also want
| | 09:13 | to subtract the htmlLoader height from that value.
| | 09:16 | We will say htmlLoader.contentHeight-htmlLoader.height.
| | 09:25 | If you didn't subtract the htmlLoader height from the
htmlLoader contentHeight then you would actually be able
| | 09:31 | to scroll down further than the actual content goes.
| | 09:35 | This way if you subtract the htmlLoader height you know that
you can only scroll the length of the webpage and no more.
| | 09:41 | Now we can go down and implement
the same thing for the hScrollBar.
| | 09:44 | We will say if htmlLoader.contentWidth is
greater than htmlLoader.width then we know
| | 09:54 | that we will need out hScrollBar enabled.
| | 09:57 | So we will say hScrollBar.enabled=true but we
also know that if it's not then we are not going
| | 10:05 | to need enabled so we will say hScrollBar.enabled=false.
| | 10:11 | Now we will also need to go in and set
the max and min scroll position values
| | 10:16 | so we will say hScrollBar.minScrollPosition
it's going to be equal to 0.
| | 10:22 | And then we will say hScrollBar.maxScrollPosition this going
to be equal to htmlLoader.content and then we are going
| | 10:33 | to subtract the htmlLoader.width from that value.
| | 10:37 | Now the last thing we are going to need to do is to tell
our HTMLLoader that every time we go to a new page we want
| | 10:43 | to update the scroll bars so I am going
to highlight the name of this method.
| | 10:46 | And then we are going to go up an
addEventListener to the HTMLLoader.
| | 10:51 | We will say htmlLoader.addEventListener and then we
are going to be listening for the Event.COMPLETE event.
| | 11:00 | And we are going to respond to that by calling
a method called onLoadComplete so we will go
| | 11:08 | down to our event handler section, we will scroll down,
we will create a new function called onLoadComplete
| | 11:16 | and it will receive an event of type event and it's not
going to return anything so we can leave the return type
| | 11:22 | as void and then we are going to
call this method updateScrollBars.
| | 11:25 | Now if we test our application by going to Control and
then Test Movie the first thing we should notice is
| | 11:32 | that we see the actual scroll bars on the Stage.
| | 11:35 | The next thing you will notice is that as the content
was loading the scroll bars were both disabled.
| | 11:40 | However now that the content has finished loading they
have been enabled and we can now scroll our content.
| | 11:46 | We can scroll vertically and we can scroll
horizontally so we can see the entire page.
| | 11:52 | In addition if we go to another page and
we click the goButton you will notice
| | 11:59 | that both of the scroll bars have been disabled.
| | 12:01 | This is because this content does not
require the scroll bars because it fits
| | 12:04 | within the HTMLLoader container width and height values.
| | 12:08 | Your browser application can now view HTML content of any
size by the use of the scroll bars that you have added.
| | 12:14 | You now should be able to create instances of the
ScrollBar class and attach them to the HTMLLoader objects.
| | Collapse this transcript |
| Accessing HTML history| 00:01 | No browser would be complete without
Forward and Back buttons.
| | 00:04 | So, in this lesson, you will learn how to access
to browser history within an HTMLLoader object.
| | 00:09 | This powerful feature of the HTMLLoader object allows you
to move back and forth within the HTML history as well
| | 00:15 | as track your current location in that history.
| | 00:17 | So we will be using the Browser Application 02 file.
| | 00:20 | So, if we go to File and then Open and
then if we look in the Chapter 6 folder
| | 00:25 | of the exercise files, we go to Browser Application 02.
| | 00:29 | Now, the first thing we'll need to do is to actually
add some buttons onto the Stage that will allow us
| | 00:35 | to use the forward and back functionality.
| | 00:37 | So the first thing I am going to do is unlock the UI Layer.
| | 00:40 | Then I am going to select the layer and
then we'll open the Components window.
| | 00:43 | Now, we are going to be dragging two more buttons
onto the Stage but first we are going to need
| | 00:48 | to actually scale our URL input so that we have rooms.
| | 00:51 | So I will select the Free Transform tool and then I
will select the URL input but I will hold down Alt
| | 00:57 | and drag from the left side and drag it in.
| | 01:00 | Then, we can drag two instances of
the button class onto the Stage.
| | 01:06 | We will make each of these only be 30 in width.
| | 01:09 | I am going to give the first one
an instance name of backButton.
| | 01:12 | And then we are going to go into parameters and instead of
having a label be label, I am actually going to use a symbol
| | 01:19 | that is going to just signify that it's a back motion.
| | 01:23 | Next, we will select the Next button.
| | 01:25 | We will do the same thing.
| | 01:26 | We will give it a width of 30.
| | 01:27 | We will give this one an instance name a forwardButton and
give it a symbol for label that signifies moving forward.
| | 01:34 | Now, we can line both of our items up.
| | 01:37 | We can then highlight all of the UI items
on this layer, we will align them to center.
| | 01:43 | Now, we will move our items over to the edge
of the Stage and then we are actually going
| | 01:49 | to select the URL input one more time, select the Free
Transform tool, hold down the Alt key and slide it
| | 01:55 | so it's getting fairly close back
to the Forward and Back buttons.
| | 02:01 | You can position yours as you like.
| | 02:04 | And now that we have given two new buttons
instance names of backButton and forwardButton,
| | 02:09 | we now can actually connect that with our ActionScript.
| | 02:11 | So let's lock the UI Layer.
| | 02:12 | Now, we will go to the Actions layer and
now we will go to Window and then Actions.
| | 02:17 | Also at this point, we are done with the
Components window so you can close that.
| | 02:21 | Now, the first thing we are going to need to do is
add event listeners for our Forward and Back buttons.
| | 02:26 | So let's scroll down to the section
of code where we add event listeners
| | 02:30 | and we are going to first add for the Back button.
| | 02:32 | We will say backButton.addEventListener and then
we will say MouseEvent.CLICK because we want
| | 02:42 | to find out when they actually click the button.
| | 02:43 | And then at this point, we will call onBackClick.
| | 02:50 | Next, we work with the Forward button.
| | 02:51 | We will say forwardButton.addEventListener
and then at this point,
| | 02:57 | we will also listen for the MouseEvent.CLICK
and we will call the onForwardClick.
| | 03:03 | Now, we are going to need to actually implement
the onBackClick and onForwardClick methods.
| | 03:09 | So, if we scroll down to the Event Handler
section, we will add a new line
| | 03:13 | and we will first create the onBackClick method.
| | 03:15 | In this case, it's going to receive an
event that will be of type MouseEvent.
| | 03:23 | It's not going to return anything so
we can leave the return type as void.
| | 03:26 | And inside of here, we are actually going to use a
method of the HTMLLoader class that allows us to go back
| | 03:32 | and that's going to be htmlLoader.historyBack.
| | 03:38 | That doesn't take any parameters.
| | 03:40 | Now, we'll do the same thing for the onForwardClick
and it will receive an event of type MouseEvent.
| | 03:50 | It's not going to return anything so
we can leave the return type void.
| | 03:53 | And then we are going to call the
htmlLoader.historyForward, again with no parameters.
| | 04:01 | So now that we have added this to our movie,
we actually can save and then we can go
| | 04:06 | to Control, Test Movie to test our application.
| | 04:09 | So, we are going to go ahead and go to another site.
| | 04:15 | Let's just say we want to go to Google.com.
| | 04:18 | We will hit the goButton and now, if we press the Back
button, we will see that indeed we'll return to Lynda.com.
| | 04:25 | However, there is a couple of problems with this.
| | 04:27 | First, we know that we are at the
beginning of our HTML history
| | 04:31 | but we can still click the Back button but nothing happens.
| | 04:33 | At this point, we can click the Forward button
and it will take us back to Google, but then,
| | 04:38 | we can hit the Forward button and it won't do anything
because we are at the end of the HTML history.
| | 04:42 | This can be a bit confusing for the end user.
| | 04:45 | So in this case, we are going to actually enable or disable
these buttons based on where we are in the HTML history.
| | 04:51 | So now that we have seen that our buttons are perfect
that even though they can go forward and back to keep it
| | 04:56 | from being confusing to the end user, we are going to enable
| | 05:00 | or disable the buttons based on
where we are in the HTML history.
| | 05:03 | So I am going to close the application and then I am
going to go, I am going to create a new method just
| | 05:08 | under the Method section and we are going
to call this method updateHTM History.
| | 05:12 | Now, this is not going to receive any events
and it's also not going to return anything.
| | 05:21 | Now, within this method, we are going to need to
check and find out where we are in the HTML history.
| | 05:26 | The great thing is that the HTMLLoader actually
gives us a couple of values that will help.
| | 05:31 | So the first thing we are going to want to do is
determine if we need to enable the Back button.
| | 05:35 | Now, we will know if we are at the very beginning of the
HTML history, in other words, if there is no pages before,
| | 05:42 | then we know that we need to disable the Back button because
we can't go back any further, and that can be accomplished
| | 05:47 | by saying if htmlLoader.historyPosition, if that
is equal to 0, then we will know that we are
| | 05:58 | at the very beginning of our actual HTML history.
| | 06:01 | So at this point, we can say backButton.enabled
is equal to false.
| | 06:10 | But we also know that if the historyPosition
is not equal to 0, then we can go back.
| | 06:14 | So we will say else backButton.enabled equals true.
| | 06:24 | Now, we need to actually check for the Forward
button and we can do this using another property.
| | 06:29 | So we will say if htmlLoader.historyPosition,
now we are going to want to check
| | 06:37 | and see if the historyPosition is equal to the end of
the history and to do this, there is actually a property
| | 06:46 | of the HTMLLoader object called historyLength.
| | 06:49 | Now, there is one important thing to note though
between historyPosition and historyLength.
| | 06:54 | historyPosition starts numbering from 0, so the
first site you go to would be historyPosition 0,
| | 07:00 | your next one would be 1 and the
following one would be 2 and so on.
| | 07:04 | However, the historyLength starts with 1, so the first
time you go to a new page, you will have a historyLength
| | 07:10 | of 1, the next page 2 and so on and so forth.
| | 07:13 | So in this case, we are going to check
and see if the historyPosition is equal
| | 07:17 | to htmlLoader.historyLength and then subtract 1.
| | 07:26 | Now, in this case, it will tell you
if you are at the end of the history.
| | 07:30 | Now, if we are at the end of the history, we know that
the forwardButton.Enabled needs to be equal to false.
| | 07:41 | However, if we are not, we know that we can go forward and
so we want to say forwardButton.Enabled is equal to true.
| | 07:55 | Now, if we save our application and we go to
Control and then Test Movie to test our application,
| | 08:05 | we can actually go through now and we can go to a new page.
| | 08:09 | But you will notice that yet both of our buttons are still
enabled and there is one reason for that because we haven't
| | 08:14 | yet told our application that every time we load in
a new page, we wanted to update the HTML history.
| | 08:19 | So, that's the last step of implementing
the history functionality.
| | 08:22 | We will close our application.
| | 08:23 | We will now go back to the Actions panel and
we will go under the onLoadComplete method
| | 08:30 | and after updateScrollBars, we
will bring in updateHTMLHistory.
| | 08:35 | Now, we will save the application and we'll go
the final time and go to Control and Test Movie.
| | 08:42 | We will be able to see immediately that after the
page is loaded, both of the buttons have been disabled
| | 08:50 | because at this point, we are at the beginning
of the HTML history and we are also at the end.
| | 08:54 | But now, if we go to a new page and we hit Go, we
will notice that our Back button is now enabled
| | 09:02 | and if we go back, we will see that
our Forward button is now enabled.
| | 09:07 | We now can go to any URL.
| | 09:08 | We can go forward and back within the HTML history and
we also can track our position within the HTML history.
| | 09:14 | And now, we will learn about some of
the ways that we can really dive in deep
| | 09:17 | and connect with the content inside of our browser.
| | Collapse this transcript |
| Using script bridging| 00:00 | AIR enables new types of communication,
| | 00:03 | between JavaScript and ActionScript and this
is generally referred to as script bridging.
| | 00:08 | This is a powerful feature that goes a bit beyond the scope
of this series but we're going to use a few small elements of
| | 00:14 | script bridging to complete the browser application.
First let's examine what's possible with script bridging.
| | 00:19 | It actually allows for JavaScript methods to call ActionScript.
methods Now again this is different from actually using the external
| | 00:25 | interface capability that you already have in Flas. This actually
allows for JavaScript methods to call actual ActionScript methods.
| | 00:32 | In addition it can work the other way so that ActionScript methods can call JavaScript methods.
| | 00:37 | Now this is what we're actually going to be utilizing today.
ActionScript what methods can communicate fully with the JavaScript
| | 00:42 | document object model so ActionScript can respond to DOM
events, ActionScript can manipulate style sheet data,
| | 00:49 | as well as adding and removing items from the document object model.
| | 00:52 | And finally JavaScript can even include ActionScript libraries.
| | 00:56 | So there's a lot of capability with script bridging.
| | 00:59 | But today we're going to use just a few small
elements of this to complete our application.
| | 01:03 | Now to add these items to our application
we're first going to open out file.
| | 01:07 | So we'll go to File,
| | 01:08 | and then Open,
| | 01:09 | and then we'll open BrowserApplication_03
in the Chapter 6 folder of the exercise files.
| | 01:16 | Now within here we're just going to go straight to the
Actions panel so we'll highlight Actions and then go to Window
| | 01:21 | and then Actions.
| | 01:23 | Now we're going to scroll down to our onLoadComplete method.
| | 01:26 | Now currently we have two things going on inside of this
method. We're updating scrollbars and we're updating the HTML history.
| | 01:32 | Now we're going to do two more things.
| | 01:34 | Now if you've noticed there's a few things that aren't quite perfect with our browser application.
| | 01:39 | First if we go to a new page by clicking
on a link, the URL input isn't updated.
| | 01:44 | To demonstrate that we'll actually test the application.
| | 01:47 | When the application loads up we're here at the
lynda.com page and if we click on the Products item
| | 01:52 | it'll actually take us to the new page. But we'll notice first
of all, when we first went to the page, the URL input wasn't updated
| | 01:58 | and any time we go to links it's not updated.
| | 02:00 | The other problem in our application
| | 02:03 | is right now it just says BrowserApplication_03
as the title for the window.
| | 02:07 | However in most browsers, the title for the window is the
actual title of the current page that you're on. So these are
| | 02:13 | the two pieces of functionality that we're going to add
by actually accessing the JavaScript document object model
| | 02:18 | within ActionScripts.
| | 02:20 | First we're going to add a new line below our updateHTMLHistory, and
we're going to set the property of the URL input. So the way that
| | 02:27 | we do that is we're actually going to say
| | 02:30 | urlInput.txt and we're going to set
that equal to the current location value
| | 02:36 | in the JavaScript document object model and that
can be accomplished by saying htmLoader.window
| | 02:44 | and that's going to actually get us to the DOM and then we're going to
say location. So now every time we go to a new location within a page,
| | 02:50 | even if it's from clicking a link, even if
it's the page that loads up automatically,
| | 02:54 | or if we enter a URL ourselves,
| | 02:56 | the page automatically update the URL input.
| | 02:59 | And the final item is we actually want to set the title of
our window. Now we'll cover a bit more about working with windows
| | 03:05 | in a future chapter,
| | 03:06 | but for the moment the thing that you
need to know is inside of the stage,
| | 03:10 | there is a current property for the current NativeWindow
and then each NativeWindow has a property called title.
| | 03:18 | And we just want to set this equal
to the title of the current page.
| | 03:22 | And this can be accomplished by going to htmlLoader.window.
| | 03:27 | document.
| | 03:30 | title.
| | 03:30 | Now if we save our application,
| | 03:34 | and we test by going to Control and then Test Movie.
| | 03:38 | We should notice that right away
lynda.com is entered into the URL input.
| | 03:42 | In addition to the title has been
added as the title of our window.
| | 03:46 | And if we now click on a page, such as Products,
| | 03:49 | we should notice that the URL has been updated
| | 03:52 | and the title has been updated as well.
| | 03:53 | And it also will be updated if we actually
type of value into the URL input and hit Go.
| | 03:59 | We can see that the URL is indeed updated
| | 04:02 | as well the title for the window.
| | 04:03 | So script bridging is a very powerful feature, allowing communication
that wasn't previously thought possible between JavaScript
| | 04:09 | and ActionScript. If you just beginning to work with JavaScript
inside of ActionScript, accessing the JavaScript document
| | 04:16 | object model is a great place to start.
| | 04:18 | By using these pieces of functionality, we expanded our browser
| | 04:21 | to where we now basically have a full featured web browser
| | 04:24 | built entirely in Flash CS3 with AIR.
| | Collapse this transcript |
|
|
7. Handling PDFsDetecting PDF support| 00:00 | In addition to being able to display HTML content,
| | 00:04 | the HTMLLoader has the ability to display PDF content. Now,
you were introduced to this concept in the Essential AIR series.
| | 00:11 | And there is one important difference between
HTML support in AIR and PDF support within AIR.
| | 00:16 | HTML support is provided by AIR with the embedded WebKit engine.
But PDF support relies on the Acrobat Reader, which does
| | 00:23 | not come bundled with AIR.
| | 00:25 | Because of this, the first step you will need to do when
actually working with PDF documents in AIR is to detect if the
| | 00:31 | user has a sufficient version of Acrobat Reader installed.
| | 00:34 | And currently, the user will need Adobe Acrobat Reader
8.1 or greater to view PDF content inside of AIR.
| | 00:41 | We are actually going to take the Browser Application that we have
created and we are going to give it the ability to load a PDF from
| | 00:46 | the hard drive.
| | 00:47 | So first, we are going to open our file. So if we go to File
| | 00:51 | and then Open and we look in the Chapter 7 folder of
the exercise files, we'll go to Browser Application 01.
| | 00:59 | Now, here within Browser Application 01,
| | 01:01 | we are going to need to add one more button to the Stage.
So if we go to the top right hand corner of our application,
| | 01:06 | the first thing we are going to do is
we are going to highlight the URL Input
| | 01:10 | and we are going to select the Free Transform tool and we are going to
hold down Alt on PC or Option on Mac and drag in from the right side.
| | 01:17 | We are then going to take the goButton and will move it to be
fairly close to even with the right side of the URL Input. Then,
| | 01:23 | being sure that the UI Layer is selected, we will go under Window
| | 01:27 | and then Components
| | 01:29 | and we will drag a new instance of the button onto
the Stage directly to the right of the goButton.
| | 01:34 | We are going to give this new button
an instance name of pdfButton.
| | 01:40 | We are also going to give it a label of loadPDF.
| | 01:45 | We will select a few of these items and be sure that we align them
to center and now that we have added them, we can go ahead and
| | 01:50 | begin working with our ActionScript.
So I will close the Components panel,
| | 01:54 | lock the UI Layer and then go to our
Actions layer and then go to Window
| | 01:58 | and then Actions.
| | 01:59 | We are not going to need to import a class that defines the
different level of support that a user's computer offers for PDF
| | 02:05 | support in AIR and that specific class is
going to be flash.html.HTMLPDFCapability.
| | 02:13 | Now, we actually can scroll down and create a method
| | 02:16 | that will be called when the application starts that will
check and see if the user has sufficient capability to view
| | 02:22 | PDF files inside of AIR.
| | 02:23 | And what we are going to do is if they do have support
for that, we are going to leave the PDF button enabled.
| | 02:29 | But if for some reason, they don't, then we are going to make
the PDF button be disabled on the screen so the user can't click it.
| | 02:35 | So if we scroll down to our method section,
| | 02:38 | we are going to create a new method
| | 02:40 | and we are going to call it checkPDFSupport. It's not going to receive
any arguments and it's not going to return anything so we can leave its
| | 02:49 | return type as void. Now, the first thing we are going
to want to do is actually check the PDF capability.
| | 02:54 | Now, to do this, the HTMLLoader class has a static property
that tells if the user can actually view PDF content. So we'll
| | 03:02 | go if an HTMLLoader- notice especially
right here I use an uppercase H
| | 03:08 | because here I am not referring to our instance of the class
but rather I am referring to a static property which means
| | 03:14 | there is a single property for every instance in the class.
So in this case, we will actually use the uppercase H.
| | 03:19 | We will say HTMLLoader.pdfCapability and we want
to be sure that that's equal to HTMLPDFCapability.
| | 03:29 | And then we want to look for Status_OK.
| | 03:32 | This will tell us that the user's Acrobat Reader is a sufficient
version to view PDF content inside of AIR and if that's
| | 03:39 | true and what we are going to do is we
are going to be sure that the pdfButton
| | 03:43 | .enabled is equal to true. Otherwise,
we are going to want to set to false.
| | 03:54 | Now, we are going to need to add a call to this method at the very
beginning of our application. So I'm just going to highlight the name
| | 04:01 | in the parentheses
| | 04:02 | and move back up to the top of the application. And then directly
after we have set up the Stage, I am going to go ahead and call
| | 04:08 | the checkPDFSupport. And I am going to create a new section here
| | 04:13 | that I am just going to call Initialization Methods and these are methods
that would just be called automatically when the application starts.
| | 04:21 | So now, when we launch our application, we should see
the PDF button enabled because we do have a current
| | 04:27 | version of Acrobat Reader installed.
| | 04:29 | So in this case, we go to Control and then Test Movie
| | 04:34 | and indeed the Load PDF button stays enabled. However,
| | 04:38 | just as a way to test our code,
| | 04:40 | if we go down to the method for checkPDFSupport and instead of
saying equals, if we change it to not equals, now when we load
| | 04:47 | our application, we should see that the PDF button is disabled.
| | 04:50 | So we go to Control and then Test Movie
| | 04:54 | and here we can see that the Load PDF button has indeed been
disabled. Now, you can actually work this functionality into
| | 05:00 | your application so that
| | 05:01 | only people that have PDF support can interact with PDFs.
| | 05:05 | Now that you can detect if the user has adequate PDF support
on their local computer, you now can create an application
| | 05:11 | that allows users to view PDF content within AIR.
| | Collapse this transcript |
| Loading a PDF file with HTMLLoader| 00:00 | So you want to be able to load a
PDF file into your AIR Application.
| | 00:05 | Well if you have already detected
that the user has the proper version
| | 00:08 | of Acrobat Reader installed then you can
load the PDF into the HTMLLoader class.
| | 00:12 | Now what we want to be able to do is actually
use the loadPDF button that we created previously
| | 00:17 | and when the user clicks it let them pick a file from
the local hard drive to view inside of the HTMLLoader
| | 00:23 | so let's go ahead and wire everything together.
| | 00:25 | First we are going to open up our file which can be
found in the Chapter 7 folder of the exercise files
| | 00:31 | and we are going to open BrowserApplication02.
| | 00:35 | Once we have loaded it up everything that we need to do is
actually going to be done in ActionScript so let's go ahead
| | 00:40 | and select the Actions layer and then
go to Window then go down to Actions.
| | 00:44 | Because we are letting the user pick a file from their local
hard drive we are going to need to import the file class.
| | 00:49 | So we will say import flash.filesystem.File. In addition we
are also going to want to limit what files the user can open
| | 00:58 | so to do this we are going to need the FileFilter
class which can be found in flash.net.FileFilter.
| | 01:06 | Now we actually can scroll down and add
the event listener for our PDF button
| | 01:10 | so in the addEventListener section we then can
add pdfButton.addEventListener we are going
| | 01:18 | to listen specifically for the MouseEvent.CLICK event.
| | 01:23 | We are going to respond to that with
onPDFClick a method that we will create shortly.
| | 01:28 | So now let's scroll down to our event handler
section let's go down below the last one
| | 01:32 | and we will create our new method, function OnPDFClick, and it
will receive an event of type MouseEvent and it's not going
| | 01:44 | to return anything so we can leave the return type void.
| | 01:47 | Now in this case the first thing that we are going
to want to do since we are prompting the user
| | 01:50 | to select a file is we are going to go ahead
and create a new instance of the file class.
| | 01:54 | So we will say var and we will just call
it F of type File is equal to a new File.
| | 02:00 | Now after this we are going to want to listen for the
Select event because once a user actually clicks a file
| | 02:06 | from the dialog box it will dispatch the Select event.
| | 02:09 | So we will say f.addEventListener and
then we will listen for Event.SELECT
| | 02:15 | and at that point we will actually
call the onPDFSelect method.
| | 02:20 | Now we are going to want to create our filter
so that users can only select PDF files.
| | 02:26 | To accomplish this we will say var filter of type
FileFilter is going to be equal to a new FileFilter.
| | 02:33 | Now we are going to need to pass a new
parameters to the FileFilter class.
| | 02:37 | First we want to give it a description so we will
say PDF Files. That will be the name of the type
| | 02:42 | of files that they will actually be selecting.
| | 02:44 | Then we need to add the extension so in this
case we will say *.pdf and that will tell it
| | 02:49 | to only allow PDF files to be viewed in this dialog box.
| | 02:54 | Now we actually can prompt the user to pick a file so
we will use f. and then we will say browseForOpen
| | 03:00 | and then we will actually need to pass
in a title. We will say select a PDF file
| | 03:06 | and then we will need to pass in an array of type filters.
| | 03:10 | Now in this case we only have one but if we just put
our filter in this parameter it would throw an error
| | 03:15 | so we can actually use this short
hand for creating an array,
| | 03:18 | use the left and right bracket and
inside of it we will put filter.
| | 03:21 | This will create an array with a single
parameter, in this case our filter.
| | 03:27 | Now we need to create our onPDFSelect method so we will
say new function onPDFSelect. It will receive an event
| | 03:36 | of type Event and it's not going to return
anything so we can leave the return type as void.
| | 03:42 | Now at this point we are going to want to extract the file
from the event so let's say var f of type File is equal
| | 03:50 | to event.target but again, event.target can
contain many different types of data so we need
| | 03:55 | to specifically tell the application
which type of data it's going to contain.
| | 03:59 | In this case it will be a file.
| | 04:01 | Now we are going to want to actually load the content in.
| | 04:04 | Now HTMLLoader we know has a .load
method and that's what we will use here.
| | 04:08 | We don't need to do anything special for the PDF.
| | 04:10 | We actually can just pass in the URLRequest as we have done
before so we will say new URLRequest and now we are going
| | 04:17 | to give it the actual URL of the file and we learned it
in a previous video that every file has a property .URL
| | 04:24 | that gives the native path in a URL formatted string.
| | 04:26 | Now that we have added the onPDFSelect method
we are actually ready to test our application.
| | 04:35 | So now let's go to Control and then Test Movie.
| | 04:38 | Now the first thing we should notice
is that the Load PDF is enabled.
| | 04:43 | This is because it actually has checked
and we do have a current version
| | 04:46 | of Acrobat Reader installed on this computer.
| | 04:48 | So now we can click the Load PDF button.
| | 04:50 | We will notice that we have the window popup that
says Select a PDF file and that it's limited to PDF files.
| | 04:56 | Then I have a file on a desktop it's actually a 20 meg
PDF file that actually is a poster of the AIR classes.
| | 05:02 | Now this is a poster that Adobe provides.
| | 05:04 | But I wanted to illustrate two things with this. The
first thing I wanted to illustrate is the ability of AIR
| | 05:08 | to load items quickly that are coming from the user's
local hard drive but also the ability to actually do a lot
| | 05:14 | of different PDF capabilities within the
HTMLLoader such as zoom in and move around
| | 05:18 | and look at a larger document. So
let's select this file and hit Open.
| | 05:21 | It will take it a second as it actually loads the PDF
but then you will see the interface that you are used
| | 05:26 | to when actually looking at PDFs inside of Acrobat
Reader and as you can see we can still zoom in
| | 05:31 | and we still can use the Hand tool
to move around the document.
| | 05:37 | And it looks very much like Acrobat Reader.
| | 05:40 | However, there is one problem with our application.
| | 05:42 | Here inside of the HTMLLoader, we have
scrollbars that are actually inside
| | 05:46 | of the PDF component inside of the HTMLLoader.
| | 05:48 | However we also have our scrollbars that we
created that are on the outside of the application.
| | 05:54 | So wouldn't it be great if we actually can hide the
scrollbars from reviewing PDF data inside of the HTMLLoader?
| | 05:58 | And that's what we are going to go
ahead and add next into our application.
| | 06:01 | This is a pretty easy fix.
| | 06:03 | When we go to the onPDFSelect method what we will need
to do is we will first say vScrollBar.v isible = false.
| | 06:12 | We will also do the same thing for hScrollBar.
| | 06:19 | Now we are actually going to need to be sure that they
in-enabled for every time that we are viewing a URL.
| | 06:25 | So to do this we are going to update another method.
| | 06:27 | The onGoClick method is fired every time that the Go
button is pressed and it is actually used to load a new URL.
| | 06:34 | So we know a couple of things about this.
| | 06:35 | Every time that we view a URL it's
going to actually call this method.
| | 06:39 | So let's now say vScrollBar.visible
is going to be equal to true
| | 06:46 | and then hScrollBar.visible is
also going to be equal to true.
| | 06:51 | Now if we save our application and then go back to Control and
then Test Movie we will now see that we can load a PDF file
| | 06:58 | and when it's viewed we have actually hidden
the scrollbars that we added previously.
| | 07:04 | And now you can see and use the scrollbars that actually are
included with the PDF viewer inside of the HTMLLoader class.
| | 07:10 | So now you have been able to create an application that
first detects if the user has adequate support for PDFs.
| | 07:16 | And you have actually created an application where they can
select a local PDF from their hard drive and then view it.
| | 07:21 | Now before you move onto creating applications that
use PDFs there probably are a few things that you want
| | 07:25 | to know about the PDF support inside of AIR.
| | Collapse this transcript |
| Limitations of PDF support| 00:01 | Now there are a few limitations to PDF Support
inside of AIR that you probably need to be familiar
| | 00:06 | with before developing applications that use PDF Support.
| | 00:09 | First as you have already learned, the user has to
have a current version of Acrobat Reader installed,
| | 00:15 | but in addition, there are other limits to the
way the PDF content can be displayed within AIR.
| | 00:20 | First, a PDF always sits at the top of the display order.
| | 00:24 | This means that you can't create anything that
actually is going to be in front of the PDF view.
| | 00:29 | In addition, if you have a Custom Chrome window,
you can't display PDF content inside of that window.
| | 00:34 | PDF content also cannot be used in a window that is set
to the Full_Screen or Full_Screen_Interactive state.
| | 00:40 | Now we haven't covered these states yet, but we will
actually cover them in an upcoming lesson and just know
| | 00:45 | that in these cases you can view
PDFs inside of these windows.
| | 00:48 | In addition unlike any other element on the
Stage, you can't adjust the alpha, scaling,
| | 00:53 | or rotation of the PDF inside of the HTMLLoader class.
| | 00:56 | And finally you must set the StageScaleMode to No Scale.
| | 01:00 | However, after you know these limitations and
you can develop your application around them,
| | 01:04 | you can build powerful PDF Support into an AIR application.
| | Collapse this transcript |
|
|
8. Using Native WindowsIntroducing native windows| 00:00 | Well many applications can exist with only a single window,
in many cases, applications will need more than one.
| | 00:06 | AIR provides robust support for
applications that utilize multiple windows.
| | 00:10 | In addition, AIR allows you to create windows that
look and behave differently based on your needs.
| | 00:15 | Also if there is not a window type that meets
your needs, you can create a custom window
| | 00:19 | and then implement the functionality yourself.
| | 00:21 | All of this functionality is encompassed
in the Windowing API for Adobe AIR.
| | 00:26 | First there are some classes you need to be familiar
with that we will be using throughout this chapter.
| | 00:30 | First flash.display.NativeWindow and it's the
base class for every window in an application.
| | 00:36 | So even the windows that we have created so far, even though
we have only referenced it once, actually use this class
| | 00:43 | in addition flash.display.nativeWindow net options
this basically just allows you to set all the options
| | 00:49 | for a new window and then you can actually
launch it after you set these options.
| | 00:53 | Next flash.display.NativeWindowSystemChrome, it defines
all the different types of chrome that you can have
| | 01:00 | for your application and we will discuss
more of what chrome is in a minute.
| | 01:03 | Also Flash.display.NativeWindowType defines
different window types, so there are different types
| | 01:09 | of window that you can create within AIR.
| | 01:11 | And then finally flash.display.NativeWindowDisplayState,
this one defines the different display states for a window.
| | 01:18 | So for example this also would include
Full_Screen and Full_Screen_Interactive
| | 01:22 | that we will look at later in this chapter.
| | 01:25 | So AIR Window Customization, there really are three
different ways that you can customize a window with an AIR,
| | 01:30 | and we can change the following properties.
| | 01:32 | First the Window Type, AIR gives you three
different window types that you can work with
| | 01:37 | and we will see what those are in a second.
| | 01:39 | In addition, Chrome. Windows can
use System Chrome or have No Chrome.
| | 01:43 | You can create your own chrome and then
implement some functionality yourself.
| | 01:46 | And finally you can change the Transparent
property, so that you can choose for your window
| | 01:50 | to have a transparent background or if you set
it to False you can have an opaque background.
| | 01:54 | Let's look at the different window types, these are going
to be specific to windows, the Mac windows will look similar
| | 02:02 | but they all have views that are
specifically tailored to OSX.
| | 02:05 | Now window types are defined in the NativeWindowType class.
| | 02:08 | You can see here the first we have a standard window,
now up till now this is what we have worked with.
| | 02:13 | You will notice that around the edge of the application, the
chrome is a little bit smaller, there is not as much there.
| | 02:19 | Next we have Lightweight window and you
will notice that it has no chrome around it.
| | 02:22 | In addition, Utility window and Lightweight
window won't appear on the windows taskbar
| | 02:26 | and they also won't be displayed
in the Windows List for Mac.
| | 02:30 | So what is Chrome? Chrome is a common layout
| | 02:33 | that an operating system places
around the outside of an application.
| | 02:36 | Now this also helps the users to be familiar
with how to interact with an application.
| | 02:40 | Anyone that's use windows is going to recognize if you are
on the right with the Close button with the Maximize button
| | 02:46 | and the Minimize button and this
is called the System Chrome.
| | 02:50 | So applications that use Custom Chrome can
have a custom look, but the developer will have
| | 02:54 | to implement the chrome functionality with an ActionScript.
| | 02:57 | The example on the right is one of the sample
applications that Adobe provides with the AIR SDK
| | 03:02 | that actually can be downloaded from the same site.
| | 03:04 | Now applications that have Standard Chrome
already have the drag, minimize, maximize,
| | 03:08 | resize, and close functionality implemented.
| | 03:10 | We have seen that in the applications
that we have created already.
| | 03:13 | So there is lot of advantage to using the Standard Chrome,
but in the cases where you really want to customize the look
| | 03:18 | in field, you can use Custom Chrome and
then just add this functionality yourself.
| | 03:22 | Next with Transparency, you can implement windows
that have regular shapes as well as add filters
| | 03:27 | such as a Drop Shadow to the outside of your application.
| | 03:29 | So you are not limited to windows that are just
rectangular, you can have circular windows,
| | 03:33 | you can have windows in crazy shapes,
however you would like to make them.
| | 03:37 | But also note that when you turn Transparency
on, your AIR Applications are going
| | 03:41 | to use a little bit more system
resources than they would have otherwise.
| | 03:44 | Now to edit a Window's properties you
can edit them inside of the applications
| | 03:49 | and Installer Settings dialog box for the initial window.
| | 03:52 | So in other words when you launch your application
that first window you can customize everything
| | 03:57 | within the application and installer settings dialog box.
| | 03:59 | But please note with the window
type Transparency and Chrome,
| | 04:03 | these properties can only be set
before opening the new window.
| | 04:06 | So whether you are editing your initial window or you are
creating a new window and launching it you have to be sure
| | 04:11 | to set those properties before
the window is actually opened.
| | 04:14 | Since you now know the basics of
the Windowing API inside of AIR,
| | 04:18 | you are now ready to convert a single window
application into a multi-windowed application.
| | Collapse this transcript |
| Creating standard windows| 00:00 | Up to this point you have been able to create
applications that utilize a single window within AIR
| | 00:05 | but you are probably ready to expand and start
working with applications that have multiple windows.
| | 00:10 | For example the browser application that we have created
utilizes a single window to load and view both HTML
| | 00:15 | and PDF content but most browsers allow you to open up
multiple windows to view multiple sites simultaneously
| | 00:21 | so we are going to go ahead and add
this functionality to our application.
| | 00:25 | First we are going to need to open the file.
| | 00:27 | We will go to File and then open and
then we will select browserapplication01
| | 00:32 | in the Chapter 8 folder of the exercise files.
| | 00:35 | Now we are first going to need to
restructure some elements of our application
| | 00:39 | so that we can actually reuse our browser
components so the first thing we are going
| | 00:43 | to do is we are going to unlock our UIlayer.
| | 00:46 | We are going to hit Ctrl+A or Cmd+A on Mac, select
all the items in this layer and then we are going
| | 00:51 | to press the F8 key and that will bring
up the Convert To Symbol dialog box.
| | 00:55 | We are going to name this browser be sure it is
set as a movie clip, we are also going to be sure
| | 01:02 | that we have checked Export for ActionScript.
| | 01:05 | Now if you don't see these bottom items linkage and source
you might not have the Advanced Options pushed so be sure
| | 01:10 | that you click Advanced Options to see the additional items.
| | 01:14 | After we check Export for ActionScript
we are just going to leave the class
| | 01:17 | as browser and we can just go ahead and hit OK.
| | 01:20 | It will then tell us that a definition for this class cannot
be found and that one would automatically be generated
| | 01:25 | in the SWF file upon export and
that's fine and we will click OK.
| | 01:28 | Now we are going to want to select a browser application.
| | 01:32 | We are actually going to move it to 00 on the Stage
and now we are going to go in and position our items.
| | 01:39 | So to edit this we can just double-click.
| | 01:42 | Now that we have entered in we actually can
be sure that everything is still selected
| | 01:45 | and we will actually now position
the elements where we want it to be.
| | 01:49 | And that's about where they were previously and that
should work fine for our application so now we are going
| | 01:56 | to call this layer UI and now we can lock it.
| | 02:00 | And now we are going to add an
Actions layer and we will drag it
| | 02:03 | to the bottom we will name it Actions
and we will lock the layer.
| | 02:08 | We will now go back to the root movie so we will click on
Scene1 we will open the Actions layer, we will go to Window
| | 02:15 | and then Actions to open up the Actions panel and
then we will just press Ctrl+A or Command+A on Mac
| | 02:21 | to select everything and then Ctrl+C or Command + C
in Mac to actually copy everything to the clipboard.
| | 02:27 | We will then close the Actions panel here, we will go
into our browser by double clicking on the browser symbol,
| | 02:33 | we will go to the Actions layer that we just created
and then we will go to window and then actions
| | 02:39 | and then we will paste everything by pressing
Ctrl+V or Command+V on Mac and we have see
| | 02:44 | that we have pasted in everything just as it was.
| | 02:47 | Up to this point we haven't changed anything
so now let's actually save our application,
| | 02:52 | we are going to close this Actions panel,
we will go Scene1 and we can go ahead
| | 02:57 | at this point and delete all of the existing actions.
| | 03:00 | So we will go back to Window Actions everything if
it's still selected you can just press the Delete key,
| | 03:06 | if not you can press Ctrl+A and select everything
or Command+A on Mac and then press Delete.
| | 03:11 | Now we can close this Actions Frame, we can press
Save and now we can go to Control and then Test Movie.
| | 03:17 | And we can see here that the core visual
elements of our browser have been preserved.
| | 03:24 | It's still able to load a URL so it has the scroll
bar, still has the forward and back buttons,
| | 03:29 | still has the Load PDF button- everything that we
have expected from our browser is still functional.
| | 03:35 | But we have actually now encapsulated it
inside of a symbol so that it can be reused.
| | 03:40 | Now at this point we are going to need to add one
more button to our browser application so now instead
| | 03:47 | of actually working here in the root movie to work with the
browser we are going to double click on the browser symbol.
| | 03:53 | Now we are going to actually move the forward
and back buttons a little bit closer together
| | 03:57 | so to accomplish this we are going to unlock the UIlayer
| | 04:01 | and we will move the Forward button a
little bit closer to the Back button.
| | 04:05 | We will now highlight the URL input, select the Free
Transform tool, hold down Alt on PC or Option on Mac
| | 04:13 | and we will just drag it a little bit
and leave it in for another button.
| | 04:16 | Now we can open up the Components window by going under
Window and then Components and now we want to drag
| | 04:22 | out another instance of the button onto Stage.
| | 04:25 | Now we can close the Components window, we are going to
give our new button an instance name of New Window Button
| | 04:34 | and then we will click on the Parameters tab and of
the label we will actually just put in a plus symbol
| | 04:40 | and we will also change the width
of this particular item to 30.
| | 04:45 | Now we can actually move it around
to position it where we would like.
| | 04:48 | I am actually going to be sure that it's going to be
aligned with all the other items currently on the Stage.
| | 04:55 | We will align it to center and then we will select the
URL input one more time, select the Free Transform tool,
| | 05:02 | hold Alt on PC or Option on Mac
and actually move it back over.
| | 05:05 | Now we are going to need to go into
ActionScript and actually put in the codes
| | 05:14 | that we can create a new window every
time the new window button is pushed.
| | 05:17 | So what we are going to need to do within the symbol,
within the browser symbol we will select the Actions layer
| | 05:24 | and we also can go ahead and lock the UI layer
and then we will go under Window and then Actions.
| | 05:29 | We are going to need to add an event
listener for our New Window button.
| | 05:33 | So we will say newWindowButton.addEventListener and
we are going to listen for the MouseEvent.CLICK event.
| | 05:42 | And then we are going to actually call the
method onNewWindow so now we can scroll
| | 05:50 | down to the event handler section and we
will create a new method onNewWindow.
| | 05:59 | It will receive an event of type
MouseEvent and it's actually not going
| | 06:03 | to return anything so we can set the return type as void.
| | 06:06 | Now we are going to need to start
the process of creating a new window.
| | 06:11 | But to do this we are going to need to be sure that we have
some classes imported so we will scroll back to the top.
| | 06:17 | Now all the classes that we need actually
exist in the flash.display package
| | 06:23 | and as you can see we have already imported all of those
items. So we are not going to have any additional items
| | 06:29 | to import but just be sure when you are working with the
NativeWindows that you are going to specifically need
| | 06:34 | to be sure that you have flash.display.NativeWindow as well
| | 06:37 | as flash.display.NativeWindowInitOptions
so let's scroll back down to our method.
| | 06:42 | Now the first thing we are going to need to do is to
create a new instance of the NativeWindow init options
| | 06:50 | so I will say var options it's going to be of
type NativeWindowInitOptions and that's going
| | 07:00 | to be equal to a new NativeWindowInitOptions.
| | 07:05 | Now this is just going to enable us to set
different values for the window before it launches.
| | 07:13 | The first thing we are going to do is actually set
the system chrome so we will say options.systemChrome
| | 07:19 | and we are going to set that equal
to NativeWindowSystemChrome.
| | 07:25 | and we are just going to use standard.
| | 07:30 | Next we are going to want to actually
set the transparent value
| | 07:36 | and in our case we are not using transparency
so will just set that equal to False.
| | 07:43 | Next we are going to change a few specific
items that we have discussed previously.
| | 07:47 | Now when we wanted our default windows to not be maximizable
and to not be resizable we could adjust those values inside
| | 07:53 | of the Application Descriptor file by using the application
and installer settings dialog box inside of Flash.
| | 07:59 | However in this case for a new window that you
create you actually have to set those values
| | 08:03 | with the NativeWindowInitOptions so we will say
options.resizable is going to be equal to false
| | 08:10 | and options.minimizable is going
to be equal to false as well.
| | 08:15 | Now that we have set most of the options we are
actually ready to create our new NativeWindow.
| | 08:20 | So we will say var window of type NativeWindow
is going to be equal to a new NativeWindow.
| | 08:28 | And to the constructor we are actually
going to pass in our options variable.
| | 08:33 | And this is how you actually pass your
NativeWindowInitOptions into the new NativeWindow.
| | 08:41 | Next we are going to need to actually set the width and
height of the window so we will say window.width is going
| | 08:47 | to be equal to 800 and then window.height=600.
| | 08:55 | Now there would be another step that we would need to take
but since we have already within our symbol actually set
| | 09:01 | up the Stage properties for Stage.ScaleMode and Stage.Align
we don't have to worry about setting those up again here.
| | 09:11 | And now we need to actually add our browser to the new
window so we are going to say var b and that will be
| | 09:17 | for browser and this again is the symbol that we just
created and that's going to be equal to a new Browser.
| | 09:24 | And then what we are going to do is there
is a Stage property inside of each window
| | 09:30 | and we can just say window.stage and then just as we
would add an item to the display list we are going
| | 09:35 | to do the same thing here with the addChild method.
| | 09:38 | We will say addChild and then just pass in P. Now
the last thing we will need to do to actually open
| | 09:44 | and activate the window is to use
the window.activate method.
| | 09:52 | Now let's review what we have done in this method.
| | 09:54 | First we have created a new instance
of the NativeWindowInitOptions class,
| | 09:58 | we have set the SystemChrome, the transparent property, the
resizable property as well as the minimizable property.
| | 10:05 | We then created a new instance of the
NativeWindow class and set the width and height.
| | 10:09 | We have then added an instance of our symbol to the Stage
of the new window and then we have activated the window
| | 10:15 | which actually launches the new window and
makes it the active window in the application.
| | 10:19 | So now we are actually ready to jump in and
test our application and see how it works.
| | 10:24 | I will first save my application and then I will go
to Control and then Test Movie to launch our application.
| | 10:33 | So now we can see that we have
our plus button here on the Stage.
| | 10:36 | We can see that our browser still works even
though we have now encapsulated it into a symbol
| | 10:40 | and if we press the New Window button we now
open up a new window that does the same thing
| | 10:44 | and we can open up as many windows as we would like.
| | 10:47 | Each of these can now view a different web page and in
addition we can still use the Load PDF functionality
| | 10:55 | to load a PDF from the local hard drive so we have
now created our first multi-window application
| | 11:01 | that uses the NativeWindow class as well as the
NativeWindow init options inside of Adobe AIR.
| | 11:07 | Now that you have done a standard window we will actually
move onto working with some more complex situations
| | 11:11 | where you would use some different properties
for SystemChrome and for Transparent.
| | Collapse this transcript |
| Creating windows with custom chrome| 00:00 | Now in many cases, you will want to give
your application a custom look and feel.
| | 00:04 | Now in these cases, you can use Custom Chrome. The
important thing to know here is that this isn't ideal
| | 00:09 | for all applications, you are going to be creating an
interface that the user is not familiar with But in cases
| | 00:15 | where you really need to provide a custom experience for
the user, Custom Chrome is one of the best ways to do it
| | 00:20 | and it gives you a level of customization
not possible any other way.
| | 00:24 | So we are going to go ahead and take
our browser application and we are going
| | 00:27 | to go ahead and make it work with Custom Chrome.
| | 00:29 | So let's go ahead and open the file.
| | 00:31 | We will go to File and then Open and then we will
look in the Chapter 8 folder of the exercise files
| | 00:36 | and we will go to Browser Application 02.
| | 00:38 | Now we are going to need to adjust some
elements within our browser movie clip,
| | 00:44 | so let's go to the library, find Browser and double click.
| | 00:47 | Now that we have loaded up our browser movie clip,
we are going to need to create our Custom Chrome.
| | 00:53 | So I am going to create a new layer and I am
just going to call this BG for background.
| | 00:58 | We are now going to drag out a rectangle, so I am
going to select a rectangle tool and for this case,
| | 01:02 | I am going to be sure that the Stroke is set to black and
for the Fill Color, I am just going to select a dark grey,
| | 01:09 | but then I am also going to go in
and be sure that the Alpha is set
| | 01:12 | and we will probably drop it down it down to be at 50%.
| | 01:15 | Now we can go ahead and drag out our rectangle.
| | 01:20 | Now in this case, I am just going to drag out a
small rectangle and then I am going to be sure
| | 01:24 | that we highlight the whole thing and then we
are going to go in and set the width and height.
| | 01:28 | The width of our entire application is
800, but we are going to set the width
| | 01:31 | of the background to 790, I will explain why in a minute.
| | 01:35 | And then for the height, we are going to set it to 590,
so we are actually leaving 10 pixels, 5 on each side.
| | 01:42 | Now we are actually going to want to set this at 5 and 5,
| | 01:45 | so that we have left some additional
space on the edge of our application.
| | 01:49 | Now we are actually going to convert this background
into a movie clip, be sure that we have it selected
| | 01:55 | and then we will press the F8 key to
bring up the Convert to Simple dialog box.
| | 01:59 | We will just call this for the moment
BG, we will leave it as a movie clip
| | 02:03 | and then we will be sure to give it an instance name of BG.
| | 02:06 | Now we are going to go ahead and add a filter.
| | 02:09 | One of the things that we discussed earlier was that we have
the capability now to add a filter to our Custom Chrome,
| | 02:15 | so let's click on Filters, we are going to add a Glow and in
this case I am just going to select black and we are going
| | 02:23 | to be sure that we set quality to High and this will
give us a shadow around the edges of our application
| | 02:28 | and this is the reason that we also didn't have
our background take up the entire width and height
| | 02:33 | of the application to leave room
around the edges for the shadow.
| | 02:36 | At this point, we could launch our application,
but we will still have the Standard Chrome set,
| | 02:41 | even if we went and change the Open New Window option.
| | 02:44 | So the first thing, we are going to do is change the
properties for the initial window that is opened.
| | 02:49 | So in this case, we can go under Commands,
AIR Application and Installer Settings
| | 02:54 | and we are going to change the window style.
| | 02:57 | At this point, it is set to System Chrome.
| | 02:59 | We are going to change it to Custom Chrome, Transparent.
| | 03:03 | Now what this does is this actually
sets multiple properties.
| | 03:06 | It sets transparent=true and then
it sets the systemChrome=none.
| | 03:12 | So let's go ahead and select that
value and then we will click OK.
| | 03:16 | In addition, we are also going to
need to go into our Actions layer,
| | 03:19 | so let's highlight the Actions layer
and go to window and then Actions.
| | 03:23 | We will scroll down to our onNewWindow method
which can be found in the Event Handler section.
| | 03:28 | And the first thing that we are going to do is we
are going to change the options.systemChrome instead
| | 03:32 | of saying NativeWindow.systemChrome.STANDARD, we
are going to say NativeWindow.systemChrome.NONE.
| | 03:38 | And we are also going to want to change the Transparent
property, so we will say options.transparent=true.
| | 03:46 | Now we can save our application and we are
going to go to Control and then Test Movie.
| | 03:53 | We can see now that we actually have a
Transparent and Custom Chrome application.
| | 03:58 | We can see here that we can actually
see under our application,
| | 04:01 | we can see the items there, because
our application is transparent.
| | 04:04 | We also can see that around the edges of
the application we have a very light shadow.
| | 04:08 | However if you notice we now can
drag our application anywhere.
| | 04:12 | We also can close our application by using the normal Close
button, so we are going to need to add some functionality.
| | 04:17 | If you ever run into a situation where you have a window
open like this, if you are on Windows you can just go
| | 04:22 | to the taskbar right click and go to Close or in
Mac you can go to the Dock and do the same thing.
| | 04:27 | So now we are going to add some
functionality to our Custom Chrome application.
| | 04:31 | We want to be able to drag our
application around, we also want to be able
| | 04:34 | to close our application as well as minimize it.
| | 04:38 | Now when you are working with Custom Chrome and you
actually have to replace some of the chrome functionality
| | 04:43 | with your own code, there are methods that are provided by
AIR that will allow you to achieve the same functionality.
| | 04:48 | First NativeApplication.exit allows you
to actually close the entire application.
| | 04:54 | NativeWindow.close actually closes the current window.
| | 04:57 | NativeWindow.startMove allows the user to actually drag
the window, so this way a user could actually click
| | 05:03 | on your Custom Chrome and drag
your application around the screen.
| | 05:07 | NativeWindow.startResize allows the user to actually resize
the window, so you could actually then wire this function
| | 05:14 | in with width and the height of the Nativewindow.
| | 05:17 | NativeWindow.maximize allows the user to maximize the window
| | 05:20 | and NativeWindow.minimize allows
the user to minimize the window.
| | 05:23 | So by using these functions, you can get the same
functionality that is provided with the Standard Chrome.
| | 05:30 | So now within our browser application, we
are going to go ahead and lock the BG layer.
| | 05:34 | We are now going to move the items in the UI Layer
down just a little bit, so I am going to press Ctrl+A
| | 05:41 | to select everything on this layer and we
are just going to move everything down,
| | 05:44 | because we want to add room for some new buttons.
| | 05:46 | In addition, after we have done this we will have to go
in and actually reposition our HTMLLoader object as well.
| | 05:52 | So first we are going to be sure that we are still on the
UI layer, we are going to open window and then components
| | 05:57 | and we are going to drag two instances
of the button out onto the Stage.
| | 06:00 | The first button, we are going to actually call the
Close button and that will be the instance name.
| | 06:08 | And instead of actually writing close inside
of this, we are just going to use an X
| | 06:13 | to almost make it mimic what would
be in the Standard Chrome.
| | 06:16 | We are only going to set the width here to 30 and we
are going to select the next button and we are going
| | 06:20 | to give it an instance name of Minimize button.
| | 06:23 | We are going to set the width to 30 and we are going
to be sure that we set the label here to underscore
| | 06:31 | to also attempt to mimic what would
normally be in the Standard Chrome.
| | 06:35 | Now we can actually position our
two elements on to the Stage.
| | 06:45 | And I will just select both of these buttons, be sure
that they are aligned to center and we will move them
| | 06:51 | over just a little bit so that they are
even with the right side of loaded PDF.
| | 06:55 | Now we actually can begin working with these methods inside
of ActionScript, so we can go ahead and lock the UI Layer,
| | 07:01 | highlight the Actions layer and then
we will go to Window and then Actions.
| | 07:05 | As I stated earlier, the first thing you are going to need
| | 07:07 | to do is reposition our HTMLLoader
object, so let's scroll up for that.
| | 07:12 | Now here you can see that we have set the width and
the height and the x and y value for the HTMLLoader.
| | 07:18 | In this case, we are just going to
bump up the htmlLoader.y value to 75.
| | 07:24 | Now we are actually going to put in the functionality
that we need for our Close and for our Minimize button,
| | 07:28 | so first we will need to add an event listener, so we will
scroll down to the section where we add event listeners
| | 07:32 | and we will create two new event listeners, first for Close
button and then we will listen for the MouseEvent.CLICK event
| | 07:45 | and then we will call the onCloseClick
method which we will implement shortly.
| | 07:51 | Then we have our Minimize button.
| | 07:53 | We will do the same thing for it.
| | 07:55 | We will add the event listener.
| | 08:02 | We will listen for the MouseEvent.CLICK event and
then we will actually call the OnMinimizeClick.
| | 08:14 | So now we actually can implement these methods,
so let's go to our Event Handler section.
| | 08:17 | We will scroll down.
| | 08:20 | The first one that will implement would be onCloseClick
and then we will receive an event that will be
| | 08:29 | of type MouseEvent and it's not going to return anything,
so we can set the return type to be equal to void.
| | 08:35 | Now at this point, what we are going to need
to do is actually get the current NativeWindow
| | 08:40 | that can be accomplished by going to
Stage.NativeWindow and then we will call the Close method.
| | 08:47 | Now we are going to need to implement our
Minimize button, so we will see onMinimizeClick.
| | 08:55 | It will receive an event of type MouseEvent.
| | 08:59 | It's not going to return anything, so
we can leave the return type = void.
| | 09:04 | Now inside of here what we will do is we
will call Stage.NativeWindow.minimize.
| | 09:11 | Now there is one last thing we need to do, we stated earlier
that we wanted to be able to drag our application around,
| | 09:18 | to do this we are going to need to listen
for a specific event on our BG layer.
| | 09:22 | So we will go up and we will call
BG which again is the instance name
| | 09:27 | of our BG movie clip, we will add an event listener.
| | 09:32 | We will listen specifically for the MouseEvent,
instead of click this time we will be listening
| | 09:37 | for mouse down and then we will say onBGMouseDown.
| | 09:40 | We will highlight the name of this method and we can use it
| | 09:47 | when we actually create the method,
which is what we will do now.
| | 09:49 | We will scroll down in the Event Handler section,
we will create a new method Function on BGMouseDown
| | 09:57 | and it will receive an event of type
MouseEvent and the return type will be void.
| | 10:04 | Now we just need to call one method to implement
this, we will say Stage.NativeWindow.StartMove.
| | 10:15 | Now this will ask to start the dragging, you
don't have to call a NativeWindow.StopMove.
| | 10:20 | AIR actually is intelligent enough to detect
when the user stops dragging the application.
| | 10:23 | Se we will now save our application
and go to Control and then Test Movie.
| | 10:29 | First, we should be able to click anywhere on our background
| | 10:32 | and actually drag our application
around which we can indeed do.
| | 10:35 | We also should be able to go to our
Minimize button and we should be able
| | 10:38 | to click it and actually minimize our application.
| | 10:41 | Finally, we should be able to actually close
our application by clicking the Close button.
| | 10:46 | So at this point we have created
an application with Custom Chrome.
| | 10:49 | We have mimicked several functions of the Standard Chrome.
| | 10:52 | We have actually enabled a Close button,
a Minimize button as well being able
| | 10:55 | to drag the application around the screen.
| | 10:58 | We have also created a transparent background
that allows us to also add a custom filter
| | 11:02 | so that we can have a custom glow on our application.
| | 11:04 | Now again this is a very powerful feature
that needs to be used only when needed
| | 11:08 | because again we are creating an interface
that the user is not familiar with,
| | 11:12 | but in situations where you want a deep level of
customization, Custom Chrome can provide that for you.
| | Collapse this transcript |
| Creating resizable windows| 00:00 | In most cases, you will want to preserve the
experience that the end user is familiar with.
| | 00:05 | With this being true, most users are
used to having windows that are resizable
| | 00:08 | when you are using the standard system chrome.
| | 00:10 | Now, responding to the resize event from the Native
window, you can create windows that are resizable
| | 00:15 | and resize the elements on the Stage accordingly.
| | 00:17 | So let's go ahead and open up a file to work with.
| | 00:19 | We will go to File and then Open and then
we will open the Browser Application 02 file
| | 00:24 | in the Chapter 8 folder of the exercise files.
| | 00:27 | Now, the first thing we are going to
need to do is go into our Browser symbol.
| | 00:33 | So we'll double-click on the browser movie
clip and then we go to the Actions layer
| | 00:36 | and then we go to Window and then Actions.
| | 00:39 | Now, we are going to want to listen inside
of this movie clip to the resize event
| | 00:43 | that gets dispatched by the NativeWindow.
| | 00:44 | To do this, we are going to say stage.nativeWindow
and this is how you get the current NativeWindow
| | 00:51 | that this movie clip is in and then we are going
to say addEventListener and then from here,
| | 00:56 | we are going to listen for the Event.RESIZE and we are
going to respond to that with a method onWindowResize.
| | 01:06 | So now we can scroll down to our Event Handler
section and begin working with that event.
| | 01:11 | We will create our new method onWindowResize and it's
going to receive an event of type event and it's not going
| | 01:22 | to return anything so we can leave the return type void.
| | 01:24 | Now, what we are going to want to do is resize
any elements that need to be resized every time
| | 01:32 | that somebody actually drags the
corner of the application to resize it.
| | 01:35 | The first thing that we are going to need to do is we
are going to need allow users to resize our window.
| | 01:39 | We currently have that disabled.
| | 01:41 | If we go under Commands and then AIR
Application and Installer settings,
| | 01:45 | we'll need to go to the Advanced Settings and then
we need to check resizable and then we can click OK.
| | 01:52 | Now, let's take a look at our application.
| | 01:54 | If we go to Control and then Test Movie, we can see that
right now we can't drag the corner of our application
| | 02:02 | but obviously nothing changes when we drag the corner
because we have set the Stage scale mode to none.
| | 02:08 | What we would like to have happen is every
time we drag the corner of the application,
| | 02:12 | we would want the HTMLLoader to
actually grow with the application.
| | 02:16 | We would want the URL input value to actually
grow with the application and then the loadPDF
| | 02:22 | and goButtons to actually move with the URL input.
| | 02:25 | In addition, we want the scroll bars to
maintain their functionality as well.
| | 02:29 | So let's actually see how we can
implement that in our application.
| | 02:32 | I am going to go ahead and close the
application and go back to the Actions panel.
| | 02:36 | The first thing that we are going to need to do
is scroll up and look at our HTMLLoader object
| | 02:40 | when we actually positioned it on the Stage.
| | 02:43 | You can see here that we already have set
the width and height values in respect
| | 02:47 | to the Stage width and Stage height values.
| | 02:50 | This is important.
| | 02:51 | When you are resizing an object,
you can't use absolute values,
| | 02:55 | so you couldn't set the width to 650 and the height to 400.
| | 02:59 | In those cases then, when you went to resize it,
it wouldn't actually scale with the application.
| | 03:03 | But if we create things that are relative
to the Stage width and Stage height,
| | 03:07 | then we can know that these values
can scale as the application scales.
| | 03:12 | So I am going to highlight these two lines and we
are actually going to reset the width and height
| | 03:16 | of the HTMLLoader object every
time that we resize the window.
| | 03:21 | So let's scroll down and in the onWindowResize,
we are going to paste these values in.
| | 03:26 | Next, we are going to need to position the
PDF button, the Go button and the URL Input value.
| | 03:32 | Well, let's take a look at our application.
| | 03:37 | The first thing that you will notice is
the Load PDF button is up to the edge
| | 03:41 | of the Stage with a little bit of padding in between.
| | 03:44 | So we know that we can position
everything off of this button as long
| | 03:48 | as we set it off a certain number of pixels from the Stage.
| | 03:51 | So let's go ahead and do that.
| | 03:52 | Now, to accomplish this, we are
first going to say pdfButton.x
| | 04:00 | because the x value is the only value
that's going to change in the PDF button.
| | 04:03 | We are not going to make it bigger, we are not going
to make it smaller, we are just going to move it.
| | 04:07 | So we will say pdfButton.x is going
to be equal to Stage.stageWidth.
| | 04:13 | But then we are going to want to actually subtract a little
bit so that it's back from the edge of the Stage width.
| | 04:20 | So we will say we want 10 pixels off the edge.
| | 04:23 | Now, in addition to that, because the x value occurs at
the top left of the PDF button, we are also going to want
| | 04:30 | to subtract the width of the PDF button itself.
| | 04:38 | Now, in addition, we are going to want to
position the Go button next to the PDF button.
| | 04:43 | So we will say goButton.x is going to be equal
to pdfButton.x and then we are going to want
| | 04:51 | to have a little padding between those
buttons as well, so we will say -10.
| | 04:55 | From there, we are going to subtract the goButton.width.
| | 04:59 | Now, the final thing that we are going to
need to set is the width of the URL Input.
| | 05:07 | So we will say urlInput.width because here unlike with
the PDF button and the Go button, we do want the URL Input
| | 05:17 | to shrink or to grow depending on how we are dragging
the application, so we will say urlInput.width is equal
| | 05:23 | to goButton.x. And then we want to
subtract the little bit of space for padding.
| | 05:28 | So we will say -10 and then we want
to subtract the urlInput.x value.
| | 05:34 | Now, we can actually test our application
and see how things are working so far.
| | 05:42 | We will go to Control and then Test Movie.
| | 05:45 | Now, if we move to the bottom right corner
of our application and we start to drag,
| | 05:52 | you can see that indeed a couple things are happening.
| | 05:55 | First, we are actually scaling the URL Input
as well as the Go button and the PDF button.
| | 06:02 | You can also see that we are scaling the HTMLLoader
but our scrollbars are remaining the same.
| | 06:07 | So we are going to have to reposition
our scrollbars as well.
| | 06:10 | Now, to accomplish this, we actually can copy
some more code that we have already written.
| | 06:17 | So let's scroll up to where we created our scroll bars.
| | 06:20 | Now, what we are concerned with here are three values.
| | 06:25 | For the vScrollBar, we are concerned
with the x and the y values.
| | 06:29 | We want to be sure that it's still positioned
directly to the right of the HTMLLoader.
| | 06:33 | In addition, we are also concerned with the height.
| | 06:35 | We want to be sure that if we make the HTMLLoader taller
| | 06:39 | that the vScrollBar still goes the
entire height of the HTMLLoader.
| | 06:43 | So we will highlight these three lines,
we will copy and the important thing
| | 06:48 | to note here is again we define the scrollbar in relative
terms to the htmlLoader.x and y and width properties.
| | 06:56 | By doing this, as the HTMLLoader grows,
the scrollbars can also update themselves.
| | 07:00 | So we will scroll down to the onWindowResize
method and we will paste these values in.
| | 07:09 | Next, we will do the same for the hScrollBar.
| | 07:13 | In this case, we are concerned with
the x and y properties and the width.
| | 07:16 | So we will select these three and we will go down
and paste them into our onWindowResize method.
| | 07:28 | Now, we'll need to call one last function.
| | 07:30 | We will need to call the updateScrollBars method.
| | 07:32 | This way, the scroll bars will be updated
with the new position of the HTMLLoader.
| | 07:41 | Now, if we save our application and test it, we can see
| | 07:50 | that indeed we can now scale our
application, we can make it resizable.
| | 07:54 | You will notice that the application grows and shrinks.
| | 07:57 | You will notice that the URL Input
grows as the application grows.
| | 08:02 | You will notice that the Go and
Load PDF buttons move with it.
| | 08:05 | You will also notice that the HTMLLoader container
grows and the scroll bars actually follow suit
| | 08:12 | and grow to the appropriate size and
also adjust themselves automatically.
| | 08:16 | As we shrink the application, the track and the
scrollbar get smaller and as we grow it, it gets larger.
| | 08:23 | So now, you know how to create resizable
applications within AIR by responding
| | 08:27 | to the Resize Event from the NativeWindow class.
| | 08:29 | We are now ready to move on to working
more with Windows inside of AIR
| | 08:33 | and moving on to some more advanced functionality.
| | Collapse this transcript |
| Creating full-screen windows| 00:00 | In some situations, you want to be able to create windows
that are full screen, up to this point you have been able
| | 00:05 | to maximize windows, which causes
a window to take most of the screen
| | 00:08 | but you still have the System Chrome around the edge.
| | 00:10 | But AIR gives you the capability to create
full screen windows that actually take
| | 00:14 | up the entire screen without any System Chrome around.
| | 00:17 | Now, this creates an immersive experience
that needs to be used carefully.
| | 00:20 | But when used properly it can provide a
very positive experience for the end user.
| | 00:24 | So, we are going to go ahead and add full screen
capability to our browser application, so let's go to File
| | 00:30 | and then Open and we are going to open BrowserApplication03,
which is the Chapter 8 folder of the exercise files.
| | 00:38 | Now, we are going to go ahead and double
click our browser movie clip and we are going
| | 00:42 | to change some of the functionality of our application.
| | 00:45 | Currently, we have a Go and Load PDF button. We're
going to go ahead and look at our Load PDF button,
| | 00:50 | we are going to unlock the UIlayer and we are going
to change its instance name to fullScreenButton.
| | 00:56 | In addition, we are going to change the label, so we will go
to the parameters tab, we will make the label Fullscreen.
| | 01:05 | Now, we are going to need to go into the ActionScript
and remove any references to the PDF button.
| | 01:11 | Now, this will occur in several places, so let's
highlight the Actions layer and we will go to Window
| | 01:16 | and then we will go to Actions and let's
scroll down first and we will just go ahead
| | 01:22 | and delete the event listener for the PDF button.
| | 01:26 | In addition, we will need to go to our
onresize event and while we are going,
| | 01:30 | we actually can delete the onPDFClick,
and onPDFSelect methods.
| | 01:34 | And every time we see pdfButton here, we are
going to need to replace it with fullscreenButton.
| | 01:43 | And so I will just copy to fullscreenButton and we
will paste it over all the references to the pdfButton.
| | 01:48 | Now, we know that we have deleted all of the important
references, if we can still run our application.
| | 02:05 | If it throws an error that means we might have missed
one; so let's Control and Test Movie and we can see
| | 02:11 | that indeed there wasn't an error because there were
few more places that we needed to delete it from.
| | 02:15 | If we look at the compiler errors, we can tell that
it gives us lines 159 and 161, so if we scroll down
| | 02:21 | and look at those lines, we can see
again we had our checkPDFSupport method.
| | 02:26 | We actually can delete this method all together
and then we can scroll back up to the top
| | 02:31 | and we can remove this from our initialization methods.
| | 02:36 | Now, we can save our application and test it again
and we can see now that everything lies properly,
| | 02:42 | so we have removed all the references to the PDF button.
| | 02:46 | Now, if we go back to our application, we are going to need
| | 02:48 | to know implement some functionality
for our Full Screen button.
| | 02:51 | So, we will go to the Add Event Listener section and we
will create a new event listener for our Full Screen button.
| | 02:57 | fullScreenButton.addEventListener and we are going to listen
for the MouseEvent.CLICK event and we are going to respond
| | 03:07 | to this with the onFullscreenClick method.
| | 03:13 | So, now we can highlight the name of that method, we can
copy it and then we can go down to our Event Handler section
| | 03:21 | under the onWindowResize and we can say, onFullscreenClick
that's going to receive an event of type, Mouse event,
| | 03:31 | that's not going to return anything, so
we can leave the return type as void.
| | 03:35 | Now inside of here, what we are going
to use is the StageDisplayState class.
| | 03:40 | Now, this is important that you need to have this class
imported, it actually is in the flash.display package.
| | 03:46 | And if we look at our imports, we can see that that
actually has already been imported, the entire package.
| | 03:51 | But if you don't have the entire package
imported then you will need to be sure
| | 03:54 | that you import the StageDisplayState class.
| | 03:57 | If you now scroll back down to our onFullscreenClick
method, we are actually going to now check
| | 04:03 | and see what state the application is
in. So we will say if stage.displayState,
| | 04:09 | which is the property that defines the
current display state of the application,
| | 04:13 | if that is equal to StageDisplayState.NORMAL,
which is the default value. If that's True,
| | 04:24 | then what we are going to want to
do, is we are now going to want
| | 04:27 | to set the stage.displayState =
StageDisplayState.FULL_SCREEN.
| | 04:39 | Now, in addition we are also going to want
to change the label of the Full Screen button,
| | 04:46 | so we will say fullscreenButton.label = End FullScreen.
| | 04:54 | This way the user can know that the button will now
function differently by taking them out of full screen mode.
| | 04:58 | Now, we are going to also put in an else statement because
if the display state is not in the normal property then
| | 05:05 | at this point we are in the full
screen mode and so we are going to want
| | 05:08 | to say stage.displayState is going to
be equal to StageDisplayState.NORMAL.
| | 05:19 | Now, we notice one error we made up here, currently,
| | 05:23 | we are saying if stage.DisplayState equals, using
the comparison operator, StageDisplayState.NORMAL
| | 05:29 | and that is correct.
| | 05:29 | But under, we actually want to use the assignment operator,
| | 05:33 | so we'll say Stage.DisplayState=Stage.DisplayState.FULL_SCREEN,
| | 05:37 | just as we have done down here with
Stage.DisplayState=Stage.DisplayState.NORMAL.
| | 05:43 | And here, we are also going to
want to change the label back.
| | 05:45 | So we will say fullscreenButton.label
is going to be equal to Fullscreen.
| | 05:52 | So, we will set it back to its default value.
And I see just another quick typo.
| | 05:56 | You need to be sure that we type fullscreenButton.
| | 05:59 | So, now we actually have implemented the functionality
to take an application and make it go full screen
| | 06:04 | by pressing a button, so let's test
our application and see how it works.
| | 06:07 | I will first save the application and then
I will go to Control and then Test Movie.
| | 06:11 | We can see now that we have the fullScreen button and if
we click it, our application takes up the entire screen
| | 06:19 | and because we actually have made a resizable
window, it also resizes to the proper size.
| | 06:23 | However, there is one thing to note here, we can click
here on the URL input, but we can't type anything.
| | 06:29 | If we click the search box inside of the
web page, we also can't type anything,
| | 06:33 | that's because there are actually
two different full screen modes.
| | 06:36 | The current mode that we are in,
| | 06:37 | StageDisplayState.FULL_SCREEN, has also
been available in Flash for sometime.
| | 06:42 | However, now we actually have the ability inside of
AIR to use a new display state full screen interactive;
| | 06:48 | that allows for the user to also interact with
your application while it's in full screen mode.
| | 06:53 | So, let's look in full screen and then click the Close
button and now let's go back to our onFullscreenClick method
| | 07:00 | and instead of saying StageDisplayState.FULL_SCREEN
we will say StageDisplayState.FULL_SCREEN_INTERACTIVE.
| | 07:09 | Now, we can hit Save and we can now go to Control
and Test Movie and now when we click Fullscreen,
| | 07:19 | we will now be able to not only see
the application in full screen mode,
| | 07:23 | we will also be able to interact with
it as well, now we will click Go.
| | 07:29 | And you can see there, now we have gone to Google's page
and we can see that now we can interact with the application
| | 07:34 | in full screen mode, so we can now click in
fullScreen and now we can close our application.
| | 07:40 | Using the full screen modes, should be used sparingly.
| | 07:42 | Again most users don't like it
when their entire desktop is taken
| | 07:45 | over by an application, unless
that's explicitly what they want.
| | 07:49 | It can be a great feature to enhance an application but in
most situations, you shouldn't play in for you application
| | 07:54 | to just automatically operate in full screen mode
and now that you know how to use full screen mode,
| | 07:58 | we are going to work with the few more
properties of NativeWindows inside of AIR.
| | Collapse this transcript |
| Setting a window to always be on top| 00:00 | In some situations, you are going to want a window of
your application to always reside on top of other windows
| | 00:06 | that are being displayed by the operating system.
| | 00:08 | The nativeWindow class actually gives you a property
alwaysInFront that allows you to set this value.
| | 00:14 | So let's go ahead and open up a file to accomplish this.
| | 00:16 | We will go to File and then Open and then
we will open up Browser Application04
| | 00:21 | in the Chapter 8 folder of the exercise files.
| | 00:23 | Now in this case, we are going to double-click on our
Browser movie clip and we are going to scroll over
| | 00:28 | and we will see that we have our Full creen button.
| | 00:30 | We are actually going to change this
button to be our alwaysInFront button.
| | 00:37 | We are also going to change the label. So we'll
go to Parameters and we will say Always In Front.
| | 00:43 | And we are also going to make this a toggle button,
| | 00:46 | so we are going to go where it says Toggle
and we change that from False to True.
| | 00:50 | Now we can actually go into our Actions layer,
| | 00:53 | so we will highlight the Actions layer, lock the
UI Layer, go to Window and then go to Actions.
| | 00:58 | The first thing that we are going to have to do is
remove any references to our Fullscreen button,
| | 01:02 | so we will scroll down, we will find our fullscreenButton
addEventListener. We will delete that event listener.
| | 01:07 | We will also scroll down to our event handlers
and we will delete the onFullscreenClick method.
| | 01:14 | Now we actually can scroll up and we can actually go
back to the section where we add our event listeners.
| | 01:21 | Now here we are going to want to add an
event listener for our alwaysInFrontButton.
| | 01:29 | And we are going to listen for the MouseEvent.CLICK event.
| | 01:35 | We are going to respond to that with an onTopClick method,
| | 01:40 | because this method will allow the
window to actually remain on top.
| | 01:43 | So let's scroll down to our Event Handler
section, we will create a new method OnTopClick
| | 01:52 | and it's going to receive an event of type MouseEvent.
| | 01:56 | It's not going to return anything, so
we can leave the return type as void.
| | 02:00 | Now inside of here, we are going to want to check and
see what the current alwaysInFront value is set to.
| | 02:05 | So we will say, If we are going to want to a
get to a reference of the current nativeWindow
| | 02:10 | that this movie clip is in, so
we will say stage.nativeWindow
| | 02:14 | and then we are actually going to
check the alwaysInFront property.
| | 02:20 | We will say if that is equal to True then
we are actually going to set it equal to False
| | 02:26 | then we'll say stage.nativeWindow.alwaysInfront = false.
| | 02:36 | But if it's not, then we are going to want to set it to
stage.nativeWindow.alwaysInfront=true and that's all we need
| | 02:48 | to do to actually implement this functionality.
| | 02:50 | So we can save our application, go to Control and then Test
Movie, oops! And we do have an error that we have run across.
| | 03:00 | We have one additional place that we have added
the Fullscreen button and that's actually
| | 03:04 | in the onResize method so let's go
and actually replace every instance
| | 03:07 | of the fullscreenButton with our alwaysInFrontButton.
| | 03:13 | We will just copy this and paste it
everywhere the fullScreenButton appears.
| | 03:26 | And be sure that we have referenced all
of them just by looking over the method
| | 03:29 | and now we can save our application
and go to Control and then Test Movie.
| | 03:33 | We can see now that it appears with
no errors and that's what we want.
| | 03:39 | Now to illustrate this functionality, I am also
going to go ahead and open up another window.
| | 03:43 | I am going to open up Internet Explorer.
| | 03:48 | So we will go and we will visit Google here
on Internet Explorer and we will notice
| | 03:53 | that this window right now currently resides directly
beside our application and when we click on our window,
| | 03:59 | it will be in front of it, but then when we click back on
Internet Explorer, it will go in front of our application.
| | 04:04 | However, if we go back to our application and we click
alwaysInFront, we now can click on Internet Explorer
| | 04:10 | and you will notice that it remains behind our application.
| | 04:13 | As a matter of fact, no matter
how many instances we open up,
| | 04:16 | this window that we have created will
always be in front of other windows.
| | 04:20 | But if we disable this button, if we untoggle it, we will
now notice that we can click back on Internet Explorer
| | 04:25 | and it will actually go in front of our application window.
| | 04:28 | So the nativeWindow.alwaysInFront property
allows you to create a certain window
| | 04:33 | that will always be in front of other windows.
| | 04:35 | This can be very useful if you are creating
an application that is going to reside
| | 04:39 | on the user's desktop while they are
working within other applications.
| | 04:42 | Again this is another bit of functionality
that's added to you
| | 04:45 | within the nativeWindow class in
the windowing API of Adobe AIR.
| | Collapse this transcript |
|
|
9. Managing Multiple WindowsShowing and hiding windows| 00:00 | Now we have already worked with many different
ways to show and hide windows within AIR.
| | 00:04 | And so we are going to review these and look at a few more.
| | 00:07 | First the nativeWindow.activate method brings the
window to the front and makes the window visible.
| | 00:12 | Now if you have created a nativeWindow and have not
| | 00:15 | yet opened it this will actually
create the window and open it as well.
| | 00:19 | nativeWindow.maximize maximizes the current window,
nativeWindow.minimize minimizes the current window.
| | 00:25 | Now we have used both of those already within our code.
| | 00:28 | And nativeWindow.restore returns the window to it's
previous state either before it was minimized or maximized
| | 00:34 | so let's look and see how this
works within an actual application.
| | 00:38 | Now that we are in Flash I am going to go ahead and open
up a sample application that utilizes these methods.
| | 00:44 | First I am going to go to File and then
Open and then in the Chapter 9 folder
| | 00:49 | of the exercise files I am going
to open BrowserApplication01.
| | 00:53 | Now in this application we actually have the capability
to test and see what these methods are going to do
| | 01:01 | so let's go ahead and go to Control and then Test Movie.
| | 01:04 | This is the same browser application
that we have seen previously.
| | 01:09 | We are going to go ahead and hit the
Plus button to create a new window.
| | 01:14 | However, now instead of seeing a new browser window we
have the show and hide methods that are going to allow us
| | 01:20 | to interact with the window that will soon be opened.
| | 01:23 | First we can choose to activate the new window
and the window has then been launched because it
| | 01:28 | yet hadn't been made visible by calling the
activate method we actually made the window visible.
| | 01:33 | Now if we choose to maximize the window it's actually
going to take up the full size of the screen.
| | 01:39 | Now the important thing to note here is it this
will happen even when we are on Mac OS X. Normally
| | 01:45 | on Mac OS X the Maximize functionality
does not work this way.
| | 01:49 | Usually the user is able to set a preferred size
and then by going to Maximize it will actually go
| | 01:54 | to that preferred size, however, with AIR in Mac
OS X the Maximize function works the exact same way
| | 02:01 | as it does on the PC version.
| | 02:03 | In addition to the maximize method we can then
restore and it will put the application back
| | 02:08 | to where it was before the Maximize command.
| | 02:11 | In addition we can call the Minimize command
and it will actually minimize the window
| | 02:15 | and then we can use restore to bring the window back.
| | 02:18 | Finally we could call the closeApplication and it
actually would close everything within the application.
| | 02:25 | So let's look and actually see
the code that accomplished that.
| | 02:28 | This was actually contained in a
movie clip called Show Utility.
| | 02:33 | Now if we open up the Actions layer by highlighting
the Actions layer and then going to Window
| | 02:38 | and then Actions we can see the code
that actually made this possible.
| | 02:41 | First we imported the NativeApplication class.
| | 02:45 | Then this particular symbol has a reference to a window.
| | 02:48 | And we actually passed in the window
that was to be launched.
| | 02:51 | Finally we created a combo box with an
event listener that fired the onActionBox method.
| | 02:57 | And we can see here that just as we learned previously
| | 02:59 | to maximize the window we called
the nativeWindow.maximize method
| | 03:04 | and the same thing for minimize, restore and activate.
| | 03:08 | So with this code you are able to actually control how
a window is displayed and how it's interacted with.
| | 03:14 | You can utilize this with custom chrome as we did
previously but you also can use this as a way to communicate
| | 03:19 | between different windows of an application.
| | 03:22 | When a user opens one window you can automatically
minimize another or if you knew that a user was going
| | 03:27 | to need a certain tool palette that was available in
a different window you actually could bring that one
| | 03:31 | and make it visible when they open another window.
| | 03:33 | This level of support provides and additional capability
| | 03:36 | that the developer can take advantage
of inside of the Windowing API with AIR.
| | Collapse this transcript |
| Changing window order| 00:00 | In addition to being able to show and hide specific
windows that you have opened for your application,
| | 00:05 | there are times when you are going to want to
change the order that these windows appear.
| | 00:08 | Now to accomplish this, AIR provides several methods
that are all methods of the NativeWindow class.
| | 00:14 | For example, we have NativeWindow.orderToFront
and this is going to bring the window
| | 00:18 | in front of all other application windows.
| | 00:21 | So if there is ever a point when you want one
application to move all the way into the front,
| | 00:25 | in front of all your application windows as well as any
other operating system windows, you can use this method.
| | 00:30 | You also can tell a specific window to go in front
| | 00:33 | of another specific window, this
is the NativeWindow.orderInFrontOf.
| | 00:38 | Next you can actually move a window to
the back behind all other opened windows
| | 00:42 | in the operating system, this is NativeWindow.orderToBack.
| | 00:46 | Next you have NativeWindow.orderBehind which
works similar to the orderInFrontOf method
| | 00:51 | in that you can move a window behind a window
that you actually pass in as a parameter.
| | 00:56 | And then finally, and we have seen this one
before NativeWindow.activate brings the window
| | 01:00 | to the front and makes it visible.
| | 01:02 | This can actually be used to launch a
window that has not yet been made visible.
| | 01:07 | So now let's go back to Flash and actually
see how this works within in an application.
| | 01:11 | Now let's go ahead and open up the application file.
| | 01:14 | If we go to File and then Open then we
are going to open browser Application02
| | 01:19 | in the Chapter 9 folder of the exercise files.
| | 01:22 | Now we are going to double click on
the Browser symbol in the library.
| | 01:27 | Now we are going to change this Fullscreen
button to actually be a Move To Back button.
| | 01:37 | In this way, when we actually press this button,
it will move our current window to the back
| | 01:42 | of the display order for all of the windows.
| | 01:44 | So now we are going to need to go in and adjust
a little bit of the code removing any references
| | 01:51 | to the Fullscreen button and will also
want to change the label to Move To Back.
| | 01:57 | So now let's highlight the Actions layer and
then we will go under Window and then Actions.
| | 02:02 | We know that first we added a reference to the Full Screen
button in the event listeners, so we will remove that.
| | 02:17 | We also know that we have a reference inside of the
onWindowResize method, so we will go ahead and rename that.
| | 02:25 | And we can then just copy and then
paste that over the other references.
| | 02:29 | Next we can actually remove the onFullscreenClick method.
| | 02:46 | And then finally, we should be ready to add the
information to actually move our window to the back,
| | 02:51 | so let's go to the section where we add our event listeners
and we are going to say moveToBackButton.addEventListener
| | 03:01 | and then we are going to listen
specifically for the MouseEvent.CLICK event.
| | 03:09 | And then we are going to actually
fire the onMoveToBack method.
| | 03:19 | So now we can go to the section where we have
our event handlers, we will move to the end,
| | 03:24 | we will create our new function onMoveToBack.
| | 03:25 | And then this will receive an event
of type MouseEvent and it's not going
| | 03:36 | to return anything so we can leave the return type void.
| | 03:42 | Now we are going to want to get a reference to
the NativeWindow the current window that we are
| | 03:46 | in which can be found as stage.nativeWindow and then we
are just going to need to call the orderToBack method.
| | 03:56 | Now by calling this method, we are going to move our
current window behind all other windows currently opened
| | 04:01 | by the operating system.
| | 04:02 | So let's test our application and see how it works.
| | 04:05 | We will now go to Control and then Test Movie.
| | 04:12 | And let's say, we want to open up a couple more windows.
| | 04:17 | So now we actually have 3 windows that are open, we should
be able to now go to the Move To Back button and press it
| | 04:23 | and we will see that our window disappears.
| | 04:26 | Not only did it move behind the two windows that we
had opened, but it actually moved behind Flash as well.
| | 04:31 | Now I can prove this, I am going to press
the button for each of these windows as well.
| | 04:34 | And now we are back to Flash and now if we minimize Flash,
behind it we will see the three instances of our windows.
| | 04:41 | So there will probably be many times as a developer
when you will want to adjust the order of your windows.
| | 04:46 | By using the methods that are provided by the
NativeWindow class, you can have fine grained control
| | 04:51 | over which windows are in front that your user can
interact with and then what other windows are either moved
| | 04:55 | to the back or minimized so that the
user can see them at the given time.
| | 04:59 | By capitalizing on this, you move one step closer to
creating a full featured desktop application with Adobe AIR.
| | Collapse this transcript |
| Listening to multiple windows| 00:00 | Now when you create multiple windows in a single application
in most cases you are going to want those windows
| | 00:05 | to be able to communicate one with another.
| | 00:08 | Now one of the approaches to doing this is by using the
openedWindows property of the NativeApplication class.
| | 00:15 | This property is an array that contains a reference
to each of the openedWindows in your application.
| | 00:20 | So by using this you can actually loop over each
of the Windows and perform a specific action.
| | 00:25 | So by doing this you can cause the actions in one window
to then be represent across the other windows as well.
| | 00:31 | So to accomplish this we are going to
go ahead and open up our application.
| | 00:35 | We go to File and then Open and then
we will open BrowserApplication03
| | 00:40 | in the Chapter 9 folder of the exercise files.
| | 00:42 | Now once we have actually gotten into the application
we are going to want to go into the Browser symbol,
| | 00:50 | so we will click on the Browser movie clip and if
we double-click we should be now into our movie clip.
| | 00:55 | Now we are actually going to drag two more
instances of the button out on the Stage.
| | 01:00 | So to do that we are going to need to make a
little room, now just note this is not going
| | 01:04 | to be a permanent change this is actually
just a change that we will do for testing
| | 01:08 | and then we will implement a more elegant solution later.
| | 01:11 | So let's go ahead and unlock the UI Layer
then I am going to select the URL Input,
| | 01:17 | I am going to get the Free Transform tool and then I am
going to hold down the Alt key or the Option key on Mac
| | 01:22 | and then I am just going to drag this in
so we have got room for a few more buttons.
| | 01:26 | Then I am going to go to the Components
window by going to Window and then Components.
| | 01:31 | And then I am going to drag two
instances of the button onto the Stage.
| | 01:40 | We will move a few things around so we
have some more room for our buttons.
| | 01:49 | And now we will position our buttons
in place and we are going
| | 01:55 | to give the first button and instance
name of cascadeButton.
| | 01:58 | And we are also going to give it
a parameter label of Cascade.
| | 02:05 | Now we are going to go to our next button and we are
going to give it an instance name of hideOthersButton
| | 02:15 | and we are going to change the label to Hide Others.
| | 02:19 | Now that we have actually added our buttons
to the Stage and positioned the items
| | 02:25 | where we want them we are actually going
to go ahead and lock the UI Layer go
| | 02:29 | to the Actions layer and then go to Window and Actions.
| | 02:32 | Now the first thing that we will need to do since
we are working with the openedWindows property
| | 02:37 | of the NativeApplication class we are going
to need to actually import NativeApplication.
| | 02:42 | So this can be accomplished by saying
import flash.desktop.NativeApplication.
| | 02:50 | Now that we have imported our class we are ready to
begin adding the event listeners for our two buttons.
| | 03:00 | So now that we are in our Event Listener
section we are going to start off
| | 03:03 | with the Cascade button. We will
say cascadeButton.addEventListener
| | 03:09 | and we are going to listen for the MouseEvent.CLICK event.
| | 03:17 | And we will respond to that with the OnCascade method.
| | 03:21 | Next we are going to need to add an
Event Listener for our Hide Others button
| | 03:26 | so we will say hideOthersButton.addEventListener and we are
going to want to listen also for the MouseEvent CLICK method.
| | 03:39 | We are going to respond to that with onHideOthers.
| | 03:46 | Now that we have added our event listeners
we can go ahead and add our event handlers.
| | 03:52 | So we will go to our event handler section we will scroll
to the end and then we will create our two new methods.
| | 03:58 | The first method that we will need to create will be
onCascade and it will receive an event of type MouseEvent
| | 04:10 | and it's not going to return anything
so we can leave the return type void.
| | 04:15 | Next inside of this method we are actually going
to want to loop through each of the windows.
| | 04:19 | To do this we are going to be using a for loop.
| | 04:21 | If you are not familiar with the for loop
you might want to go back and review some
| | 04:25 | of the other ActionScript 3 Series here at www.lynda.com.
| | 04:29 | We will say four and then we are going to
create our iterator which we will just call i.
| | 04:34 | That will be an unsigned integer
and we will set it equal to 0.
| | 04:39 | Then we are going to want to be sure that i is
less then NativeApplication.nativeApplication.
| | 04:49 | and then here is the property that I
mentioned in the introduction, openedWindows.
| | 04:55 | And since this in an array we know
that it also has a Length property.
| | 04:59 | So we are going to want to be sure that i is
less then the length of the openedWindows array.
| | 05:04 | Next we are just going to increment our iterator and now we
have actually successfully set up our loop to go through all
| | 05:14 | of the different windows within our application.
| | 05:17 | Now we're going to go ahead and create a variable
for the window, it will be of type NativeWindow.
| | 05:24 | And then we are actually going to set that equal
to NativeApplication.nativeApplication.openedWindows
| | 05:34 | and then we are going to set it equal to the
current value of the array from our iterator.
| | 05:41 | Now we are going to need to position
the x and y of this window.
| | 05:44 | Now the goal is going to be that the first window
will be positioned at the top left of the screen.
| | 05:50 | Then the next window will be a little bit down
and a little bit to the right of the first window.
| | 05:55 | It also will be on top of that window.
| | 05:58 | So it will be positioned so that the windows
basically form a cascade from the top left
| | 06:02 | to the bottom right corner of the screen.
| | 06:05 | Now we are going to set the window.x property.
| | 06:08 | And we are going to set that equal
to a very specific formula.
| | 06:12 | We are going to say 25 times i.
Now what this will do the first time
| | 06:19 | through since i will be 0 it will
position the window to 0 for the next time
| | 06:23 | through because it's one it will position the
window at 25 and then 50 and 75 and so forth.
| | 06:28 | Now we are going to make one small change because we
don't want the windows to be flushed with the edge
| | 06:33 | of the desktop so we are just going to add 10.
| | 06:36 | Next we are going to set the window.y property
| | 06:41 | and in this case we actually can just copy our
previous formula and use that here as well.
| | 06:49 | Now the next thing we are going
to do is actually very crucial.
| | 06:52 | We are going to want to use the OR in
front of method of the NativeWindow class.
| | 06:57 | And we are going to want to position the
current window in front of the previous window
| | 07:02 | but obviously the first window
will not have a previous window.
| | 07:06 | And so if we don't add some type of an
If statement in here that checks to see
| | 07:10 | if it's the first window it will throw an
error when you try to run your application.
| | 07:14 | So we will say If i is greater than 0 and this will just
ensure that it is not the first time through it will ensure
| | 07:24 | that it's at least the second time looping through.
| | 07:26 | And then we will say window.orderInFrontOf and now we will
want to get a reference to the previous window that looped.
| | 07:35 | So to do this we will say
NativeApplication.NativeApplication.openedWindows
| | 07:46 | and then we will want to say instead of saying i, which
will be the current window, we will just say i minus 1.
| | 07:59 | Now we are going to implement the onHideOthers method.
| | 08:03 | It's going to receive an event of type MouseEvent
and its return type is going to be void.
| | 08:18 | Now we need to loop through each of
the windows in this method as well.
| | 08:22 | So in this case we can just copy everything and
then we will just drop it over to our new method.
| | 08:28 | Now we are going to need to delete
everything from here down.
| | 08:32 | And now we are going to want to do something
specific with the onHideOthers method.
| | 08:37 | We are going to want to basically minimize every window
accept the current window that we are working on so we need
| | 08:42 | to ensure that we don't minimize that one.
| | 08:44 | So we will say if stage.nativeWindow does not equal
window then we will know at that point that this window
| | 08:59 | that it's looping through is not our window so yes we
can minimize it so then we will just say window.minimize.
| | 09:10 | Now we can save our application.
| | 09:11 | We will go Control and then Test Movie
and we can see that our application comes
| | 09:19 | up with our Hide Others and our Cascade buttons.
| | 09:21 | Let's go ahead and open a few windows.
| | 09:24 | So here I have opened four windows. Let's say that
I want to grab this window and I want to hide all
| | 09:28 | of the other windows of this application.
| | 09:30 | If I hit Hide Others we can see that
the other windows are indeed minimized.
| | 09:35 | And now if we take these windows again then we move
some of the positioning around and just put them
| | 09:40 | in different places actually on the screen.
| | 09:41 | Now if we hit the Cascade button we will notice that
all of the windows are nicely lined up on the left side.
| | 09:47 | They cascade down so as you can see the windows
have been positioned correctly not only in their X
| | 09:53 | and Y positions but also in their stacking order.
| | 09:55 | You will notice that the first window that is furthers
to the left is actually in the back of the stacking order
| | 10:00 | and then it increments all the way
up unto the window that's furthest
| | 10:03 | to the right is actually on the top of the stacking order.
| | Collapse this transcript |
|
|
10. Using Native Operating System IntegrationIntroducing native operating system integration| 00:00 | The cross-platform compatibility of AIR provides a great
platform to build applications for both Windows and Macs.
| | 00:06 | AIR has the capability to work with many elements of
the core operating system in both Windows XP and Vista,
| | 00:11 | and Mac OS X. Understanding what these
items are is essential to a developer,
| | 00:16 | who is developing an application within Adobe AIR.
| | 00:19 | So let's look at some integration issues when we are
building applications that are going to be cross-platform.
| | 00:23 | First, we are going to look at some differences
between Windows and Mac within Adobe AIR.
| | 00:28 | In Windows, we actually have support for the System
Tray, but in Mac we have support for the Dock.
| | 00:33 | Now these items have some similarities, but they also
have some differences that will have to be addressed
| | 00:37 | when you are creating an application
that will run on both platforms.
| | 00:41 | Windows actually has Nativemenus for a Nativewindow
| | 00:45 | and Mac they actually have Native
menus for a NativeApplication.
| | 00:49 | So there is a big difference in the way that you
actually have to add your items to your menus.
| | 00:54 | So now let's go on and let's look
at some of these items specifically.
| | 00:57 | I have stated that in Windows, there is a Native
menu for a NativeWindow and a mini-bar can be added
| | 01:02 | to an Application window but not the entire application.
| | 01:06 | So as you can see here with just the version
of Notepad that comes with Windows by default
| | 01:10 | that you can see there is an actual Menu
bar that's attached to the window instance.
| | 01:15 | In Mac, however a Menu bar can be added to
an application but not to a single window.
| | 01:20 | Here you see an example of the menu bar that's the default
in Mac OS X and you can actually see that one application,
| | 01:27 | no matter how many Windows it has
only has, only has one Menu bar.
| | 01:31 | Now inside of Windows, we have Taskbar support and a
Taskbar is used to list currently opened windows as well
| | 01:36 | as display icons for currently running
applications in the System Tray.
| | 01:40 | Now AIR supports the use of a custom icon in the
Taskbar for your application and in addition,
| | 01:45 | we also can attach Menus and ToolTips to these icons.
| | 01:48 | And we also can utilize a system
for notifying users of key events.
| | 01:53 | With the dock, the dock is used to list currently opened
applications as well as shortcuts to other applications,
| | 01:59 | but the dock can also be used to
notify the end user of events.
| | 02:03 | So in AIR, we actually can attach a
Menu object to a Dock icon as well.
| | 02:08 | So here are some things that we
need to consider when we start going
| | 02:11 | down the road to creating cost-platform applications.
| | 02:13 | First we will need to test the application in both Mac OS
X and Windows, if you are using both sets of functionality.
| | 02:21 | When you just spend time working in the other operating
system, so that we can create a more consistent experience
| | 02:25 | for the user, it can be very tempting to just do things the
way that you have always done them without actually going
| | 02:30 | and reviewing some of the other operating systems.
| | 02:32 | And then that can cause problems when you are
trying to create and immersive experience with users
| | 02:36 | that are coming from different operating systems.
| | 02:39 | Next, since your ".air" file can be
installed on any computer with AIR installed,
| | 02:43 | you just can't ignore an unfamiliar operating system.
| | 02:46 | You really need to dive in and learn it so that
you can build the best possible application.
| | 02:51 | The cross-platform integration that's provided with AIR is a
huge benefit and it shouldn't be a burden to the developer.
| | 02:56 | It opens up a lot more power and so we are going to do
take some time to look at each of these items specifically
| | 03:01 | and determine how we are going to implement
them inside of our AIR application.
| | Collapse this transcript |
| Using application menus| 00:00 | Now I have exported a version of the browser application
that already has a NativeMenu integrated in it.
| | 00:05 | So I am going to double click on the application.
| | 00:08 | When we see it launch here, you can see that
in the top left corner of the application here
| | 00:12 | where we normally have the File options and stuff
within Windows, we actually have a Menu here as well.
| | 00:16 | We have the File option.
| | 00:18 | We can open a PDF, close and exit the application.
| | 00:21 | We also have a View option here for
Cascade, Hide Others and Always on Top.
| | 00:25 | So we have integrated this in using a NativeMenu.
| | 00:28 | Now in this video, we are going to go through
the process of recreating this NativeMenu.
| | 00:33 | We are not going to yet attach it to a
window, but we are going to learn how to work
| | 00:36 | with the flash.display.NativeMenu class as
well as the flash.display.NativeMenuItem class.
| | 00:44 | So when we wok with NativeMenus, those
are the two classes that we will be using
| | 00:47 | and the NativeMenu class specifically is
a menu or sub-menu within the application.
| | 00:53 | You can pretty much guarantee that it's going to have child
elements that are going to be of the type NativeMenuItem.
| | 00:57 | And any time that you will actually
have an item within a menu, for example,
| | 01:02 | in the example I just showed, the
LoadPDF item. That was a NativeMenuItem.
| | 01:07 | So here is the structure one more time that
we are going to recreate in this video.
| | 01:11 | First, we have a root NativeMenu and then we have two
NativeMenuItems under that, a File menu and a View menu.
| | 01:19 | Then under each of those, they
each have a NativeMenu as a child.
| | 01:23 | And this is actually the sub-menu
that contains the other options.
| | 01:27 | And then inside of those sub-menus,
we have more NativeMenuItems
| | 01:30 | that actually contain the different
options that are found on our menu.
| | 01:33 | So let's go through and actually create a
portion of this NativeMenu from scratch.
| | 01:38 | So now that we're back in Flash, let's go to File and then
Open and we are now going to open Browser Application01
| | 01:44 | in the Chapter 10 folder of the exercise files.
| | 01:47 | Now we are going to actually double click on the
browser movie clip and now we are going to be sure
| | 01:52 | that the Actions layer is selected and we
are going to go to Window and then Actions.
| | 01:56 | Now the first thing to check is to be sure that we have
the NativeMenu and NativeMenuItem classes imported.
| | 02:02 | Now in this case, we have imported
the entire flash.display package
| | 02:06 | so we actually already have these classes
imported without any additional work.
| | 02:09 | Now we are going to add in several
methods to our application,
| | 02:13 | so let's scroll down to the section
that contains our methods.
| | 02:16 | Now the first method is going to create our
root menu, it's also going to create the File
| | 02:21 | and View items that exist under that menu.
| | 02:24 | So the first thing we need to do is create our method and
it will be called createRootMenu and then within here,
| | 02:31 | it's not going to accept any parameters
and it's not going to return anything.
| | 02:35 | So now that we have created our createRootMenu method, we
can go ahead and create a new instance of the NativeMenu.
| | 02:42 | And I am just going to comment things, so that we can
keep things clear, this will actually be the Root Menu
| | 02:47 | and we will call this one nm for NativeMenu and
that's going to be equal to a new NativeMenu.
| | 02:58 | Now from here, we are going to want to create the two
items that we had discussed the File menu and the View menu
| | 03:04 | and each of these actually start out as a menu
item and then they have a sub-menu property
| | 03:09 | that contains the options for within those items.
| | 03:11 | So the first thing we will do is we will say var
fileMenu and this will be up type NativeMenuItem.
| | 03:20 | Now within NativeMenuItem, you are actually required
to give it a label, so when we finish our constructor,
| | 03:25 | it will prompt us to input something for the
label. For here, we are just going to say File.
| | 03:30 | Now this is important to know, because whatever you put here
is what is actually going to show up. If you are in windows,
| | 03:36 | it will actually show up on your Window default menu.
| | 03:40 | Next, we are actually going to create the View menu.
| | 03:57 | And we are going to give it the label name a View.
| | 04:01 | Now let's go back and look at the File menu for a moment.
| | 04:04 | We are going to want to create a
sub-menu, now we learned first of all
| | 04:08 | that a NativeMenuItem is actually the item that's displayed
as an item within a menu, now in this case we are wanting
| | 04:14 | to add an entire menu to the file, NativeMenuItem so
that when we click on File, another window pops down.
| | 04:21 | This is a standard feature, but to accomplish this,
we are going to have to create another instance
| | 04:25 | of the NativeMenu class and we are going to call this
one File Sub-Menu, so we will say var fileSubmenu,
| | 04:32 | it will be of type NativeMenu and it
will be equal to a new NativeMenu.
| | 04:40 | Now this would be the normal way that we would create it,
but in this case to actually keep from stacking so much code
| | 04:48 | into this one method, we are actually going to delegate
the creation of our sub-menu to another method.
| | 04:53 | So we will go back and instead of saying that it's equal to
a new NativeMenu, we are actually going to say it's going
| | 04:59 | to be equal to createfileMenu and
we will create that method shortly.
| | 05:06 | Obviously that method will be returning a NativeMenu.
| | 05:09 | So in this case, we will pretend that we actually
already have that item and we will say fileMenu
| | 05:13 | and anytime you are actually wanting
to add a sub-menu to a NativeMenuItem,
| | 05:18 | you simply have to just add it as the submenu property.
| | 05:21 | So we will say fileMenu.submenu = fileSubmenu
and now that will actually be used
| | 05:30 | as the submenu for the fileMenu NativeMenuItem.
| | 05:33 | Now the last thing we need to do is we haven't yet added
our fileMenu to the NativeMenu that we have created first,
| | 05:40 | the root menu. So to do that, we are just going to
say nm, which is the name of our NativeMovie, .addItem
| | 05:47 | and then we are going to pass in
whatever item we want to add.
| | 05:51 | In this case, we are just going
to want to add in the fileMenu.
| | 05:53 | Now let's actually go down and
implement the createfileMenu method.
| | 05:59 | So we will scroll down below our current
method and we will create a new one.
| | 06:03 | We will say function createfileMenu and it will not
accept any parameters, but it will return a NativeMenu.
| | 06:13 | Now inside of here, we are going to want to add several
options, but the first thing that we are going to do is
| | 06:24 | since we need to return a NativeMenu, we are going to
go ahead and create a NativeMenu to add our items too.
| | 06:28 | So we will say var fileSubmenu and this is the same
name that we used before. This will help us remember
| | 06:35 | that when we return this item, it actually will be
passed into the fileSubmenu and this is going to be
| | 06:40 | up type NativeMenu and it will be
equal to just a new NativeMenu.
| | 06:47 | Now we actually can go ahead and scroll down
below this and return this value as well.
| | 06:55 | We will say return fileSubMenu.
| | 06:58 | Now we can actually add the items that
are going to be inside of this menu.
| | 07:02 | First, we are going to want to add the Open PDF
option so we need to create a new NativeMenuItem
| | 07:08 | because again here we are creating an item
that's actually going to be a part of a menu.
| | 07:13 | So we will say var pdfItem is going to be of type
NativeMenuItem, will be equal to a new NativeMenuItem.
| | 07:24 | Now again with the NativeMenuItem, we have to pass in
a label, in this case our label is going to be Open PDF
| | 07:33 | and that will actually be what's displayed within our menu.
| | 07:36 | By default, your menu items don't do anything. Even if you
use common words such as Exit or Close they are not going
| | 07:43 | to do anything unless you actually
add an event listener to them.
| | 07:46 | So in this case, we are going to add an event
listener, let's say pdfIten.addEventListener.
| | 07:52 | And then we are going to be listening for a specific event,
because every time a user clicks a specific menu item,
| | 08:00 | it's going to dispatch the Event.SELECT method.
So we will listen for the Event.SELECT.
| | 08:05 | And then we will respond to it by
calling the onPDFSelect method.
| | 08:11 | Now we have actually already implemented
this functionality in a previous video.
| | 08:15 | If you are not sure how you would proceed from here
to actually configure the listener to prompt the user
| | 08:20 | for a file in their local hard drive then
I would suggest going back and looking
| | 08:23 | at the PDF chapter here within these series.
| | 08:27 | Next, we actually can add the item to the fileSubmenu,
| | 08:30 | so we will say fileSubmenu.addItem
and it will actually add the PDF item.
| | 08:36 | Now this is the exact same process that we will follow
for the other two items that we are going to add.
| | 08:42 | We will say var and the next one will be closeItem, it
will be of type NativeMenuItem and that will be equal
| | 08:55 | to a new NativeMenuItem and that will receive a
label and this one will just have the label of Close.
| | 09:02 | It will signify the user so they
can close the current window.
| | 09:05 | We will follow the same step that we did before.
| | 09:07 | We will say closeItem.addEventListener and
we will listen for the Event.SELECT method.
| | 09:14 | And we will respond to it by calling the onCloseItem method.
| | 09:20 | Now the next thing we are going to do is we are actually
going to add in a separator because if you notice,
| | 09:25 | in our sample movie in between Open PDF and
Close, there is an actual line, a file separator.
| | 09:32 | And this is a special property that you have
with inside of the NativeMenuItem class.
| | 09:38 | So instead of actually going through here and creating
a new NativeMenuItem and then adding an event listener,
| | 09:42 | what we are just going to do is we are just going
to create the menu item and we are going to pass
| | 09:46 | through to the second parameter of the constructor.
| | 09:48 | So we will say var, we will just call this sep, for
separator. That's going to be equal to a NativeMenuItem
| | 09:56 | and we are going to say that's
equal to a new NativeMenuItem.
| | 10:00 | And then we are going to want to pass in a label,
in this case it really doesn't matter what we pick,
| | 10:06 | but we are going to say isSeparator and we are
just going to say true, this is a separator.
| | 10:10 | All items that get added to a menu also have some additional
properties, for example, if you notice in the sample movie
| | 10:19 | when we open the sample movie, we now have
some keyboard shortcuts that we can use
| | 10:24 | to access some of these pieces of functionality.
| | 10:26 | For Open we can do Ctrl+O and for Exit we can do Ctrl+Q
that is actually a property of the NativeMenuItem class.
| | 10:33 | So for example in PDF, we could go up
and say pdfItem.keyEquivalent is equal to
| | 10:41 | and in this case we could just say o, and it will
automatically append either Control or Command depending
| | 10:47 | on if you are on Mac or PC to the beginning of this command.
| | 10:50 | So just by simply putting keyEquivalent it's actually
going to listen for the keyboard event, respond accordingly
| | 10:55 | and then dispatch an event so that
you can actually react to this.
| | 10:58 | Pretty much adding all items to a menu is
just as easy as doing what we have just done.
| | 11:02 | Well you can create very complex menus,
you can create very complex nested menus,
| | 11:07 | it can be used in many different
places throughout your application.
| | 11:10 | But to create a basic menu, one things stays the same
however, you are going to be using the NativeMenu
| | 11:15 | and the NativeMenuItem class to create your menus,
menus that you will use in your Window menus
| | 11:20 | in your Application menus, in your Context menus,
in your Taskbar menus, pretty much all of the menus
| | 11:26 | that you can create within AIR are
going to be based on these two classes.
| | Collapse this transcript |
| Using window menus| 00:00 | One of the major differences between
Mac OS X and Windows is the way
| | 00:04 | in which default menus are attached to an application.
| | 00:07 | As you learned in the introduction to this chapter, in
Windows these are attached to the Individual windows,
| | 00:12 | but in Mac these are attached to the application as a whole.
| | 00:15 | Now, in this video, we are going to be able to take the
menu that we created in the previous video and we are going
| | 00:21 | to actually take it and attach it to
an application window of our browser.
| | 00:24 | So, let's go ahead and open the file.
| | 00:26 | If we go to File and then Open, we
are going to open BrowserApplication02
| | 00:32 | in the Chapter 10 folder of the exercise files.
| | 00:34 | Now, we are actually going to double click on the browser
movie clip and now we have actually loaded up our browser.
| | 00:41 | Now, we are going to go ahead and go to the Actions
Layer and we are going to do a bit of review.
| | 00:46 | If we scroll down, the first thing I want you to notice
is that now I have actually added a section for all
| | 00:52 | of our NativeMenu and event handlers code.
| | 00:54 | It's quite a bit of code, so we want to
be sure that we just know where it is
| | 00:57 | and that we keep it separate from the others.
| | 00:59 | If you look, you will see that as we discussed in
the previous video, we have implemented both the File
| | 01:03 | and View menu, we also have implemented
the methods that add items to those.
| | 01:08 | So, currently in the View menu we can Cascade, we can
Hide Others and we can set the value to be Always on Top.
| | 01:15 | Now, we are actually using code from
previous videos to accomplish this,
| | 01:20 | so if you are not sure about how
this code works, you can go back
| | 01:22 | and look at previous video to determine
how these methods work.
| | 01:26 | And if we go to the File menu, we now have a few specific
options as well, we can open a PDF, we can close a window
| | 01:32 | or we can exit the application and
we have also added in a separator.
| | 01:37 | We also were using the key equivalence
that we discussed in the previous video
| | 01:40 | to make keyboard shortcuts for
these items inside of our menu.
| | 01:45 | Finally, if we look we are actually calling
the createRootMenu method at the very beginning
| | 01:52 | of our application in the initialization
methods section of our code.
| | 01:56 | So, now with all of that we are going to need
to add this actually to our application window.
| | 02:01 | If we launch right now, our menu is nowhere to be seen.
| | 02:05 | It has not yet been added to the application.
| | 02:08 | This actually is not a difficult
process, but again because we are working
| | 02:11 | with cross-operating system issues here, we need to be
sure that we are actually either on a Windows machine
| | 02:17 | or on a Mac machine before we decide how to handle our menu.
| | 02:20 | So, let's close this window. We will go back into
our application. We are going to actually scroll
| | 02:26 | down to the createRootMenu method, that's
now in our menu section of our code.
| | 02:32 | At the very end of the createRootMenu method,
we are going to add in a little bit of code.
| | 02:37 | The first thing we are going to say, we are actually
going to basically ask the AIR application a question,
| | 02:42 | we are going to say if NativeWindow.supportsMenu.
| | 02:49 | Now, we were on a Mac and we were actually running this
application, it would come back and it would say "False-No."
| | 02:54 | The Nativewindow doesn't support a
menu on Mac; the NativeApplication does.
| | 02:59 | And the same is true for Windows in the opposite.
| | 03:01 | It does support a menu for NativeWindow, but it
doesn't support a menu for the NativeApplication.
| | 03:07 | So, in this case we actually can know that we are
working with a Windows machine, so we will say Windows.
| | 03:15 | So everything inside of this
if statement will only execute,
| | 03:18 | if we are on an operating system that
supports menus for a NativeWindow.
| | 03:22 | So, now we can say stage.nativeWindow and
to attach this menu to the NativeWindow,
| | 03:31 | you only need to actually set the menu property
of the NativeWindow equal to your root menu.
| | 03:36 | So, we will say nativeWindow.menu
is equal to nm for our NativeMenu
| | 03:42 | that we have created at the beginning of this method.
| | 03:44 | Now, if we save our application and
we go to Control and Test Movie.
| | 03:48 | We will now see that we have actually created
our browser application with the NativeMenu
| | 03:54 | that has been attached to the NativeWindow.
| | 03:57 | In this case it works and that we
have all the options that we plan
| | 04:00 | to have including the separator between Open PDF and Close.
| | 04:03 | We also could open up multiple windows and we
could see that our Close method does indeed work.
| | 04:08 | We also can test and see that if we do
Ctrl+Q, it closes our application and that's
| | 04:14 | without configuring any keyboard events for our application,
| | 04:17 | we simply have just added the keyEquivalent
property to the NativeMenu item.
| | 04:21 | Now, that you have developed NativeMenu
integration inside of Windows,
| | 04:25 | we will need to look how to integrate with the Mac.
| | Collapse this transcript |
| Using context menus| 00:00 | The Application menu for Mac OS X
application is tied to the entire application.
| | 00:05 | However, it can be edited and configured in the
exact same way that you would for a Windows machine.
| | 00:10 | So, let's go ahead and take the previous application that
we had where we added support for the Windows menu bar
| | 00:16 | and let's go ahead and also add support for Mac, so that
we can have an Application menu for our application.
| | 00:23 | So, let's go to File and then Open and
then inside of the Chapter 10 folder
| | 00:27 | for the exercise files, we will go to BrowserApplication03.
| | 00:33 | Just to do a very quick review, if
we go to Control and Test Movie,
| | 00:37 | we have actually created our normal
Browser application, but with the menu bar
| | 00:45 | that includes several different options
encompassed into submenus for File and View.
| | 00:50 | So, now let's close our application.
| | 00:53 | If we go back to the Browser movie clip by
double-clicking and now we go to the Actions layer
| | 01:00 | by highlighting the Actions layer and
then going to Window and then Actions.
| | 01:05 | We now can actually scroll down to our
createRootMenu method, it will be in our NativeMenus
| | 01:13 | and EventHandlers section and we see here that we
have actually integrated it already for Windows.
| | 01:19 | Just with these three lines of code, we have actually
been able to add our menu bar to Windows' NativeWindow.
| | 01:25 | But we now want to add our menu bar to a Mac
NativeApplication. So I will first add a comment
| | 01:33 | so I can remember when I come back to this code
why I added these lines. And now for Mac we say,
| | 01:40 | just as we asked the question for Windows,
does the NativeWindow support a menu?
| | 01:45 | In this case, we are going to ask our application
NativeApplication, does it support a menu?
| | 01:55 | If the answer is yes, then we know that
we are working on a Mac and because
| | 01:59 | of that we can now set the
NativeApplication.nativeApplication.menu equal
| | 02:10 | to our NativeMenu, which we named "nm" and
now if we save our movie we can now test it
| | 02:19 | and see what it would look at like on a Mac.
| | 02:21 | So, I have actually installed the application on a
Mac, I am going to go ahead and launch the application
| | 02:28 | and we will see that everything looks just as it did.
| | 02:30 | One of the great benefits of AIR is that your
application really does look the same on Mac
| | 02:34 | or PC, with the few exceptions that we stated.
| | 02:36 | But notice here that we do preserve our File and View menus.
| | 02:41 | As long as our application is selected we can go under
File and we see our Open PDF, our separator is preserved,
| | 02:46 | Close and Exit as well as our keyboard shortcuts were
preserved and one of the benefits of this is because we are
| | 02:53 | on Mac and Mac users generally don't use Ctrl shortcuts,
it automatically converted those to Command Shortcuts,
| | 02:59 | so now Command+O can open the PDF and
Command+Q will close the application.
| | 03:04 | We also have all the view options as we did previously.
| | 03:08 | Now, as you can see, we can now fully support
the application NativeMenus inside of Mac
| | 03:13 | with our AIR applications even though we have created
our AIR applications on a Windows machine and this is one
| | 03:18 | of the great benefits of AIR the cross-operating
system compatibility that you gain.
| | Collapse this transcript |
| Setting up context menus| 00:00 | Context menus are staple of user experience.
| | 00:04 | Most users who use computers on any regular basis are
actually going to be very familiar with Context menus.
| | 00:10 | For example if you are in a browser and if you
have ever right clicked, this is a Context menu.
| | 00:15 | It's basically going to give you information
based on what you right clicked on.
| | 00:19 | And you also can add Context menus within
AIR and the great thing about Context menus
| | 00:24 | within AIR is they have been using the same menu classes
| | 00:27 | that you are already familiar with,
NativeMenu and NativeMenuItem.
| | 00:31 | To illustrate how easy it is to create a Context menu
once you have actually created your menu structure,
| | 00:37 | we are actually going to add a
Context menu to our application.
| | 00:41 | So let's go ahead and close our browser and we will
go back to Flash, and we go to File and then Open
| | 00:51 | and then in the Chapter 10 folder of our Exercise
Files we are going to open BrowserApplication04.
| | 00:57 | Now we are going to double click on the Browser movie
clip, now we are going to go to the Actions layer
| | 01:05 | and we are going to go under Window and then Actions.
| | 01:09 | We are now just going to scroll down until we get
to our createRootMenu method which is at the bottom,
| | 01:15 | you can see that we have already added our code for
Windows and Mac and directly below this we are going
| | 01:20 | to go ahead and just add code for our Context menu.
| | 01:23 | Again if you already have your menu created, it's
just as easy as saying this.contextMenu = nm.
| | 01:32 | The one thing that does need to be understood about
Context menus is that you can only right-click
| | 01:38 | on an interactive object on the
Stage to view a Context menu.
| | 01:42 | So it needs to be something that can accept user input.
| | 01:45 | I will illustrate this now by testing the application.
| | 01:48 | If we go to Control and then Test Movie,
the first thing I want you to notice is
| | 01:54 | that there already is a default Context menu within HTML.
| | 01:59 | If you right-click, you are not
going to see your Context menu.
| | 02:02 | However, if we go up and look at the top of our application
and we right-click, you can see the exact same File
| | 02:08 | and View menu options that we created for
the menu bar here within our application.
| | 02:13 | So it's just as easy as passing your
NativeMenu instance to the contextMenu property
| | 02:19 | of any interactive object on the
Stage to create a Context menu.
| | 02:23 | Context menus can be a great asset if used properly.
| | 02:27 | However, if used improperly they can
create a confusing user experience.
| | 02:31 | So take some time to examine how other
applications are using them before you decide
| | 02:36 | that they are right for your application.
| | Collapse this transcript |
| Using system tray interaction| 00:00 | The system tray in Windows is a place
where icons for programs reside.
| | 00:04 | These icons are also unique and that they can have
millions attached to them as well as tool tips.
| | 00:09 | Now, there are many used cases for
system tray icons including applications
| | 00:13 | that don't launch with a visible window.
| | 00:15 | But in this case, we can add some additional
functionality to our browser application by adding an icon
| | 00:21 | to the System Tray and then connecting an
instance of one of our menus to that as well.
| | 00:25 | So to get started, let's go ahead and open up the file.
| | 00:28 | We will go to File, Open and we are
going to open up BrowserApplication04
| | 00:34 | in the Chapter 10 folder of the exercise files.
| | 00:37 | Now, we are going to go ahead and double click on the
Browser movie clip and then we are going to be sure
| | 00:44 | that the Actions layer is selected and
we are going to go Window and Actions.
| | 00:47 | Now, we are going to actually scroll
down to the method section,
| | 00:52 | which should be under our Event Handlers,
and we are going to create a new method.
| | 00:58 | This method is going to be called setUpIcon and it's
not going to take any parameters and it's not going
| | 01:07 | to return anything, so we can set
the return type equal to void.
| | 01:11 | Just when we are working with NativeMenus,
we can ask AIR questions
| | 01:15 | about the application and what type of icon it supports.
| | 01:19 | In this case, since we will be working
on Windows we are going to want
| | 01:22 | to ask the NativeApplication if
it supports a system tray icon.
| | 01:27 | So, to do that we are first going to just add in a
comment, so we know that we are adding in code that's meant
| | 01:32 | for Windows, and then we are going to say if and then we
are going to say NativeApplication.supportsSystemTrayIcon.
| | 01:44 | So if it returns True then we know that we are on
Windows system that supports the system tray icon.
| | 01:51 | So, now we actually can begin the process of loading
in an image to use as the icon for the system tray.
| | 01:57 | So, the first thing we are going to need to do is create an
instance of the Loader class, so we will save var loader is
| | 02:03 | of type Loader and we will just set
that equal to a new Loader object.
| | 02:08 | Next, we are going to actually add an event listener.
We will say loader.contentLoaderInfo.addEventListener
| | 02:22 | and we are going to listen for the
Event.COMPLETE method and that will tell us
| | 02:30 | when our actual content is done being loaded.
| | 02:33 | And when that's done, we are going to
call the onIconLoadComplete method.
| | 02:39 | And now, we will go ahead and create the shelf
for this method that will be using later.
| | 02:47 | We will scroll up to our Event Handler
section, we will go under our last one,
| | 02:51 | we will create a new function that
will be named onIconLoadComplete.
| | 02:56 | We know it will accept an event of type
Event and it's not going to return anything.
| | 03:04 | Now, let's go back down to our setupIcon method.
| | 03:07 | We now have told our application to listen for
the COMPLETE event, now we need to actually load
| | 03:13 | in what we are going to be using for our icon.
| | 03:16 | If we open the Chapter 10 folder of the Exercise Files,
you will notice that there is an Icons folder inside of it
| | 03:22 | and inside of this Icons folder are just some icons
of different sizes that we used earlier in the series.
| | 03:28 | Now, inside of here is one called icon-16.png.
| | 03:33 | By default system tray icons inside
of Windows are 16x16 pixels,
| | 03:38 | so we are going to use this image as our system tray icon.
| | 03:42 | We can cancel this window and now we can
tell the loader to load that specific file.
| | 03:47 | We will say loader.load and then inside of here,
we are going to need to pass it a new URLRequest
| | 03:55 | and for this URLRequest we can just say icons/icon-16.png.
| | 04:05 | We can close our URLRequest and then
close our load call and now we are ready
| | 04:13 | to set a few properties of our NativeApplication.
| | 04:16 | Now, the first thing that we will need to do is we
will need to reference our NativeApplication class,
| | 04:21 | so we will say NativeApplication.nativeApplication and
then we are going to actually go to the icon property.
| | 04:30 | However, if we are on Mac, this icon is
actually going to be of type dockIcon,
| | 04:36 | but since we are on a PC this is
going to be of type system tray icon.
| | 04:41 | So, we need to actually cast this so that the
application knows which we are dealing with.
| | 04:46 | Now we can do that by going to the beginning
of this reference and saying SystemTrayIcon.
| | 04:58 | And we actually can then put everything
in parenthesis up through the icon.
| | 05:04 | Now, we can set the tooltip value and we will
just set this equal to Browser Application.
| | 05:14 | This is what will actually appear when the
user's mouse hovers over our system tray icon.
| | 05:21 | In addition, we can actually attach an instance
of the NativeMenu to our system tray icon,
| | 05:28 | so that if the user right-clicks or clicks on our
system tray icon they will actually see our menu.
| | 05:34 | So, in this case we will also say system tray icon
| | 05:39 | and then we will say
NativeApplication.nativeApplication.Icon
| | 05:47 | and we'll say .menu.
| | 05:51 | Now, in this case we don't want our entire NativeMenu to be
added. Instead we only want to add a portion and it's nice
| | 05:58 | in the system tray icons to have the ability to close the
application or maybe to do some key pieces of functionality,
| | 06:04 | but not necessarily everything and if we look
down inside of our NativeMenu and event handlers,
| | 06:09 | we can see the method createFileMenu returns a
NativeMenu and it actually gives us the option
| | 06:16 | to open a PDF, close the item or exit the application.
| | 06:20 | So, in this case we just set the .menu Property
of our system tray icon to createFileMenu
| | 06:28 | and it will actually return the instance of
our NativeMenu that we will be using here.
| | 06:32 | Now we have pretty much set up what we need to have set
up inside of our setupIcon, but now we are going to need
| | 06:39 | to respond to the Event.COMPLETE method that was
dispatched when the loader loaded in our icon.
| | 06:44 | So we will scroll back up to the method that we created
and what we are going to use now is we are going
| | 06:50 | to use the bitmap's property of the
NativeApplication.icon to actually set the system tray icon.
| | 06:57 | So we'll say NativeApplication.nativeApplication.icon.bitmaps.
| | 07:08 | And as you can see, it actually is plural
so it's actually looking for an array.
| | 07:13 | We are actually only going to pass it one value, but
when we need to create an array from a single item,
| | 07:19 | we can just use the square brackets for the shorthand for
an array, so we will go ahead and create our short brackets
| | 07:25 | and then inside of here, we are going to enter some
information about the event. We will say event.target
| | 07:32 | and that target was the loader object. So then we'll
say content and this will actually return the image,
| | 07:39 | it was actually brought back from this loader and then
we will go one step deeper and we will say bitmapData.
| | 07:44 | And this will actually return the
BitmapData from the image that was loaded in,
| | 07:50 | the nativeApplication.icon.bitmaps property is now set to
this BitmapData and the system tray icon will be updated
| | 07:57 | with the icon that we have actually
passed into our application.
| | 08:01 | So, let's test it out and see how it works.
| | 08:03 | We will go to Control and then Test Movie and we're going
to get an error and the reason is is because we have not
| | 08:12 | yet imported the SystemTrayIcon class. So to accomplish
that let's go back to the top section of our code
| | 08:19 | and we are going to now import flash.desktop.SystemTrayIcon.
| | 08:30 | Now, before we test our application again, we are
actually going to have to tell the application to go ahead
| | 08:35 | and set up our icon, so under Initialization
Methods, under createRootMenu,
| | 08:40 | we then can go below that and say setupIcon.
| | 08:44 | Now, the application will upon launch
actually set up our system tray icon
| | 08:49 | and place an instance of it in the system tray.
| | 08:51 | So, now let's save our application and we
will go to Control and then Test Movie.
| | 08:55 | We can now see that our icon has been added, we do
have our tool tip that says browser application,
| | 09:02 | if we right-click on, we do have
the options that were contained
| | 09:05 | within the File menu to Exit, Close, and then Open PDF.
| | 09:09 | System tray support just gives you another layer that
you can use to connect to the local operating system.
| | 09:16 | People that use Windows are familiar with using system
tray icons, so again by grabbing onto this common piece
| | 09:21 | of user experience, you can create
more engaging and rich applications.
| | Collapse this transcript |
| Using dock integration| 00:00 | Now that we have built an application that utilizes the
system tray support within windows, we now are going to want
| | 00:05 | to build an application that can also take advantage of
the dock support within Mac OS X. So to accomplish this,
| | 00:11 | we are going to need to add some
code to our setupIcon method.
| | 00:14 | So let's go ahead and open the file.
| | 00:16 | If we go to File and then Open, we are
going to now look for Browser Application05
| | 00:21 | in the Chapter 10 folder of the exercise files.
| | 00:24 | When we open this, we are now going to
double-click on the Browser movie clip,
| | 00:29 | then we are going to select the Actions layer and
then we are going to go to Window and then Actions.
| | 00:36 | We are going to scroll down to our setupIcon
method which is in the Method section of our code.
| | 00:49 | And we can see that we have clearly
delineated this section for Windows.
| | 00:53 | We are now going to create a section of
code that's going to specific for Mac.
| | 00:56 | We are now going to ask a different question.
| | 01:01 | Instead of NativeApplication.supportsSystemTrayIcon, we are
now going to ask AIR, NativeApplication.supportsDockIcon?
| | 01:15 | If this comes back as true then we know
that we are now actually working on a Mac.
| | 01:19 | So now it's actually going to take less steps for us to
get everything setup, there are a couple reasons for that.
| | 01:27 | First of all, we automatically
get an icon on the dock in Mac,
| | 01:31 | so we don't have to worry about
loading in an icon externally.
| | 01:35 | The icon is used for our application
that will appear on the dock.
| | 01:39 | In addition we don't have the capability
to add a tooltip so we don't need that.
| | 01:43 | By default in the dock, your icon already has
a menu, but the great thing is within AIR,
| | 01:48 | we still can set the menu property of the
NativeApplication.icon and this will just add our items
| | 01:54 | on top of the existing menu that exists
for the application with its dock icon.
| | 01:59 | So now to accomplish this, we are
going to need to import another class.
| | 02:03 | So let's scroll back up to the top of our application.
| | 02:10 | Under where we say import flash.desktop.SystemTrayIcon,
we will say import flash.desktop.DockIcon.
| | 02:21 | Now we will scroll back down to our setupIcon method,
which again is in the Method section, and now we're going
| | 02:29 | to cast NativeApplication.nativeApplication.icon. So we will
say DockIcon and then we will cast it by using parenthesis,
| | 02:38 | and we will say NativeApplication.NativeApplication.icon,
and then we will close the parenthesis
| | 02:49 | in this way the application knows that in this
case the application .icon is actually a DockIcon.
| | 02:56 | And then we will go to the menu property, and
then we will set that equal to createfileMenu.
| | 03:05 | So now we have actually mimicked the menu support that
we have within the system tray. Since on Mac OS X,
| | 03:12 | it already supports an icon, the only code that we really
need to add to mimic the support that we have in Windows is
| | 03:18 | to add our menu items to the existing dock menu.
| | 03:21 | So now let's test our application and
let's see what this looks like on the Mac.
| | 03:26 | I have launched the application now on the Mac
and we will see what we were able to accomplish.
| | 03:30 | If we go down to the dock, we move our mouse to
the bottom of the screen, we will see a pop-up.
| | 03:36 | We can see here that it's preserved the icon, this is
actually just the default icon for all the AIR applications,
| | 03:41 | but in addition to that if we right-click on the dock icon,
we can now see that it has added our options of Open PDF,
| | 03:48 | Close and Exit on top of the existing items
that are already supported within the Dock.
| | 03:53 | There is a great deal of flexibility with this. You
don't have to choose between the traditional dock menu
| | 03:58 | or your own custom menu. You actually can have the
best of both worlds by just combining them together.
| | 04:03 | So within AIR, you simply need to adjust your
application icons to change the dock icon
| | 04:08 | and then you can use the menu property to add your own
custom menu options to the dock menu for your dock icon.
| | Collapse this transcript |
| Setting up event notifications| 00:00 | One of the core components of an operating system is
its ability to notify the user when key events occur.
| | 00:06 | Now this can be done in several ways. It can bring up pop-up
window, maybe it has a flashing icon on the system tray.
| | 00:12 | AIR supports a few cross-platform ways
that we can inform users when events occur.
| | 00:17 | Just as with many of the elements that we have worked
with this chapter, there is a specific way to do it
| | 00:21 | in Mac and a specific way to do it in Windows.
| | 00:23 | So we are actually going to have
an alert that goes out to our users
| | 00:26 | after each web page is fully loaded within our browser.
| | 00:29 | So let's go ahead and open the file.
| | 00:31 | If we go to File and then Open, we are
now going to go to Browser Application06
| | 00:38 | in the Chapter 10 folder of the exercise files.
| | 00:41 | We're going to double-click on our Browser movie
clip, we're going to highlight the Actions layer
| | 00:48 | and then we are going to go to Window and then Actions.
| | 00:51 | We are going to scroll down to the Method section
and directly below where we added the code to set
| | 01:02 | up our icon, we are going to create a new method.
| | 01:04 | And this one is going to be called notifyUser.
| | 01:11 | It's not going to accept any parameters
and it's just going to return void.
| | 01:16 | Now we are going to ask the same
questions that we have asked before of AIR,
| | 01:23 | so that we can determine which system we are running on.
| | 01:26 | In this case, we are going to ask if
NativeApplication.supportsSystemTrayIcon?
| | 01:37 | This will tell us if this is true
that we are on a Windows computer.
| | 01:40 | So we can now go and we will put a comment that at this
point we are dealing with Windows and then we will go
| | 01:47 | and ask another question that will
tell us if we are working with Mac.
| | 01:50 | We will ask if NativeApplication.supportsDockIcon.
| | 02:03 | Now to actually notify the user of an event, there
actually is a method named notifyUser that's attached
| | 02:09 | to the NativeWindow and this only
works if you are actually in Windows.
| | 02:13 | So we will say stage.nativeWindow.notifyUser
and then we can choose to pass
| | 02:24 | in basically a string that tells how critical this alert is.
| | 02:28 | These different types of alerts are actually
defined in the NotificationType class.
| | 02:32 | So we are actually going to need to
import this class into our application.
| | 02:36 | So if we scroll back to the top of our application where
our inputs are, we are going to go right below the Dock Icon
| | 02:42 | and we are going to say
import flash.desktop.NotificationType.
| | 02:51 | Now we can scroll back down to our notifyUser
method and inside of the notifyUser method,
| | 03:02 | we can actually pass in one of a few values.
| | 03:04 | We'll say NotificationType. You can see that we have
two options here, we have Critical and Informational.
| | 03:13 | It will actually cause the alert to behave differently
based on whether you just say it's an Informational alert
| | 03:17 | that the user can respond to or maybe
not whereas if it's a Critical alert,
| | 03:21 | the system is going to keep alerting them
until they actually take notice of it.
| | 03:24 | So in this case, we are going to start
off actually using the Critical alert.
| | 03:28 | So we can see its functionality.
| | 03:30 | Now to actually notify the user
inside of Mac, it's a bit different.
| | 03:35 | Inside of Mac the dock icon can actually
bounce thus signifying to the user
| | 03:39 | that there is something they need to pay attention to.
| | 03:41 | So to do this, we are first going to look
at the NativeApplication.icon property.
| | 03:46 | We will also need to cast it again as a DockIcon.
| | 03:49 | So we will say DockIcon and then inside of our parenthesis
we'll say NativeApplication.nativeApplication.icon
| | 04:00 | and then outside of the parenthesis we can say bounce.
| | 04:06 | Now with this method just as with the notifyUser method
we can pass in which type of notification this is.
| | 04:13 | In this case, we'll also say NotificationType.CRITICAL.
| | 04:22 | There are a couple important things to
remember, however, about notification.
| | 04:26 | Notification when it occurs only is displayed
to the end user if your window is not activated.
| | 04:33 | So this operating system expects that if your window is
activated and you need to alert the user of something,
| | 04:38 | you can do so in a more efficient manner.
| | 04:40 | However if your application is
minimized and it needs to tell the user
| | 04:44 | that something is happening then
the alert will actually occur.
| | 04:47 | In Windows, the Taskbar reference for
your current window of your application
| | 04:51 | that sent the notification will actually flash.
| | 04:54 | If you have set it to NotificationType.INFORMATIONAL,
it will flash one time.
| | 04:59 | However if you have set it to Critical, it will
continue to flash until the user activates that window.
| | 05:04 | The operating system assumes that at
that point you can inform the user
| | 05:07 | of what action they need to take
and then it will stop flashing.
| | 05:10 | With Mac, the dock icon will bounce one time if you
actually set it to NotificationType.INFORMATIONAL,
| | 05:16 | however, it will keep bouncing if you
set it to NotificationType.CRITICAL.
| | 05:20 | So how we are going to trigger the notifyUser
event, just for the sake of testing,
| | 05:24 | we are going to go to our onLoadComplete method.
| | 05:29 | And if you remember, this is the method that is actually
executed every time an HTML page has completed loading.
| | 05:36 | So we will go and we will create a
new line and we will say notifyUser.
| | 05:44 | So now we can save our application. We
will go to Control, we will Test Movie.
| | 05:51 | We will actually minimize it, we will click
on Flash and we will actually see that now
| | 05:58 | since the page has finished loading the reference for
that current window is flashing and you will notice
| | 06:03 | that it's continuing to flash and that's because
we have set the NotificationType to Critical.
| | 06:08 | Now if we select that window, it will stop flashing.
| | 06:11 | We now can close our application.
| | 06:13 | If we go back to our application and we set NotificationType
to Informational, we will notice a different response.
| | 06:19 | So if we scroll down to the notifyUser method again
and we change NotificationType to Informational,
| | 06:30 | we can save our application. We will test
our movie, which will load our application.
| | 06:35 | We will minimize the window.
| | 06:37 | We will notice that now when it completes, it
will flash one time and it will remain solid.
| | 06:43 | But it won't flash anymore.
| | 06:45 | This will still tell the user that
something needs to happen,
| | 06:48 | but they will also know that it's not something as critical.
| | 06:51 | Now let's take a look at what the
notifications look like on the Mac.
| | 06:54 | So I have loaded up the Browser application and we are
going to test the actual notification functionality.
| | 07:00 | So the first thing I am going to do is I am going to go
here into the URL box and I am going to just put in the name
| | 07:07 | of another site, we will just type in Google.
| | 07:10 | Then as soon as I hit Go, I am going to have to switch
back. I have opened up a Safari window directly behind this.
| | 07:16 | The reason is as we stated earlier notification
only works if your window isn't active.
| | 07:22 | Now this window is going to actually
attempt to notify the user as soon
| | 07:25 | as the page is downloading, so we
will have to switch pretty quick.
| | 07:27 | If we hit Go and then move to the other screen, you
will see now that the page is downloading and indeed
| | 07:33 | because we have set the NotificationType to
Critical, the dock icon continues to bounce.
| | 07:40 | If we would set it to NotificationType.INFORMATIONAL
the Dock Icon would have bounced one time
| | 07:45 | and that would have been it.
| | 07:47 | And here now, if we actually select the dock icon
when it bounces, we actually can activate our window.
| | 07:52 | So now you can see that not only do we have the
functionality to notify the user within Windows
| | 07:58 | to the Taskbar, but we also can use the DockIcon.bounce
method to notify the user inside of Mac OS X.
| | Collapse this transcript |
|
|
11. Monitoring Network ConnectionsUnderstanding the service monitor framework| 00:01 | One of the additional benefits of AIR that we haven't yet discussed
| | 00:04 | is AIR's ability to be an online/offline application.
| | 00:08 | What this means is,
| | 00:09 | AIR is designed so that an application could
easily receive information from the internet
| | 00:14 | and then also be able to store that
information locally on the hard drive
| | 00:17 | and then be able to actually pull a local copy of
the data if there isn't an internet connection available.
| | 00:22 | There is a framework built into AIR
called the Service Monitor Framework
| | 00:26 | that exists to be able to detect if the user
does have a valid connection to the internet.
| | 00:30 | At a basic level,
| | 00:32 | you can just monitor and see if the user can get to a certain URL.
| | 00:35 | At a more advanced level, you can even check and see if
the user has a path to a specific host on a specific port.
| | 00:41 | So the Service Monitor Framework is very powerful within Adobe AIR.
| | 00:45 | However,
| | 00:46 | to use it you actually have to do something that
you haven't had to do for any other AIR components.
| | 00:51 | That is you are actually going to have to drag
| | 00:53 | an instance of the ServiceMonitorShim from the Components window
| | 00:56 | into your application.
| | 00:58 | So let's go ahead and take our Browser application
| | 01:01 | and let's go ahead and equip it so that we can work with
| | 01:03 | the Service Monitor Framework in the upcoming videos.
| | 01:06 | We'll go to File
| | 01:08 | and then Open and
| | 01:10 | then we open BrowserApplication01 in the
Chapter 11 folder of the exercise files.
| | 01:16 | Now we are going to need to go
under Window and then Components
| | 01:20 | and then you will notice that we have
the ServiceMonitorShim component.
| | 01:25 | It's actually listed under AIR ServiceMonitor.
| | 01:27 | If for some reason you don't see this you might want to go
back and be sure that you have installed the AIR update for
| | 01:32 | Flash CS3 Professional.
| | 01:34 | We will drag an instance of the
ServiceMonitorShim into our library.
| | 01:39 | We can now close the Components window,
| | 01:42 | and now we are actually ready to begin
working with the Service Monitor Framework
| | 01:46 | with Adobe AIR inside of Flash CS3 Professional.
| | Collapse this transcript |
| Using the URL monitor| 00:01 | One of the benefits of using the Service Monitor
Framework is that it truly does allow your application
| | 00:05 | to react differently based on whether the user
has a valid internet connection at the time.
| | 00:10 | The easiest way to get started with the Service
Monitor Framework is to use the URL Monitor.
| | 00:15 | And as I mentioned in the last video to be
able to access this class you actually have
| | 00:19 | to have the ServiceMonitorShim component
that's been added to your library.
| | 00:23 | So let's go ahead and actually
work with our Browser application
| | 00:26 | so that our Browser application can
work differently when it's offline.
| | 00:29 | In this case we will actually disable
the Go button when the user is offline
| | 00:33 | and then reenable it again when they are online.
| | 00:35 | So let's go to File and then Open and we
are going to open BrowserApplication02
| | 00:40 | in the Chapter 11 folder of the exercise files.
| | 00:44 | The first thing we are going to do is double-click
| | 00:46 | on our Browser symbol then we will highlight the
Actions layer and we go Window and then Actions.
| | 00:52 | Now the first thing we are going to need to do is import
two classes that we know we are going to be dealing with.
| | 00:58 | First we are going to need to import air.net.URLMonitor
| | 01:06 | as stated earlier you must have the
ServiceMonitorShim component for this to work.
| | 01:11 | Next you are going to need to import a specific
event that's going to be flash.events.StatusEvent.
| | 01:20 | Now that we have imported the classes we
can begin actually creating our method
| | 01:23 | that will set up the internet connection monitoring.
| | 01:26 | So we will scroll down to the method section of our code
| | 01:28 | and we will create a new method and
we will call it monitorConnection.
| | 01:36 | It's not going to receive anything as parameters
and we will set the return value equal to void.
| | 01:42 | Now the first thing we are going to do inside
| | 01:44 | of this application is we will create
a new instance of the URLMonitor class.
| | 01:47 | Say var monitor of type URLMonitor.
It's going to be equal to a new URLMonitor.
| | 01:59 | Now this URLMonitor is expecting something
in the constructor. It wants a URLRequest
| | 02:03 | and dictates which URL you wanted to visit.
| | 02:06 | In this case we are going to create a new URLRequest.
| | 02:08 | We will say var request of type URLRequest
it's going to be equal to a new URLRequest
| | 02:18 | and we are actually going to set
the URL for that equal to Google.
| | 02:20 | Now that we have created our new URLRequest we actually
can pass the request value into the URLMonitor.
| | 02:28 | There is one more item that we do however.
| | 02:31 | Adobe AIR gives us the capability to work with different
HTML headers than what we are used to in the past.
| | 02:36 | Normally we could just use certain
methods such as post and get.
| | 02:40 | However inside of AIR we now can use the
method of just retrieving the headers.
| | 02:45 | This saves greatly on the amount of data that has to be sent
back and forth between your AIR application and the server
| | 02:51 | that you are checking to see if you
have a valid internet connection.
| | 02:54 | So we will say request.method is going to be equal to HEAD.
| | 03:00 | Now the next step that we need to do is actually
add an eventlistener into our URLMonitor.
| | 03:05 | So we will say monitor.addEventListener and we are going
to listen for the StatusEvent.STATUS and we are going
| | 03:16 | to respond to it with the method onStatusEvent.
| | 03:20 | We are going to need to set one more
property of the URLMonitor class
| | 03:26 | and that's going to be the Polling Interval.
| | 03:28 | So we will say monitor.pollInterval and this is
going to be the number in milliseconds that it waits
| | 03:36 | in between each check to see if you
have a valid internet connection.
| | 03:39 | In this case we are going to set it
to 1000 milliseconds or at one second.
| | 03:43 | Next we are ready to actually start our URLMonitor.
| | 03:46 | So we will now say monitor.start.
| | 03:50 | Next we actually can begin working
on the OnStatusEvent method.
| | 03:53 | So let's scroll up to our event handler section, we
will add in a new method OnStatusEvent and it's going
| | 04:03 | to receive an event of type StatusEvent.
| | 04:08 | Now aside of this StatusEvent we are first going to
want to pull the URLMonitor out from the event.target.
| | 04:14 | So we will say var monitor of type
URLMonitor equal to event.target
| | 04:23 | and as I stated before the event.target
can contain many different types of data
| | 04:27 | so we will tell us specifically to expect a URLMonitor.
| | 04:30 | Next we are going to need to check and see
if the monitor's connection is available.
| | 04:35 | To do this there is a property inside
of the URLMonitor called available
| | 04:40 | and this will tell us if the connection is available.
| | 04:41 | So we will say if monitor.available is going to be equal
to True then we need to actually enable the Go button.
| | 04:51 | So we will say goButton.enabled is equal to True.
| | 04:58 | But we know that if the monitor is not available
that means we don't have a valid internet connection
| | 05:04 | so in those cases we can set the goButton.enabled = false.
| | 05:12 | Now with this in place we are actually ready to go
ahead and test the functionality of our application.
| | 05:17 | So if I had to go to Control and Test
Movie it will actually bring up our movie
| | 05:22 | and in the beginning everything looks fine.
| | 05:24 | However, I have got my network connections
window open in the background and I am going
| | 05:28 | to disable my current internet connection.
| | 05:32 | As I disable it you will see that the button
instantly turns to the disabled state.
| | 05:37 | One of the reasons that it did that so quickly was
| | 05:39 | because we set the polling interval
to be 1000 milliseconds or one second.
| | 05:43 | Now the downside of this that means there is a lot
of data that's being transferred back and forth even
| | 05:47 | if you are using the head for the Request
method but now we can enable our connection
| | 05:53 | and we will notice that our button was enabled again.
| | 05:56 | So this is a basic introduction to using a
Service Monitor Framework and the URLMonitor.
| | 06:01 | Again, if you have a specific server that you know
that your application is going to be interacting
| | 06:06 | with you can use the URLMonitor to monitor the endpoint of
that server to ensure that the user has a valid connection
| | 06:12 | to the internet that can be used with your AIR application.
| | Collapse this transcript |
| Using the service monitor| 00:00 | Another powerful feature of the AIR Service
Monitoring Framework is the Socket Monitor.
| | 00:05 | It works similar to the URLMonitor.
| | 00:08 | And a matter of fact we are actually going to replace our
current URLMonitor with the SocketMonitor in the application.
| | 00:13 | But it gives you much more power and
that you are not just monitoring a URL,
| | 00:17 | but you can monitor a specific
host name and a port on that host.
| | 00:21 | This can easily be expanded into developing an AIR
application that would monitor the status of a web server
| | 00:27 | for example, or the status of a server that had multiple
servers such as Apache and MySQL running at the same time.
| | 00:33 | So we are actually going to begin working with the
SocketMonitor inside of our browser application.
| | 00:38 | So we go to File and then Open, it will open
BrowserApplication03, we now double click on the browser,
| | 00:46 | to bring up the movie clip, we will highlight the
Actions layer and then go to Window and Actions.
| | 00:52 | Now to use the SocketMonitor as you can
see we had to change one of our imports.
| | 00:57 | Instead of being air.net.URLMonitor we have
already changed it to air.net.SocketMonitor.
| | 01:03 | Now in addition we are also going to have to change
any reference in our application from one to the other.
| | 01:09 | So you can see that in our onStatus event we have updated
it. Instead of being a URLMonitor, it's now a SocketMonitor
| | 01:15 | and we also have cast the event.target as a SocketMonitor.
| | 01:18 | The final change, if we go down to the
monitorConnection method, we have actually changed all
| | 01:27 | of the code here to reference a SocketMonitor.
| | 01:29 | And as you can see we have actually entered in a host name
and then in addition to that we have entered in a port.
| | 01:35 | In this case we are going to want
to check, for instance at ynda.com,
| | 01:40 | and see if port 80 is running. The
button should be enabled if it is.
| | 01:45 | Now this port 80 is the generic port for most web
servers, so we actually can test this just to see
| | 01:51 | if the server is responding on this port.
| | 01:53 | There are a lot of uses for this if you will think about it.
| | 01:55 | Most applications actually get data through
HTTP, which is going to be through on port 80.
| | 02:01 | But in a lot of situations you might develop an
application that talks to a server on a custom port
| | 02:07 | or you might develop an application that needs to monitor
if a database server is actually running on a certain port.
| | 02:12 | The SocketMonitor can give you
this capability and even more.
| | 02:15 | So this is just a brief introduction to
what is possible with the SocketMonitor,
| | 02:19 | so let's go ahead and test our application.
| | 02:23 | And as we can see the button is enabled so we
can see that the SocketMonitor has detected
| | 02:27 | that port 80 is running properly on the lynda.com server.
| | 02:32 | The Service Monitoring Framework
in AIR gives you the ability
| | 02:35 | to truly create powerful online and off line applications.
| | 02:39 | They function perfectly well when they can access
online data and then maybe store some of the data
| | 02:43 | on the local hard drives that it can be
accessed when the application isn't online.
| | 02:47 | This framework can be leveraged in many
different ways and is certainly a tool that needs
| | 02:51 | to be in the arsenal of any AIR developer.
| | Collapse this transcript |
|
|
12. Using the Local DatabaseUsing the Contacts application| 00:00 | The sample application that we'll be
working with in this chapter is going
| | 00:04 | to be specifically related to a server side component.
| | 00:07 | Now this server component is going to be
installed using the XAMPP installed Web server.
| | 00:12 | Now if you are not familiar with how to
install this you can go to Chapter 17
| | 00:16 | and view the first video and we cover it in depth there.
| | 00:19 | For this we are going to need to add
a directory to our web server as well
| | 00:23 | as we are actually going to import
some data into a database.
| | 00:26 | So to accomplish this, the first
thing we need to do is just to go
| | 00:29 | to our local host page and our
default XAMPP installation page.
| | 00:32 | Now that we have brought up the XAMPP window we
are going to be going to the phpMyAdmin tools.
| | 00:38 | Now we are going to be using phpMyAdmin
to import some of our data.
| | 00:42 | So let's go ahead and click on phpMyAdmin to go to the page.
| | 00:45 | Now that we are here at phpMyAdmin the first thing we are
going to do is we are going to create a new database oh
| | 00:53 | and also if you see any warnings at the bottom telling
you that you have to configure without a password as long
| | 00:58 | as you are just on a local machine
you are not a server that's actually
| | 01:01 | out on the internet you should be
okay just for development purposes.
| | 01:04 | But you should always reset your password
if you are using a production box.
| | 01:07 | Now we are going to create a new database
named Contacts and we can just click Create
| | 01:15 | and now we are going to go to the Import option.
| | 01:20 | We are now going to open a file that can be
found under the exercise files in Chapter 12
| | 01:27 | under Data and then the contacts.sql option.
| | 01:32 | We can leave most of the other settings the same
and we need to be sure that it is set as an SQL file
| | 01:37 | and then we will hit Go and it will
take a minute as it reads in the file
| | 01:41 | and populates the database with the pre-included values.
| | 01:45 | Once it's done it will inform us that several
queries have been executed and we can test to be sure
| | 01:50 | that things are working properly by clicking on the
Person table and it tells us that it has a 1000 rows.
| | 01:55 | If we click browse we can see some of
the data that we will be dealing with.
| | 02:00 | This is all just generated names and addresses that have all
been generated just at random and now we are actually going
| | 02:06 | to look at the structure and we can see that we have
many different fields inside of this table we have an ID,
| | 02:13 | a first name, a last name, street
address, city, state, email and phone.
| | 02:17 | And so we are going to be creating an application that
allows us to view this data but also an application
| | 02:21 | that uses the embedded SQL database
so that we can store this data
| | 02:25 | so that we can access it even if we are not online.
| | 02:27 | Now the next thing we are going to need to do is we are
going to need to open up the XAMPP directory which for me is
| | 02:36 | under C and then XAMPP and then we are going to need to
go under htdocs and we are going to create a new folder.
| | 02:42 | We will say New Folder and we are
going to call this Contacts.
| | 02:48 | Now that we have opened up this directory we
are going to open up the php directory inside
| | 02:56 | of Chapter 12's exercise files and we are going to copy
everything inside of this directory and we are going
| | 03:01 | to drop it in to the Contacts directory under XAMPP.
| | 03:06 | Now that you have configured the server
side we are actually going to being looking
| | 03:09 | at the actual application that we
will be using for this chapter.
| | 03:13 | Now the application that we will be dealing within this
chapter actually takes advantage of many of the things
| | 03:18 | that we have already learned throughout this series.
| | 03:20 | So let's go ahead and open the sample movie.
| | 03:22 | We can go to Control and then Test Movie.
| | 03:27 | We can see here that we had a Custom Chrome application.
| | 03:29 | We see that we can drag the application
around, we see that we also have Custom Close
| | 03:33 | and Minimize buttons that function properly.
| | 03:35 | In addition we have got a list and when we click
items on the list and it actually pulls data
| | 03:40 | in from the server and actually displays it on the screen.
| | 03:43 | This is just a basic Contact Manager application.
| | 03:45 | We are going to assume that the server keeps all
the data for us but we are going to want to be able
| | 03:49 | to actually store it on our local hard
drive so that's what we will be doing.
| | 03:52 | But let's take a quick look at the actual code
behind this application so that we will all be caught
| | 03:56 | up by the time we jump into programming
with the SQL live embedded database.
| | 04:00 | So I will go ahead and close the application
and now I will go look at the code.
| | 04:08 | We have imported several classes
and we also have defined a location.
| | 04:12 | This location value is equal to one of the php
scripts that you actually installed on the machine.
| | 04:17 | Next we actually have a property called Connection State
| | 04:20 | and this will let the entire application
know if it's online or off line.
| | 04:24 | We have a new method that actually
loads in the data from the server
| | 04:27 | and then we have some different properties
that are set on some of the buttons.
| | 04:30 | We have added in several event listeners as we have
done many times before including an event.ChangeListener
| | 04:36 | on the actual peopleList which is the
list on the left side of the application.
| | 04:39 | The loadData method actually uses the URLLoader
to go and download XML from the server.
| | 04:45 | The server will return an XML file with all of the contacts.
| | 04:49 | Currently this is at a 1000 so when
it loads in a 1000 contacts to the XML
| | 04:53 | and then when it's done loading it actually passes it
| | 04:56 | to a different method it passes it
to the onLoad or Complete method.
| | 04:59 | So if we look at the onLoad or Complete method
it actually goes through and creates an object
| | 05:04 | for each person that's listed inside of the XML
and actually adds that item to the peopleList.
| | 05:10 | In addition, we also have a method called setData that
actually assigns the current selected person in the list
| | 05:17 | so that their information is actually displayed
on the right side of the application as you saw.
| | 05:22 | Next we have a URL monitor that actually
monitors the connection to the server.
| | 05:27 | So this way if anything ever happens and
for some reason our local server goes
| | 05:30 | down our application will know it and
should be able to act accordingly.
| | 05:34 | By the end of this chapter you should be able
to keep sync data between the server as well
| | 05:38 | as your application with the embedded SQLite database.
| | Collapse this transcript |
| Introducing the SQLite local database| 00:01 | SQLite expands on what we have even thought
possible with AIR even up to this point.
| | 00:05 | SQLite is an amazing addition to Adobe AIR that
allows us to store data in the local hard drive
| | 00:11 | and access it in a very quick and efficient manner.
| | 00:14 | There are sometimes when storing data in files
make sense; other times storing data in things
| | 00:19 | like the encrypted local store also makes sense.
| | 00:21 | But a lot of the time if we are going to store
large amounts of data and work with it within AIR,
| | 00:26 | the best choice is using the SQLite Embedded Database.
| | 00:30 | Now you might be wondering, how does a database fit in?
| | 00:33 | You might have worked with things like MySQL or you might
have worked with things like SQL Server and these all seem
| | 00:38 | to be server side implementations, so how
does this actually fit in with Adobe AIR?
| | 00:42 | Well let me give you an example.
| | 00:44 | The first thing that you will need to know is that SQLite
files are just files, the entire database is contained
| | 00:52 | within a single file and I actually
have one here on the desktop
| | 00:55 | and we are going to be working with that one momentarily.
| | 00:58 | But the other problem that you come into with that is a
lot of database developers are used to working with tools
| | 01:03 | such as PHP MyAdmin or working with some other
GUI tools that come in with MySQL to do the work.
| | 01:09 | So how do you work with SQLite databases?
| | 01:12 | Well one of the tools that will be
very helpful to you is from Christophe
| | 01:15 | and Adobe who has developed the SQLite Admin.
| | 01:18 | And it actually was developed inside of AIR.
| | 01:20 | You can see the URL here on the screen and I
would recommend downloading this application
| | 01:25 | and installing it whenever you are
working on an application that is going
| | 01:28 | to be using the embedded SQLite support inside of AIR.
| | 01:31 | I am going to go ahead and open up the application,
and it is going to let us actually open up a database.
| | 01:37 | So to prove to you that this context file on the desktop is
actually a database, we are going to select an existing one.
| | 01:43 | So we will just go to desktop and we will select
Contacts and we can look here and we can see
| | 01:50 | that this just has some basic information, ID,
last name, middle initial, so on and so forth
| | 01:56 | and we actually can even query this data.
| | 01:58 | Now this is going to seem a lot like working with
some of those tools that you are used to working with.
| | 02:03 | And the queries are going to seem a lot like the normal
queries that you would write for MySQL or for SQL Server.
| | 02:08 | So we can just go in if we wanted to and say
Select all from Contacts, and then Execute Query.
| | 02:19 | And now we would see all the results returned.
| | 02:21 | So working with the SQLite database inside of AIR
and while it is encapsulated inside of a single file,
| | 02:27 | still gives you the developer, the familiarity of
working with SQL statements and working with queries
| | 02:33 | but it just happens to be very
efficient and works very well.
| | 02:36 | That entire query was made on a dataset of over 10,000
entries and so the speed that you can access data within AIR
| | 02:42 | through the SQLite Database is also a
great asset as you code your applications.
| | 02:46 | So let's begin to look at this
functionality and see how we are going
| | 02:49 | to integrate it into our Contact Manager application.
| | Collapse this transcript |
| Working asynchronously vs. synchronously| 00:01 | Just as with File System Support inside of AIR,
| | 00:03 | the embedded database provides two different
programming models for interacting with it.
| | 00:07 | First being synchronous allows you to chain
multiple commands together without having
| | 00:12 | to worry about responding to event handlers.
| | 00:14 | Asynchronous is quite different.
| | 00:16 | Commands can be executed in sequence
simultaneously but you have to know
| | 00:20 | that they are completed by using event handlers.
| | 00:22 | So let's give an example of what
the code would look like for each.
| | 00:26 | Now I know we haven't covered any of these classes yet but
we are going to go in depth into them in the next videos.
| | 00:31 | But I just wanted to give you an example of what it
would look like for each of the two programming models.
| | 00:36 | So first, with the synchronous example, we create a new
SQLConnection, we then actually open the connection and we know
| | 00:41 | that that is synchronous because we didn't call the
openAsync method, we created a new SQLStatement,
| | 00:47 | we then create a query, we execute
it and then we get the results back.
| | 00:51 | All of this is done within only 7 lines of code.
| | 00:54 | And not only that but this code could
reside inside of one single method.
| | 00:59 | The asynchronous example is quite different.
| | 01:01 | It starts off by creating an SQLConnection, but then
we immediately see that we have added an event listener
| | 01:06 | that tells us when the connection has actually been opened.
| | 01:09 | Then we actually open an async connection.
| | 01:11 | Once the event SQLEvent.OPEN is fired, then we can
actually create the SQLStatement, we create the query
| | 01:17 | and then we add yet another event listener
to tell us when the query has been completed.
| | 01:21 | Then we execute the query.
| | 01:23 | Finally when the query has been
completed the onResult method is called
| | 01:27 | and then the results are actually
extracted from the SQLStatement.
| | 01:31 | So we can see that there is quite a lot more programming
involved in the asynchronous programming model.
| | 01:35 | But there are some things to understand.
| | 01:38 | First, as we said the asynchronous connection to the
embedded database will have a lot of additional code.
| | 01:43 | Now this becomes even more complicated if you are chaining
multiple queries together, which leads us to the next point.
| | 01:49 | If you are using transactions with a lot of
queries this can become even more complicated,
| | 01:53 | to be sure that everything is handled in the proper order.
| | 01:56 | But in the end asynchronous still provides
the end user with a more quality experience.
| | 02:01 | Because of this, the examples that we are
going to be using are going to be asynchronous.
| | 02:05 | The other reason for that is if you can program
| | 02:08 | in the asynchronous model you don't have any
trouble using the synchronous programming model
| | 02:12 | in situations where it is appropriate.
| | 02:15 | Now because of the speed of the embedded database you
can consider using the synchronous programming model
| | 02:19 | when you are working with small datasets.
| | 02:21 | So if you are in a controlled situation and you know
that the data is not going to grow to be a variable
| | 02:26 | in a large dataset, there are situations
where synchronous programming is okay.
| | 02:29 | And another great use of synchronous programming is
when you are developing prototypes of applications,
| | 02:34 | it is a lot quicker to develop a code with
synchronous than it is with asynchronous.
| | 02:38 | So we are going to keep this in mind but we are
actually going to stick with the asynchronous model
| | 02:42 | when we are building our applications in this chapter.
| | Collapse this transcript |
| Creating a database| 00:00 | Now that you have heard all this wonderful talk about
the power that you will have as a developer working
| | 00:04 | with the embedded database, you are probably
ready to jump in and start working with it.
| | 00:09 | The first step obviously for database
support is to actually create a database.
| | 00:13 | Now it's a little bit different within AIR as
it is from working in something like MySQL.
| | 00:18 | So we are going to cover the whole process from
beginning to end on how to create a database within AIR.
| | 00:23 | So we are going to go to File and then Open and
then we are going to open the Contact Manager01 file
| | 00:29 | within the chapter 12 folder of the exercise files.
| | 00:34 | Once our application loads up, we are going to highlight
the Actions layer and then go to Window and then Actions.
| | 00:40 | Now we are going to scroll down, you can see that we have
already organized the code, but we are going to go ahead
| | 00:45 | above the section that has event handlers and we
are going to add a new section to our application.
| | 00:51 | We are going to keep all of the code for our database
in one place, so we can easily refer back to it.
| | 00:58 | So we will just say this is going to be
database code and we will just enter tag.
| | 01:05 | Now the first step to creating a database
is actually creating a reference to a file,
| | 01:11 | then you actually connect that file to the database.
| | 01:15 | Now the good thing is that if a file already exists,
| | 01:17 | it won't be created again, it will
just open the existing database.
| | 01:21 | So we actually can pretty much contain all of this code
inside of a function that we will call openConnection.
| | 01:26 | So we will say function openConnection and it's not
going to receive any events, because this is something
| | 01:34 | that we are actually just going to call when
the application launches and then it's not going
| | 01:38 | to return anything, so we can leave the return type as void.
| | 01:41 | Now inside of here, the first thing that we are going to
need to do is actually create an instance of the File class,
| | 01:46 | but for us to be able to do that, we are going to
need to be sure that we have imported some classes.
| | 01:51 | So let's scroll back to the top of our application.
| | 01:54 | Now we already have imported flash.desktop and we are going
to need to import a new set of classes and those are going
| | 02:01 | to be the classes that relate to the database.
| | 02:03 | Now there are many, many different
classes that we are going to need,
| | 02:06 | so we are going to just import it in entire package.
| | 02:08 | We'll say import flash.data.*.
| | 02:13 | You can quickly see that if you have to import a
lot of different classes it is a lot easier at times
| | 02:18 | to import the entire package and in a lot of
situations it makes sure codes are lot cleaner as well.
| | 02:23 | So let's scroll down back to our method openConnection and we
are going to start off by saying var dbFile of type File is equal
| | 02:35 | to and we are going to actually point
it to the applicationStorageDirectory.
| | 02:39 | So we will say File.applicationStorageDirectory.
| | 02:43 | and then we will use the resolvePath
method and then we will pass in the name
| | 02:48 | of our database file, in this case, contacts.db.
| | 02:54 | Now AIR does not require that you
name your files .db or .sqlLite.
| | 02:59 | You actually can choose whatever extension you would like.
| | 03:03 | Now the important thing also to remember here is because
we are saving it in the Application Storage Directory,
| | 03:07 | we can then access this whether it's on Mac or PC because
we are using the reference to Application Storage Directory
| | 03:13 | which will be automatically updated for each of the OS's.
| | 03:15 | Now that we have created the reference to our file,
we now can actually connect that to an instance
| | 03:21 | of the SqlConnection class and that's the class that
allows you to actually open a file for database use.
| | 03:28 | So we will say var conn:SQLConnection = new SQLConnection.
| | 03:38 | And now here is where we are actually going
to choose between doing synchronous calls
| | 03:46 | within the database and asynchronous calls.
| | 03:48 | As we stated in the previous video, we are going to choose
to use asynchronous calls because in almost all situations,
| | 03:54 | it's going to provide for a better user experience.
| | 03:56 | So we are going to say conn.openAsync and then we
can actually pass in the reference to our file.
| | 04:05 | Now there is an option here, you can
choose not to pass in a reference to a file
| | 04:10 | and it will actually create a temporary
database that exists only in memory.
| | 04:14 | It will last as long as the application is open, but
then when the application is closed, it will be deleted.
| | 04:19 | In some situations, this can be useful.
| | 04:21 | For our application, we are not
going to be using this functionality.
| | 04:25 | So now we are going to pass in the reference to the file.
| | 04:27 | We will say dbFile.
| | 04:30 | Now because we are using asynchronous methods
we are going to need to be sure that we listen
| | 04:35 | for when the connection is actually ready to use.
| | 04:38 | So before we actually call the openAsync method, we
are going to add an event listener to our conn object.
| | 04:43 | And now we are going to listen for the SQLEvent.OPEN event.
| | 04:54 | And then we will know that the connection has actually
been opened and we can work with the database file
| | 04:59 | and we respond to that with the onDBOpen.
| | 05:04 | However there might be situations where there is an
error, maybe the file that we have configured is corrupted
| | 05:10 | or maybe there has been a mistake in our code
that's actually leading up to this point,
| | 05:12 | so we are also going to want to listen
for one more event conn.addEventListener.
| | 05:18 | We are actually going to listen for another
event that will be SQLErrorEvent.ERROR.
| | 05:26 | Now in this case, this could be caused by a
multitude of things, but basically what it's saying is
| | 05:33 | that for some reason we could not open the
database connection the way that we would like.
| | 05:37 | So we are also going to listen for
this and we will call the onDBError.
| | 05:44 | So now we are going to go ahead
and create those two methods.
| | 05:46 | First we will create the onDBOpen and it will
receive an event of type SQLEvent and it's not going
| | 05:58 | to return anything so we can set the return type as void.
| | 06:02 | Next we are going to create the onDBError method and
it's going to receive an event of type SQLErrorEvent
| | 06:13 | and it's also not going to return anything.
| | 06:15 | So we can leave the return type as void.
| | 06:16 | Now we are going to go ahead and just make
notes of where we are in these methods.
| | 06:23 | Ready to work with database and down here we will put a
trace statement just so that we know that's been an error.
| | 06:30 | We will say "Error Opening Database."
| | 06:35 | Now just with this code, you have been
able to first of all create a reference
| | 06:39 | to a file that will soon be your database.
| | 06:42 | You have learned to use the SQLConnection
class, you have learned to listen
| | 06:45 | to the SQLEvent.OPEN event as well
as the SQLErrorEvent.ERROR.
| | 06:50 | You have opened an asynchronous connection to
the database file and now we are actually ready
| | 06:54 | to start creating tables inside of our database.
| | Collapse this transcript |
| Creating tables| 00:01 | Now that we have created a connection
to a database within AIR,
| | 00:04 | we are now ready to actually create
the table that will hold the data.
| | 00:07 | So now to accomplish this, we are going to
be introduced to a new class SQLStatement.
| | 00:11 | So let's go ahead and open up our
application and work with it.
| | 00:15 | We will go to File and then Open and we
are going to go to Contact Manager02 that's
| | 00:19 | in the Chapter 12 folder of the exercise files.
| | 00:23 | Now we are going to be sure that
we are on the Actions layers
| | 00:27 | and then we are going to go to window and then actions.
| | 00:31 | Now once inside of here, we are going to scroll down
to where we actually created our database connection
| | 00:37 | and we are going to change one piece
of code that we have already written.
| | 00:40 | This works great for our sample before in
just showing how to connect with database.
| | 00:44 | One of the things that you will learn is with
the SQLStatement class you will actually need
| | 00:48 | to pass it a reference of the SQLConnection, so we are
actually going to make this SQLConnection a property
| | 00:55 | that can be accessed from the entire application, so we
will go ahead and take just this section of code right here,
| | 01:01 | we will cut it and we will scroll up to the top.
| | 01:05 | Now you see here, we have a section
called Constants and Properties.
| | 01:08 | When I press Enter and we will go ahead and paste this in.
| | 01:12 | We don't need to do anything else to it yet.
| | 01:15 | Now we can actually scroll down into our openConnection
method and now we can just say conn = new SQLConnection.
| | 01:24 | By doing it this way, we have now just made it
a lot easier to get to our SQLConnection object.
| | 01:29 | Now we actually can begin working with the SQLStatement.
| | 01:32 | Once we know that we have connected to the database,
we now can start working with the database file.
| | 01:37 | So inside of onDBOpen, we are going to call a method
called createTable and now we need to create this method.
| | 01:44 | So we will scroll down below our onDBError and
we will create a new function called createTable.
| | 01:49 | It's not going to return anything, so
we can leave the return type as void.
| | 01:54 | Now the first thing that we are going to need to do
is create a new instance of the SQLStatement class.
| | 01:59 | So we will say var query:SQLStatement= new SQLStatement.
| | 02:11 | Now the next thing that you are going to have to do for
each of your SQLStatement objects is you are going to need
| | 02:15 | to pass it a reference to your SQLConnection, so we will say
query.SQLConnection is going to be equal to and we are going
| | 02:24 | to set this equal to our connection
object which is just con.
| | 02:27 | Next we actually can begin constructing our actual query.
| | 02:31 | So the first thing that we are going to
need to do is actually load up phpMyAdmin.
| | 02:36 | So let's open Internet Explorer and we are going to look at
the way that the database is structured on the server side.
| | 02:42 | So we will go to local host, then we will go to
phpMyAdmin and then we will look on the side,
| | 02:48 | we will find the contacts database and then we will find
the person table and then we will look at its properties.
| | 02:54 | We are going to need to create 8
different fields within this table.
| | 02:57 | We are first going to have a person ID, then
we are going to have a first name, a last name,
| | 03:02 | street address, city, state, email and phone.
| | 03:06 | So we are actually going to keep
this window open over to the side
| | 03:10 | as we begin working with the database inside of Flash.
| | 03:13 | So we are going to go ahead and resize Flash so
that we can still see the window from phpMyAdmin.
| | 03:20 | So let's be sure that we are on the Actions
layer and we will press Window and then Actions.
| | 03:25 | And we actually can scale this
so it will fit into the window.
| | 03:30 | So we will actually begin creating
our statement by saying var queryText
| | 03:37 | and you can choose whatever you would
like, it's just going to be a String.
| | 03:40 | And we are going to begin now crafting the query.
| | 03:42 | We are going to say "CREATE TABLE IF NOT EXISTS,"
| | 03:49 | this way we can ensure that we are not actually
writing over the table if it is already created.
| | 03:53 | If some of this looks unfamiliar to you, it's okay.
| | 03:55 | You might want to take some time just to go
back and research some basic SQL statements.
| | 04:00 | We are going to be using createStatements and
selectStatements and then insertStatements
| | 04:04 | and so these statements are actually very basic in nature.
| | 04:06 | We are not going to be going and doing very complex joins or
other complicated SQL procedures and a lot of times in AIR,
| | 04:12 | you are not going to be doing that either, so just
brushing up on some of the basics might be helpful
| | 04:16 | to you if any of this is looking strange.
| | 04:18 | So we are going to say "CREATE TABLE IF NOT EXISTS" and then
we are going to say "CREATE TABLE person" and now we are going
| | 04:24 | to need to actually create each of the specific fields.
| | 04:28 | Now we are actually going to place the name of the table
in single quotes and now we actually can leave a space
| | 04:34 | and then we are going to move this down to the next line.
| | 04:37 | Now inside of here we are going to need to
start listing names of each of the fields.
| | 04:42 | So we will say first that we are going to want to
create the field personid and it's going to be
| | 04:47 | of the type INTEGER then we can put a comma, we will
leave a space and then we will move down to the next line.
| | 04:54 | Next we are going to create firstname and
it's going to be all lowe case to match what's
| | 05:00 | on the server and that's going to be of type TEXT.
| | 05:02 | Then we will leave a space and
then we will move to the next line.
| | 05:06 | Then we will create lastname, TEXT.
| | 05:09 | We will leave a space, move to the next line and after that
we will do street address and that will be of type TEXT,
| | 05:17 | leave a space, move to the next line and
after street address, we will do city,
| | 05:21 | TEXT and move to the next line then we
will do state, it will be TEXT as well.
| | 05:28 | Then we will actually do email and I bet
you will never guess, yes it's TEXT too.
| | 05:33 | And then after email we will do phone and in this
case we are actually going to make phone TEXT as well
| | 05:38 | because it actually will possibly contain some special
characters and actually we don't need to leave a comma
| | 05:44 | after the last one. Then we can add our closing
parenthesis and then we can actually close our statement.
| | 05:52 | Now the important thing to understand
here some of these items might not look
| | 05:55 | like they exactly match the types
that are listed on the server side.
| | 05:59 | SQLite actually has a different way of looking at it,
| | 06:03 | instead of actually calling them types each
column has what's called an affinity type
| | 06:07 | and an affinity type is a little bit
different and functions differently.
| | 06:10 | Now for the purpose of working with the database in AIR,
you can actually find a type that corresponds very closely
| | 06:15 | to a type inside of MySQL but whatever your server
side database is and then just choose to use that.
| | 06:21 | In this case, everything should map fine between server
side and between here locally with the embedded database.
| | 06:27 | Now after we have created our query text, we can now
actually assign that as the query text for our query,
| | 06:35 | so we will say query.text is going to be equal to queryText.
| | 06:41 | Now we are going to need to add some of event listener,
so we can find out if our query actually succeeded,
| | 06:46 | so we are going to say query.addEventListener and we
are going to listen specifically for the SQLEvent.RESULT
| | 06:54 | and then will actually call the queryResult method.
| | 07:00 | Next, we are going to add another event listener
just as we did with the SQLConnection to be sure
| | 07:06 | that there wasn't an error. So now we
will listen for SQLErrorEvent.ERROR.
| | 07:13 | And in this case, we are going to call a method that we have
already created onDBError and in this case we also can give
| | 07:19 | that one a much more generic trace statement.
| | 07:23 | We will just say "Error with Database."
| | 07:27 | Now before we actually implement the queryResult
method, we actually need to execute our query
| | 07:32 | and it's actually done by just saying query.execute.
| | 07:36 | Next we actually can go and create a new
function and of course this one is queryResult
| | 07:43 | and it receives an event of type SQLEvent.
| | 07:47 | It doesn't return anything, so we can leave
the return type as void and now inside
| | 07:51 | of here we can just say for the
moment, "Query was Successful."
| | 07:56 | At this point, we will actually put in a
trace statement that also says Successful.
| | 08:00 | And we will actually put a breakpoint here so that when
we debug our application, it will actually let us know
| | 08:06 | if it was successful in the same way open
a breakpoint next to the onDBError method.
| | 08:11 | Now that we have actually added these items in we are ready
to actually start executing some things with our database.
| | 08:17 | First we are going to have to call the openConnection
method at the very beginning of our application,
| | 08:23 | so we will go ahead and highlight the name of that method.
| | 08:26 | We will scroll up to the top, under
where it says INIT Methods,
| | 08:29 | and right under loadData, we are
going to call openConnection.
| | 08:33 | Now again remember the loadData method that's already
included in the application doesn't have anything to do
| | 08:37 | with the embedded database at least not
yet, it just loads data from the server.
| | 08:41 | So here is what will happen.
| | 08:42 | We will call the openConnection method.
| | 08:45 | The openConnection method will fire to create your
reference to the file, create a new SQLConnection,
| | 08:51 | assuming it opens properly, it will respond by calling
the onDBOpen method and again it's opened synchronously.
| | 08:58 | When the onDBOpen method fires, it will call to
createTable method which will then call the query,
| | 09:04 | which will then be executed, and then if everything works
as it should, it should call the queryResult method.
| | 09:12 | So let's go ahead and go to Control and then Test Movie.
| | 09:17 | And that's going to give us an error that
we have not yet included in the file inside
| | 09:22 | of our application so we actually can quickly remedy that.
| | 09:26 | Let's go up to the top and we will
say import flash.FileSystem.File.
| | 09:33 | Now we can save our application and now this time
since we know that we have actually fixed that error,
| | 09:39 | we are going to want to actually debug our
movie, so we will go to Debug, Debug Movie.
| | 09:44 | It will take it a second as it's loading and we can see
here that it actually blended in our breakpoint successful,
| | 09:53 | so that means that our table was created and it
actually was created with the fields that we wanted.
| | 09:57 | So now at this point, we have actually gone a long way
in creating SQLConnection and then executing a query
| | 10:03 | that created a table within our database.
| | 10:06 | Now at this point we should be ready to create and
execute SQL queries on the table that we created.
| | Collapse this transcript |
| Creating SQL statements with parameters| 00:01 | Now at this point you have actually
done a lot with the database.
| | 00:04 | You have learned how to actually create
a reference to a database file as well
| | 00:07 | as create a database in memory if you need to.
| | 00:09 | We have also walked through the process of creating a table
and basically learning how to use the SQLStatement class
| | 00:15 | but now we are going to take that one step further.
| | 00:17 | We are going to work with several
things for the first time in this video.
| | 00:20 | We are going to learn how to work
with parameterized queries.
| | 00:23 | We are also going to use Insert and Delete
statements for the first time so let's go ahead
| | 00:27 | and jump into our application and let's make it work.
| | 00:30 | We will go to File and then Open and
we are going to open ContactManager03
| | 00:35 | in the Chapter 12 folder of the exercise files.
| | 00:37 | We will open the file and before we jump into the code we
are going to need to add one item to the Stage so I am going
| | 00:44 | to go ahead and I am going to lock all the layers
except for the Components layer and I am going
| | 00:48 | to select the lists currently on the left side.
| | 00:51 | I am then going to go to the Free Transform tool and then
I am going to select the list and then I am going to hold
| | 00:56 | down the Alt key or the Option key on
Mac and we are just going to bring this
| | 01:00 | up a little bit to liver him for a button below.
| | 01:02 | Now I am going to go and drag a
button from the Components window
| | 01:08 | and just drag it on to the Stage directly below the list.
| | 01:15 | Now in this case I am going to highlight first the list
and then the button and then we are going to make sure
| | 01:20 | that they match size by pressing the Match Size button then
| | 01:23 | at this point we will be sure that
they are aligned to the left side.
| | 01:28 | We will be sure everything is positioned properly
and now we need to give our button an instance name.
| | 01:33 | We are going to call this button syncButton.
| | 01:35 | Then we are going to also want to change the parameters
because let's face it, label is not that descriptive.
| | 01:43 | We are going to call it Sync to Database.
| | 01:47 | Okay now that we have created our button, put it on
the Stage, given it an instance name, we are ready
| | 01:54 | to actually jump into the code. So I
am going to lock the Components layer.
| | 01:57 | I am going to highlight the Actions layer
and then go to Window and then Actions.
| | 02:01 | The first thing that we need to do is add
an event listener for our Sync button.
| | 02:04 | So let's go down to the section where we add event listeners
and we are going to say syncButton.addEventListener
| | 02:12 | and then we are going to listen
for the MouseEvent.CLICK event
| | 02:16 | and then we respond to that with the onSync method.
| | 02:22 | So now let's go ahead and scroll down to our database code
and we are just going to scroll to the end and we are going
| | 02:29 | to create a new method called onSync and this is going
to receive an event of type MouseEvent and it's not going
| | 02:36 | to return anything so we will leave the return type as void.
| | 02:39 | Now let's think a minute about
what we need our application to do.
| | 02:42 | Now that we have created a table we are
going to want to be able to push a button
| | 02:46 | and download all of the contacts from the server.
| | 02:50 | At that point we are going to want to be sure that those are
the only ones that are actually in the database at that time
| | 02:55 | so we don't want any old records left behind only what's
on the server and then we are going to want these to stay
| | 03:00 | on our hard drive so that if we need to
open up our application at some point
| | 03:03 | and we don't have an Internet connection
we still have access to our contacts.
| | 03:08 | So the first thing we are going to need to do is we are
going to need to run an SQL statement that will delete all
| | 03:12 | of the records from the person table inside of our database.
| | 03:16 | As I said before this will ensure that
we are dealing with only the newest data
| | 03:19 | so let's go ahead and create a new SQL statement.
| | 03:22 | We will say var q of type SQLStatement
is equal to a new SQLStatement.
| | 03:32 | Then we will attach it to our SQLConnection and
we will just reference it to the conn variable.
| | 03:39 | Then we need to actually put in a text for our query.
| | 03:42 | In this case it's actually going to be pretty easy.
| | 03:44 | We are going to say q.text is going to be equal to
Delete From, and then we will put in single quotes, person.
| | 03:54 | And that's the name of our table and you
will know this if you are familiar with SQL.
| | 03:57 | When you run a delete command you can say delete from
person where first name equals David if you want.
| | 04:04 | But if you just say delete from person, it's going to delete
everything in the entire table so you want to be sure
| | 04:09 | that this is what you want to do before you enter a
command like this but it is what we want to do so we want
| | 04:14 | to go ahead now and add event listener
so we can then respond to this.
| | 04:17 | So we will say q.addEventListener and we listen
for the SQLevent.RESULT that will be fired
| | 04:23 | when our query is run successfully and then we are on to
another method that will create called addContactData.
| | 04:30 | Next we are going to want to listen for an error and that
will be an SQLErrorEvent.ERROR and then we will respond
| | 04:43 | with the method that we have used previously onDERROR.
| | 04:47 | Now we are actually ready to execute
the query so we will say q.execute.
| | 04:53 | Now this is a query that we have done before.
| | 04:55 | This is very similar to the way
that we setup or Create Table query
| | 04:59 | but now when we build our addContactData method we are
going to use another new technique, parameterized queries.
| | 05:05 | So let's go ahead and create the new method addContactData.
| | 05:10 | We will receive an event of type SQLEvent and it's not
going to return anything so we can leave the return type
| | 05:18 | as void so what we are going to do is
we are going to go and look at the list.
| | 05:21 | When we opened up the application the application
called the server, downloaded all of the current items
| | 05:27 | and then stored it inside of the list
that's on the left side of the application.
| | 05:32 | Now that list contains a property called dataProvider
and that is actually of the type DataProvider
| | 05:38 | and there is a function in the DataProvider class that
allows us to extract from that basically all the data
| | 05:44 | in the form of an array and so that's what we are going
to use but to do that we are actually going to have
| | 05:48 | to import the DataProvider class so let's go ahead and
scroll back up to the top where we have our imports.
| | 05:55 | Now this point we are going to import fL.data. DataProvider
and we will scroll down back to our method.
| | 06:03 | Now we are going to want to loop through each of
these items so to do that we are first going to need
| | 06:09 | to extract the array from the data provider and then
we can loop over it using it for each statement.
| | 06:13 | So first let's go ahead and grab the data out of the data
provider so we will say var contactData of type Array
| | 06:22 | and we are going to set that equal to the
peopleList which again is the list on the left side
| | 06:27 | of our application, .dataProvider and
then we will call the toArray method.
| | 06:33 | And that will return all the items as arrays.
| | 06:36 | Now that we have our array we can
look through it by saying four each.
| | 06:40 | We will say var o Object in contactData.
| | 06:47 | Now again what this means is it will create an
object for each of the items in the contact data
| | 06:54 | and then we will loop through them each one by one.
| | 06:56 | Now at this point we are going to need to run a query
that actually will insert each item into the database
| | 07:02 | so we are actually going to run an
insert query so we will start off
| | 07:06 | by creating our new SQL statement. var q SQLStatement
and we will just use q because that's short for query
| | 07:13 | and at this point you know what's next we are going to
go ahead and add the reference to our SQL connection.
| | 07:21 | Then after that we are going to go ahead and type the text
for our query so here is what we are going to need to do.
| | 07:26 | We are going to use a new format
for the entries within our query.
| | 07:31 | We are going to say Insert Into and then of course we use
our table name which in this case would be person, Values.
| | 07:40 | Now we can move down to the next line and here
is where we will start adding in our parameters.
| | 07:45 | So the first parameter that we
are going to enter is personid.
| | 07:48 | Now to make it known that it's a parameter,
we are going to put a colon in front
| | 07:51 | of it so we will say colon and then personid.
| | 07:55 | The next we will say colon and then firstname.
| | 07:59 | Then we will say colon and lastname and we will just
go ahead and do it for each of the items in the query.
| | 08:15 | So now we have created our query with parameters.
| | 08:18 | Now because we use parameters there is one extra step.
| | 08:21 | We now have to actually assign a
value to each of the parameters.
| | 08:25 | Now at first this might seem like a lot of work
and you want to know why do we do it this way.
| | 08:28 | And if you remember back to some of the other code
when we don't use parameters, number 1, we run the risk
| | 08:33 | of not actually treating our data as it should be treated.
| | 08:36 | When we use parameters it actually looks and finds the
affinity type of the column it's supposed to insert data in
| | 08:41 | and we can actually format that data appropriately so
for example it knows that it doesn't need to put integers
| | 08:46 | in single quotes but it does need
to put text in single quotes.
| | 08:49 | In addition queries can look horrendous without
using parameters because you are going to have
| | 08:53 | to concatenate a lot of different data types in with the
text so in this case parameters may occur much more stable,
| | 08:59 | more legible and it's certainly going to be a lot
easier to deal with when we have to debug anything.
| | 09:04 | So the way that you enter a parameter is you are going
to look at the parameters property of the SQLStatement.
| | 09:10 | So we will say q.parameters and then we just need
to tell it which parameter we are talking about. So
| | 09:16 | in this case we are talking about personid and notice that
we also did include the colon here as well so we will say
| | 09:22 | that parameter is equal to o.personid and we will
just need to go ahead and do this for all of them
| | 09:28 | so to make it a little bit easier
I am just going to copy this line.
| | 09:31 | I am going to paste it 7 more times and
now we are going to go through and change.
| | 09:37 | The next one would be firstname then we will do lastname.
| | 09:52 | Then after streetaddress we will do
city and then finally we will do phone.
| | 10:07 | Now we are going to need to do one
more thing before we execute our query.
| | 10:10 | It's generally a good practice that if you are using
parameters within an SQLStatement you are going to need
| | 10:14 | to call the clearParameters method of the SQLStatement.
| | 10:17 | Now this is especially important if you
are reusing your SQLStatement classes.
| | 10:21 | If you actually get into the habit of doing this before
you actually enter your parameters you can ensure
| | 10:25 | that you will never have any problems.
| | 10:27 | Now next we are going to need to add our event listeners.
| | 10:29 | So we will add our event listeners.
| | 10:31 | The first one we will say we are
going to listen for SQLEvent.RESULT
| | 10:36 | and that will fire the onInsertResult method.
| | 10:44 | The next we are going to listen for the error.
| | 10:51 | And that will go to our onDBError method and then
now we are ready to actually execute the query.
| | 10:59 | Now I am going to make one more change that we actually
can look at the data that we have actually put in.
| | 11:05 | If you look when we actually created our connection
to the database we created our database inside
| | 11:11 | of the application storage directory and that's fine.
| | 11:14 | As a matter of fact that's where you
would want it for your application
| | 11:17 | but just so that we can preview our actual data fairly
easily we are actually going to take and we are just going
| | 11:22 | to put it on the desktop directory for the moment. So
this will actually store our database file, contacts.db,
| | 11:29 | on the desktop. So now we can go ahead and save our
application and everything should work properly.
| | 11:35 | Just to be sure we are going to be
sure that we have some breakpoints set.
| | 11:38 | We do at this point actually have one more method that
we need to create and that is our onInsertResult method
| | 11:42 | so we will go to create a new function,
onInsertResult, and that's going to receive an event
| | 11:51 | of type SQLEvent and the return type's void.
| | 11:56 | Now we don't really need this to do much because this
will actually be happening a lot of times really,
| | 12:00 | really fast when we actually push the Sync button. So
we just want to actually put a trace statement in so
| | 12:05 | that we can actually get some feedback
on what's happening when we are
| | 12:08 | in Debug mode and we will just say "Insert Successful."
| | 12:12 | Now it looks like everything is about ready to go.
| | 12:14 | I am going to go ahead and put one breakpoint here
inside of the onInsertResult so now we can go ahead
| | 12:20 | and save our application and go
to Debug and then Debug Movie.
| | 12:29 | So now we can see we have actually got a
breakpoint left over from another query.
| | 12:32 | If you actually have a breakpoint in
your code that you want to be sure
| | 12:35 | that it doesn't hit again during your debugging session
you actually can just click it and it will revert
| | 12:39 | from having a red circle with the
arrow to just having the arrow.
| | 12:41 | Then we will press Play which will
move through to the next breakpoint.
| | 12:46 | We can see here that it says successful and
that was for when our table was created.
| | 12:50 | Now we can open our Contact Manager and
we can actually sync this to the database
| | 12:55 | and that's actually going to pass back another SQL event.
| | 12:58 | That's actually the breakpoint that we set directly
inside addContactData and then we will press one more time
| | 13:05 | and we can see here that we had a successful event
on our onInsertResult. It came back without any errors
| | 13:11 | and you actually could go through here and see more
properties of the SQL event and the SQL statement
| | 13:15 | but this just tells us that everything is working properly.
So now again if we hit the Continue button it's going
| | 13:20 | to keep going through every time it's trying to
insert data so we also can just press the break points
| | 13:26 | so that it doesn't fire again and then we will go ahead
and hit the Continue button and it will cycle through
| | 13:30 | and you can see all the insert successfuls
that are coming in from our queries.
| | 13:34 | We will go ahead and let that finish up and this just
shows you how to use parameterized queries in this case
| | 13:39 | with an insert statement but you can easily expand on this
and use this for select queries as well so we are going
| | 13:45 | to take what we have learned from
this and we are going to finalize some
| | 13:47 | of the online/offline capabilities of our application.
| | Collapse this transcript |
| Selecting data and retrieving results| 00:00 | So now that you know how to actually execute queries and
parameterized queries within the embedded database in AIR,
| | 00:06 | we are now going to work on how to
retrieve results from a Select Statement.
| | 00:09 | So to accomplish this we are going
to need to open our application.
| | 00:12 | So let's go under File and then Open and we
are going to open ContactManager04 which is
| | 00:17 | in the Chapter 12 folder of the exercise files.
| | 00:19 | Now pretty much everything we are going to need to do
in this video is going to be within the Actions panel
| | 00:25 | so we will select the Actions layer
and then go to Window and then Actions.
| | 00:29 | Now here is the theory of what we are going to do.
| | 00:31 | We want our application to be able
to function online or offline.
| | 00:35 | Now we did most of that actually in the last
video where we took and we actually inserted all
| | 00:39 | of the values from the server into the database.
| | 00:42 | Now at this point we are going at the application when
it starts up to detect whether it's online or offline.
| | 00:48 | And then depending on whether it's online or offline
either load data from the server or from the database.
| | 00:54 | The first thing that we are going to need
to do is look at our loadData method.
| | 00:58 | Currently inside of our loadData method as you can see
we just use the URLLoader to actually load in the XML.
| | 01:04 | But now we are going to want to actually
have it check to see if it's online.
| | 01:08 | So if you notice we created a connectionState variable
this actually either holds the word Online or Offline.
| | 01:14 | And so we are going to be using that when we actually test
| | 01:16 | when the application launches to
see if it is online or offline.
| | 01:20 | In addition we are going to create one more parameter,
| | 01:22 | Initialize it will be Boolean and
we will set initially to False.
| | 01:29 | And the reason that we are doing this is, we want
the application to check one time when it's launched.
| | 01:34 | After it's checked to see if it's online or offline then at
that point we will load data from the appropriate method.
| | 01:40 | So at the moment we can go ahead and delete the
loadData method from the Init Method section of the code
| | 01:44 | and then we will add it back in a moment.
| | 01:48 | So let's go to our loadData method, we are
going to go ahead and put and if statement,
| | 01:52 | we are going to say if connectionState is
equal to Online then we are going to want
| | 01:59 | to execute the code that we have been executing.
| | 02:02 | However, if it's not then that's where we are
going to start working with our SQL statement.
| | 02:08 | So then we will say else and then we are going to create a
new instance of the SQLStatement class we will say var q
| | 02:15 | of type SQLStatement is equal to a new SQLStatement.
| | 02:19 | And then we will say q.sqlConnection is
equal to conn, which we defined previously.
| | 02:25 | After that we are going to go ahead and
add our query text which will be q.text
| | 02:29 | and that will be equal to Select,
then asterix(*), From Person.
| | 02:35 | And this is just the way that an SQL you basically
say go and grab everything from this table,
| | 02:39 | we want all of the different columns and all
of the data just go ahead and bring it back.
| | 02:43 | And so now that we have added that we could
add our event listeners and we are going
| | 02:47 | to be listening firstly SQLEvent.RESULT and that will take
us to the onLoadSQL method which we will create shortly.
| | 02:55 | And we also want to listen for any errors so
we will say addEventListener SQLErrorEvent.ERROR.
| | 03:02 | And then we can use the method that
we have been using previously onDBError.
| | 03:06 | Now that we have added our event listeners we can
actually execute our query so we will say q.execute.
| | 03:15 | So this is only going to be executed if
the application starts in an offline mode.
| | 03:21 | Now to actually tell the application to start the process
of checking to see if it is online we are going to have
| | 03:26 | to move one method call up to the
Init Method section of our code.
| | 03:29 | So we will copy the name here of this method, which is
monitorConnection. Basically it is just sets up a URLMonitor
| | 03:35 | that checks the local WebServer to see if we can access
it and then it calls a method called onConnectionStatus,
| | 03:40 | which we will be heading to in just a second.
| | 03:42 | And finally it actually starts the URLMonitor.
| | 03:44 | So we will move this call to monitorConnection
directly up after openConnection.
| | 03:52 | Now we will scroll down to the method that
we referenced with the URLMonitor and here is
| | 03:59 | where that initialized property is
actually going to come in useful.
| | 04:02 | We are going to come down here and say "If a value of
initialized is false" then we are actually going to want
| | 04:10 | to first set initialize to true and then we
are going to want to call the loadData method.
| | 04:17 | So that every times it loops through and it
is checking the URLMonitor it isn't trying
| | 04:20 | to load the data each an every time.
| | 04:22 | So now we actually can head back up to the SQL section
and we are going to create a new method onLoadSQL.
| | 04:31 | It's going to receive an event of type
SQLEvent. It's not going to return anything
| | 04:38 | so we can leave the return type equal to void.
| | 04:41 | Now inside of the onLoadSQL method we are going to
remove all of the people that are in the peopleList
| | 04:46 | and then we are going to loop through the results
for the query and place those people's names inside
| | 04:49 | of the peopleList inside of our application.
| | 04:51 | So the first thing that we need to
do is just say peopleList.removeAll
| | 04:56 | and that will give us a fresh place to start.
| | 04:59 | Next we are actually going to grab the SQL
statement out of our event.target property
| | 05:03 | so we will say var q SQLStatement is
equal to event.target as SQLStatement.
| | 05:14 | Next we are going to create a variable that's going
to be results and it's going to be of type SQLResult.
| | 05:20 | And we are going to set that equal to the method of the
SQL statement class that actually returns the results.
| | 05:25 | So we can just say q.getResult.
| | 05:27 | So this is actually going to pull the results back.
| | 05:31 | Now inside of the results variable that we have
created there is going to be a property called Data
| | 05:36 | and that's actually going to contain the data
from the SQL query so next we are going to go
| | 05:41 | down at this point we are going to add in the trace
statement that says we are going to check values.
| | 05:45 | So we are going to actually set a breakpoint right here
next to this trace statement and we are going to look
| | 05:51 | at what is actually returned from the SQL query.
| | 05:53 | So we need to be sure that a few things are true, first we
need to be sure that if we disable our internet connection.
| | 05:59 | But for me I am actually going to have to go one step
further because I am using the local Web server so I am going
| | 06:05 | to actually go and I am going to
shut down the local Web server.
| | 06:10 | You obviously don't have to worry about that step
it you are using a server that's somewhere else
| | 06:14 | or if you are using a shared Web server somewhere.
| | 06:16 | But now since we disabled the Web server, when we go to the
loadData method it should actually see that it's not online
| | 06:24 | and we will actually put a breakpoint here as well.
| | 06:27 | Then it will start executing the SQL statement
it will select all of the records from person
| | 06:31 | and then will add the event listener and it will go
to the onLoadSQL method, if it's executed properly.
| | 06:36 | If not, if there is some type of an
error, it will go to the onDBError method
| | 06:40 | and we already have a breakpoint next to that.
| | 06:41 | So at this point we should be ready to
test the first part of our application.
| | 06:45 | Now notice we haven't inserted any values yet into the
actual peopleList but using this we are actually going
| | 06:51 | to be able to see the results that come back from the
SQL query so let's go to Debug and then Debug Movie.
| | 06:59 | Okay we can see our first query result has come
back and this is when we created the table.
| | 07:03 | We still have a breakpoint there,
so we can go ahead and just select
| | 07:06 | that breakpoint to unbreakpoint and then keep going.
| | 07:10 | Here you can see we have ended up at the loadData method
and we actually could go through and check and we would see
| | 07:14 | that the connectionState is equal to Offline so it
should actually loop through and go to our SQL code.
| | 07:19 | And we can see again that we have ended
up here at our SQLResult so we can see
| | 07:23 | that we have actually queried the
database and got results back.
| | 07:26 | And you can see here that our results
variable is of type SQLResult.
| | 07:30 | If we open it up we can see here that it has several
properties and data is the one that we are concerned with.
| | 07:36 | So if we click on Data it will take it just a second
because it's having to look through a lot of values
| | 07:43 | but then it will load up and you can see that each of
the items that comes back is an object and inside of each
| | 07:48 | of those objects or the properties that
are in the database for that given person.
| | 07:52 | So we can now use this data to populate the peopleList
and now truly have a nice online offline application.
| | 07:58 | So let's end our debugging session
and let's finish up the application.
| | 08:02 | Now we can delete this trace statement and we can
start the process of looping through the results.
| | 08:06 | We will say for each var o, which will
just be a generic object, in results.data.
| | 08:16 | Now for each of these we are going to
want to add them to the peopleList
| | 08:21 | so we will say peopleList.addItem
and then I want to add the object.
| | 08:29 | Now the great thing is this requires a lot less code than
when we loaded in the data from XML because when we loaded
| | 08:34 | in the data from XML we actually had to parse it and we sure
that all the data was in the right format, here however,
| | 08:39 | we can just add the data to the peopleList.
| | 08:41 | There is one additional item that we have to do however.
We need to go to our peopleList. Each of the objects inside
| | 08:47 | of the peopleList also has a label property and this
label property is equal to last name, first name.
| | 08:52 | So we will add that in as well we will say last name, then
we will put a comma and a space and then say o.first name.
| | 09:01 | Now we should be able to save our application
and since we have already done our debugging
| | 09:06 | at this point we should be able to actually just
go to Control and then Test Movie and notice again
| | 09:11 | that our Web server is not running we can see
that Apache doesn't have running next to it
| | 09:15 | and also our internet connection is disabled so I have
nothing up my sleeves and then we can go to Control
| | 09:20 | and then Test Movie and we can see
that all of our values have been pulled
| | 09:25 | in even though we are offline we are actually syncing data
from the local database and we can use the application just
| | 09:31 | as we did previously to retrieve information
for different contacts within our list.
| | 09:35 | So this is the beginning of a powerful
Online/Offline application.
| | 09:39 | You might also want to develop an application that allows
the user on the AIR app to add a context and then send
| | 09:44 | that data back to the server, developing a true two-way
form of communication as opposed to just one way.
| | 09:50 | However you use it, the SQL support inside of AIR
is powerful and you can use it to create a lot
| | 09:55 | of different types of applications
not just Online/Offline applications.
| | 09:58 | We have now looked at two different ways to
store data on the user's local hard-drive.
| | 10:02 | Now we will look at one other option
that's available to store encrypted data.
| | Collapse this transcript |
|
|
13. Using the EncryptedLocalStore ClassWorking with byte arrays| 00:00 | Another one of the powerful classes that's
available within AIR is the ByteArray class.
| | 00:04 | And in this chapter we will be looking specifically
at the encrypted local store which allows you
| | 00:08 | to store encrypted binary data on the user's hard
drive using native operating system encryption methods,
| | 00:14 | but to do this you going to need
to be familiar with ByteArray.
| | 00:16 | But the good thing is even though a ByteArray
might seem a little foreign to you at first;
| | 00:20 | working with the ByteArray is very
similar to working with the FileStream.
| | 00:23 | So we will be moving forward with it and some of
these methods should look fairly familiar to you.
| | 00:27 | Now there are different ways that ByteArrays can
be used, in this case, we are going to be working
| | 00:31 | with the encrypted local store, but in addition to
that, if you are going to be working with files
| | 00:35 | on the user's hard drive, you will be working with ByteArray
data which basically just means a stream of binary data.
| | 00:40 | So we are not talking here about strings
and arrays, we are actually dealing
| | 00:43 | with actual ones and zeros that exist for a given file.
| | 00:46 | And then you also have to use ByteArray instances
inside of the encrypted local store as I mentioned.
| | 00:51 | When we actually get data to store
in this encrypted local store,
| | 00:55 | it actually has to be in the ByteArray
format when we pass it in.
| | 00:57 | And then finally and we will be doing this later, if you
are going to download and update for an AIR application,
| | 01:02 | you will be using ByteArrays to actually get data from
the URL stream and then save it to the user's hard drive.
| | 01:07 | So let's look at the sample used for ByteArray.
| | 01:09 | We are going to take a string and write it
into the ByteArray and then we are going
| | 01:13 | to take that same string and read it back out.
| | 01:15 | So if you notice here we just have defined a string and
then we create a new instance of the ByteArray class.
| | 01:20 | Then we use a method called writeUTFBytes.
| | 01:23 | Now this is the same name that we used
when we worked with FileStream earlier.
| | 01:27 | This is basically what you are going to
use anytime you are working with strings.
| | 01:30 | So you actually write it into the ByteArray,
but then you can actually take the ByteArray
| | 01:33 | and use the readUTFBytes method to return
the string back to you in its original form.
| | 01:38 | There is also a property that we use here called
ba.bytesAvailable which will be a property of your instance
| | 01:43 | of the ByteArray class that will tell
you how many bytes are available.
| | 01:47 | You can pass that into the readUTFBytes
and it will return the entire string.
| | 01:50 | Now the important thing to understand
is that there is a different one
| | 01:53 | of these methods for each of the different data types.
| | 01:56 | In addition there is even some multiple
data types for some numeric values.
| | 02:00 | So you just want to be sure that you use
the appropriate method for your data type.
| | 02:03 | And here are some of the common methods here.
| | 02:05 | We have already talked about write and read UTF
bytes, but you also can write an int, read an int,
| | 02:09 | and then write a Boolean and read a Boolean as well.
| | 02:11 | ByteArrays can do a lot of different things, this basically
can allow your application to read files of any format,
| | 02:17 | but in this instance we are going to using it specifically
to read data into the encrypted local store inside of AIR.
| | Collapse this transcript |
| Inserting data| 00:00 | We are now going to begin working
with the encrypted local store.
| | 00:03 | Now the first task that we are going to take in
is actually inserting data into the local store.
| | 00:07 | And you might be asking yourself, why would I
want to do this and that's a valid question.
| | 00:10 | The encrypted local store is a little bit different in the
way that it stores data, it gives you some advantages
| | 00:16 | over storing sensitive data either in a file or
in the database, because the truth is with a file,
| | 00:21 | it's just a file saved on the computer,
it can be opened by any other application.
| | 00:25 | The same thing for the database. Even though it's a
SQLite database, it's still a file on the hard drive.
| | 00:30 | By default other applications whether they would
be AIR applications or even other applications
| | 00:35 | that support SQLite can easily go in
and open your files and view the data.
| | 00:38 | So when you are dealing with sensitive information,
you either want to encrypt the file or you want to look
| | 00:43 | at storing data within the encrypted local store.
| | 00:46 | It gives you the capability to store small bits of
data that you can then come and access at a later time.
| | 00:51 | Now I know though this isn't for storing tons of
data, there is a 10 MB limit per AIR application
| | 00:56 | for the encrypted local store, so only to keep that
in mind is you are planning your application.
| | 01:00 | Now we are going to extend our application that we
created previously that was the Contact Manager.
| | 01:05 | We are going to add some login functionality so
that not everyone can see our list of contacts.
| | 01:10 | And we are going to be storing the user
credentials inside of the encrypted local store.
| | 01:13 | So let's go ahead and open our application.
| | 01:17 | We are going to be in the Chapter 13 folder of
the exercise files and we are going to start
| | 01:21 | with ContactManager01 and then we will click Open.
| | 01:26 | Now if you will notice, if you are really
astute a few small things have changed.
| | 01:30 | First of all, we have added a new movie clip that we will be
working with called AddUser and it's a window that's going
| | 01:36 | to pop up and give you, the administrator
the ability to add a username and password
| | 01:40 | and then add that user to the encrypted local store.
| | 01:43 | Now to actually launch this window, we are
going to have to add a new button to the Stage.
| | 01:47 | And so we are just going to bring it a button and
place it on the Components layers and we are just going
| | 01:59 | to make this button the adduserButton and we
are going to also change the label to AddUser.
| | 02:09 | So now we actually can go in and begin to wire in our button.
| | 02:13 | So if we go to Actions, we can go to Window
and then Actions and view the Actions panel.
| | 02:19 | And I want to show you one thing so
that you don't think that I cheated.
| | 02:22 | We have already added in the code for launching
the window, we covered the Windowing API
| | 02:26 | in pretty good detail a few chapters ago.
| | 02:28 | So if you need this, code looks forward
to you, you can go back and check it out.
| | 02:32 | But basically we create a new window, we start with
creating a new instance of the NativeWindowInitOptions
| | 02:37 | and this is going to be a lightweight
window with no System Chrome.
| | 02:41 | And then we basically just positioned the
Window in the center of our current window
| | 02:45 | and then we also have configured some custom controls
that I will show you in a second on that movie clip
| | 02:50 | that will control the minimizing and closing of the window.
| | 02:53 | And then we finally just activate the window.
| | 02:57 | But we need to actually go ahead and add our event
listener, so let's go ahead and scroll up to the section
| | 03:01 | where we add our event listeners
and we are going to go ahead
| | 03:04 | and highlight the name before we head
up there for launchAddUserWindow.
| | 03:07 | And we will add in a new event listener,
we will say addUserButton.addEventListener
| | 03:18 | and then we will listen specifically
for the MouseEvent.CLICK event.
| | 03:25 | And then we will respond to it with the method that we
highlighted launchAddUserWindow, you can go ahead
| | 03:30 | and save our application and we can go back to the Stage
and now we are going to double-click on the AddUser movie.
| | 03:36 | The rest of the code that we are going to do for
this video is going to be inside of this movie clip.
| | 03:41 | Now you can see it's already got a couple
of layers, it's got to Display layer,
| | 03:44 | a Background layer and then an Actions layer.
| | 03:46 | We are going to want to notice the instance
name of this button, it's going to be addUser.
| | 03:50 | So we are going to want to be sure that we
reference that inside of our ActionScript.
| | 03:54 | And the plan is that you the administrator will
enter a username and password and then click AddUser
| | 03:58 | and then it will store that value
inside of the encrypted local store.
| | 04:01 | So let's highlight the Actions layers
and then go to Window and then Actions.
| | 04:06 | You can see that we already have
a few pieces of functionality.
| | 04:08 | We have imported the flash.data.EncryptedLocalStore
class as well as the flash.util.ByteArray class.
| | 04:15 | In addition, we have already configured a
button that will actually close the window.
| | 04:18 | This way the user can actually close the window if
they decide that they are done entering in users.
| | 04:23 | But now we need to actually wire it
together with the encrypted local store.
| | 04:26 | So we will go ahead and add an event
listener for our AddUser button.
| | 04:29 | We will say addUser.addEventListener.
| | 04:36 | We will listen for the MouseEvent.CLICK event and then
we will respond to it by calling the onAddUser method.
| | 04:44 | Now we will create a new method onAddUser and it will
receive an event of type MouseEvent and it's not going
| | 04:57 | to return anything so we can leave the return type as void.
| | 04:59 | Now what we are going to want to do inside of
here is take that username and password value
| | 05:04 | and pass it in to the encrypted local store.
| | 05:07 | The encrypted local store works by having a key that's
in plain text, you can then store value with that key.
| | 05:14 | When you go to retrieve it, you will give it the
key and it will give you back the data as well.
| | 05:17 | So in this case, we are going to use the username as
the key and then we are going to store the binary data
| | 05:22 | of the password inside of the encrypted local store.
| | 05:24 | So first we need to create a new
instance of the ByteArray class,
| | 05:28 | we will just call it BA for ByteArray
equals a new ByteArray.
| | 05:34 | And then we are actually going to
write the password into the ByteArray.
| | 05:41 | Now if you remember from what we talked about earlier
with ByteArrays, we can use the write UTFBytes method
| | 05:47 | to actually write data into the ByteArray that's in
the string format, so we will say ba.writeUTFBytes
| | 05:55 | and it will pass in the value of the password.
| | 06:01 | Now in this case, the two text inputs on the Stage are named
username and password, so we will pass in password.text.
| | 06:10 | So now we have actually created
our ByteArray and populated it.
| | 06:12 | Now we are actually ready to interact
with the encrypted local store.
| | 06:15 | Now the EncryptedLocalStore uses only static
methods, so we don't ever have to create an instance
| | 06:21 | of the EncryptedLocalStore class, but rather we
just use the actual static instance of the class
| | 06:26 | and we will say EncryptedLocalStore and then
we will use the setItem method when we want
| | 06:33 | to actually put a value into the EncryptedLocalStore.
| | 06:37 | Then first, it asks you for the key or the name for this
piece of data and so we are going to use the username
| | 06:42 | for that value so we will say username.text and then we want
to pass in the data which in this case will be a ByteArray.
| | 06:49 | Now we want to do one more thing when the user hits
AddUser, we want to go ahead and clear the username
| | 06:55 | and password field, so that they will know that it is
actually being entered into the encrypted local store.
| | 06:59 | So we will say username.text equals and that will set
it to a blank string and the same thing for password.
| | 07:06 | So now just with that amount of code,
we have actually created a custom window
| | 07:12 | that will let us store data inside of encrypted local store.
| | 07:15 | Let's test it out.
| | 07:17 | We go to Control and then Test Movie.
| | 07:20 | We see now that we have our AddUser button, we can
click our button and see that it displays our window.
| | 07:28 | We can now enter in the username, I will
enter in David and then for the password,
| | 07:32 | I will just enter in 12345 and then hit AddUser.
| | 07:36 | And then we can see that the values disappear and it's
actually been entered into our encrypted local store.
| | 07:41 | We now can close this window and
we are back to our application.
| | 07:45 | We will go ahead and close our application as well.
| | 07:47 | Now there is a couple other things to
know about the encrypted local store,
| | 07:51 | each application has its own encrypted local store.
| | 07:53 | In addition, the encrypted local store that an
application contains when it's being debugged
| | 07:58 | with the AIR Debug Launcher is not going
to be the same as when it's installed,
| | 08:02 | so you can't guarantee that values you set
during development will actually remain.
| | 08:06 | There needs to be a way for you to enter those pieces
of information after the application is installed.
| | 08:10 | So the encrypted local store is a great way for
storing data, but now we are actually going to need
| | 08:14 | to use it to extract data to validate our users.
| | Collapse this transcript |
| Retrieving data| 00:00 | Now that we can actually set data inside of
the encrypted local store we are not going
| | 00:04 | to want to be able to extract that data.
| | 00:06 | There is a lot of used cases for this.
| | 00:07 | In this case we are going to be using it as
a log in for our contact manager application.
| | 00:12 | But in addition you could use it if you are working
with some type of an API that required a username
| | 00:17 | and password you could store the credentials inside of
the encrypted local store as opposed to actually having
| | 00:21 | to store it in a file somewhere or inside of a database.
| | 00:24 | This way you know that the data is secure because it
uses the Nativeoperating system encryption algorithms
| | 00:30 | and actually stores the data in such a way that
it can only be accessed by your application.
| | 00:34 | So now let's go ahead and open our file if we go to File
and then Open we will then go to the ContactManager02 file
| | 00:41 | that can be found in the Chapter
13 folder of the exercise files.
| | 00:44 | Now you will notice that one thing has changed immediately.
| | 00:48 | I have just added a login window there is really not a whole
lot but we will go ahead and look and see what it contains.
| | 00:53 | Inside of this movie clip we have got
a username and a password text input
| | 00:58 | and then we also have a status dynamic text input
and then we have got a button called loginButton.
| | 01:05 | Now this already has an Actions layer and this is what we
are going to be doing most of our work so let's go ahead
| | 01:09 | and go with the Actions layer and then
just go to Window and then Actions.
| | 01:12 | Now I have already set up some of the code.
| | 01:14 | We have imported flash.data.EncryptedLocalStore
and we have imported flash.utils.ByteArray.
| | 01:20 | We also have already added an event listener for
our loginButton and now we are actually ready
| | 01:24 | to write the code for our onLogin function.
| | 01:27 | So the first thing that we going to want to do is we are
going to want to basically check the user name and password
| | 01:35 | and see if they match what's in the encrypted local store.
| | 01:37 | Now we are going to go ahead and create a new instance of
the ByteArray class, we will say var ba of type Byte Array.
| | 01:44 | Instead of creating a new ByteArray we are actually
going to extract our data from the encrypted local store
| | 01:51 | and that will return data in the byte array format.
| | 01:53 | So we will say EncryptedLocalStore and
then we are going to use the getItem method.
| | 02:00 | We used the setItem before it and now we use the getItem.
| | 02:04 | So now it's just going to want to know that one
piece of information that was the key or the name.
| | 02:09 | So in this case we can use username.text as that value.
| | 02:14 | This will look in, see if any pieces of data have been
stored under this key inside of the encrypted local store.
| | 02:20 | If it can find it, it will return the binary data
from the password into the ByteArray object.
| | 02:26 | Now we are going to want to check
and see if it returned anything.
| | 02:29 | If it didn't return anything then we will know that that
value was not stored inside the encrypted local store.
| | 02:36 | That would mean that you have not yet entered a user name
for that user and saved it in the encrypted local store.
| | 02:40 | So if that's the case if there is not
a ByteArray that is returned we know
| | 02:46 | that we can just tell the user we will set
the status.text value equal to User Not Found.
| | 02:58 | But if it does return the ByteArray then we can begin the
process of comparing the password that the user entered
| | 03:06 | with a password that's actually
in the encrypted local store.
| | 03:09 | So we are going to say var returnedPassword and
that's going to be a String. It's going to be equal to,
| | 03:19 | and we are going to set it equal to our
ByteArray, .readUTFBytes and then it's going to want
| | 03:27 | to know how many bytes it's supposed to
read and we will tell it to read all of them
| | 03:31 | by using the bytesAvailable property of the ByteArray.
| | 03:38 | So now this gives us the actual password that we'll store
| | 03:41 | in the encrypted local store where
we can actually do some comparison.
| | 03:45 | So now we'll add another if statement and we'll say if password.text
is equal to returnedPassword. If that's true then we know
| | 04:00 | that the password is correct and what we
will do is we'll just set this.visible = false
| | 04:07 | and this is what will hide the login window but we can then
say else and we'll set status.text = Incorrect Password.
| | 04:17 | So if everything works we should have now implemented
a login method for our contact application.
| | 04:27 | So let's review the process.
| | 04:28 | We first created a ByteArray and then we actually
pulled an item out of the encrypted local store based
| | 04:33 | on the username that the user entered on the screen.
| | 04:36 | Next we actually extracted the password data from
that byte array in string form and then we compared
| | 04:42 | that with what the user entered in for
the password field on our login screen.
| | 04:46 | So now let's go ahead and save our application
and we go to Control and Test Movie.
| | 04:50 | We will see that we are presented with the window to enter
in our login information and we can type in the password
| | 04:58 | that we have created before for me was David
and then for the password, 1, 2, 3, 4, 5.
| | 05:03 | And then we hit Login, I will see that indeed it works.
| | 05:07 | We are now able to login to the application.
| | 05:09 | And again this is all done using
comparison of usernames and passwords
| | 05:13 | that are actually stored within the encrypted local store.
| | 05:15 | Just a reminder if you are ever going to store sensitive
information whether it be user credentials or information
| | 05:20 | about the user that you don't want to have accessible to any
other applications your best method for storing that data
| | 05:25 | within AIR is going to be encrypted local store.
| | Collapse this transcript |
|
|
14. Invoking Your ApplicationUsing command-line arguments| 00:00 | Another way that you can connect your AIR application
with the operating system is being able to work
| | 00:04 | with command line arguments that
are passed into your application.
| | 00:07 | This can just give you another level of
communication between your application
| | 00:11 | and other applications running on the user's computer.
| | 00:14 | Now we are going to go ahead and open up the sample, we
will go to File and then Open and then we are going to look
| | 00:19 | in the Chapter 14 folder of the exercise files
and we are going to look at Contact Manager01.
| | 00:26 | This is the same application that we worked with in the
previous chapter except that I have made one change.
| | 00:30 | When we launched the application; the Login window
is actually going to be set to not be visible.
| | 00:35 | But we are going to go ahead and we
are going to go to the Actions layer,
| | 00:37 | we are going to go to Window and then Actions.
| | 00:40 | Now the important thing to know is that
every time an AIR application gets launched
| | 00:45 | or it has new arguments passed to
it, it receives an Invoke event.
| | 00:50 | This event has several pieces of information;
we are going to be focussing specifically
| | 00:54 | on the Arguments property of this event for this video.
| | 00:56 | So the first thing that we are going to do is
we are going to need to add an event listener.
| | 01:01 | Now when you want to listen for the Invoke event,
you are actually going to add an event listener
| | 01:05 | to the NativeApplication, so we will say
NativeApplication.nativeApplication.addEventListener
| | 01:13 | and we are going to listen for the
InvokeEvent.INVOKE and then we are going
| | 01:22 | to respond to this with the onInvoke method.
| | 01:26 | So let's go ahead down in our event handler section,
and we are going to add a new method, onInvoke.
| | 01:42 | Now our goal for this is going to be- we are going to want
to be able to launch the Add User window that we created
| | 01:47 | in one of the previous tutorials just
by passing in a command line argument.
| | 01:51 | So the Invoke event is going to
receive an event of type InvokeEvent.
| | 01:58 | It's not going to return anything, so we
can leave the return type equal to void.
| | 02:02 | Now we are going to want to examine
the arguments that are passed in.
| | 02:07 | Now the arguments are passed in under the event.arguments
property and it's actually passed in as an array.
| | 02:13 | When you enter in arguments, it's going to
consider each space to be at a delimiter.
| | 02:16 | So if you enter the line 'David is cool', just as
an example- you might think that, you might not-
| | 02:23 | but it would actually divide that into
three separate items within the array.
| | 02:27 | So that will be passed in as three different arguments.
| | 02:29 | So for this specific example, we are going to look
| | 02:31 | and see if the user entered the phrase
"add user" as the first argument.
| | 02:36 | So we are going to say if event.arguments, and then we
are going to look at the first argument which will be zero, equals
| | 02:46 | and then we are going to look for addUser.
| | 02:49 | Then we are going to want to call
the method launchAddUserWindow.
| | 03:01 | One other item just to notice,
you will notice that the argument
| | 03:05 | for the launchAddUserWindow method is actually configured
so that it can take a MouseEvent or by default it is Null.
| | 03:11 | So by launching it this way without
actually passing it an event,
| | 03:14 | we can still launch the window without throwing an error.
| | 03:16 | So now we can actually save our application and
now we are actually going to need to package it.
| | 03:22 | In all honesty, working with command line arguments inside
of Flash CS3 for AIR is a bit more difficult than dealing
| | 03:28 | with them for people that develop
AIR applications using Flex.
| | 03:32 | In this case, the easiest way to test your
application is to actually install the application
| | 03:36 | and then pass command line arguments that way.
| | 03:39 | You also can use the command line tools with ADL, the
AIR Debug Launcher but that becomes a bit more difficult.
| | 03:44 | So let's go ahead and go to Commands
and then create AIR file.
| | 03:48 | It's going to ask as for the certificate.
| | 03:51 | We have the same one that we used previously
and we will enter in the password of 12345,
| | 03:56 | again you chose a better password, we will
say OK and then it will take it a second
| | 04:00 | and it will tell us if the AIR file has been created.
| | 04:03 | So open back up, the Chapter 14 folder and you will see
that here is our application, we are going to go ahead
| | 04:08 | and double click it and that will
start the process of installing it.
| | 04:11 | We will say Install, and we will
just install it in the Program files.
| | 04:14 | It will say Continue.
| | 04:16 | It will say Installation Complete.
| | 04:19 | And here is our application, as I stated
earlier, for this specific purpose,
| | 04:23 | I went ahead and disabled the Login method,
so we can go ahead and close this application.
| | 04:29 | Now we are going to go ahead and go to the desktop.
| | 04:33 | You can see that we now have an icon for our application
and now we are going to open up the command line.
| | 04:37 | If you are inside of Windows, you can go to the Start
and then Run or in Vista, you can go to the Start Search.
| | 04:42 | We are just going to type in "cmd"
that will bring up the command line.
| | 04:46 | If you are on Mac, you are actually going to go
to the Terminal option to open up the Terminal.
| | 04:51 | Now we are actually going to find where our
application is installed, so in this case we are going
| | 04:55 | to change directory C:ProgramFiles and then
we are going to look for Contact Manager01.
| | 05:03 | Now we can actually list all the files in the
directory and we will see our executable file
| | 05:08 | which is going to be contactmanager01.exe.
| | 05:11 | Now if we just run this file without passing in any
arguments, it will actually bring up our application
| | 05:23 | and this is the way that the operating
system actually launches your application.
| | 05:26 | However, now if we go in and type
contactmanager01.exe, and just a quick note for Mac users,
| | 05:32 | your executable file will not be a .exe file ,but
you should be able to find your contactmanager01.app
| | 05:38 | and then you can launch it from there, besides
that everything should be fairly similar.
| | 05:42 | But now we are going to launch it and this time
we are actually going to pass in 'addUser.'
| | 05:46 | And when we pass this in, you will
notice that the window pops up.
| | 05:51 | Now the unique thing about this is, is this
can actually give you a layer of compatibility
| | 05:55 | between different programs on the same operating system.
| | 05:58 | Right now, AIR does not have the power to open up other
applications or to communicate with other applications,
| | 06:04 | but through this other applications,
it can actually pass information
| | 06:07 | to AIR applications if you have configured it that way.
| | 06:10 | So this is just another way to invoke your
application and then pass in data and arguments
| | 06:15 | that can be used within your application.
| | Collapse this transcript |
| Using AIR to open files| 00:00 | In addition to receiving onInvoke events
when applications are first launched as well
| | 00:04 | as when they are sent command line arguments
another time that they can receive arguments is
| | 00:08 | when they are called on to actually open a file.
| | 00:11 | In those cases they will receive an Invoke event
in which the first argument will be the path
| | 00:15 | of the file that they are called to open.
| | 00:17 | To illustrate this I have created a basic text reader.
| | 00:19 | This application should be able to actually display
any text file within this area in the middle.
| | 00:24 | However if I take the sample text file and
drag it over the application and then drop it
| | 00:29 | onto it the application launchers it is invoked but yet
nothing happens and so we are going to actually have
| | 00:34 | to configure our application for how to handle those kind
of Invoke events so let's go ahead and open up Flash.
| | 00:40 | We are going to go to File and then Open
and then we are going to open TextReader01
| | 00:46 | in the Chapter 14 folder of the exercise files.
| | 00:48 | Now we are going to go to the Actions layer.
| | 00:52 | We don't have anything in our Actions layer yet.
| | 00:54 | You will notice that on the Stage the only thing we have
is you have a text area with an instance name of text data
| | 01:00 | so we can now lock that layer and we can go to Window
and then Action that so we select the Actions layer.
| | 01:05 | Now we are going to need to import
a few classes to begin with.
| | 01:08 | We are going to go ahead and import flash.desktop.*.
| | 01:12 | We'll just import the whole package. That will have
NativeApplication and some other ones that we'll be using.
| | 01:16 | We are also going to want to import
the entire flash.filesystem package
| | 01:21 | as we will be working with FileStream, File and FileMode.
| | 01:25 | So the first thing we are going to need
to do is listen for the onInvoke event
| | 01:30 | so we'll say NativeApplication.NativeApplication.addEventListener
| | 01:37 | and we'll listen for InvokeEvent.INVOKE
and when that happens we will call onInvoke.
| | 01:44 | Now we are going to go ahead and create that method. Say
function onInvoke and then we will pass in the InvokeEvent
| | 01:53 | that the application receives and then we will return void.
| | 01:58 | Now inside of here we are going to want
to create a new instance of the File class
| | 02:03 | from the argument that's actually passed into
the application but first we want to ensure
| | 02:08 | that there are actually being arguments passed in.
| | 02:10 | If not we don't need to create a new instance of
the File class and attempt to read it so we will say
| | 02:15 | if event.arguments.length > 0 and we know
that we actually have been passed in arguments.
| | 02:25 | If not we can just let it pass
through and have nothing happen
| | 02:28 | so the first thing we will do is we will create a new
instance of the File class, we call it f. It will be equal
| | 02:33 | to a new file and then inside of the constructor
of the file we are going to pass event.arguments 0.
| | 02:40 | So we will pass the first event that's received.
Because if your application is ever called
| | 02:44 | to open a file the path will always
be passed in as the first argument.
| | 02:48 | Next we are going to need to create a
new instance of the FileStream class.
| | 02:52 | If you need more information on the FileStream class
you can feel free to go back and look at the chapter
| | 02:57 | that we did previously on the File system.
| | 02:59 | We will now create a new FileStream then after
that we are going to want to add an event listener.
| | 03:07 | This event will actually fire when the FileStream has
done reading a file and we will call it onComplete.
| | 03:13 | After we added the event listener we
are ready to actually open our file.
| | 03:17 | So we will open an asynchronous connection.
| | 03:21 | We will pass in the file and then we will tell it we wanted
to be in FileMode.READ because in this case we are not going
| | 03:26 | to be saving or writing over these files
we just want to be able to view them.
| | 03:30 | Now we can go ahead and create our onComplete method.
| | 03:37 | It will receive an event of type Event.
| | 03:39 | It's not going to return anything so we
can leave the return type equal to void.
| | 03:44 | Now the first thing we are going to do is actually
grab the FileStream from the event.target property
| | 03:49 | so we will say var fs of type
FileStream = event.target as FileStream.
| | 03:58 | Next after that we are actually going to extract the text
from the file and then set that inside of our text area
| | 04:07 | so we will say textData.text is going to be equal to FS,
which is our FileStream, .readUTFBytes and then we are going
| | 04:19 | to need to pass in the amount of bytes we
wanted to read and in this case we wanted
| | 04:22 | to read everything so we will say fs.bytesAvailable.
| | 04:26 | Finally we can close the connection from our FileStream.
| | 04:30 | Now we can go ahead and test our movie
before we package it as an application.
| | 04:37 | We will just go to Control and Test Movie and we
will see that the application launches without
| | 04:41 | and errors so we will close the application.
| | 04:44 | We will now go to Commands and then create AIR file
and then the AIR file will actually have been created
| | 04:50 | so we can now go to the Chapter 14 folder and then
in this case it be published as TextReader01.air.
| | 04:56 | You can double click the file and it will walk you
through the process of installing the application.
| | 05:00 | Now we can actually go back to the desktop and we can see
that we now have a TextReader01 option and that's going
| | 05:11 | to be our new application so we can delete the old shortcut.
| | 05:15 | We will drag our new one out and we should be able to
drag our sample text file on top of the application.
| | 05:20 | We will see that indeed it brings in the text file.
| | 05:24 | It just has a few words in it.
| | 05:26 | Now we can close our application and we can get something
a little bit more intense and the Apache Conf File
| | 05:32 | that we dealt within a previous video, even though it doesn't
technically end in a .txt format, it's still a text file
| | 05:38 | so we can drag that on top of the application
as well, open it up and we can see it will open
| | 05:43 | up the entire Apache Configuration File and
we can view it inside of our application.
| | 05:47 | Now this is very useful when you
are working with applications
| | 05:50 | that have specific file types that they normally deal with.
| | 05:53 | Now that you know how to respond to the Invoke event to open
a file you will now be able to create a custom file type
| | 05:58 | that the operating system will
associate with your application.
| | Collapse this transcript |
| Custom file types| 00:00 | Now that you can open a file by Invoke event this opens
up doors to what's possible with you inside of AIR.
| | 00:06 | In addition to being able to just open files AIR
gives you the capability to create custom file types
| | 00:11 | for your application that the operating system will
associate with your application so let's go ahead
| | 00:16 | and open up the text reader that we had created previously.
| | 00:19 | We go to File and then Open and we will
see TextReader02 in the Chapter 14 folder
| | 00:24 | of the exercise files and then we will click Open.
| | 00:26 | We will now go under Commands and then
AIR Application and Installer Settings.
| | 00:31 | Now we are going to spend some time
looking here under the Advanced Settings.
| | 00:39 | You can see here at the top we have associated file types.
| | 00:42 | Now if you want your application to work with a
certain file type by default you are going to need
| | 00:46 | to add it here inside of the Advanced Setting dialog box.
| | 00:49 | We want to add a new file type so we will
click plus and then we will give it a name.
| | 00:54 | Now since we are talking about the power of the API in
these circumstances we are just going to call it AIRAPI
| | 01:00 | for the name of the file type so we will say AIRAPI.
| | 01:03 | Now we have to give an extension, we are also going to
make the extension airapi. We will just keep it lowercase
| | 01:10 | and again here notice that we didn't
put the period before the extension.
| | 01:13 | We actually just used the later part.
| | 01:15 | We can give it a description we will call it air api text
file and then we will give it a content type. I happened
| | 01:23 | to know that the mime type is a plain
text file is going to be text/plain.
| | 01:27 | Now after you have entered all of that information
you can now setup an icon for your file type.
| | 01:33 | Now if you click on the folder to the right of each listing
it will open up a window where you can select an icon.
| | 01:39 | Now this works exactly like the icons for the application.
| | 01:42 | You request 4 different sizes.
| | 01:43 | If you look in the File icon's folder in the
Chapter 14 Exercise Files folder you will see
| | 01:48 | that I have some icons that we can already use.
| | 01:50 | Now I happen to know that this
one is the 128 so we can select
| | 01:53 | that for the 48 we will select the file that designates 48.
| | 01:57 | 32 will be the same and finally for 16.
| | 02:01 | So now we have created our custom file type and
now it will be attached to our AIR application.
| | 02:07 | Now there is another thing that we need to actually
set inside of our application so we will go back
| | 02:13 | to the Actions layer and we will go to Window and then
Actions and there is a command within NativeApplication.
| | 02:20 | We are going to NativeApplication.setAsDefaultApplication
and then we are going to want
| | 02:32 | to tell it what extension we want
to be the default application for.
| | 02:36 | Now here is a word of warning on this.
| | 02:37 | This doesn't work for just any file type you
have to have included this file type inside
| | 02:42 | of your application descriptor file in the AIR
Installer Settings dialog box for it to actually work.
| | 02:47 | For instance right here if I wanted to enter in PDF
that wouldn't work because I hadn't already registered
| | 02:52 | that inside of the application descriptor file
but here I can say "AIRAPI" and we can close it
| | 03:00 | and now the first time I launched my
application it will actually set this application
| | 03:03 | as the default for that file type.
| | 03:05 | Now in this situation there technically isn't an AIRAPI file.
| | 03:08 | It is really just a text file that we
are calling an AIRAPI file so I am going
| | 03:12 | to tactually go into Notepad and create a file.
| | 03:15 | So we will open Notepad, I will just say this is an
AIRAPI file and then we will save it we go to File
| | 03:26 | and then Save and then we go here onto to the desktop.
| | 03:32 | We want to be sure that we select all files and then we
will save it as sample.airapi and then we will hit Save.
| | 03:40 | So now we have saved our first AIR API file.
| | 03:45 | Now we can actually export our application,
we will first actually run it to be sure
| | 03:49 | that we don't have any coding errors
to see if it launches properly.
| | 03:54 | We can now go to Commands, Create AIR File.
It will tell us the AIR file has been created.
| | 04:00 | We can go into the Chapter 14 folder, take TextReader02
and double click it to begin the installation process.
| | 04:06 | We will say yes we want to install and we
will leave all the other settings the same
| | 04:10 | and there let's actually launch our TextReader02 file.
| | 04:15 | Now if we go back to the desktop we can already see that
our sample AIR API file has been registered with our icon
| | 04:24 | so that's one level of customization that you
already have available to you but in addition now
| | 04:28 | if we double click this file because our
application is registered as a default handler
| | 04:32 | for that file it will automatically open it up and you
can automatically read the data that's within the file
| | 04:38 | so setting your application to be the
default handler for this file enables you
| | 04:41 | to just double click the file and then open it.
| | 04:43 | So this is another powerful feature within AIR that gives
you the ability to have your own file types that can be used
| | 04:48 | with your application and again this doesn't mean you
have to go out and create some new way of storing data
| | 04:53 | but you can use something like a customize XML file to
store preferences for your application or to store data
| | 04:58 | for your application so that the user can
simply double click the file and install it.
| | Collapse this transcript |
| Launching an application at startup| 00:00 | Another way that you can invoke your application is by having
your application configured to start automatically when
| | 00:05 | the operating system starts up.
| | 00:07 | It's actually very easy to set this within your file.
| | 00:10 | So we are going to go to File
| | 00:11 | and then Open
| | 00:13 | and then we are going to open Text Reader03
in the Chapter 14 folder of the exercise files.
| | 00:19 | We are going to go to the Actions layer
| | 00:21 | and then we will go to Window
| | 00:23 | and then Actions.
| | 00:24 | The way that we actually tell the application to start
automatically at log in is to set a property on the instance of
| | 00:30 | NativeApplication.
| | 00:31 | So if we want an application to start at log in we can say
| | 00:35 | NativeApplication.nativeApplication
| | 00:39 | .startAt
| | 00:42 | Login = true. Simply by setting this value and then having your
application run, it will then be configured to start when the
| | 00:50 | operating system launches.
| | 00:52 | However, if you actually set the value to true and don't run
your application then it won't be registered. It actually
| | 00:57 | has to run and see that value set.
| | 00:59 | In addition, if your application is currently configured to run
at log in and you want to actually turn that off, you can actually
| | 01:05 | set startAtLogin = false.
| | 01:09 | And this can be very handy for applications
that users always want to have on their desktop.
| | 01:13 | For instance, maybe some type of an instant messaging
application or some type of an application that allows them to
| | 01:18 | keep track of what's going on with their
friends or other people around them,
| | 01:21 | and so this can be a very powerful tool.
| | 01:24 | However, you certainly never want to set this value without
giving the user some type of customization to turn it on or off.
| | 01:30 | And this is yet another way that you can invoke your application.
| | Collapse this transcript |
|
|
15. Updating AIR ApplicationsUnderstanding the updater| 00:00 | If you have created your first amazing AIR application
and now you have sent it all to your friends and then all
| | 00:05 | of a sudden you realize there is a big coding problem inside
of your application, you are going to want to find a way
| | 00:09 | to officially get an update out to each of those users.
| | 00:12 | If you are working in a big company and maybe
somebody discovers a security flaw in your application
| | 00:16 | and maybe the problem becomes even more urgent.
| | 00:19 | Included with AIR is the Updater capability, with this
you can actually, basically anywhere that you would
| | 00:25 | like configure your application to check for updates
| | 00:27 | and then update itself whenever it finds
that there is a new update available.
| | 00:31 | The great thing about this is that it frees the developer
| | 00:33 | up to include this functionality
in any way that they would like.
| | 00:36 | Now I have got a sample application right here that
will allow us to test the Updater functionality.
| | 00:41 | This way you can see what part of the process you
the developer can actually script and what part
| | 00:46 | of the process is automatically controlled by AIR.
| | 00:49 | We currently have Version 1 of this application, I am going
to highlight Version 2 and say that we want to update.
| | 00:54 | First, it is going to download the file and save it here
on the local computer then if everything works properly,
| | 01:00 | you will then tell the application to begin the
update process by telling it that you are currently
| | 01:04 | on Version 1 and want to go to Version 2.
| | 01:06 | So you can see that at the point after I click the Update
button, the application started downloading the file,
| | 01:11 | at that point AIR took over and actually
handled the rest of the update process.
| | 01:15 | After AIR was done updating the
file, the application launched again
| | 01:19 | and we can see that it has been updated to Version 2.
| | 01:21 | So we are going to begin integrating this
functionality into one of our applications.
| | 01:25 | So what I have done is I have created a folder under
XAMPP, under htdocs and under a new directory, update,
| | 01:34 | where I have an updated AIR file as well as an XML file.
| | 01:37 | So I am going to go ahead and open up the XML file.
| | 01:40 | And just so you know, both of these files are also
available in the Chapter 15 folder of the exercise files.
| | 01:46 | Inside of here is a very simple XML file, it defines
two settings for an update, the version and the location
| | 01:54 | and those are the two items that you will have
to have when you go to update your application.
| | 01:57 | So we will go ahead and close the XML file.
| | 02:00 | The first thing we are going to want to do is inside of
one of our AIR applications is we wanted to be able to go
| | 02:05 | and check this XML file to see if there
is a newer version of the application
| | 02:08 | than the version that they currently have installed.
| | 02:10 | So we are going to go ahead now and go to Flash
and begin developing this in our application.
| | 02:15 | Now once we are in Flash, we are going to go to File and
then Open and then we are going to open Text Reader01
| | 02:23 | in the Chapter 15 folder of the exercise files.
| | 02:25 | We are going to go to the Actions layer and then
we are going to go to Window and then Actions.
| | 02:32 | Now we are going to first create a
new function called checkForUpdate.
| | 02:43 | Now it's not going to take any parameters
and we can set the return type equal to void.
| | 02:46 | And what we are going to do inside of this method
is we are just kind of tell the application to go
| | 02:51 | and look at that XML file and bring the data back.
| | 02:53 | So we are going to create a new first URLRequest and we
are going to point it to the XML file, which in this case,
| | 03:05 | because I have installed it with XAMPP, it's
going to be under localhost/update/update.xml.
| | 03:13 | Now we are going to create a new instance of the
URLLoader, so we will say var loader of type URLLoader.
| | 03:21 | It is going to be equal to a new URLLoader.
| | 03:25 | Then we will add an event listener to listen for
when the file has been completely downloaded,
| | 03:30 | we will say loader.addEventListener and
will listen for the Event.COMPLETE event.
| | 03:38 | And now we are going to respond
with the onXMLLoadComplete method.
| | 03:53 | So now for the last step in this method, we are actually
going to tell the loader to begin loading the XML file.
| | 04:00 | So now we can copy this onXMLLoadComplete
name for the next method.
| | 04:04 | And now we are going to actually complete the method.
| | 04:10 | So we paste in onXMLLoadComplete, now
we will receive an event of type event,
| | 04:16 | but it won't return anything so
we can set that equal to void.
| | 04:20 | Now inside of this method, the first
thing we are going to do is we are going
| | 04:22 | to extract the URLLoader from the event.target.
| | 04:25 | So we will say var loader of type URLLoader is
going to be equal to event.target as URLLoader.
| | 04:35 | Now once we have that, we are going to go ahead and extract
the XML data from the loader, so will say var xmlData
| | 04:44 | of type XML is going to be equal to. And then we
wanted to create a new XML object from the text data
| | 04:49 | that was downloaded, so we will say XML
and then we will pass in loader.data.
| | 04:54 | Now we are going to want to extract those 2 pieces
of data that were contained in the XML file.
| | 05:01 | So we will first say var updateVersion and that's going to
be a String. It's going to be equal to we will say xmlData
| | 05:13 | and then it actually was inside of a tag called Update, and
we are going to want the first tag and then we are going
| | 05:20 | to go and find the attribute that was, Version.
| | 05:25 | So by using that code, we can obtain the application version
of the update, and then we will create one more variable,
| | 05:30 | UpdateFile, and that can be found
by looking at xmlData.update
| | 05:41 | and then also finding the first
value and then looking for location.
| | 05:47 | Now we are going to actually place a trace statement at
the end and it will say "Check to see if it is accurate."
| | 05:54 | So this way we actually can know that
when we need to go into our debugger,
| | 05:59 | I am going to put a breakpoint right there
at line 35 and we are going to go ahead
| | 06:03 | and call this checkForUpdate method
as soon as the application launches.
| | 06:07 | So now we can save it.
| | 06:11 | We will check over our code and make sure that everything
looks good and then we will go to Debug, Debug Movie.
| | 06:16 | First it tells us we have an incorrect number of
arguments, we look at line 28 and indeed we forgot
| | 06:23 | to pass the URLRequest into the Loader.load method.
| | 06:26 | So we will add that and now we can
hit Save and go to Debug, Debug Movie.
| | 06:35 | We can see now that it stopped at our breakpoint,
| | 06:38 | we can see that it's already grabbed the XML
data, we can see the entire XML data here.
| | 06:42 | Well we can see that our value for update version has been
set to 2.0, which was the same value that was contained
| | 06:48 | in the XML file and the UpdateFile variable has been set
to localhost/update/update.air which also is correct.
| | 06:56 | So now that we have got this data, we can now interact
with the update functionality included with the Adobe AIR.
| | Collapse this transcript |
| Retrieving an update file| 00:00 | In continuing to work with the update functionality within
AIR we are going to learn how to actually take a file
| | 00:05 | that exists somewhere else we are
going to download it and we are going
| | 00:08 | to save it as our file on our local file system.
| | 00:10 | Now this is important because with AIR with the updater
you can't just say go update my application at this URL
| | 00:16 | that wouldn't be a good idea for a lot of different reasons.
| | 00:19 | But what you actually have to do is you have to take
that file from the URL and save it on your local computer
| | 00:23 | and then you can actually pass that into the updater.update
function along with the new version of the application.
| | 00:29 | So to accomplish this we are going to need to look at a few
other properties within AIR and we are also going to need
| | 00:33 | to utilize some of the file system
methods that we learned previously.
| | 00:36 | So let's go to File and then Open we will now open
TextReader02 in the Chapter 15 folder of the exercise files
| | 00:47 | and now we are going to actually go to the Actions
layer and we will go to Window and then Actions
| | 00:55 | and we can now actually begin the
process of downloading the update file.
| | 00:59 | Now we are going to change a few things around within
the code that we just wrote to check for the update.
| | 01:04 | First we are going to actually make the
location of the update file an actual property
| | 01:09 | that will be available throughout the whole application.
| | 01:11 | So we will create a new section
in our code here for Properties.
| | 01:19 | And we will say var updateURL is
String, we won't set its value yet.
| | 01:25 | We will also make the updateVersion a
property and it also would be a String.
| | 01:33 | We can go down to our onXMLLoadComplete method
and we will change the value for these two
| | 01:39 | to just be updateVersion, we don't
need that, and then updateURL.
| | 01:47 | So those values will now be set after
we would run the checkForUpdate method
| | 01:53 | and then the onXMLLoadComplete method response.
| | 01:57 | Now at this point we are going to go ahead and assume
that we are going to be downloading the update.
| | 02:01 | We will actually do some calculating in the next video to
determine if we need to download the update and then what
| | 02:05 | to do with it after we actually finish that.
| | 02:07 | But we are going to go ahead and have a function called
startUpdate that will actually begin downloading the file.
| | 02:14 | So now the first thing that we are going to need to
do is we are going to create a new URLRequest object
| | 02:23 | with the URL inside of it so we will say var req is
a URLRequest= new URLRequest and then it is willing
| | 02:33 | to pass in the URL which is just updateURL.
| | 02:36 | Now after we have actually created that we are going to
need to create a new instance of the URLStream class.
| | 02:44 | Now at this point we are going to also create two new
properties that will help us in the update process.
| | 02:48 | So just as we created updateVersion
and updateURL we can scroll back
| | 02:52 | up to the top then we can actually add var
stream which should be of type URLStream.
| | 03:01 | We will also create var fileData which should
be of type ByteArray and now we can go down
| | 03:10 | and continue working with our startUpdate method.
| | 03:13 | So first we will say stream is equal to a new URLStream.
| | 03:17 | And then next after that we will say fileData
is going to be equal to a new ByteArray.
| | 03:25 | Now we are going to need to add
an event listener so that we know
| | 03:30 | when this URLStream has actually finished downloading the
file so we will say stream.addEventListener we will listen
| | 03:40 | for the Event.COMPLETE event with
the onDownloadComplete method.
| | 03:45 | Now after we have added the event listener for the stream
we actually can begin the process of downloading the file
| | 03:55 | so we will say stream.load and then we
will actually pass in the URLRequest req.
| | 04:01 | Now when you create our onDownloadComplete method
so we will go down to create one more new method
| | 04:07 | and say function onDownloadComplete within this
method or receive an event that will be of type Event
| | 04:15 | and we can just set the return type equal to void.
| | 04:20 | Now we are actually going to need to take the data
from the URLStream and pass it into our Byte Array,
| | 04:25 | so first we will say stream.readBytes and then
we will want to tell it first where we wanted
| | 04:35 | to read it into and so we will say file data.
| | 04:37 | Next we wanted to tell where we wanted to start
reading the bytes from and we will just say 0
| | 04:43 | and then they will ask us how much do you
wanted to read and we will say that we wanted
| | 04:47 | to read all of it by saying stream.bytesAvailable.
| | 04:49 | Next we are going to want to actually create a new file
reference on the file system so we will say var updateFile
| | 04:58 | of type File is equal to
File.applicationStorageDirectory.resolvePath
| | 05:09 | and it will actually pass in the name update.air.
| | 05:15 | So once it actually creates this
file object it will create a file
| | 05:19 | in the Application Storage Directory named update.air.
| | 05:22 | Now, we will need to create a new
FileStream object as we have done in the past
| | 05:25 | to actually pass these bytes into the file.
| | 05:27 | So, we will say var fs of type FileStream,
this is going to be equal to a new FileStream.
| | 05:34 | Now, we will need to create an
event listener we will say fs.addEventListner.
| | 05:40 | We want to listen specifically for the
Event.CLOSE event and this will tell us
| | 05:45 | when the FileStream has actually
completed writing the bytes into the file
| | 05:48 | and then we will actually call the performUpdate method.
| | 05:51 | Now, we need to actually open a connection to the
file, so we will say fs.openAsync and then we will want
| | 06:00 | to actually pass in the reference to
the file, which will be updateFile,
| | 06:05 | and then it will tell it what mode it will be FileMode.WRITE
because we actually be writing data to the file.
| | 06:16 | Finally, we will use the fs.writeBytes
to actually write data into the file.
| | 06:22 | We will actually tell it to put the fileData and we will
start at 0 and we will actually go to fs.bytesAvailable.
| | 06:30 | Now, finally once it's actually done right in that data, we
can just call fs.close and because we are using async here,
| | 06:41 | we can actually wait until it's done before
we actually perform any additional options.
| | 06:45 | So, now let's actually create the next method which will
be performUpdate, we are not going to implement this method
| | 06:50 | in this video, but we are going to actually
see that we can actually download the file.
| | 06:54 | So, we will actually say performUpdate,
it will receive an event of type Event,
| | 07:00 | we will set the return type equal to void.
| | 07:05 | So, now we will go ahead and put a breakpoint
at line 64 here and I will actually put
| | 07:09 | in a Trace statement here, so we know. 'Testing download.'
| | 07:13 | And now just so that we can actually see how
things work instead of actually storing this file
| | 07:22 | on the Application Storage Directory, we will
temporarily store it on the desktop directory.
| | 07:27 | So, now we can save our application and we
actually can go to Debug and Debug Movie.
| | 07:33 | Actually, before we debug our movie we need to do one
more thing, at the end of the onXMLLoadComplete method,
| | 07:40 | we are going to go ahead and call the startUpdate method.
| | 07:44 | This way these are actually chained together, so as
soon as we download the information about the XML file,
| | 07:48 | it will actually start downloading the file.
| | 07:49 | So, now let's go to debug and Debug Movie.
| | 07:52 | It will first tell us that we actually
have an undefined property and it seems
| | 07:57 | as though I have just actually entered in, here we go,
actually entered in the wrong name for the property.
| | 08:02 | We can now save it and now we can go to Debug
and Debug Movie and now once we debug our movie,
| | 08:12 | we will see that there is one small little problem.
| | 08:14 | We actually have one small problem we will
need to fix in our onDownloadComplete method.
| | 08:17 | So, let's go ahead and end our debug session. We
close the Compiler Errors window and the problem is,
| | 08:22 | is that here we have actually used the
fileStream.bytesAvailable, but that's not what we want to do
| | 08:27 | because we are not going to want to use
the fileStream.bytesAvailable property,
| | 08:30 | instead we are going to want to take the binary data that
we are actually writing in and we are going to want to use
| | 08:35 | that as determining how many bytes we want to read in.
| | 08:38 | So, we will actually say, fileData.bytesAvailable.
| | 08:47 | Now, if we debug our application, we will now see
that it stops at our breakpoint at performing update
| | 08:59 | and if we end our debug session
and actually go to the desktop,
| | 09:02 | we can see that indeed our AIR file has been downloaded.
| | 09:04 | We can right click to see the properties and see that we
have actually downloaded roughly 53.5K and actually saved it
| | 09:11 | to the desktop using the URLStream,
the FileStream and the ByteArray classes.
| | Collapse this transcript |
| Performing an update| 00:00 | So in this lesson, we are actually
going to work specifically
| | 00:03 | with the Updater.update method to
actually perform the AIR update.
| | 00:07 | We are also going to learn how to
look and find the application version
| | 00:10 | of the current application that we are running.
| | 00:11 | We are going to use all that together to
determine when we need to download an update
| | 00:15 | and then we will actually finish the update by performing
it and actually having AIR install our new version.
| | 00:20 | So, let's go ahead and open up the file we will be
working with, which is going to be Text Reader03
| | 00:26 | in the Chapter 15 folder of the exercise files.
| | 00:29 | Now, well be sure that the Actions layer is
selected and we will go to Window and then Actions.
| | 00:36 | We will scroll down to where we actually had the
PerformUpdate method, because we just had a trace statement
| | 00:45 | in here, so we could test and see that
the application had properly downloaded.
| | 00:49 | However, in this place, we are actually going to perform
the application update, so to do this we are going
| | 00:54 | to create a new instance of a new
class, we haven't yet dealt within AIR
| | 00:57 | and that's going to be the actual updater class.
| | 00:59 | So we will say var updater:Updater = new Updater.
| | 01:08 | Now, at this point all we actually have to do is called
the Updater.update method and then we will need to pass
| | 01:18 | in two things, first is going to be the update file.
| | 01:21 | Now, we happen to know that our file, we
actually already defined here as updateFile. Now,
| | 01:27 | to make this easier so that we can
access this from this method as well,
| | 01:31 | we are actually going to convert
updateFile into a property.
| | 01:34 | We will delete the var keyword before and we will
scroll up and we will say var updateFile:File.
| | 01:43 | We actually set the value in the onDownloadComplete method
and now we actually use that here, we will say updateFile.
| | 01:57 | And then the only thing we have left to do
is to actually pass in the update version.
| | 02:08 | So, now we actually have performed the update from
beginning to end just with the code we have here.
| | 02:14 | However, there is a problem, we are not going to want
| | 02:16 | to download the update file every
single time we launch our application.
| | 02:20 | There is going to be times when
we have the most current version.
| | 02:23 | So what we need to do now is we need to actually develop
a method that will tell us if we even need to update,
| | 02:29 | it will actually look at the XML file and it will
compare the version from the XML file to the version
| | 02:34 | that actually is available on our local system.
| | 02:37 | So, let's actually scroll up to
the onXMLLoadComplete method.
| | 02:43 | Directly, below here we are going to create a new
method called checkStatus that will check the status
| | 02:48 | of our application and see if we need to download a new one.
| | 02:51 | This will be a method that does not receive
any events and it won't return anything,
| | 02:56 | so we will set the return type equal to void.
| | 02:58 | The first thing we will need to do is determine the current
version of our application, this actually is not available
| | 03:04 | as a property of the NativeApplication
class as you might thing.
| | 03:07 | However, inside of the NativeApplication
class there is your application descriptor file
| | 03:12 | that is actually brought in as XML data.
| | 03:14 | So, we actually can access that by saying var, we will
create a variable called AppXML it will be of type XML
| | 03:21 | and we will set that equal to
NativeApplication.nativeApplication.applicationDescriptor.
| | 03:31 | And as I stated earlier, that's your actual
ApplicationDescriptor file in XML form that was created
| | 03:39 | with your application that was the file
that we edited with the AIR Application
| | 03:43 | and Installer Settings inside of Flash CS3.
| | 03:45 | Now, we are going to actually need
to look into this XML file.
| | 03:49 | However, this XML file uses something called namespaces,
so to ensure that we can actually view the right tags,
| | 03:55 | we are just going to need to be sure that
we are looking at the default namespace.
| | 03:58 | So, we can do that by saying var air,
we are going to call this a Namespace,
| | 04:03 | it's going to be equal to appXML.namespaceDeclarations and
then we are just going to call the method and it's going
| | 04:13 | to return an array and we are just going to say that
we want the first of the namespace declarations.
| | 04:18 | Now, if you are not familiar with XML namespaces, don't
worry about it, right here we are basically just saying,
| | 04:23 | we just want to use whatever is default for this document
| | 04:26 | and now we can easily determine what our application version
is by saying appXML, which is the name of our XML object
| | 04:34 | that we got earlier and then saying .air,
which says what namespace we are going to use
| | 04:39 | and then we actually can just use
two colons and then say version
| | 04:42 | and this will actually return the
version of our application.
| | 04:45 | Now, just to test this, we will actually set this
equal to another variable, we will say var version,
| | 04:51 | which will be a String, will be equal to that and
then we will actually add a trace statement below
| | 04:56 | and we will say "Check if it's accurate," just to
remind us what we are actually debugging for.
| | 05:04 | So now we can actually put a breakpoint here and now
on the XMLLoadComplete instead of calling startUpdate,
| | 05:11 | we are just going to call checkStatus,
then we can actually save our application.
| | 05:19 | And now that we have this breakpoint set, we will go and
actually check and see what our application version is.
| | 05:24 | Currently, it's version 1.0, so we will click OK.
| | 05:32 | Now, we actually can test by going at Debug and Debug Movie.
| | 05:41 | And here we can see that indeed version was set as 1.0,
| | 05:44 | so we are being able to properly
read in our application version.
| | 05:48 | So, now we are going to want to put one
extra item on the Stage of our application.
| | 05:51 | We are going to put a button, we are going to go to the
Components window and we are going to unlock Layer 2 here
| | 05:58 | and then we are going to drag a button onto the Stage, but
first we need to be sure that we have Layer 2 selected.
| | 06:03 | Then we will just drag the button onto the Stage and then
we will actually give this an instance name of updateButton
| | 06:11 | and then we will actually go under Parameters,
we will change the label to say Update
| | 06:18 | and we will set the enable property once we get into
the ActionScript to false, because we don't want this
| | 06:23 | to be an option that's normally there, we want this to be a
button that's only enabled when we actually need to update.
| | 06:28 | So, we will now relock Layer 2, we will go to the Actions
layer, we will go to the Window and then go to Actions.
| | 06:36 | So, up where we declare our properties, we are also going
to say updateButton.Enabled is going to be equal to false.
| | 06:45 | Now, we are going to back down to our checkStatus method and
we are going to say if version does not equal update version
| | 07:01 | in other words, if the version that's on the update side
does not equal our current version then we are going
| | 07:06 | to actually enable the Update button.
| | 07:14 | In addition, we are going to use the Update
button to actually trigger the startUpdate Method.
| | 07:19 | So it will now receive an event, MouseEvent and then we just
need to actually go and add in our event handler up above.
| | 07:27 | We will say updateButton.addEventListener and we
will actually listen for the MouseEvent.CLICK event
| | 07:39 | and then we will actually call the
method below, which is StartUpdate
| | 07:47 | and that will actually start the download process.
| | 07:57 | And now we can click Save.
| | 07:58 | So now let's actually test the
application and we will see what happens.
| | 08:03 | We will go to Control, Test Movie.
| | 08:06 | We can see now that the button
was not enabled and now it is.
| | 08:17 | If I went to the actual XML file, under XAMPP
and then under htdocs and then went under Update
| | 08:26 | and I actually change the value from
2.0 to 1.0 and then save the XML file
| | 08:33 | and then I went back and tested the movie again.
| | 08:36 | You can see that now it would be disabled and
it would stay disabled, because it's determined
| | 08:42 | that we actually have the most
current version of the application.
| | 08:45 | Now, the last thing that we are going to do before we
actually update our application is we are actually going
| | 08:52 | to package a version of our application as version 2.0
and put it on the server, because one of the things
| | 08:56 | that you have to understand is AIR actually has some
limits on how the update functionality can be enabled.
| | 09:01 | It wants to be sure that both of the applications have the
same Application ID. Let's go to Commands, AIR Application
| | 09:07 | and Installer Settings and let's make this version 2.0.
| | 09:12 | Now, even though most of the times you will see numbers for
that value, the application actually reads them as strings,
| | 09:17 | so for instance Version 3 doesn't necessarily mean that
it's newer than version 2, you can choose a naming scheme
| | 09:23 | for your application versions that will be
whatever you would like and then just be sure
| | 09:26 | that you are consistent in the way that you implement it.
| | 09:28 | So now we have created our AIR file, which
can be found under the exercise files.
| | 09:32 | And now that the file is being packaged, we
will actually take the file and we will copy it
| | 09:48 | into the same directory with our XML file.
| | 09:52 | We will actually delete the old update.air
file and we will rename this one Update.
| | 09:58 | Now we can close that window and we will go back in, we
will now change our current application version to 1.0
| | 10:09 | and we will say OK and that will create another
packaged version of our AIR application and it will say
| | 10:18 | that the AIR file has been created and now
we will actually install our application.
| | 10:23 | We will say Install.
| | 10:28 | Now we will actually go back to our XML file, we will change
the version back to 2.0, which is the version of the file
| | 10:38 | that we actually uploaded to this directory
| | 10:41 | and then we re-launch our application,
we will actually go to the desktop.
| | 10:44 | We will re-launch Text Reader03.
| | 10:47 | We will now see that the Update button is enabled.
| | 10:50 | If we press the button we will actually begin
the update process and AIR will actually carry us
| | 10:55 | through the rest of the installation and there we go.
| | 10:59 | Now we have the most up-to-date version, version 2.0.
| | 11:01 | You should be very careful, anytime you distribute
an application to include some form of update
| | 11:06 | with the application, if you choose not to, you
could run into the possibility that many of the users
| | 11:10 | of that application are going to have out-to-date versions,
they might have security flaws or they might just not have
| | 11:15 | that kind of functionality that you want in your
application and because of that, once you actually put it
| | 11:20 | out without an updater, there is no way
to bring it back, it's already out there.
| | 11:23 | So, if you take some time and implement the Update
functionality in your application then you can ensure
| | 11:28 | that the users are going to have the best experience
that you can offer through your application.
| | Collapse this transcript |
|
|
16. Using Advanced TechniquesClosing an application gracefully| 00:00 | There will be times when you create applications
| | 00:02 | that you will want to keep windows for the entire applications from
closing until you have had a chance to actually do some cleaning up.
| | 00:08 | In these situations you can listen to events that are dispatched
by both NativeWindow and NativeApplication to perform
| | 00:14 | some last minute cleanup
| | 00:15 | to save things like preferences or to save the application
state before the application actually closes.
| | 00:20 | So we are going to illustrate this with the
Contact Manager, so let's go ahead and open the file.
| | 00:24 | We are going to go to File and then Open
| | 00:26 | and then we are going to open ContactManager01
in the Chapter 16 folder of the exercise files.
| | 00:32 | We are going to go ahead and test the movie,
| | 00:36 | and you will see here that we have our window that's popped up.
| | 00:39 | Now what we are going to look at specifically
is we are going to click the Add User button
| | 00:42 | and that will bring the Add User window to the front.
| | 00:45 | Now,
| | 00:46 | as we have discussed before we can enter in a username and
a password that will be added to the encrypted local store,
| | 00:51 | such as David.
| | 00:52 | And then 12345 if we wanted to,
| | 00:55 | and then we can press
| | 00:57 | Add User and it would actually save the user.
| | 00:59 | However, in this case, what if somebody actually entered in
the username and password and then chose to close the window.
| | 01:04 | You can handle that in a lot of different
ways you can prompt the user for an alert.
| | 01:07 | But there is a way to illustrate this functionality, if there is
actually a value still present in the username and password when
| | 01:13 | the user goes to click the field,
| | 01:14 | it will actually store that value inside of the encrypted local store.
| | 01:18 | So let's go ahead and close the application.
| | 01:20 | We are going to go to the Add User movie clip,
| | 01:23 | and we are going to open up Actions.
| | 01:26 | So it will highlight the Actions layer and then go to Window
| | 01:28 | and then Actions.
| | 01:30 | Now there are a couple of important things
to know about the way the windows work.
| | 01:33 | First,
| | 01:34 | when a window is closing, it always dispatches a closing
event, so other objects within the application can actually
| | 01:40 | listen for that event.
| | 01:41 | You can also call the method preventDefault to prevent the
window from actually closing to give you an opportunity to
| | 01:46 | perform some actions.
| | 01:48 | Now generally most of the cleanup should
always be done by the window itself.
| | 01:52 | So if the window listened for its own close event
then it can perform actions before it actually closes.
| | 01:57 | And one additional note on this.
| | 01:58 | When you're working, when you're doing this type of clean up operations
right before a window or application is getting ready to close,
| | 02:04 | you can only use synchronous methods.
| | 02:07 | So if you're doing anything with the file system or anything with
the database you're going to have to use synchronous programming
| | 02:12 | because there's no way for sure here that we can know
| | 02:14 | that our asynchronous methods would actually dispatch their
events before the application actually closed. So let's go
| | 02:19 | ahead and listen for the closing event here within this window.
| | 02:22 | We will say stage.NativeWindow,
| | 02:25 | which is the way that we get an access to
the NativeWindow inside of a movie clip,
| | 02:29 | then we will say addEventListener,
| | 02:31 | it will listen specifically for the Event.CLOSING event.
| | 02:35 | And then,
| | 02:36 | we will actually call the onWindowClosing method.
| | 02:40 | Now don't get just confused with the actual Close event.
| | 02:43 | The Close event is dispatched when the window is already closed.
| | 02:46 | So if you are listening for that event in hopes of doing
some cleanup, you are probably going to be out of luck
| | 02:50 | but the closing event is dispatched before the Close event.
| | 02:54 | So now we are going to create a method, onWindowClosing,
| | 03:03 | and it'll receive an event
| | 03:05 | of type event.
| | 03:08 | And it's not going to return anything
so we can leave the return type as void.
| | 03:12 | Now here inside of this method.
| | 03:13 | As I stated we were going to want to
actually execute the onAddUser method
| | 03:17 | and you can see I have already actually made
the default value for this event equal to null
| | 03:22 | so that it can be called either as an
event handler or just as a regular method.
| | 03:26 | So in this case we are going to check and see if username
| | 03:30 | .text
| | 03:31 | .length
| | 03:32 | and of course this will return "true"
if the length here is greater than 0,
| | 03:35 | and if password
| | 03:39 | .text
| | 03:40 | .length,
| | 03:42 | which also would do the same.
| | 03:44 | So basically we want to see, did the
user enter something into both of those?
| | 03:48 | If they did, then we are going to go
ahead and call the onAddUser method.
| | 03:54 | By doing this we can actually do some last
minute cleanup before the window closes.
| | 03:58 | So even if they click the Close button we can still
be sure that those items get put into the local store.
| | 04:03 | In addition, windows are not the only things that dispatch events.
| | 04:07 | The NativeApplication actually dispatches an event as well.
| | 04:10 | So if we were to go back over to our root movie,
| | 04:14 | and go to Window and then Actions,
| | 04:17 | we then can go to our event handler section and we can actually
add an Event Listener to the NativeApplication. We can say
| | 04:23 | NativeApplication.
| | 04:25 | nativeApplication.
| | 04:27 | addEventListener
| | 04:30 | and we are going to listen here in
this case for the Event.EXITING.
| | 04:34 | This works in a very similar way to what it does for the window
and that the exiting is actually dispatched before the actual exit is.
| | 04:41 | So in this case we can listen for
the onApplicationExit method,
| | 04:45 | and perform any clean up that needed
to be performed. In this specific instance,
| | 04:49 | we don't have anything that needs to be performed at this time.
We can consider possibly syncing the data from the server
| | 04:55 | and actually putting in the database before the application closed
| | 04:57 | but there would be a couple of problems with that.
| | 04:59 | First of all we can only use synchronous methods
| | 05:02 | and we would actually have to do about a 1000 queries. Now this can
create a problem for the user if they're having to wait for the
| | 05:07 | application to close during that time, they would be much more
likely here to actually find a manual way of closing your application
| | 05:12 | before it's actually completed, and so that can be a problem as well.
| | 05:15 | You generally want to keep your items that you do
in cleanup before a window or an application closes
| | 05:20 | as short as possible so as to not
degrade the experience of the end user.
| | Collapse this transcript |
| Supporting multiple monitors| 00:00 | There are going to come times as you develop AIR
applications, where you are going to want to know more
| | 00:04 | about the monitors that the user
is using to view your application.
| | 00:07 | You might want to know this so that you can know
where to best position your window on the screen.
| | 00:11 | You might want to know this, so that you know which
screen is the main screen and you might also want
| | 00:14 | to know some other information, such as the
actual bounds of the monitors themselves.
| | 00:19 | So we can find out a lot of these things
by using the Screen class inside of AIR.
| | 00:23 | So if we go to File and then Open, we are
going to open the Screen Analyzer01 file
| | 00:29 | in the Chapter 16 folder of the exercise files.
| | 00:32 | We are now going to go to the Actions layer and
first we will actually take a look at the Stage.
| | 00:37 | We just have basically a skin of an application with
one big text area in the middle and then a button
| | 00:41 | with an instance name Analyze button, but it's actually
going to be used as the trigger for analyzing the monitors.
| | 00:49 | So now if we go back under Actions
and go to Window and then Actions,
| | 00:54 | we actually begin now to analyze the
monitor structure of the current computer.
| | 00:58 | Now again if you run this application, you
will probably get different results from me.
| | 01:02 | We probably have different screen sizes
or you might have multiple monitors,
| | 01:05 | but what this will do is this will allow you to get
the information you need as a developer to know enough
| | 01:09 | about the user screens to where again you can fully
take advantage of positioning for your application.
| | 01:13 | So the first thing that we are going to do is we are going
to utilize a property of the Screen class called Screens
| | 01:20 | that contains an array of each of
the different screen references.
| | 01:23 | So we actually can look through that, but first we are
actually going to add an iterator to say i, it's a uint,
| | 01:30 | will be equal to 1 and then we will say for each
var screen of type Screen in Screen.screens.
| | 01:43 | Now we actually can use this to get some
information about each of the screens.
| | 01:47 | Each of the instances of a Screen class
contains information on the bounds
| | 01:51 | which includes the x and y as well as the width and height.
| | 01:54 | That also contains other pieces of
information such as the color depth.
| | 01:57 | So let's try to get as much information
as we can about each monitor.
| | 02:03 | We will start off by declaring what monitor it is.
| | 02:05 | We will say monitor and then will add in the iterator that
we created earlier, then outputText.text += and then we want
| | 02:15 | to find out the width and we can
pass in screen.bounds.width.
| | 02:23 | We actually can copy that line and do the same
thing again for the height, screen.bounds.height.
| | 02:33 | Finally, we are going to just copy down some
of the information about the color depth
| | 02:38 | so we actually can copy this line one more time
and we will say color depth and then we want
| | 02:45 | to actually have a reference to screen.colorDepth.
| | 02:48 | Now the last thing that we will do is to add a
little bit of space at the end of each of these.
| | 02:52 | We will just add a new line indicator and
then we can paste that to the end of each.
| | 03:01 | And we will actually add a couple of
new line indicators at the end as well
| | 03:04 | so we can separate the information
about our multiple monitor.
| | 03:09 | Now let's see what we found out about our screens,
so we can go ahead to save our application
| | 03:14 | and we can go to Control and then Test Movie.
| | 03:17 | Oops and it's going to tell us we actually
have an undefined property here of output text.
| | 03:21 | If we go back to the Stage, we highlight the text of
output area so we will just change this to output text
| | 03:31 | and then we will go to Control and Test Movie.
| | 03:37 | Now here we can actually press the Analyze button
and we will get back information about the monitor.
| | 03:42 | Now I currently only have one monitor setup, but if you
have multiple monitors you will see information come
| | 03:46 | through about each of these.
| | 03:48 | So we can see here that this is monitor 1 with a width
of 10x24 and a height of 768 and a color depth of 32,
| | 03:54 | but these aren't the only properties that
you can use with your AIR application.
| | 03:58 | In addition, there is also the screen.mainscreen which is
a reference to the operating system designated main screen.
| | 04:05 | So you can be sure if you have positioned your
application on the main screen that is actually
| | 04:09 | in the prime place for the user to see it.
| | 04:11 | In addition you also can measure the entire bounds
of all of the monitors together to get an idea of how
| | 04:16 | to position elements that might need to flow horizontally
or vertically depending on the user's monitor alignment.
| | Collapse this transcript |
|
|
17. Distributing AIR ApplicationsInstalling a local web server| 00:01 | When working with the samples for distributing
your AIR application it is going to be beneficial
| | 00:05 | to install a development web server on your local computer.
| | 00:08 | Some of the samples won't actually run properly if you
are just running them directly from your hard drive.
| | 00:12 | Now if you are using Windows, one of
the best solutions is to use XAMPP.
| | 00:17 | And you actually can find that at
apachefriends.org/en/xampp.html.
| | 00:25 | If you are on Mac probably the best option available is
MAMP and that can be found at mamp.info/en/mamp.html.
| | 00:35 | We will go ahead and go back to XAMPP for the moment;
we will scroll down and find XAMPP for Windows.
| | 00:44 | We will then click on the XAMPP1.6.6a
and it will bring us to an option
| | 00:51 | where we can select from different types of files.
| | 00:53 | In this case, we just want the easiest installer, so
we will go ahead and just select the Installer method.
| | 00:58 | It will take you to another page where it
will begin the download process and depending
| | 01:02 | on which browser you are using it might prompt
you to confirm that you want to download the file.
| | 01:06 | We are now actually going to go
ahead and run the application.
| | 01:09 | Now it will confirm that we want to run the file and we will
go ahead and click Run and if you see any warnings related
| | 01:15 | to UAC on Vista you can just go ahead and click OK.
| | 01:19 | Now we will have the option to walk through the setup,
| | 01:21 | we can pretty much accept the default
settings for almost everything.
| | 01:24 | The one thing that you are going to want
to really pay attention to is that XAMPP
| | 01:28 | by default installs everything at the root of the C: drive.
| | 01:31 | That's fine but we just need to remember where
that location is because we will be using it later.
| | 01:35 | Next, we will have it install a desktop
icon, also included in the Start menu
| | 01:40 | and we also want to run Apache and MySQL as the service.
| | 01:46 | Once the installation has been
completed, you can click Finish.
| | 01:53 | As it installs Apache and MySQL as services
you will see a few other windows pop up.
| | 01:58 | This is nothing to be alarmed about.
| | 02:00 | It will finally tell you that the
server's installation has been finished;
| | 02:03 | it also says that you can use the
XAMPP control panel to manage services.
| | 02:06 | We will click OK, and we will say that
we want to start the Control panel now.
| | 02:12 | So here is the Control panel and we have it
available in the system tray when we need it.
| | 02:17 | Now that we have installed the local development web
server, we will begin to look at different methods
| | 02:21 | for distributing our AIR applications the way we have
built, configured and packaged inside of Flash CS3.
| | Collapse this transcript |
| Using a download link| 00:00 | Now that you have completed your AIR application and you
have got your .air file and you are ready to distribute it
| | 00:05 | to the world, one of your first
choices might be to take that .air file
| | 00:10 | and then place it somewhere, like on a web server.
| | 00:12 | You might have some web hosting space or you might
even have a server yourself that you can place it on
| | 00:16 | and then you figure that you can just take
the link and then hand it out to everybody
| | 00:20 | and then they can receive your application that way.
| | 00:22 | Well that's not always the best idea
and I am going to demonstrate why.
| | 00:26 | First, be sure that you actually have XAMPP installed
because we are going to be using some samples from it.
| | 00:30 | Now I am going to open the htdocs directory for XAMPP
that can be found under C:XAMPP and then htdocs.
| | 00:40 | This is the root for the web server.
| | 00:42 | Now I have already put in here a download.html file
and you can see here that it just has one single tag
| | 00:49 | that allows the user to download the browser
application and it references the browser.air file.
| | 00:55 | In addition, you can see that I have copied
the browser.air file into this directory.
| | 01:01 | Now we can actually visit this directory
by just going to localhost/download.html.
| | 01:06 | Now if we click on this link, what is going to happen is
that right now, Windows believes that this is a zip file,
| | 01:13 | so if the user clicks open, it is basically going
to take your .air file and unpackage everything.
| | 01:21 | You are going to see your compile sweep and you are going
| | 01:23 | to see any other assets that you
included with your application.
| | 01:26 | And certainly there is no way to install it from this point.
| | 01:29 | The problem lies with the fact that the web server
does not have the proper MIME type for AIR files.
| | 01:36 | In other words, it doesn't know
what to do with that AIR files.
| | 01:39 | It doesn't know how to send it to the end user.
| | 01:41 | So we are going to need to go in and
update the configuration for Apache.
| | 01:46 | Now just to note; if you have your own server
it might be easy enough to go and do this.
| | 01:51 | However, if you are on a shared host you
might have to contact your technical support
| | 01:54 | and see if they can go in and do this for you.
| | 01:56 | So I am going to close this window, and I
am going to go ahead and close this window,
| | 02:02 | and we are going to go to another directory within XAMPP.
| | 02:05 | We are going to go to XAMPPapacheconf.
| | 02:10 | Then we are going to locate the httpd.conf file
and we can just right click and go to edit.
| | 02:15 | Now in this file; you are going to want to search for
default type and directly under is where you are going
| | 02:24 | to place the MIME type declaration for AIR.
| | 02:26 | But you are probably wondering what
is the MIME type declaration for AIR.
| | 02:30 | What is a MIME type declaration at all?
| | 02:31 | That's basically just phrase that you
put into your server configuration file
| | 02:37 | that tells it how to handle certain things.
| | 02:39 | So I am actually going to go to myblog for a
moment because I have actually posted an article
| | 02:43 | that explains how to do this for multiple web servers.
| | 02:46 | The first option here is Apache and since that's
what we are using we actually can just copy
| | 02:51 | and paste this directly under our configuration file.
| | 02:53 | So if we go we can hit the plain text option here
| | 02:57 | and then we can just highlight this
entire line and then we can copy it.
| | 03:01 | Now we can go ahead and minimize
this browser window and now directly
| | 03:05 | in the httpd.conf file we are just
going to add this declaration.
| | 03:10 | And basically what it says is, it is going to add the type
and then there is the specific MIME type for Adobe AIR files
| | 03:16 | and then it is going to tell it to
handle any .air file with that MIME type.
| | 03:21 | Now we can save the configuration
file but we are not done yet.
| | 03:25 | We actually have to restart Apache
for these changes to take effect.
| | 03:28 | So I am going to go ahead and close this window
and I am going to open up the XAMPP control panel.
| | 03:36 | We can see that Apache is currently
running and so we are going to stop it.
| | 03:40 | Now that it has said that the Apache service
has stopped, we are now going to hit Start,
| | 03:45 | and now it says that Apache is not running
| | 03:47 | so we can minimize the control panel
and we will open up a new web browser.
| | 03:52 | In this case, we can go to local
host and go back to download.html.
| | 03:56 | Now the first time you clicked this link it still might give
you the wrong MIME type, but in most cases it should update
| | 04:02 | to where now the Adobe AIR Installer
can actually handle this file.
| | 04:05 | Oops and they still gave the old one, just refresh the page,
and click it again, and now we can see that it recognizes it
| | 04:13 | as a .air file and now we can click Open.
| | 04:17 | And we now can see that it actually begins
going through the AIR installation process.
| | 04:21 | So you need to be very careful when distributing your AIR
files, that if you are placing them somewhere on a server
| | 04:26 | where they can just be easily downloaded,
you need to be sure
| | 04:29 | that the server has been updated with
the MIME type for Adobe.AIR files.
| | Collapse this transcript |
| Using the Seamless Install Badge| 00:00 | There is another method for distributing
your AIR applications
| | 00:03 | that can make the entire process
quite a bit easier for your users.
| | 00:07 | Let's think about what is required
to install an AIR application.
| | 00:10 | First, the user has to be sure that they have AIR
installed, so if they don't, they are probably going to have
| | 00:15 | to go and download it from the Adobe site.
| | 00:18 | Next, they are going to need to go somewhere and
download your ".air" file and then they are going to need
| | 00:22 | to download it to their computer and then install it.
| | 00:25 | Now for most users if you just want
them to install a single application,
| | 00:29 | they might not be willing to go through all of these steps.
| | 00:32 | But Adobe has actually developed some
functionality that makes it quite a bit easier
| | 00:35 | to distribute your AIR applications
by using the Seamless Install Badge.
| | 00:40 | Now recently, I wrote an article for the Adobe
Developer Network that actually outlines the process
| | 00:44 | for using the Seamless Install Badge, but also
using it with another one of the Adobe Technologies
| | 00:49 | and that's the Adobe Express Install for the Flash Player.
| | 00:53 | Now the purpose of this is to actually
use the Seamless Install Badge you have
| | 00:57 | to at least have Flash Version 9.0.115.
| | 01:02 | The Express Install can update most older versions
of the Flash player up to at least that version
| | 01:08 | and then it can proceed with the Seamless Install Badge.
| | 01:11 | And what makes the Seamless Install Badge
so useful is, it actually can walk the user
| | 01:15 | through installing AIR without them ever leaving your site.
| | 01:19 | So you don't have to tell the user, stop downloading
my file, go and unload Adobe AIR and then come back,
| | 01:24 | all of that is taken care of with
the Seamless Install Badge.
| | 01:27 | So the address for this particular article is
adobe.com/devnet/air/articlesair_badge_install.html.
| | 01:41 | On the first page of the article,
you will see the sample files.
| | 01:43 | We are going to be using the sample files.
| | 01:46 | I have already downloaded the files and
actually extracted them to the desktop,
| | 01:50 | and so here is the directory badge install samples.
| | 01:53 | So we now can go ahead and close this window.
| | 01:55 | We are going to go ahead and close all the tabs.
| | 01:58 | Next, we are going to actually open up our htdocs directory.
| | 02:02 | Again, this is under C:XAMPP and then htdocs.
| | 02:06 | We are now going to create a directory
inside and we will just call it Badge.
| | 02:12 | Now we are going to open up the sample
files that came with the article,
| | 02:18 | we are going to go to the Express Install
example and we are going to copy all
| | 02:23 | of these items directly into the Badge directory.
| | 02:28 | Next, we are going to copy our browser.air file or
whichever AIR file that you have packaged and we are going
| | 02:35 | to place it in the directory with these items.
| | 02:39 | We can go ahead and close the Badge Install samples window.
| | 02:42 | The other files were there to either support the use of
the badge, or to support the use of the Express Install.
| | 02:49 | In this case, we actually can right
click and just edit index.html.
| | 02:53 | Now the main section need to worry about when using
the Flash Install Badge, is this section right here
| | 02:59 | between these two script tags, where it defines
a lot of settings for this specific application.
| | 03:04 | The first thing they were going to want to change
is we are going to want to change the location
| | 03:08 | of our AIR file, ours is at localhost/badge/browser.air.
| | 03:19 | In addition, you also can set an application
image to be used with the Seamless Install Badge
| | 03:26 | and you will see what I mean with that in a second.
| | 03:28 | We can go ahead and save this file and now we actually can
open up a browser window, we can go to localhost/badge.
| | 03:42 | When this loads up, you will see that
we now have a button on the Stage.
| | 03:45 | This is actually a Flash file, and you can see that
there is an Install Now option for this application.
| | 03:50 | We can now click on it, and it will tell us
| | 03:53 | that it's actually downloading the AIR file
and beginning the installation process.
| | 03:57 | Now here is the great thing though.
| | 03:58 | If you didn't have AIR installed already, the process would
look almost identical except it will also install Adobe AIR
| | 04:06 | as it installed your application.
| | 04:08 | The other great thing is that with this you don't have to
worry about what version of the Flash player users have.
| | 04:14 | As long as they have something later than Flash
player version 5, they can go to this page;
| | 04:18 | they might be required to update their version of
the Flash Player, but they can do so from this window
| | 04:24 | and once their version of the Flash Player has been updated,
they will see the Install Badge, they can click Install Now.
| | 04:30 | Then, again if they don't have AIR that
can also automatically be installed.
| | 04:33 | So by using the Seamless Install
Badge with the Express Installation,
| | 04:38 | what it allows you to do is basically deliver
your entire application including Adobe AIR
| | 04:42 | and including updating the Flash player
without ever having to leave your site.
| | 04:46 | And this is a powerful feature and the
best way to distribute AIR applications.
| | 04:50 | So in this case, we could go ahead and click Open, it would
walk us through the process of installing our application.
| | 04:56 | Now as I said, there is a bit of customization
that can go into the Install Badge,
| | 05:00 | if we go back to the index.html file, you can
see that we can change the application image
| | 05:05 | and then within the documentation included with the sample
files from the article, you can see that there are a lot
| | 05:10 | of other settings that can be adjusted as well.
| | 05:12 | So by using the Seamless Install Badge, we are able
to do deliver a seamless experience for the user
| | 05:18 | as they download and install your AIR application.
| | Collapse this transcript |
|
|
ConclusionGoodbye| 00:00 | I hope you really enjoyed this series.
| | 00:02 | I really enjoyed getting to share some of the cool things
about AIR with you and hopefully you enjoyed some of the cool
| | 00:06 | applications that we got to build.
| | 00:08 | Now you've got the tools to go out and build
the next generation of rich internet applications
| | 00:12 | using the visual tools of Flash with
some of the great capabilities of AIR.
| | 00:16 | Go to it.
| | Collapse this transcript |
|
|