Using AIR to Get and Set Clipboard Text

WARNING: This was written for a BETA version of AIR and may not be valid for the most recent release

Normally, your operating system's clipboard information is not directly available to Flash SWFs, whether they run in the browser or if running in the stand alone version of the Adobe Flash Player. You can manually copy content from a Flash movie onto your clipboard or manually paste content to a Flash movie from your clipboard, but there is no way for Flash to do that automatically through ActionScript.

With the Adobe Integrated Runtime (AIR) that has all changed. With the advantages of running as a desktop application, AIR applications also gain the additional functionality of being able to both get content from the operating system's clipboard as well as set it. This tutorial will show how you can do both with simple text data.

Requirements:

Note: Though this tutorial uses Flash CS3, the same ActionScript could be applied to an AIR project in Flex Builder.

Source files:

The ClipboardManager Class

The ActionScript class that grants access to the clipboard in AIR is called ClipboardManager (flash.desktop.ClipboardManager). It's a static class that you would not create an instance of but rather use directly access static properties or call static methods. The properties and methods of most interest are the data property and the accessClipboard() method.

The data property of ClipboardManager class represents the actual data on the clipboard. It's value is a TransferableData (flash.desktop.TransferableData) instance. As a TransferableData instance, the data can have many representations even if comprised of only one value. For example, consider copying a url from a web site. This data would be represented as two different values in the clipboard data, one being the url, and the other being the text of the url.

Each different available format native the AIR is represented in a constant in the TransferableFormats class (flash.desktop.TransferableFormats). Currently, there are 4: text, url, bitmap, and file list, though you can also add your own format types to a TransferableData instance. In the case of this example, we will just be using text which is defined in TransferableFormats as TransferableFormats.TEXT_FORMAT. This will be used to specify the kind of data desired from the data property of ClipboardManager.

The ClipboardManager's data property, however, can not be directly accessed as you can with other property values. Given that you are accessing clipboard data from the operating system, a special precaution is needed to assure other processes don't try to modify that data as you are working with it. The way AIR handles this is through the accessClipboard() method.

The accessClipboard() method accepts a single closure function which it wraps and calls when access to the system's clipboard is available. This happens asynchronously meaning the function used may not be called immediately when accessClipboard()is called. If you want to access the clipboard's data (via ClipboardManager.data) it would have to be done from within this closure function. Also, once this function resolves, any reference to the data's TransferableData instance will be invalid. This can be a small inconvenience when working with clipboard data but can be easily managed if treated like an event.

The AIR Application Source

This sample application will consist of two text areas, one from which the AIR application will be able to copy selected text to the system's clipboard and one to which data will be added from the system's clipboard. Two buttons control these actions.

  1. Open simpleClipboardText.fla from the source files

You will notice the two text fields and two buttons. The text fields have the instance names input (top) and output (bottom). The buttons have the instance names copyButton and pasteButton.

  1. Select the first frame of the actions layer
  2. If not already open, open the Actions panel using F9 or Window > Actions

The ActionScript for this example is divided into essentially 2 parts. The first handles copying data to the clipboard, and the other "pasting" data from the clipboard. Both have a similar structure since both are relying on buttons to handle these actions and for both getting and setting clipboard data, the accessClipboard() method must be used.

The Copy Code

The code used to copy data to the clipboard starts with an event handler called copy being added to listen for the CLICK event of the copyButton instance.

copyButton.addEventListener(MouseEvent.CLICK, copy);
function copy(event:MouseEvent):void {
	ClipboardManager.accessClipboard(setClipboardText);
}

Inside the copy event handler, the accessClipboard() method is being used with the custom setClipboardText() method. The copy handler itself would not be able to access clipboard data. Instead, it uses accessClipboard() to allow that access to a second method, in this case setClipboardText(). There, the clipboard data can be correctly accessed and a copied value can be set.

The setClipboardText() method is as follows:

function setClipboardText():void {
		
	if (input.selectionBeginIndex != input.selectionEndIndex){
	
		var selectedText:String = input.text.slice(input.selectionBeginIndex, input.selectionEndIndex);
		var data:TransferableData = new TransferableData();
		data.addData(selectedText, TransferableFormats.TEXT_FORMAT);
		ClipboardManager.data = data;
	}
}

The logic of this application requires that text be selected in the input textfield. The first if statement checks for that by checking to see if the beginning and ending selected indices of that text field match. If they don't, the selection can be added to the clipboard.

The next line gets the text selected using the String slice command with those indices. This is the text that will be added to the clipboard (in text format). But first, to be sent to the clipboard, the text must be added to a TransferableData instance. That happens in the following lines:

var data:TransferableData = new TransferableData();
data.addData(selectedText, TransferableFormats.TEXT_FORMAT);

Here a new TransferableData instance is created and provided the selectedText value as a text value through the TransferableData addData() method. This method has 2 parameters, data and format (there is also an additional optional serializable parameter not covered here). For data, the selected text is being used since that is the data we want to be stored in the TransferableData instance. To indicate that the data has a format of text, the TransferableFormats.TEXT_FORMAT is used as the format argument. Other data could be added on top of this, but here, we're only interested in the text data.

After the data has been defined, it is simply set to the data property of the ClipboardManager class. The text is now copied! Remember, this is only allowed within setClipboardText() here because it was given to the accessClipboard() method in the copy event handler.

The Paste Code

Like the copy code, the paste code starts off with an event handler for the paste button sending another method (displayClipboardText()) to accessClipboard().

pasteButton.addEventListener(MouseEvent.CLICK, paste);
function paste(event:MouseEvent):void {
	ClipboardManager.accessClipboard(displayClipboardText);
}

Just like when clipboard data is set, retrieving it also requires accessClipboard() to function correctly. The displayClipboardText() method is as follows:

function displayClipboardText():void {
	var data:TransferableData = ClipboardManager.data;
	if (data.hasFormat(TransferableFormats.TEXT_FORMAT)){
		output.text = String(data.dataForFormat(TransferableFormats.TEXT_FORMAT));
	}else{
		output.text = "";
	}
}

Here, the clipboard data is taken from the ClipboardManager class and saved to a data variable. This is a TransferableData instance containing the contents of the clipboard in whatever format the last data saved to it was (which could be coming from any application - even this one). Since this AIR application is only concerned with text data on the clipboard, the hasFormat() method is used on the data instance to see if text data exists.

If hasFormat() returns true, the text from that TransferableData data instance will be displayed in the output text field using dataForFormat(). The dataForFormat() method lets you selectively extract data from a TransferableData instance by type, in this case text (TransferableFormats.TEXT_FORMAT). If text is not a format found in the clipboard data, the output field text is simply cleared.

Using the Application

With the source FLA opened in Flash, test your movie.

Once opened in the AIR player (ADL), try selecting some text from the top text field (input) and clicking the copy button. To check to see if the text copied, try pasting the text in some other application such as a text editor or just in the output text field in the AIR application itself.

Next you can test the paste button. Try it with text copied from within the application as well as text copied from another source. It should work just as though if you pasted it yourself. If you try to paste non-text data, it should come up empty (hasFormat() should return false setting the output value to an empty string).

Conclusion

Thankfully, access of the clipboard through AIR does not stop at just text alone. You've already seen that other data formats are also supported as seen through the values in the TransferableFormats class. Not only that, but you can define your own formats which can be added to the clipboard and restored within your or any other AIR application that is able to recognize and use that data.

But be careful. With access to the clipboard comes responsibility. You shouldn't be changing the clipboard's data on a whim. The clipboard should only change when the user expects it to. I don't know how well received a rogue application changing your clipboard data randomly would be.