Chapter 13. Taskbar and Dock Integration

By leveraging taskbar and Dock functionality in your AIR application, you can enhance your application’s usability. This ability is especially useful when you want to notify the user that an event of interest has occurred.

On Windows, you can place an additional representation of your application (other than the taskbar button) in the form of an icon in the system tray (also called the notification area) of the taskbar. On a Mac, you can place an icon referencing your application in the Dock when the application is running. To get the attention of the user when something important happens, you can make a system tray icon flash (Windows) or the Dock icon of your application bounce (Mac).

On both operating systems, you can also add menus to the icons in the system tray or Dock.

Because the implementations in this chapter are operating system specific, it is a best practice to first check which operating system and associated icon is supported on the user’s computer. You can check which icon types are supported using the static NativeApplication properties: supportsDockIcon and supportsSystemTrayIcon. Both types of icons support menus and custom images, but Table 13-1 outlines some differences.

Table 13-1. Icon Type Differences

System Tray Icon (Windows)

Dock Icon (Mac)

This icon is visible only when you set an image.

This is always visible, showing the image specified inside the application descriptor, unless you set a different image.

You can set tooltip text.

You cannot set a tooltip text.

You can listen for mouse events dispatched by the system tray icon.

Clicking the Dock icon doesn’t dispatch any events; however, you can detect a click on the icon by listening to the invoke event of the NativeApplication object.

The code you need to check the available icon type is as follows:

if(NativeApplication.supportsDockIcon){
   //Dock available

}else if (NativeApplication.supportsSystemTrayIcon){
   // taskbar and system tray available
}

Adding an Icon to the System Tray (Windows)

Problem

You want to add an icon to your application button in the Windows system tray.

Solution

Assign an Array containing the new image or images to the bitmaps property of the icon object in your NativeApplication instance.

Discussion

The icon property of NativeApplication is an InteractiveIcon instance that represents the application icon(s). The bitmaps property of InteractiveIcon holds the images that will be shown inside the system tray on your Windows taskbar. This property expects an array of several images and enables you to define several sizes of your icon image. AIR automatically selects the image according to the current display size of the system tray icon (set on the operating system level). At runtime, AIR will detect the dimensions of the icons in the array, and the bitmap in the array closest to the display size will be used and scaled if necessary. Most typical sizes (in pixels) are 16 × 16, 32 × 32, 48 × 48, and 128 × 128.

Note

To set the icon in your application’s taskbar button, you specify it in your application descriptor file (see Setting the Default Program Menu Folder).

ActionScript/Flex

This example demonstrates how to add an Array of images to the bitmaps property of your application icon. The images you put in the Array must be of type BitmapData. A BitmapData object represents the pixels of a Bitmap object.

The full MXML code for the example is as follows:

<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml"
    applicationComplete="init()"
    layout="absolute"
    title="Recipe 13.1: Adding an icon to the Windows taskbar"
    >
    <mx:Script >
        <![CDATA[
            //embed the images to use as icon
            import mx.core.BitmapAsset;

            [Embed(source="app:/assets/icons/flashing/Icon_fl_32.png")]
            public var img32:Class;

            [Embed(source="app:/assets/icons/flashing/Icon_fl_16.png")]
            public var img16:Class;

            //define the bitmapData object

            private var icon32:BitmapAsset;
            private var icon16:BitmapAsset;

            private function init():void{
                //define bitmapData object

                icon32= (new img32()as BitmapAsset);
                icon16= (new img16()as BitmapAsset);
                //assign the bitmapData objects to the icon.bitmaps
                if(NativeApplication.supportsSystemTrayIcon){
                    this.nativeApplication.icon.bitmaps =[icon32.bitmapData, 
icon16.bitmapData];
                }
            }
        ]]>
    </mx:Script>
</mx:WindowedApplication>

You first embed the images in your AIR application by using the Embed directive so that they are available at runtime. You then instantiate the embedded assets and store them in local variables that you can readily access when needed. When the application is fully loaded (as indicated by the dispatch of the applicationComplete event), you make a new instance of every loaded image, which is actually a BitmapAsset instance, so you cast the object to a BitmapAsset object, as shown here:

icon32= (new img32() as BitmapAsset);
...

Lastly, you can now access the bitmapData property of the Bitmap, so put the image instances in an Array, and assign that Array to the icon.bitmaps property of the NativeApplication object. This example adds four sizes of the icon image:

this.nativeApplication.icon.bitmaps =[ icon32.bitmapDta,icon16.bitmapData];

JavaScript

This example demonstrates how to add an Array of images to the icon.bitmaps property. The images you put in the Array must be of type BitmapData. A BitmapData object represents the pixels of a Bitmap object.

This is the code when developing AIR applications with JavaScript:

<html >
<head>
<title>Recipe 13.1: Adding an icon to the Windows system tray</title>

<script src="AIRAliases.js" type="text/javascript"></script>

<script type="text/javascript">

var iconLoadComplete = function(event) {
        if (air.NativeApplication.supportsSystemTrayIcon) {
            air.NativeApplication.nativeApplication.icon.bitmaps =
                new runtime.Array(event.target.content.bitmapData);
        }
    }
function init(){
    var iconLoad = new air.Loader();
    iconLoad.contentLoaderInfo.addEventListener(air.Event.COMPLETE,iconLoadComplete);
       iconLoad.load(new air.URLRequest("assets/Icon_16.png"));
}
</script>
</head>
<body onLoad="init()">
</body>
</html>

First, define a new air.Loader instance to load the icon file. To initiate the loading process, you call the load method of the air.Loader class. The load method needs a URLRequest object. This object contains the location information of the image file that needs to be loaded. This example loads one image file (Icon_16.png). When the icon is loaded, you assign it to the icon.bitmaps property in order for it to show in the system tray.

Adding a Custom Menu to the System Tray Icon (Windows)

Problem

You want to attach a menu to the system tray icon on Windows.

Solution

Make an instance of the NativeMenu class, and assign it to the icon.menu property of the NativeApplication object. On Windows, the system tray icon is represented by the SystemTrayIcon property.

Discussion

To attach a menu to the system tray icon, you use the NativeMenu instance. The following examples first embed several sizes of the icon image, read the bitmapData of the images, and assign the data to the icon.bitmaps property of the NativeApplication object. This approach is similar to Adding an Icon to the System Tray (Windows), but this time you using only two sizes of the icon image.

ActionScript/Flex

The example code in bold indicates the line where you instantiate a new NativeMenu object and attach one item to that menu with the label “Close.” To know when the menu item is clicked, you add a listener for the Event.SELECT event. Finally, you attach the menu to the SystemTrayIcon.menu property. When you run the example and right-click the system tray, your custom menu will pop up. When you click the close menu item, the nativeApplication is exited (NativeApplication.exit).

The example code is as follows:

<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml"
    applicationComplete="init()"
    layout="absolute"
    title="Recipe 13.2: Adding a custom menu to the systemtray icon (windows)"
    >
    <mx:Script >
        <![CDATA[
            //embed the images to use as icon
            import mx.core.BitmapAsset;

            [Embed(source="app:/assets/icons/flashing/Icon_fl_32.png")]
            public var img32:Class;

            [Embed(source="app:/assets/icons/flashing/Icon_fl_16.png")]
            public var img16:Class;

            //define the bitmapData object

            private var icon32:BitmapAsset;
            private var icon16:BitmapAsset;

            private function init():void{
                //define bitmapData object

                icon32= (new img32()as BitmapAsset);
                icon16= (new img16()as BitmapAsset);
                //assign the bitmapData objects to the icon.bitmaps
                if(NativeApplication.supportsSystemTrayIcon){
                    this.nativeApplication.icon.bitmaps 
=[icon32.bitmapData,icon16.bitmapData];
                }


                var myMenu:NativeMenu = new NativeMenu();
                myMenu.addItem(new NativeMenuItem("Close",false));
                myMenu.addEventListener(Event.SELECT,closeApp);

                //add the menu to the system tray icon
                if(NativeApplication.supportsSystemTrayIcon){
                    SystemTrayIcon(NativeApplication.nativeApplication.icon).menu 
= myMenu;
                }
            }
            private function closeApp(event:Event):void{
                this.nativeApplication.exit();
            }
        ]]>
    </mx:Script>
</mx:WindowedApplication>

JavaScript

In this example, you first load the icon file as you did in Adding an Icon to the System Tray (Windows). Next you create a new air.NativeMenu object with one air.NativeMenuItem object. When the user clicks the application, the closeApp function is called:

var myMenu = new air.NativeMenu();
myMenu.addItem(new air.NativeMenuItem("Close application",false));
myMenu.addEventListener(air.Event.SELECT,closeApp);

The closeApp function calls the exit method of the NativeApplication class to close the application.

To attach the menu to the system tray icon, set your custom menu as the value for the icon.menu property of the NativeApplication instance. Before you do so, however, check that the guest operating system supports system tray icons using the air.NativeApplication.supportsSystemTrayIcon property of the NativeApplication class:

    //set the menu of the system tray icon
    if (air.NativeApplication.supportsSystemTrayIcon) {
        air.NativeApplication.nativeApplication.icon.menu = myMenu;
    }

The full example JavaScript code is as follows:

<html >
<head>
<title>Recipe 13.2: Adding a custom menu to the systemtray icon (windows)</title>

<script src="AIRAliases.js" type="text/javascript"></script>

<script type="text/javascript">

var iconLoadComplete = function(event) {
            if(air.NativeApplication.supportsSystemTrayIcon) {
                air.NativeApplication.nativeApplication.icon.bitmaps =
                    new runtime.Array(event.target.content.bitmapData);
            }
    }
function init(){
    var iconLoad = new air.Loader();
    iconLoad.contentLoaderInfo.addEventListener(air.Event.COMPLETE,iconLoadComplete);
       iconLoad.load(new air.URLRequest("assets/Icon_16.png"));
    //define a menu
    var myMenu = new air.NativeMenu();
    myMenu.addItem(new air.NativeMenuItem("Close application",false));
    myMenu.addEventListener(air.Event.SELECT,closeApp);
    //set the menu of the system tray icon
    if (air.NativeApplication.supportsSystemTrayIcon) {
        air.NativeApplication.nativeApplication.icon.menu = myMenu;
    }
}
function closeApp(event){
    air.NativeApplication.nativeApplication.exit();
}
</script>
</head>
<body onLoad="init()">
</body>
</html>

Adding a Custom Menu to the Dock Icon (Mac)

Problem

You want to attach a menu to the Dock icon on a Mac.

Solution

Make an instance of the NativeMenu class, and assign it to the icon.menu property of the NativeApplication object. The Dock icon is represented as an instance of the DockItem class.

Discussion

The technique you use to attach a menu to the Dock icon on a Mac is the same as demonstrated in Adding a Custom Menu to the System Tray Icon (Windows). You will, however, need to check for Dock icon support on the user’s operating system.

ActionScript

To check that the Dock icon is supported, test the Boolean value of NativeApplication.supportsDockIcon. If it is supported, you can copy the example from Adding a Custom Menu to the System Tray Icon (Windows) in full and change the if structure to this:

//add the menu to the system tray icon
if(NativeApplication.supportsDockIcon){
   DockIcon(NativeApplication.nativeApplication.icon).menu = myMenu;
}

JavaScript

To check that the Dock icon is supported, you test the Boolean value of air.NativeApplication.supportsDockIcon. You will copy the example code from Adding a Custom Menu to the System Tray Icon (Windows) and change the if structure according to the following code:

//set the menu of the Dock icon
if (air.NativeApplication.supportsDockIcon) {
   air.NativeApplication.nativeApplication.icon.menu = myMenu;
}

Changing the System Tray or Dock Icon

Problem

You want to change the system tray or Dock icon at runtime.

Solution

Assign an Array containing the new icon image (or several icon images with different sizes) to the icon.bitmaps property of the NativeApplication object.

Discussion

Changing the system tray icon or Dock icon is as easy as assigning a new icon image to the icon.bitmaps property of the NativeApplication object.

Note

You cannot change the icon image used for your application on the taskbar button of your application window (on Windows). That image is always the image you specified as the icon image in your application descriptor file (see Setting the Default Program Menu Folder).

The following example creates an animated system tray or Dock icon (depending on the user’s operating system) by constantly changing the icon at a given time interval, similar to the way a traditional GIF animation works, sequencing images over time.

As you did earlier, you first load the different sizes of the primary icon image. This time you load a second set of icon images with the slightly altered versions of the primary icon with some color changes. When you continuously change the icon to one of those two icon images, the user has the illusion that the icon is flashing in your system tray or Dock.

ActionScript/Flex

You implement the “flashing icon” behavior by using a Timer object with a timer interval set to 500 milliseconds. The Timer class gives you the possibility of running code on a specific time sequence. You have to set up an event listener for the TimerEvent.TIMER event, and then at each interval, the changeIcon function is executed that assigns the new array of images to the icon.bitmaps property. These parts of the code are highlighted in bold.

Here is the full MXML code:

<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml"
    applicationComplete="init()"
    layout="absolute">


    <mx:Script >
        <![CDATA[
            import mx.core.BitmapAsset;
            [Embed(source="app:/assets/icons/flashing/Icon_fl_128.png")]
            public var img128:Class;

                [Embed(source="app:/assets/icons/flashing/Icon_fl_48.png")]
            public var img48:Class;

                [Embed(source="app:/assets/icons/flashing/Icon_fl_32.png")]
            public var img32:Class;

            [Embed(source="app:/assets/icons/flashing/Icon_fl_16.png")]
            [Bindable]
            public var img16:Class;
            [Embed(source="app:/assets/icons/Icon_128.png")]
            [Bindable]
            public var imgfl128:Class;
            [Embed(source="app:/assets/icons/Icon_48.png")]
            [Bindable]
            public var imgfl48:Class;
            [Embed(source="app:/assets/icons/Icon_32.png")]
            [Bindable]
            public var imgfl32:Class;
            [Embed(source="app:/assets/icons/Icon_16.png")]
            [Bindable]
            public var imgfl16:Class;

             private var iconfl128:BitmapData
             private var iconfl48:BitmapData
             private var iconfl32:BitmapData
             private var iconfl16:BitmapData
             private var icon128:BitmapData
             private var icon48:BitmapData
             private var icon32:BitmapData
             private var icon16:BitmapData

            private function init():void{
                //define bitmapData object
                icon128= (new img128()as BitmapAsset).bitmapData;
                icon48= (new img48()as BitmapAsset).bitmapData;
                icon32= (new img32()as BitmapAsset).bitmapData;
                icon16= (new img16()as BitmapAsset).bitmapData;
                iconfl128= (new imgfl128()as BitmapAsset).bitmapData;
                iconfl48= (new imgfl48()as BitmapAsset).bitmapData;
                iconfl32= (new imgfl32()as BitmapAsset).bitmapData;
                iconfl16= (new imgfl16()as BitmapAsset).bitmapData;
                //define timer object

                var tmr:Timer = new Timer(500);
                tmr.addEventListener(TimerEvent.TIMER,changeImage);
                tmr.start();
            }

            private function changeImage(event:TimerEvent):void{
                if(event.target.currentCount%2){
                    this.nativeApplication.icon.bitmaps 
=[icon128,icon48,icon32,icon16];
                }else{

                    this.nativeApplication.icon.bitmaps 
=[iconfl128,iconfl48,iconfl32,iconfl16];
                }
            }
        ]]>
    </mx:Script>
</mx:WindowedApplication>

JavaScript

In JavaScript, you use an air.Timer object to create the illusion of a flashing icon. Every time the air.TimerEvent.TIMER event is dispatched, you execute the changeImage function that assigns one of the two icons to the icon.bitmaps property of the air.NativeApplication.nativeApplication instance.

<html >
<head>
<title>Recipe 13.4: CHANGING THE DOC OR TASKBAR ICON</title>

<script src="AIRAliases.js" type="text/javascript"></script>

<script type="text/javascript">

var iconsNormal = ["Icon_16.png","Icon_32.png"];
var iconsFlashing = ["Icon_fl_16.png","Icon_fl_32.png"];

//arrays that hold the icons there bitmapdata
var bitmapDataArrNormal =[];
var bitmapDataArrFlashing =[];

function iconNormalComplete(event) {
        bitmapDataArrNormal.push(event.target.content.bitmapData);
}
function iconFlashingComplete(event) {
        bitmapDataArrFlashing.push(event.target.content.bitmapData);
}
function init(){

    //load the icons
    loadIcons(iconsNormal,0);
    loadIcons(iconsFlashing,1)
    //start a new timer to change the icon
    //every 500 miliseconds
    var tmr = new air.Timer(500);
    tmr.addEventListener(air.TimerEvent.TIMER,changeIcon);
    tmr.start();
}

function changeIcon(event){
    //
    if(event.target.currentCount%2){
        air.NativeApplication.nativeApplication.icon.bitmaps = 
bitmapDataArrNormal;
    }else{
        air.NativeApplication.nativeApplication.icon.bitmaps = 
bitmapDataArrFlashing;
    }
}
function loadIcons(arr,flag){
    for(var i=0;i<arr.length;i++){
        //define the loader
        var iconLoad = new air.Loader();
        //register the right listener
        if(flag){
            iconLoad.contentLoaderInfo.addEventListener(air.Event.COMPLETE,iconFlashingComplete);
        }else{
            iconLoad.contentLoaderInfo.addEventListener(air.Event.COMPLETE,iconNormalComplete);
        }
        //load the icon image
           iconLoad.load(new air.URLRequest("assets/"+ arr[i]));
    }
}
</script>
</head>
<body onLoad="init()">
</body>
</html>

Notifying the User Through the Dock (Mac)

Problem

You want to attract the user’s attention through the Dock.

Solution

If the operating system supports window-level notification, you can make the Dock icon “bounce” by calling the DockItem.bounce method.

Discussion

You can pass a NotificationType to the bounce method to inform the user that something critical has happened (the application continuously bounces until the application is in the foreground) or just to give the user some information (a single bounce). The two appropriate NoticationType constants are NotificationType.CRITICAL and NotificationType.INFORMATIONAL. To determine whether the operating system has this notification capability, you access NativeWindow.supportsNotification.

ActionScript

The following example shows a small application that has two buttons defined. When clicked, the buttons notify the user in either a critical or informational way. After checking that the operating system supports Dock icons, you can cast the NativeApplication.icon property to an instance of the DockIcon class.

<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml"
    layout="vertical"
    title="Recipe 13.5: Bouncing the dock icon (MAC)"
    deactivate="bounce()" >

   <mx:Script >
       <![CDATA[

           private function bounce():void
           {
               if (NativeApplication.supportsDockIcon)
               {
                   var myIcon:DockIcon = NativeApplication.nativeApplication.icon 
as DockIcon;
                   var type:String = critical.selected ? NotificationType.CRITICAL 
: NotificationType.INFORMATIONAL;
                   myIcon.bounce(type);
               }
           }

       ]]>
   </mx:Script>
   <mx:RadioButtonGroup id="notificationType" />
   <mx:RadioButton id="critical" group="{notificationType}" label="NOTIFY THE USER 
CRITICAL" selected="true"/>
   <mx:RadioButton id="informational" group="{notificationType}" label="NOTIFY THE 
USER INFORMATIONAL"/>
</mx:WindowedApplication>

JavaScript

In AIR, you define the notification types in the air.NotificationType class. You can bounce the icon of the air.NativeApplication instance by calling the bounce method:

<html >
   <head>
   <title>Recipe 13.5: Bouncing the dock icon (MAC)</title>
   <script src="AIRAliases.js" type="text/javascript"></script>
   <script type="text/javascript">

      function notify()
      {
         if (air.NativeApplication.supportsDockIcon)
         {
            var critical = document.getElementById("critical");
            var type = (critical.checked ? air.NotificationType.CRITICAL : 
air.NotificationType.INFORMATIONAL);
            if (air.NativeApplication.supportsDockIcon)
            {
               air.NativeApplication.nativeApplication.icon.bounce(type);
            }
         }
      }

      function setListener()
      {
         nativeWindow.addEventListener('deactivate', notify);
      }


   </script>
</head>
   <body onload="setListener()">
      <form >
          <div><input id="critical" type="radio" name="notify" value="NOTIFY THE 
USER CRITICAL" checked="checked" />NOTIFY THE USER CRITICAL</div>
          <div><input id="information" type="radio" name="notify" value="NOTIFY THE 
USER INFORMATIONAL" />NOTIFY THE USER INFORMATIONAL</div>
      </form>
   </body>
</html>

Notifying the User Through the Taskbar (Windows)

Problem

You want to attract the user’s attention through the taskbar.

Solution

If the operating system supports window-level notification, you can make the taskbar and window flash by calling the NativeWindow.notifyUser method.

Discussion

You can pass a NotificationType to the notifyUser method to inform the user that something critical has happened (the taskbar flashes until the application is in the foreground) or just to give the user some information (the taskbar and window flashes only ones). The two appropriate NoticationType constants are NotificationType.CRITICAL and NotificationType.INFORMATIONAL. To determine whether the operating system has this notification capability, you access NativeWindow.supportsNotification.

ActionScript

The following example shows how to implement this notification with the NativeWindow class. When the application window is deactivated (is not on the foreground), the taskbar and window flash to get the attention of the user:

<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml"
    layout="vertical"
    title="Recipe 13.6: Flashing the window/taskbar (WINDOWS)"
    deactivate="notify()"
    >

    <mx:Script >
        <![CDATA[

            private function notify():void{
                if(NativeWindow.supportsNotification && 
NativeApplication.supportsSystemTrayIcon){
                    var type:String = critical.selected ? NotificationType.CRITICAL 
: NotificationType.INFORMATIONAL;
                    this.nativeWindow.notifyUser(type);
                }
            }
        ]]>
    </mx:Script>

    <mx:RadioButtonGroup id="notificationType" />
        <mx:RadioButton id="critical" group="{notificationType}" label="NOTIFIY THE 
USER CRITICAL"
            selected="true"/>
    <mx:RadioButton id="informational" group="{notificationType}" label="NOTIFIY 
THE USER INFORMATIONAL"/>

</mx:WindowedApplication>

JavaScript

The following example shows how to implement the notification with the air.NativeWindow class. When the application window is deactivated (is not on the foreground), the taskbar and window flash to get the attention of the user:

<html >
<head>
<title>Recipe 13.6: Flashing the system tray icon (WINDOWS)</title>
<script src="AIRAliases.js" type="text/javascript"></script>
<script type="text/javascript">

function notify(){
    if(air.NativeApplication.supportsSystemTrayIcon && 
air.NativeWindow.supportsNotification) {
        var critical = document.getElementById('critical'),
        var type = (critical.checked ?  air.NotificationType.CRITICAL
 : air.NotificationType.INFORMATIONAL);
        nativeWindow.notifyUser(type);
    }
}
function setListener(){
    nativeWindow.addEventListener('deactivate',notify);
}
</script>
</head>
<body onLoad="setListener()">
<form >
 <div><input id="critical" type="radio" name="notify" value="NOTIFY THE USER 
CRITICAL" checked="checked" />NOTIFY THE USER CRITICAL</div>
 <div><input id="information" type="radio" name="notify" value="NOTIFY THE USER 
INFORMATIONAL" />NOTIFY THE USER INFORMATIONAL</div>
</form>
</body>
</html>
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset