Memovox, AIR still on top

Two years ago, we coded a beautiful app named Geophysic for the famous luxary watches brand Jaeger-LeCoultre. Made with the cross-platform technology Adobe AIR, and Starling & Feathers, we finished the dev diary asking which other technologies could have done the app, but didn’t get a strong answer.
Today, with Pixelfordinner agency, we’re proud to share this new app named Wake-Up Memovox, for the same client, available for iOS and Android.
It was developed with the same technology, and if it’s obvious the game development market moves in favour of Unity, AIR is still rocking for making apps! Let’s see the development part!

Graphics pipeline
Working for Jaeger-LeCoultre is synonymous with a high precision, the app must be pixel perfect! I’m not a big fan of measuring everything in Photoshop but didn’t know strong alternative. Hopefully Pixelfordinner introduced Zeplin as a walkway between designers & developers. This is an ultimate tool for getting easily measurements, colors, updated graphics, and annotate & comment sketches. Most recommended!
zeplin screenshot

Date
Making an alarm clock application, you can’t miss dealing with date operations. AS3 Date object offers less options than C# or Php’s Date, but it did the job pretty well. The hardest part was to determine for a given day the next time it occurs:

// I want the next sunday:
var dayNumber:uint = 0; //(0 sunday, 1 monday...)
var date:Date = new Date();
var dayUntil:uint = (dayNumber - date.day + 7) % 7;
date.date += dayUntil;

Also I’d to manage day recurrences and snooze.

Background process
Due to iOS Sandbox mode, you can’t make a wake-up application similar to the native one. But you can’t miss the alarm clock neither, isn’t it? So the app must be running in background! For checking alarm clock while your app is in background, you have to enable:

NativeApplication.nativeApplication.executeInBackground = true;

You won’t be able to do stage3D operation on iOS (be careful!), but the app can execute code and so vibrate device, play sound etc.

// if you want to hear a sound while your app is in background add:
SoundMixer.audioPlaybackMode = AudioPlaybackMode.MEDIA;

On iOS, you have to specify the UIBackgroundModes, add this code in your *-app.xml:

<key>UIBackgroundModes</key>
<array>
	<string>audio</string>
</array>

Still on iOS, I’d to put up two tricks:
– For whatever reason on Adobe AIR, a sound won’t play when the screen is black. So I fire a local notification to wake-up the screen.
– Be sure to keep your sound channel alive, just pause/resume the alarm song, otherwise iOS may “lose” the sound and it takes ages for being heard!

On Android, an application can wake-up itself, even if it’s killed! It’s a top gun feature for an alarm clock app, so I asked Distriqt (ANEs provider) if they supported the Android’s AlarmManager API. At that time they didn’t, but quickly they added it to the Application ANE, wonderful!

Saving ringtone on device
Among the features requested, we’d to be able to save the ring alarm as a ringtone so it could be used with the native app.

On iOS, we’d to enable file sharing, add in the -*app.xml:

<key>UIFileSharingEnabled</key>
<true/>

Then we just have to copy & paste the local wav file in File.documentsDirectory.

For Android, I tried to put this file at different places on the device but it wasn’t recognized directly as a ringtone. After looking the documentation, I found some metadatas were requested. Unfortunately I didn’t find an ANE, so I wrote my own.

Lang, many lang!
In addition to the Latin languages, this app supports traditional and simplified Chinese, Korean, Japanese and Russian. The weight of the fonts is 30Mo! The default language is English, so I don’t need to have all the fonts ready when I start the app if they are not required. So I created a SWF per font (not a SWC since I don’t want to waste memory), then at runtime loading the required font if needed.

var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, function(evt:Event):void {
	
	loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, arguments.callee);
	
	//trace(loader.contentLoaderInfo.applicationDomain.hasDefinition(_dicTypo[currentLang].font));
	
	var fontClass:Class = loader.contentLoaderInfo.applicationDomain.getDefinition(_dicTypo[currentLang].font) as Class;
	Font.registerFont(fontClass);
	TextField.updateEmbeddedFonts();
	
	//trace(Font.enumerateFonts(false));
	
	_dicTypo[currentLang].loaded = true;
});

loader.load(new URLRequest("swfs/" + _currentLang + ".swf"), new LoaderContext(false, ApplicationDomain.currentDomain));

// dictionnary is defined like: _dicTypo["ja"] = {font:"HonokaMincho", loaded:false};

Due to SWF restriction on iOS, I won’t be able to unload it later but it didn’t really change if I added them via a SWC or embed.

Video
The app was made with AIR 23, so before Adobe added asynchronous texture upload (the final piece of cake). VideoTexture wasn’t running well if uploading textures at the same time. I tested with StageVideo and it was working fine on iOS! There are some troubles with StageVideo and Android, unfortunately AIR 24 wasn’t fully stable, so no video intro on Android yet.

AIR shine and other tech?
With latest AIR updates (Workers, VideoTexture, asynchronous texture upload), Adobe has a strong platform in its hands. Which other cross-platform technologies could have done this app?

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.