The Adobe Developer Center has posted a couple of video training pieces on Flash Lite: one on Flash Cast and one on Flash Lite 1.1. They’re kind of a companion set, since if you’re not doing Flash Cast development or dev for the Japanese market, I don’t know why you’d be targeting FL 1.1 these days.
Archive for the ‘Flash Lite 1.1’ Category
New Flash Lite Video Training
Thursday, December 18th, 2008MAX 2008 Tips and Tricks Demo Files
Monday, November 24th, 2008Last week’s MAX conference was a blast – Alessandro did a great job of summarizing all of the exciting new developments in the mobile space for Flash developers, so I won’t rehash those here. Adobe did a fantastic job of putting together an excellent set of sessions on Flash Lite/mobile development, and the other organized events were equally, if not even more, worthwhile to attend. On a general note, it was great to meet a wide range of people who were either involved in or were exploring mobile development – beyond the usual Flash Lite suspects I met a bunch of people from companies all over the world that are seriously considering Flash Lite, and I think that speaks to the current and future health of the mobile part of the Flash ecosystem.
On a personal note, I had a great time presenting in the “Twenty Tips and Tricks” session – unfortunately I think that Monday’s session was not the best of my three cracks at it, but that’s the one that’ll get posted to Adobe TV eventually! As promised, I’m also posting the files that I used to demo/explain some of my tips and tricks. Feel free to use any of the code in your projects in any way you wish. No need to provide any kind of attribution, but if you find these code samples informative and/or actually do use them in one of your projects, please drop me an email to let me know! The files are all for the latest version of Flash, so you’ll need CS4 installed to use them.
Hope to see you at MAX 2009 in Los Angeles – don’t know if I’ll be presenting again (although I’d like to) but even if I’m not I’ll definitely be there!
Flash Lite 1.1 array sorting
Sunday, March 16th, 2008The question of how to sort emulated arrays came up on one of the Flash Lite email lists, so I thought I’d post my solution here.
// fake array
p1 = 5;
p2 = 3;
p3 = 6;
p4 = 2;
p5 = 9;
arrayLength = 5;
// sort
for (outer = 1; outer < arrayLength; outer++) {
for (inner = outer + 1; inner <= arrayLength; inner++) {
if (eval("p" add inner) > eval("p" add outer)) {
tempVal = eval("p" add outer);
eval("p" add outer) = eval("p" add inner);
eval("p" add inner) = tempVal;
}
}
}
// show results
for (i = 1; i <= arrayLength; i++) {
trace(eval("p" add i));
}
The code is pretty straightforward - basically you're just looping through each value in the array, comparing that value to all of the other values in the array. If another value is larger, you swap the two values. The result is an array sorted from highest value to lowest. If you want to sort from lowest to highest, simply change the 'greater than' in the if() statement to a 'less than', and you're good to go.
One thing to be careful of is if you're sorting a very large number of values. The nested for loops can result in a large number of iterations, and could cause your movie to hang. If that happens, simply break the code over multiple frames, using counters and conditionals to iterate through the array.
Flash Lite 1.1: Rotation toward a point
Sunday, March 2nd, 2008Rotating a movie clip so that it point toward a specific point is a handy little technique. If you’re using Flash Lite 2 and up, it’s pretty easy; this code will do it for you:
// 'point' is what we want to rotate toward
pointX = 50;
pointY = 50;
// 'rotater' is the clip that we want to rotate,
// so that it's pointing toward 'point'
rotaterX = 100;
rotaterY = 100;
// get the X and Y distances between the two objects
dX = pointX - rotaterX;
dY = pointY - rotaterY;
// find the angle between the two objects
radians = Math.atan2(dY, dX);
// convert from radians to degrees
angle = radians * 180 / Math.PI;
// apply the angle
radar._rotation = angle;
What makes this such a simple technique is the use of Math.atan2(), which does all the heavy lifting.
The Math class is available in Flash Lite 1.1, which is based on Flash 4 ActionScript. But, as the help docs in Flash 8 (although not Flash CS3) say, “In Flash Player 4, the methods and properties of the Math class are emulated using approximations and might not be as accurate as the non-emulated math functions that Flash Player 5 supports.” Math.atan2 is one area where the Math class is inaccurate. The result of this is that rotation toward a point only works as expected when the _x value of the point is larger than the _x value of rotating object.
The work-around for this is some extra code that checks the exact position of the point object, and adjusts the value of the angle accordingly. This sample file shows how all of this works. If you publish this as a Flash Lite 1.1 file, you’ll see that the arrow doesn’t point in the right direction when the ball is to the left of the arrow. If you publish the file as a Flash Lite 2 or higher file, the code works as expected. To get it to work in Flash Lite 1.1, you need to uncomment the conditional code in the second frame.
'Hacking' dynamic text fields inFlash Lite 1.1
Thursday, August 16th, 2007Positioning content around dynamic text fields in Flash Lite 1.1 can be very difficult. While you can make the text field any size you want when you’re developing your content, there’s no way to directly increase the size of the text field via ActionScript. This can create a problem if you don’t know how much text will end up in the text field – if the field is too small, not all of the text will show up.
To get around this, you could simply make the text field really big, so that it is certain to contain all of the text that it might end up displaying. This would work, but it makes the placement of other assets on the stage difficult. So one of three things can occur:
There’s not enough room in the text field for the text. In this case, the content underneath the text field lines up nicely with the bottom of the text. But you can’t read all of the text because the text field is too small:

Or, the the text field is big enough, but now the text overlaps the other content:

Or, there will be a large white space because there’s not enough text to fill the field. The text field is large enough to accomodate more text, and the main content has been moved down so that it won’t overlap any of the text. However, since the actual text in the text field is minimal, it creates wasted space between the text and the content:

(I added the dashed outlines so you could see how large I made the text fields in the IDE.)
I’m going to illustrate two fairly simple methods of using the maxscroll property of the text field to position other content. The Flash help docs define maxscroll as a read-only property that “indicates the line number of the first visible line of text in a scrollable text field when the last line in the field is also visible.”
Our first method will use ActionScript to position our other content based on the value of maxscroll. It’s a pretty simple set-up in Flash, with only three frames required:

The first layer is the standard actions layer. The second layer contains our text field, and the ‘bg’ layer contains the content we want to position. The text field layer is what makes the trick work. The first keyframe contains a text field that is one line high. The second keyframe has a much larger text field. We’ll see why in a second.
(You may have noticed that the two keyframes are spread across three frames. The first keyframe assigns a value to the variable displayed in the text field. However, the value of maxscroll isn’t available until the end of that frame. So the first time you can check the value of maxscroll is in the next frame of the clip. We therefore need this one frame ‘buffer’ to get the proper value for maxscroll. You can test this by tracing the value of txtToFit.maxscroll in the first and second frames. The thing to remember is that however you apply this method, you’ll need to have this buffer, or else these methods won’t work.)
On the stage, we have the one-line text field, and the other content. These are positioned at the same spot (the orange rectangle is the content to be positioned; the dashed line is the outline of the text field):

Since the text field will not be moving, it should be placed wherever you want the text to be. Remember that we’ll be moving the other content after we determine maxscroll. The initial position is just our starting reference point.
To start with, we need to figure out the total number of lines. We do this using the one-line text field. If we get the value of maxscroll when the field is one line high, then maxscroll represents the total number of lines of text when all of the text is visible. So if maxscroll == 7, then there are seven lines of text. Remember that the text field at this point must be one line high; if it’s larger than that, you’ll get a different value for maxscroll and this method won’t work.
After assigning a value to the variable in the first frame, in the second frame can then use the value of maxscroll to calculate the new position for the other content. Here’s the code for that:
multiplier = 17;
deltaY = txtToFit.maxscroll * multiplier;
contentCurrentY = getProperty("content_mc", _y);
setProperty("content_mc", _y, contentCurrentY + deltaY);
The first line simply calculates how far we need to move the content down the screen; the value is a multiple of maxscroll. By the way, the value for multiplier is no magic number; it was selected on the basis of trial and error to find out what value works best with the particular font being used in the text field. You’ll have to do some testing to determine what works best for your situation.
The second line gets the current position of the content movie clip, and the third line simply moves the content down the screen by adding deltaY to the current _y value of the content. We also increase the size of the text field so that it now shows all of the text. Since we can’t do that via ActionScript, we advance to the second keyframe, in which we have a larger text field. And that’s all there is to it. Here’s what you get:

This method is a little cleaner than the second method I’m about to show you. One downside to the first method is that it can be difficult to find a multiplier that works well with every possible value of maxscroll that you might have. The result can be less than pixel-perfect precision in the placement of your elements. The second method, while somewhat more involved than the first method, allows for that level of precision.
The second method is also quite simple: create a movieclip, and on successive frames make the dynamic text field large enough to fit an additional line of text. We start with the first frame, which again has a one-line text field. We check the value of maxscroll. If maxscroll == 1, then we can stop here because we know all the text is visible. If maxscroll is not 1, then we go to the next frame, with the slightly larger text field, and repeat the process. In each of these frames, the other content is repositioned to line up with the text field. You can repeat this over as many frames as you like.
The movieclip is set up like this:

Notice that the ‘buffer’ frame is present again, so that we can get a proper value for maxscroll. If you wanted to place other content, you can create additional layers and position the elements as needed. Now let’s walk through the code. There’s not much too it!
In the first frame of the clip, we have:
_visible = false;
txtToFit = "here is the test text";
I’ve hidden the movie clip because otherwise you get a bit of an animation while the clip seeks out the frame to stop at. Once we’ve found that frame, we’ll display the clip again. I’ve set the value of the text field in this frame, but depending on how your app is set up, this may get done elsewhere. If you download the sample files, you can add more text to see how this works. The second, third, and fourth frames all contain the same single line of code:
call("checkfit");
Since Flash Lite 1.1 doesn’t support functions, we have to emulate functions through the use of call(). This executes the code of another frame within the frame containing the call() statement. This way, we only have to write the code once and can re-use it many times. In this case, we want to execute the code in the ‘checkfit’ frame. That code is what makes this whole thing work:
if (txtToFit.maxscroll == 1) {
stop();
_visible = true;
}
And that’s it! All we’re doing is checking to see if the value of maxscroll equals one; if it does, we know that all of the text fits inside the text field, so we can stop at this frame. We also set _visible to true so that we can see the movieclip containing our text field. I won’t include screenshots for this method since the shots for method one give you the idea of what’s happening.
You can download sample files to see how these work: Dynamic text sample files
Here are a few things to keep in mind:
This is meant for only relatively limited circumstances, where you don’t know for sure whether the content for a text field will stretch across, say, one to three lines (as in the example). For example, if you’re reading book or CD titles from a database, this would work nicely. If you don’t know how much text you’ll need to display, this may not be the best method for your needs.
Also, I’ve embedded the font used in the text field rather than using a device font. Since device fonts will vary across devices, embedding a font means I can figure how large to make the text fields for each keyframe, and that will work across devices. The method will work with device fonts, of course, but the variation in font size across devices can effect how consistently this will work.
Finally, a slightly quicker way of doing the second method would have been to read the value of maxscroll in the second frame, then jump to a subsequent frame based on that value.
Hope you find this helpful!
For want of a minus sign
Thursday, July 19th, 2007It’s amazing what a difference a minus sign can make: it is, in fact, the difference between Winnipeg and Mumbai – at least from the perspective of UTC (or Greenwich Mean Time) offsets. Winnipeg is UTC – 5 hours, Mumbai is UTC + 5 hours. But a bug in Flash Lite has Winnipeg, and every other place in UTC – 5, way over on the other side of the world.
If you want to find out the time zone offset on a device running Flash Lite, you can use:
fscommand2("GetTimeZoneOffset", "timezoneoffset");
If the device supports this particular command, then timezoneoffset is set to the number of minutes between the time zone on the user’s device and UTC. This number would be plus or minus depending upon the side of Greenwich that particular time zone is on. In Winnipeg, since it’s at UTC – 5 hours, GetTimeZoneOffset should return a value of -300.
But, here’s what gets returned for Winnipeg on the various devices I have at my disposal:
| Device | FL 1.1 | FL 2.0 | FL 2.1 |
|---|---|---|---|
| Nokia E65 | 300 | n/a | -300 |
| Nokia 5300 | n/a | -300 | n/a |
| Nokia 6620 | n/a | 300 | n/a |
‘n/a’ means that version of Flash Lite was not tested on that device. In most cases, that version is simply not available on that device. While the 6620 can run FL 1.1, I don’t have it installed and didn’t bother installing it to test this.
(I also tested this on a Nokia 6131, a series 40 device with FL 1.1 pre-installed. It doesn’t seem to support GetTimeZoneOffset at all, so there’s no value in including it in this test. In fact, not supporting GetTimeZoneOffset at all would be preferable to buggy support. GetTimeZoneOffset fails in an interesting way on the 6131: the command appears to return nothing at all. Normally, fscommand2 arguments will return -1 if they’re not supported. Returning nothing means it’s necessary to test not just for -1 if you want to see if an fscommand2 is supported.)
Using the UTC time zone offset to calculate the time in another time zone is admittedly not foolproof: it assumes that the user has set the time zone on their device properly to correspond to their actual local time. Nevertheless, it seems that GetTimeZoneOffset is only reliable on newer devices that run at least FL 2.0.
(Note: you can use the Date object if you’re coding in FL 2.x. But the Date object is not supported in FL 1.1, so if you want to support both 1.1 and 2.x devices, that means using GetTimeZoneOffset.)
(Note2: this post has been edited to correct some time zone mistakes I made in the original post.)
Installing Flash Lite 1.1 and Flash Lite 2.0 on the same device
Friday, February 23rd, 2007(I wrote this about a year ago, when Adobe was still offering Flash Lite 2.0 for download and most developers were working with S60 2nd Edition devices, which did not have any version of Flash Lite pre-installed. Now that devices are on the market that have 1.1 (or 2.0) pre-installed, this information isn’t really useful to very many people. Also, if you have a S60 3rd Edition device and are installing Flash Lite 2.1 on top of the pre-installed 1.1, you don’t need to go through all these steps. But a lot of people have ended up on the original page that contained this information, so I thought I’d keep it up, in case it’s helpful to somebody.)
In my experience , if you try to install Flash Lite 2.0 on a phone that has 1.1 already installed, 2.0 will overwrite 1.1. However, it’s possible, and relatively easy (once you’ve figured it all out) to run Flash Lite 1.1 and 2.0 on the same phone. Alessandro posted a suggestion on his blog for how to get 1.1 and 2.0 installed on the same phone, and I’m happy to report that it works. I’ll recreate his steps here and add in some extra detail for those who want to try this on their own. Thanks to Alessandro for posting the suggestion, and keep in mind that although this worked out fine for me, you do this at your own risk and Ludicrous Software isn’t responsible if something goes wrong and your phone starts staying out late at night and not calling to tell you when it’ll be coming home.
1. Unsis one of the players on your PC
There are a bunch of programs out there to do this. Unsis requires perl to be installed on your system, and UnMakeSIS has a pretty straightforward GUI. I used Unsis, which created a folder called “system”, and contains subfolders called “apps”, “data”, “help”, “libs”, and “recogs”. If your folder is not called “system”, rename it to that, to make things easier on yourself later.
2. Create a pkg file and 3. replace the UID with another one and make any necessary changes to file names)
Here’s what I slapped together based on the helloworld.pkg file that comes with the Symbian SDK. It probably ain’t pretty, but it works nicely. I called my file “flash2.pkg”. Notice that all of the file paths start with the “system” folder. If you didn’t feel the need to make sure that your folder is called “system” in step one, either change it now, or change the pkg file to whatever your folder is called.
I changed the UID to one of the numbers that had been assigned to me by Symbian. Feel free to use it, or change it to one that has been assigned to you.
; Flash2.pkg
;
;Language - standard language definitions
&EN
;standard SIS file header
;the UID has been changed from its original value.
;feel free to change it to something else if you wish.
#{"Flash2"},(0x10275722),2,0,0
;Supports Series 60 v2.0
;Commented this out because I didn't know if it was necessary.
;If you comment it out, you get a warning that the product may
;not be compatible with your system, and asking if you want to
;continue. Continue.
;(0x101F7960), 0, 0, 0, {"Series60ProductID"}
"systemappssaflash2saflash2.aif"-"!:systemappssaflash2saflash2.aif"
"systemappssaflash2saflash2.app"-"!:systemappssaflash2saflash2.app"
"systemappssaflash2saflash2.rsc"-"!:systemappssaflash2saflash2.rsc"
"systemappssaflash2saflash2_caption.rsc"-"!:systemappssaflash2saflash2_caption.rsc"
"systemdata101fb454.dat"-"C:systemdata101fb454.dat"
"systemdataflash2engine.rsc"-"!:systemdataflash2engine.rsc"
"systemdataflash2ui.mbm"-"!:systemdataflash2ui.mbm"
"systemdataflash2ui.rsc"-"!:systemdataflash2ui.rsc"
"systemhelpsaflash2.hlp"-"!:systemhelpsaflash2.hlp"
"systemlibsflash2.dll"-"!:systemlibsflash2.dll"
"systemlibsflash2engine.dll"-"!:systemlibsflash2engine.dll"
"systemlibsflash2snddec.dll"-"!:systemlibsflash2snddec.dll"
"systemlibsflash2ui.dll"-"!:systemlibsflash2ui.dll"
"systemrecogsrecswf2.mdl"-"!:systemrecogsrecswf2.mdl"
4. Create a SIS using makesisGiven the way the pkg file is written, the pkg file and the “system” folder need to be in the same location. So I had a “test” folder containing the pkg file and the “system” folder. You need to run makesis from within the “test” folder. The command is “makesis -v flash2.pkg”. The verbose option isn’t strictly necessary, but it’s always nice to see what’s going on.
5. Try to install
Should proceed as normal, except for the additional warning about compatibility. The only downside to this is that you’ll end up with two icons on your phone, both called “Flash”, so you’ll have to remember that the silvery one is 1.1, and the blue one is 2.0. I think that in order to make the icon name different, you’d need to recreate the aif file contained in the sis (I think). If anybody has any other suggestions, let me know!