{"id":500,"date":"2017-01-06T11:18:00","date_gmt":"2017-01-06T10:18:00","guid":{"rendered":"http:\/\/davikingcode.com\/blog\/?p=500"},"modified":"2017-01-06T11:29:24","modified_gmt":"2017-01-06T10:29:24","slug":"memovox-air-still-on-top","status":"publish","type":"post","link":"https:\/\/davikingcode.com\/blog\/memovox-air-still-on-top\/","title":{"rendered":"Memovox, AIR still on top"},"content":{"rendered":"<p>Two years ago, we coded a beautiful app named <a href=\"http:\/\/www.aymericlamboley.fr\/blog\/geophysic-making-air-shine-thanks-to-feathers\/\" target=\"_blank\">Geophysic<\/a> for the famous luxary watches brand <a href=\"http:\/\/www.jaeger-lecoultre.com\" target=\"_blank\">Jaeger-LeCoultre<\/a>. Made with the cross-platform technology Adobe AIR, and <a href=\"http:\/\/gamua.com\/starling\/\" target=\"_blank\">Starling<\/a> &amp; <a href=\"https:\/\/feathersui.com\/\" target=\"_blank\">Feathers<\/a>, we finished the dev diary asking which other technologies could have done the app, but didn&#8217;t get a strong answer.<br \/>\nToday, with <a href=\"https:\/\/pixelfordinner.com\/\" target=\"_blank\">Pixelfordinner<\/a> agency, we&#8217;re proud to share this new app named Wake-Up Memovox, for the same client, available for <a href=\"https:\/\/itunes.apple.com\/us\/app\/wake-up-memovox\/id1175403937?mt=8\" target=\"_blank\">iOS<\/a> and <a href=\"https:\/\/play.google.com\/store\/apps\/details?id=air.com.jaeger_lecoultre.Memovox\" target=\"_blank\">Android<\/a>.<br \/>\nIt was developed with the same technology, and if it&#8217;s obvious the game development market moves in favour of Unity, AIR is still rocking for making apps! Let&#8217;s see the development part!<br \/>\n<a href=\"http:\/\/davikingcode.com\/blog\/wp-content\/uploads\/2017\/01\/watch.jpg\"><img loading=\"lazy\" class=\"size-medium wp-image-545 alignleft\" src=\"http:\/\/davikingcode.com\/blog\/wp-content\/uploads\/2017\/01\/watch-169x300.jpg\" alt=\"\" width=\"169\" height=\"300\" srcset=\"https:\/\/davikingcode.com\/blog\/wp-content\/uploads\/2017\/01\/watch-169x300.jpg 169w, https:\/\/davikingcode.com\/blog\/wp-content\/uploads\/2017\/01\/watch.jpg 506w\" sizes=\"(max-width: 169px) 100vw, 169px\" \/><\/a><a href=\"http:\/\/davikingcode.com\/blog\/wp-content\/uploads\/2017\/01\/watch_night.jpg\"><img loading=\"lazy\" class=\"size-medium wp-image-547 alignleft\" src=\"http:\/\/davikingcode.com\/blog\/wp-content\/uploads\/2017\/01\/watch_night-169x300.jpg\" alt=\"\" width=\"169\" height=\"300\" srcset=\"https:\/\/davikingcode.com\/blog\/wp-content\/uploads\/2017\/01\/watch_night-169x300.jpg 169w, https:\/\/davikingcode.com\/blog\/wp-content\/uploads\/2017\/01\/watch_night.jpg 506w\" sizes=\"(max-width: 169px) 100vw, 169px\" \/><\/a><a href=\"http:\/\/davikingcode.com\/blog\/wp-content\/uploads\/2017\/01\/alarms.jpg\"><img loading=\"lazy\" class=\"size-medium wp-image-550 alignleft\" src=\"http:\/\/davikingcode.com\/blog\/wp-content\/uploads\/2017\/01\/alarms-169x300.jpg\" alt=\"\" width=\"169\" height=\"300\" srcset=\"https:\/\/davikingcode.com\/blog\/wp-content\/uploads\/2017\/01\/alarms-169x300.jpg 169w, https:\/\/davikingcode.com\/blog\/wp-content\/uploads\/2017\/01\/alarms.jpg 506w\" sizes=\"(max-width: 169px) 100vw, 169px\" \/><\/a><br \/>\n<!--more--><\/p>\n<div style=\"display:block; clear:both;\"><\/div>\n<p><strong>Graphics pipeline<\/strong><br \/>\nWorking for Jaeger-LeCoultre is synonymous with a high precision, the app must be pixel perfect! I&#8217;m not a big fan of measuring everything in Photoshop but didn&#8217;t know strong alternative. Hopefully Pixelfordinner introduced <a href=\"https:\/\/zeplin.io\/\" target=\"_blank\">Zeplin<\/a> as a walkway between designers &amp; developers. This is an ultimate tool for getting easily measurements, colors, updated graphics, and annotate &amp; comment sketches. Most recommended!<br \/>\n<img src=\"https:\/\/zeplin.io\/img\/sneakpeek\/ssTypeface.png\" alt=\"zeplin screenshot\" \/><\/p>\n<p><strong>Date<\/strong><br \/>\nMaking an alarm clock application, you can&#8217;t miss dealing with date operations. AS3 Date object offers less options than C# or Php&#8217;s Date, but it did the job pretty well. The hardest part was to determine for a given day the next time it occurs:<\/p>\n<pre class=\"brush: as3; title: ; notranslate\" title=\"\">\r\n\/\/ I want the next sunday:\r\nvar dayNumber:uint = 0; \/\/(0 sunday, 1 monday...)\r\nvar date:Date = new Date();\r\nvar dayUntil:uint = (dayNumber - date.day + 7) % 7;\r\ndate.date += dayUntil;\r\n<\/pre>\n<p>Also I&#8217;d to manage day recurrences and snooze.<\/p>\n<p><strong>Background process<\/strong><br \/>\nDue to iOS Sandbox mode, you can&#8217;t make a wake-up application similar to the native one. But you can&#8217;t miss the alarm clock neither, isn&#8217;t it? So the app must be running in background! For checking alarm clock while your app is in background, you have to enable:<\/p>\n<pre class=\"brush: as3; title: ; notranslate\" title=\"\">\r\nNativeApplication.nativeApplication.executeInBackground = true;\r\n<\/pre>\n<p>You won&#8217;t be able to do stage3D operation on iOS (be careful!), but the app can execute code and so vibrate device, play sound etc.<\/p>\n<pre class=\"brush: as3; title: ; notranslate\" title=\"\">\r\n\/\/ if you want to hear a sound while your app is in background add:\r\nSoundMixer.audioPlaybackMode = AudioPlaybackMode.MEDIA;\r\n<\/pre>\n<p>On iOS, you have to specify the <a href=\"https:\/\/developer.apple.com\/library\/content\/documentation\/iPhone\/Conceptual\/iPhoneOSProgrammingGuide\/BackgroundExecution\/BackgroundExecution.html\" target=\"_blank\">UIBackgroundModes<\/a>, add this code in your <em>*-app.xml<\/em>:<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n&lt;key&gt;UIBackgroundModes&lt;\/key&gt;\r\n&lt;array&gt;\r\n\t&lt;string&gt;audio&lt;\/string&gt;\r\n&lt;\/array&gt;\r\n<\/pre>\n<p>Still on iOS, I&#8217;d to put up two tricks:<br \/>\n&#8211; For whatever reason on Adobe AIR, a sound won&#8217;t play when the screen is black. So I fire a local notification to wake-up the screen.<br \/>\n&#8211; Be sure to keep your sound channel alive, just pause\/resume the alarm song, otherwise iOS may &#8220;lose&#8221; the sound and it takes ages for being heard!<\/p>\n<p>On Android, an application can wake-up itself, even if it&#8217;s killed! It&#8217;s a top gun feature for an alarm clock app, so I asked <a href=\"http:\/\/distriqt.com\/\" target=\"_blank\">Distriqt<\/a> (ANEs provider) if they supported the Android&#8217;s <a href=\"https:\/\/developer.android.com\/reference\/android\/app\/AlarmManager.html\" target=\"_blank\">AlarmManager API<\/a>. At that time they didn&#8217;t, but quickly they added it to the <a href=\"http:\/\/airnativeextensions.com\/extension\/com.distriqt.Application\" target=\"_blank\">Application ANE<\/a>, wonderful!<\/p>\n<p><strong>Saving ringtone on device<\/strong><br \/>\nAmong the features requested, we&#8217;d to be able to save the ring alarm as a ringtone so it could be used with the native app.<\/p>\n<p>On iOS, we&#8217;d to enable <a href=\"https:\/\/support.apple.com\/en-us\/HT201301\" target=\"_blank\">file sharing<\/a>, add in the <em>-*app.xml<\/em>:<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n&lt;key&gt;UIFileSharingEnabled&lt;\/key&gt;\r\n&lt;true\/&gt;\r\n<\/pre>\n<p>Then we just have to copy &amp; paste the local wav file in <em>File.documentsDirectory<\/em>.<\/p>\n<p>For Android, I tried to put this file at different places on the device but it wasn&#8217;t recognized directly as a ringtone. After looking the documentation, I found some metadatas were requested. Unfortunately I didn&#8217;t find an ANE, so I wrote <a href=\"https:\/\/github.com\/DaVikingCode\/SaveRingtone-ANE\" target=\"_blank\">my own<\/a>.<\/p>\n<p><strong>Lang, many lang!<\/strong><br \/>\nIn 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&#8217;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&#8217;t want to waste memory), then at runtime loading the required font if needed.<\/p>\n<pre class=\"brush: as3; title: ; notranslate\" title=\"\">\r\nvar loader:Loader = new Loader();\r\nloader.contentLoaderInfo.addEventListener(Event.COMPLETE, function(evt:Event):void {\r\n\t\r\n\tloader.contentLoaderInfo.removeEventListener(Event.COMPLETE, arguments.callee);\r\n\t\r\n\t\/\/trace(loader.contentLoaderInfo.applicationDomain.hasDefinition(_dicTypo[currentLang].font));\r\n\t\r\n\tvar fontClass:Class = loader.contentLoaderInfo.applicationDomain.getDefinition(_dicTypo[currentLang].font) as Class;\r\n\tFont.registerFont(fontClass);\r\n\tTextField.updateEmbeddedFonts();\r\n\t\r\n\t\/\/trace(Font.enumerateFonts(false));\r\n\t\r\n\t_dicTypo[currentLang].loaded = true;\r\n});\r\n\r\nloader.load(new URLRequest(&quot;swfs\/&quot; + _currentLang + &quot;.swf&quot;), new LoaderContext(false, ApplicationDomain.currentDomain));\r\n\r\n\/\/ dictionnary is defined like: _dicTypo[&quot;ja&quot;] = {font:&quot;HonokaMincho&quot;, loaded:false};\r\n<\/pre>\n<p>Due to SWF restriction on iOS, I won&#8217;t be able to unload it later but it didn&#8217;t really change if I added them via a SWC or embed.<\/p>\n<p><strong>Video<\/strong><br \/>\nThe app was made with AIR 23, so before Adobe added asynchronous texture upload (the final piece of cake). <a href=\"http:\/\/help.adobe.com\/en_US\/FlashPlatform\/reference\/actionscript\/3\/flash\/display3D\/textures\/VideoTexture.html\" target=\"_blank\">VideoTexture<\/a> wasn&#8217;t running well if uploading textures at the same time. I tested with <a href=\"http:\/\/help.adobe.com\/en_US\/FlashPlatform\/reference\/actionscript\/3\/flash\/media\/StageVideo.html\" target=\"_blank\">StageVideo<\/a> and it was working fine on iOS! There are some troubles with StageVideo and Android, unfortunately AIR 24 wasn&#8217;t fully stable, so no video intro on Android yet.<\/p>\n<p><strong>AIR shine and other tech?<\/strong><br \/>\nWith 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?<\/p>\n","protected":false},"excerpt":{"rendered":"<p>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 &amp; Feathers, we finished the dev diary asking which other technologies could have done the app, but didn&#8217;t get a strong answer. Today, with Pixelfordinner agency, we&#8217;re proud to &hellip; <a href=\"https:\/\/davikingcode.com\/blog\/memovox-air-still-on-top\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Memovox, AIR still on top<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_discordance_state":"","_discordance_checked":true},"categories":[4],"tags":[8,32,21,22,34,31,7,9],"_links":{"self":[{"href":"https:\/\/davikingcode.com\/blog\/wp-json\/wp\/v2\/posts\/500"}],"collection":[{"href":"https:\/\/davikingcode.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/davikingcode.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/davikingcode.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/davikingcode.com\/blog\/wp-json\/wp\/v2\/comments?post=500"}],"version-history":[{"count":58,"href":"https:\/\/davikingcode.com\/blog\/wp-json\/wp\/v2\/posts\/500\/revisions"}],"predecessor-version":[{"id":573,"href":"https:\/\/davikingcode.com\/blog\/wp-json\/wp\/v2\/posts\/500\/revisions\/573"}],"wp:attachment":[{"href":"https:\/\/davikingcode.com\/blog\/wp-json\/wp\/v2\/media?parent=500"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/davikingcode.com\/blog\/wp-json\/wp\/v2\/categories?post=500"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/davikingcode.com\/blog\/wp-json\/wp\/v2\/tags?post=500"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}