In the previous chapter, we designed an interactive virtual reality (VR) experience using beta document types in Animate based on WebGL standards.
For this chapter, we'll focus on the Adobe Integrated Runtime (AIR) platform and build a small utility application for browsing photographs. To develop this application, we'll need to download and install an AIR software development kit (SDK) and make use of ActionScript 3 (AS3) as a programming language. We'll populate our application with the help of both components and button symbols, two features of Animate that we haven't explored until now. To close, we'll examine how to convert the application for use on iOS and Android.
After reading this chapter, you'll be able to perform the following functions in Animate:
You will need the following software and hardware to complete this chapter:
The code in action video for this chapter can be found here: https://bit.ly/3Dln3ga
In this section, we will download and install an AIR Software Development Kit (SDK) within Animate and configure a new AIR for Desktop document using the chosen SDK version.
AIR is simply one of the most amazingly flexible development platforms available. We went over the general history and usage of AIR in Chapter 2, Exploring Platform-Specific Considerations, but will really dive into building with the platform now. Since it's been a while, I suggest perhaps going back to that chapter to refresh your memory.
We are going to use AIR to build an image file browser application in this chapter. The user will be able to select a folder from their local filesystem, and any image files from that folder will display within a data grid. We'll write a bit of logic so that only image file types will be displayed in the grid. When the user chooses a file from the grid, the image will be rendered within the application.
The first step in all of this is to install an AIR SDK in order to work with AIR documents.
Before 2020, Animate would include the most recent version of the AIR SDK packaged along with it, so it was easy to get started with the platform. Following the June release of that year, users would be greeted with a notice when attempting to create a new AIR-based document for the first time.
The notice appears when choosing AIR for Desktop, AIR for iOS, or AIR for Android from the New Document dialog:
The notice reads: AIR SDK is no longer shipped with Animate. In order to enable AIR publishing, please refer to the following link.
Clicking the Enable AIR SDK button at the bottom of the panel brings the user to a page hosted by Adobe (https://helpx.adobe.com/animate/kb/get-started-with-latest-airsdk.html) that explains how to acquire and install the HARMAN version of Adobe AIR.
If you want to use the older version of AIR that was maintained by Adobe, the final version of the AIR SDK maintained by Adobe (version 32) is now found only through the AIR SDK archives at https://helpx.adobe.com/air/kb/archived-air-sdk-version.html. This is not recommended but may be useful in some scenarios.
Note
While Adobe gave the AIR SDK freely, as its development and maintenance were supported by their tooling, HARMAN does charge a licensing fee for use of the SDK. Thankfully, most users who are not using the SDK for commercial purposes can make use of it for free, with the inclusion of a quick splash screen to help market the technology.
In order to locate and download an AIR SDK on your computer, perform the following steps:
I suggest visiting the HARMAN site at https://airsdk.harman.com/download as the most recent version of AIR can be found there.
You can choose between macOS and Windows versions and select either the main builds of the SDK or those to be used alongside Apache Flex. When dealing with Animate, you'll seek out the non-Flex builds.
Choose a version of the Full AIR SDK with new ActionScript Compiler to download.
Note
Apache Flex (formerly Adobe Flex) is a development platform that makes use of Flash Platform technologies, including ActionScript 3.0 and the Macromedia FleX Markup Language (MXML) markup language, for cross-platform application development. You can learn more at http://flex.apache.org/.
Once you have completed copying the .zip archive's full contents into the folder you've created, you'll want to make note of that location when we go to install the SDK in Animate. You can install many different versions of the AIR SDK—just be sure to keep each one in its own unique directory with an identifiable name.
We'll now turn our attention back to Animate to install the AIR SDK so that we can develop applications and games using the technology. Proceed as follows:
If you haven't installed any AIR SDK versions in the past, this will be empty, but if you have other versions of the SDK installed, they will appear here.
The AIR SDK is now integrated within Adobe Animate, but we will likely need to provide additional permissions to run and test any documents we create.
Before we do that, we'll need to create a new AIR document and perform some basic configuration to set up our project.
With at least one version of the AIR SDK installed, we can now create and manage AIR for Desktop, AIR for iOS, and AIR for Android documents. While you might think you have to make platform decisions at this point, these three choices can always be modified even when your application development is complete by switching the target platform. We'll see how to do this at the end of the chapter.
Let's create a new AIR for Desktop document to work with in this chapter:
Because we have at least one version of the AIR SDK installed and ready to go, Animate now displays the document details along with a Create button.
Aside from these basic document settings, we'll also add a text-based header to the application to provide it with more of a visual identity before laying out all the interactive components in the next section.
To create a text header for the application, perform the following steps:
The text object is non-interactive, so should be set to Static Text. I've chosen an Adobe font called BadTyp (https://fonts.adobe.com/fonts/badtyp) for the text header, made its size 50 pt, and have set the fill color to white (#FFFFFF). In the Paragraph section, I've chosen to Center Align my text.
The text object is nearly the size of our stage and the text remains centered.
The width should be 464 px with an X value of 18 and a Y value of 20. This will position the header down the stage a little bit while also centering it within the application.
Our AIR project is now configured with the appropriate Document Settings and a nice title header for the application.
Before we conclude this section, we should ensure that we are able to run the AIR project effectively in order to test features as they are built.
To test an AIR document, the process is very similar to any other document type we've seen. Click the Test Movie button in the upper-right corner of the Animate interface, or you can have finer control over how you test by selecting Control | Test Movie and choosing an option from the menu that appears, as illustrated in the following screenshot:
Here is a quick overview of the options presented by this menu:
If you are using Adobe Animate on Apple macOS and have downloaded and added the AIR SDK from the internet, you will likely be presented with a number of security warning dialogs when attempting to run an AIR document with the Test Movie option for the first time, such as the following one:
If this occurs, simply open your Apple macOS System Preferences and locate the Security & Privacy option. From here, choose the General tab and look at the section with the text Allow apps downloaded from, and you should see an alert about either the AIR Debug Launcher (ADL) or the AIR framework processes:
Choosing Allow Anyway will grant permission for these processes to run without problem from Animate. Depending upon how many dialog warnings you receive, you may need to allow multiple processes before macOS stops alerting you of these processes.
When using Windows, simply provide permission to these processes if prompted by the system dialogs. It is normal for everything to just work without any additional procedures when developing AIR projects on Windows.
In accordance with the documentation from HARMAN, you may want to make one additional change to your application before testing. Choose File | AIR for Desktop Settings to open the AIR Settings dialog. Be sure to choose Application with runtime embedded as the Output as option, as illustrated in the following screenshot:
This will ensure that your application will compile and run properly in the current and future versions of AIR provided by HARMAN.
In this section, we downloaded and installed an AIR SDK within Animate, allowing us to create AIR documents. We also created and configured a new AIR for Desktop project, added an application title header, and explored the AIR testing options. Coming up, we will focus on the elements required in our application interface to allow a user to interact with the application.
In this section, we'll focus on all the interactive parts of the interface we'll build for our AIR application, starting out with a look at how to construct Button symbols, followed by the use of precompiled UI Components, and wrapping up with a more in-depth look at advanced Movie Clip symbol properties.
Let's start off by building a Button symbol that a user will click to choose a folder of photographs within the application.
Button symbols are not supported in every document type in Animate and are pretty unique as their internal timeline is constrained to four isolated states. Nonetheless, Button symbols are very useful for applications such as the one we are building in this chapter.
The easiest way to start building a Button symbol in Animate is by creating a simple shape:
In the dialog, name the new symbol ChooseFolderBtn, since this is the button a user will click to choose a folder of files. We are creating a Button symbol, so be sure the Type selection is set to Button.
Recall that providing a movie clip or Button symbol instance with an instance name will allow us to address this object with code.
With our Button symbol created, we can now enter into its internal timeline and complete setting up our button to provide it with a set of interactive states and a text label so that the user knows what the button's function is.
a) Up—Leave the color at #595959. This is our resting state.
b) Over—Change the color to a lighter gray color at #999999. This is the hover state.
c) Down—This is the state of the button when pressed. It will be a darker gray fill color at #333333.
d) Hit—You can leave this be, but I like to change any non-visible elements to a vivid green (#00FF00). The Hit state is not rendered visually and determines which pixels count toward interaction with a mouse cursor. You can make the Hit state a completely different shape from the visual elements, but in this case, we want it to be identical.
Use whichever text settings look good. I used a 27 pt, Arial Black font with a completely black fill. Notice that this text spans all four states, though you could create keyframe variants with this layer as well, if desired.
When your internal button timeline is complete, click the Scene 1 label in Edit Bar above the stage to return to the main timeline.
One of our three user interface elements is now complete. For the remaining two elements, we will use prebuilt Components.
Components are a feature of HTML5 Canvas, ActionScript 3.0, and AIR documents. They are prebuilt, modular packages that generally serve a single function. Some function as video playback or a progress bar, or even a data grid or media display mechanism, as we'll see for this project.
Note
The set of available components will differ drastically between HTML5 Canvas documents and all other document types that support the use of components.
We will make use of two different components in this project: the DataGrid component and the UILoader component. Proceed as follows:
The Components panel lists a number of different component types. We will be using components from the User Interface folder.
A placeholder for this component instance will be visible on the stage.
This opens the Component Parameters panel and displays all parameters for the selected DataGrid component.
These settings will make each piece of data more clickable, especially if we were to publish this app to a mobile device. UILoader does not require any parameter adjustments. You may need to scroll down in the Component Parameters panel to locate both parameters.
The UI elements of our AIR application are now in place and the project is ready for programming with ActionScript. Here's what it looks like now:
Our UI elements have now been established within the project layout. Before moving on to the next section though, we should explore some additional properties of movie clip symbols, as they are also incredibly useful in building application interfaces.
We've now established our application interface through the use of Button symbols and components. If you look in the Properties panel with a component selected, you'll discover that these components are actually Movie Clip symbols! Additionally, in place of any of the objects we've used for the layout, Movie Clip symbols are always a great choice for custom interactive controls in AIR applications.
While we aren't going to be using these advanced settings for Movie Clip symbols in this project, it is good to know about them—especially with the relationships that exist between Movie Clip symbols and components.
With the more common Movie Clip settings covered in Chapter 5, Creating and Manipulating Media Content, let's expand on that overview and have a look at the Advanced settings of Movie Clip symbols available to us. To access these advanced properties, select a Movie Clip symbol in the Library panel, right-click to open the contextual menu, and choose Properties…. Once the dialog appears, expand the Advanced settings section.
The first section of the Advanced settings is the most important and appears at the top of the expanded portion of the dialog, as illustrated here:
The first option you see here is actually more of a design setting than anything to do with development. When enabled, the Enable guides for 9-slice scaling option will allow you to enter into a symbol from the Library panel and modify a set of guides to specify which visual areas of your symbol should scale and which should stay their original size if an instance of the symbol is scaled. This allows a good amount of control for properly resizing UI elements that you create so that different sized instances can easily be created upon the stage from the same exact symbol. This is only available with ActionScript 3.0-based documents.
Below this are the ActionScript Linkage settings:
Again, most of these options have to do with ActionScript development. While very convenient, unless you are creating applications or games using AIR, as we are in this chapter, they likely will not matter much.
Following the ActionScript Linkage settings are two additional groups of settings:
Most Animate users will have no need for either of these settings, but it is good to be aware of what each is for.
Note
Again, while we won't be using Movie Clip symbols in our project, apart from the existing components, it is good to have an understanding of their advanced properties and settings.
In this section, we built out our entire user interface using custom Button symbols and prebuilt components. We also had a look at advanced symbol properties that tie directly into ActionScript programming. Coming up, we'll start writing all the ActionScript code to drive the functional aspects of the application.
In this section, we'll use ActionScript to tie all of our interface components together into a unified application. ActionScript is similar to JavaScript in some ways (they are both based on ECMAScript), but very different in other ways, since both are derived from different branches of the specification.
While we could write all of our ActionScript code using frame scripts, it is better to leverage the Object-Oriented Programming (OOP) features that are so prominent in the language and create a Document Class.
We'll now create a document class and bind it to our .fla document. The document class will exist as a .as file separate from the .fla file. When you use a document class for your project, it must extend either the MovieClip or Sprite classes, depending upon whether you require animation or not in your main document timeline. Extending one class with another will give you access to all the functionality you write, plus all the functionality that is within the base class. It's a powerful way of programming!
Let's go ahead and instruct Animate to create a new Document Class for us:
This dialog contains imported ActionScript settings for your project. You'll want to check and be sure that Export classes in frame is set to 1 and that Automatically declare stage instances is selected. They should be selected by default, but it never hurts to check.
You will likely receive a warning from Animate informing you that it cannot find the specified class file. This is expected, as we have yet to save it! Dismiss the warning dialog if it appears.
A new ActionScript class appears within Animate.
The newly created document class will look like this:
package {
import flash.display.MovieClip;
public class Main extends MovieClip {
public function Main() {
// constructor code
}
}
}
This is boilerplate code that defines a Document Class named Main, which extends flash.display.MovieClip. Note that we also have to import flash.display.MovieClip in order to use it. Within the class is a single function called a constructor function. Any code within this function runs immediately upon initialization.
Note
Any additional functions we create later will go below the constructor function, one after the other. These functions and any variables created must all exist within the class definition.
Be sure that the class Target dropdown is set to bind to your Animate document named PhotoBrowser.fla:
Once everything looks to be set, we can move on to write the rest of our application code within the Main class.
The first task we have is to import a set of additional classes to be used within the application. Type the following import statements directly beneath the existing import:
import flash.filesystem.File;
import fl.controls.DataGrid;
import fl.data.DataProvider;
import fl.containers.UILoader;
import flash.events.MouseEvent;
import flash.events.Event;
import flash.events.FileListEvent;
We'll touch upon each of these classes as we get to them in the various functions we'll define further on.
Directly following public class Main extends MovieClip {, enter a set of variable declarations, as follows:
var photoDirectory:File;
var photos:Array;
var photoGridProvider:DataProvider;
These are class-level variables that are accessible from any function within the class. photoDirectory:File will be used to reference a selected folder, photos:Array will hold references to each image file we find, and photoGridProvider:DataProvider will be used to display these files within our DataGrid component.
Note
Variables and other references in ActionScript must be assigned a type through the use of a colon after the name is declared—as AS3 is a strongly typed programming language.
The next lines of code will go directly within our constructor function beneath the line that reads public function Main() {:
ChooseFolder.addEventListener(MouseEvent.CLICK, chooseDirectory);
PhotoGrid.addEventListener(Event.CHANGE, photoSelected);
PhotoGrid.columns = ["Name", "Type", "Size"];
photos = new Array();
photoGridProvider = new DataProvider();
PhotoGrid.dataProvider = photoGridProvider;
The first line adds a MouseEvent.CLICK event listener to the ChooseFolder button symbol instance. When a click is detected, we will invoke a function named chooseDirectory. We also add an Event.CHANGE listener to the PhotoGrid DataGrid component instance. When the selection is changed by the user, the function named photoSelected will fire off. We also set the column names within PhotoGrid directly afterward to Name, Type, and Size.
The remaining lines of code instantiate the class-level variables declared previously.
All that is left is to write the various functions referenced in our listeners and any additional functions they will need to invoke. Add a few line breaks following the closing curly braces below the constructor function to make room, as illustrated here:
We'll begin with the chooseDirectory function and will place it directly after the closing curly brace of the constructor function, as follows:
private function chooseDirectory(e:MouseEvent):void {
photoDirectory = new File();
photoDirectory.addEventListener(Event.SELECT, directorySelected);
photoDirectory.browseForDirectory("Select Photo Folder...");
}
Here is where the photoDirectory file variable is instantiated. This will clear out any existing references from a previous folder selection. We then add a listener to this file of the Event.SELECT type, which will trigger when a new folder is selected and will invoke a function called directorySelected. We have to open a system-level file explorer in order for the user to browse the filesystem and make a folder selection, so use the browseForDirectory() method of the File class to do so.
We'll next write a directorySelected function in response to the folder selection. Place the following code directly beneath the previous function:
private function directorySelected(e:Event):void {
photoDirectory.getDirectoryListingAsync();
photoDirectory.addEventListener(FileListEvent.DIRECTORY_ LISTING, directoryListed);
}
In this function, we first invoke the getDirectoryListingAsync() method to get a list of all the files within the selected directory. We need to listen for an event to tell us when this process has been completed so that we can perform further manipulation on the file references, so listen for the FileListEvent.DIRECTORY_LISTING event, and this will invoke the directoryListed function once it is safe to do so.
The directoryListed function will do most of the work in this application. We'll write it directly beneath the previous function, as follows:
private function directoryListed(e:FileListEvent):void {
photos = new Array();
for(var p:uint = 0; p<e.files.length; p++){
if(e.files[p].extension == "jpg" || e.files[p]. extension == "png" || e.files[p].extension == "gif") {
photos.push(e.files[p]);
}
}
photoGridProvider.removeAll();
for(var i:uint = 0; i<photos.length; i++){
photoGridProvider.addItem({"Name":photos[i].name, "Type":photos[i].extension, "Size":photos[i].size});
}
}
In this function, we start by clearing out the photos array to prepare it for holding the valid image file references from our FileListEvent, which was triggered from the initial folder selection.
We then set up a for loop to iterate over all the files that were detected within this folder. for loops in ActionScript work exactly like they do in JavaScript, if you recall their usage from Chapter 11, Developing Web-Based Games. For each iteration, we check the file extension to determine whether or not it is an image file using the or operator, a double pipe: ||. If it is, we then add the file reference to our photos array.
Once the array is built, containing only image files from the chosen folder, we can populate our DataGrid component with data. First, we will remove any existing data from photoGridProvider so that it is empty. We then run another for loop, but this time it simply adds information about each image file to photoGridProvider, which is then reflected within the visible DataGrid component for the user to select.
The final function to write is the one that is invoked when the user selects an image reference from the DataGrid component. Place the following function directly beneath the last one:
private function photoSelected(e:Event):void {
var selectedPhoto:File = photos[e.target.selectedIndex];
PhotoViewer.source = selectedPhoto.url;
}
This function simply creates a new File variable reference called selectedPhoto and populates it with data from a certain position of the photos array, which matches the row selected by the user as part of the visible DataGrid component on the stage. The source property of our PhotoViewer UILoader component on the stage is then set to the url property of that File reference, thereby rendering the visible image within the UILoader component for the user to view.
For reference, here is the full, completed code for the Main.as class:
package {
import flash.display.MovieClip;
import flash.filesystem.File;
import fl.controls.DataGrid;
import fl.data.DataProvider;
import fl.containers.UILoader;
import flash.events.MouseEvent;
import flash.events.Event;
import flash.events.FileListEvent;
public class Main extends MovieClip {
var photoDirectory: File;
var photos: Array;
var photoGridProvider: DataProvider;
public function Main() {
ChooseFolder.addEventListener(MouseEvent.CLICK, chooseDirectory);
PhotoGrid.addEventListener(Event.CHANGE, photoSelected);
PhotoGrid.columns = ["Name", "Type", "Size"];
photos = new Array();
photoGridProvider = new DataProvider();
PhotoGrid.dataProvider = photoGridProvider;
}
private function chooseDirectory(e: MouseEvent): void {
photoDirectory = new File();
photoDirectory.addEventListener(Event.SELECT, directorySelected);
photoDirectory.browseForDirectory("Select Photo Folder...");
}
private function directorySelected(e: Event): void {
photoDirectory.getDirectoryListingAsync();
photoDirectory.addEventListener(FileListEvent.DIRECTORY_LISTING, directoryListed);
}
private function directoryListed(e: FileListEvent): void {
photos = new Array();
for (var p: uint = 0; p < e.files.length; p++) {
if (e.files[p].extension == "jpg" || e.files[p].extension == "png" || e.files[p].extension == "gif") {
photos.push(e.files[p]);
}
}
photoGridProvider.removeAll();
for (var i: uint = 0; i < photos.length; i++) {
photoGridProvider.addItem({
"Name": photos[i].name,
"Type": photos[i].extension,
"Size": photos[i].size
});
}
}
private function photoSelected(e: Event): void {
var selectedPhoto: File = photos[e.target.selectedIndex];
PhotoViewer.source = selectedPhoto.url;
}
}
}
Once all of your code is written, perform a Test Movie and locate a folder of image files on your system to see the application in action:
In this section, we created our Document Class in ActionScript, bound it to our project, and then wrote all of the code necessary for our application to function. Coming up, we will finish off this chapter with a look at how to convert our AIR for Desktop project to be used on mobile devices.
We developed our application using AIR for Desktop, but it is possible to create versions of the application using AIR for iOS and AIR for Android so as to target mobile devices as well. Since the underlying code is all ActionScript, and AIR includes the capabilities of publishing ActionScript to mobile platform packages, we can often convert our documents without much hassle.
Note
For a refresher regarding the various platforms that AIR can target, you may want to refer to Chapter 2, Exploring Platform-Specific Considerations, and locate the sections on Adobe AIR. To further explore the publish settings available across different AIR targets, refer to Chapter 4, Publishing and Exporting Creative Content.
In order to convert a document from one AIR target to another, perform the following steps:
Note that this .fla file will still make use of the Main.as file for all functionality, so you will likely want to re-engineer your class file to be more modular or simply have a unique Document Class for each version of the app.
Note
Publishing to mobile platforms is complicated, and you will need to register as a developer with Apple or Google to do so. This also involves paying a fee and installing a code-signing certificate. These steps are beyond the scope of this book.
You will likely want to consider some of the mobile-specific classes in ActionScript when looking through your code and testing against mobile hardware. You will also need to take screen size and dynamic interface scaling and positioning into consideration. There is a lot to think about!
Of course, there is a lot more to know about design and development for mobile devices. While such topics are beyond the scope of this book, there are many other resources dedicated to such development.
Tip
I cover a number of mobile-specific design and development considerations and functionalities in my book, Flash Development for Android Cookbook, which is focused on AIR for mobile devices: https://www.packtpub.com/product/flash-development-for-android-cookbook/9781849691420.
In this section, we converted our AIR for Desktop project to target mobile devices through AIR for iOS and AIR for Android.
In this chapter, we wrote an entire application from scratch using Adobe AIR! We first downloaded and installed an AIR SDK within Animate and then created a new document with that SDK and configured it for desktop usage. Following this, we built the application interface with the use of button symbols and special premade Movie Clip packages called components. Next, we created a new ActionScript class and wrote all of our application code to develop a fully functioning application. Finally, we had a look at how to convert our desktop project for use on mobile devices using the same AIR technologies.
The final chapter of this book is next, in which we'll explore a number of neat ways of extending Adobe Animate yourself or through the work of others.