Skip to content


AIR Native Extension Example: iBattery for iOS

Introduction

The most exciting new feature coming to Adobe AIR to me is the ability to compile against a library that can communicate with a device natively. Though some of the Stage* API opens a whole new world of rendering improvements, the inclusion of Native extensions for Adobe AIR (NE) relieves the wishing and waiting of what will be exposed at the device level in future AIR SDK releases; we can now extend the Runtime ourselves. With the arrival of Native extensions, the possibilities of what can be achieved with a mobile AIR application grow larger; and certainly with that, so does complexity in design and the requirement to develop with mobile performance in mind.

Keeping the complexities and performance in check (and to calm myself down from excitement of the endless possibilities) I decided to give it a quick test-run by creating a Native Extension that I thought was sorely missing from the Adobe AIR SDK – battery information on iOS. In all seriousness, getting up and running and accessing the battery information of my iPhone from an application AIR application was rather painless and – dare i say it – easier than i expected. I intend to give a quick walk through of how I went about creating the iBattery Native Extension and how to use it in an AIR application.

Disclaimer

I am going to assume you are familiar with setting up an Apple Developer account and downloading the SDK and won’t even go into the headache of provisioning profiles and the deployment process for an iOS application. I am also going to assume that you are familiar with using the recent Flex 4.5 SDK to create mobile Flex applications. The application in this example is in no way complex, but I am not going to cover how the pieces of the application work – only how you can compile against and include an Native extension for Adobe AIR.

Source

If you are curious or just want to jump to code, I created a github repo with all the source as well as deployment builds or if you just came here for the Native Extension and know your way around you can download ibatteryextension.ane directly.

Requirements

Also, take a look at these excellent articles:

I am not going to cover how to get this going with any IDEs (eg. Flash Builder 4.5). I will show you how to do all this from the command line. There are some niceties with IDEs that will separate you from invoking the command line tools of the SDK directly, but sometimes it is nice to see what is going on behind the scenes.

I went about downloading the Flex 4.5 SDK and unzipping it somewhere on my local disk, then downloaded the Adobe AIR SDK and overlaid it on the Flex SDK using the instructions here: How To Overlay the AIR SDK. For the purposes of the examples in this article let’s just say that SDK is located on my machine at: /Users/todd/SDKs/flex_4.5_air_3rc1.

The whole iOS & Xcode set up, you are on your own. Sorry, not to be mean. There is some great information already out there and i want to keep this article more focused on Native Extensions for Adobe AIR and not to prevent hair-loss developing for iOS.

Moving Pieces

There are three major portions to create an AIR application utilizing the Native Extension for Adobe AIR:

  1. Native code compiled for target platform.
  2. Flex library project to deploy the Native Extension for Adobe AIR.
  3. Mobile AIR application.

Depending on your target device/platform, the language and generated library on the native-side can vary and really is covered well in Oliver Goldman’s article. For the purposes of this example, the native part involved me writing some C/Obj-C and creating a static library (.a file). The Flex library project is actually two-fold; I created a library that interfaced with the flash.external.ExtensionContext, then generated an .ane file from the SWC and static library. The Mobile AIR application is then compiled against this Native Extension and the .ane library file is included in the generated .ipa file.

Native

I am not that much of an C/Objective-C developer. I have developed and deployed a handful of iOS applications in the past (some reaching the AppStore), but honestly have not touched it in quite some time. So I have some history, but cannot speak at length on how things work and why. Let’s just say, for the example in this article, that I knew enough to get in and get out and carry on on the ActionScript side of things.

When creating a native extension targeting the iOS platform, you’ll write some C code (which can call Obj-C) and deploy a static library with a .a extension. What i did was create a new Library project in Xcode, imported the header file included with the AIR SDK (found at /include/FlashRuntimeExtensions.h) and added a .m (Obj-C implementation) file to the project that will serve as the implementation of the native context and expose the API for accessing the battery life and information of the iOS device:

// Access battery life.
FREObject GetBatteryLife(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[]) {
    UIDevice *device = [UIDevice currentDevice];
    [device setBatteryMonitoringEnabled:YES];
    float life = [device batteryLevel];

    FREObject retVal;
    FRENewObjectFromDouble( life, &retVal );
    return retVal;
}

// Access info about battery
FREObject GetBatteryInfo(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[]) {
    UIDevice *device = [UIDevice currentDevice];
    [device setBatteryMonitoringEnabled:YES];
    int info = [device batteryState];

    FREObject retVal;
    FRENewObjectFromInt32( info, &retVal );
    return retVal;
}

Boiled down and abstracted in thinking on the ActionScript side of things, the API of this native library exposes two methods: GetBatteryLife and GetBatteryInfo. Each return a numerical value related to their context: a Number representing the percent of battery life left on the device and an Integer representing battery state, respectively. The relation of the Number value to percent is fairly straight-forward. The Integer returned from [[UIDevice currentDevice] batteryState] relates to the various “states” that the battery can be in, and they are:

  • 0 : Unknown
  • 1 : Unplugged
  • 2 : Charging
  • 3 : Full

The FREObject is covered more properly by Oliver Goldman in his article, and I just blindly assume that the ExtensionContext of the AIR SDK knows how to interpret this value for me so I can cast as an ActionScript type and move on. We’ll see how that happens in the next section.

The Native Extension

The previous section lightly covered the native side of things and generated a static library file that will be used to compile an Native Extension (NE) library that will be used by an AIR application to access battery information of an iOS device it is deployed to. Creating the Native Extension file (.ane) is actually a two step process:

  1. Create a Flash library project compiled against AIR libraries and expose an API that interfaces with the native library through ExtensionContext.
  2. Use the ADT command line tool with to generate an .ane file compiled against the library SWC and the native library.

The flash.external.ExtensionContext from the AIR SDK is your main access point to the native library. Essentially, you create a new instance of an ExtensionContext using an ID defined in an extension descriptor file compiled into the Native Extension. For the iBattery Native Extension, this is what my extension descriptor file looks like:

<extension xmlns="http://ns.adobe.com/air/extension/2.5">
  <id>com.custardbelly.ibattery</id>
  <versionNumber>1</versionNumber>
  <platforms>
    <platform name="iPhone-ARM">
            <applicationDeployment>
                <nativeLibrary>libAIRExtensionC.a</nativeLibrary>
                <initializer>ExtInitializer</initializer>
                <finalizer>ExtFinalizer</finalizer>
            </applicationDeployment>
        </platform>
  </platforms>
</extension>

Highlighted in that snippet are some important bits. The id node value will be used to create a new ExtensionContext instance. The nativeLibrary node value is the native library created in the previous section. For this example, it is also of note that we have defined the iPhone-ARM platform as a target, as well. This extension descriptor file describes the association of id to native library that the ExtensionContext will look up upon instantiation. To create an ExtensionContext:

com.cusardbelly.air.extensions.battery.ios.Battery

_extensionContext = ExtensionContext.createExtensionContext( "com.custardbelly.ibattery", "main" );

… and then use the call() method to invoke the corresponding method exposed in the native library. For the purposes of the example in this article, and for the iBattery Native Extension, I basically exposed the same API that was on the native side:

com.cusardbelly.air.extensions.battery.ios.Battery

public function getBatteryLife():Number
{
    return _extensionContext.call( 'GetBatteryLife' ) as Number;
}

public function getBatteryState():int
{
    return _extensionContext.call( 'GetBatteryInfo' ) as int;
}

With my API done, I compiled the library into a SWC:

> /Users/todd/SDKs/flex_4.5_air_3rc1/bin/compc -output build/iBattery.swc -load-config+=ibattery_lib.config +configname=airmobile

If you are unfamiliar with using the command line tools of the SDK, I used the compc tool which is used to generate SWC files. The iBattery.swc file is generated and placed in a build directory and is compiled against an additional custom config (which just defines source location) and the +configname=airmobile directive. That’s actually a little fun tidbit. If you want to generate a SWC or SWF that uses the AIR mobile libraries, just add +configname=airmobile and they’ll be compiled against for you without defining them in an additional config file.

I then took the iBattery.swc and unzipped it to get the library.swf file. This is necessary for generating a Native Extension file (.ane) using the ADT command line tool:

> /Users/todd/SDKs/flex_4.5_air_3rc1/bin/adt -package -target ane ../release/ibatteryextension.ane extension.xml -swc iBattery.swc -platform iPhone-ARM library.swf libAIRExtensionC.a

That generates an ibatteryextension.ane in a release directory and defines the target SWC library and platform as well as compiling in the descriptor, SWF library and native library.

That Native extension is then used as one would as SWC library in an AIR Mobile application to interface with the native library. You need to compile against the .ane and include it in an extension directory within the AIR application.

The AIR Mobile Application

The application I created to showcase the iBattery Native Extension is pretty dead simple. Again, I am assuming you have some knowledge of a mobile AIR application and its pieces. There are a ton of great articles out there that can help in developing an AIR application targeting mobile, so I won’t provide any more explanations in this article, I just wanted to show you quickly how the communication works and the requirements for compilation of the application.

To being I just have a main ViewNavigatorApplication that defines a single view:

iBatteryExample.mxml

<?xml version="1.0" encoding="utf-8"?>
<s:ViewNavigatorApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
        xmlns:s="library://ns.adobe.com/flex/spark"
        firstView="BatteryTestView">

</s:ViewNavigatorApplication>

… and the BatteryTestView provides a UI to request the battery information on the device and does all the communication through the ActionScript side of the Native Extension library generated previously:

BatteryTestView.mxml

<?xml version="1.0" encoding="utf-8"?>
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009"
        xmlns:s="library://ns.adobe.com/flex/spark"
        title="BatteryTestView" creationComplete="handleCreationComplete();">

    <fx:Script>
        <![CDATA[
            import com.custardbelly.air.extensions.battery.ios.Battery;

            protected var _batteryExtension:Battery;

            protected function handleCreationComplete():void
            {
                _batteryExtension = new Battery();

                lifeButton.addEventListener( MouseEvent.CLICK, handleLifeRequest, false, 0, true );
                infoButton.addEventListener( MouseEvent.CLICK, handleInfoRequest, false, 0, true );
            }

            protected function handleLifeRequest( evt:Event ):void
            {
                try {
                    console.appendText( "Battery Life Percentage: " );
                    console.appendText( ( _batteryExtension.getBatteryLife() * 100 ).toString() + "%\n" );
                }
                catch( e:Error )
                {
                    console.appendText( "Error: " + e.message );
                }
            }

            protected function handleInfoRequest( evt:Event ):void
            {
                console.appendText( "Battery State: " + ( _batteryExtension.getBatteryState() ).toString() + "\n" );
            }
        ]]>
    </fx:Script>

    <s:layout>
        <s:VerticalLayout paddingLeft="10" paddingRight="10" paddingTop="10" paddingBottom="10" />
    </s:layout>

    <s:TextArea id="console" width="100%" height="100%" editable="false" text="Hello World!" />
    <s:HGroup width="100%" height="24" verticalAlign="middle">
        <s:Button id="lifeButton" label="get life" />
        <s:Button id="infoButton" label="get info" />
    </s:HGroup>

</s:View>

Access to the ActionScript API from the Native Extension is available just as if you were developing against an external SWC library, and I created a new instance of a Battery to request life and information of the device which is then just printed out in a text area:

BatteryTestView.mxml

_batteryExtension = new Battery();
console.appendText( "Battery State: " + ( _batteryExtension.getBatteryState() ).toString() + "\n" );

To generate my AIR application for iOS, was a two step process. First, I generated the application SWF targeting AIR mobile:

> /Users/todd/SDKs/flex_4.5_air_3rc1/bin/mxmlc +configname=airmobile -output build/iBatteryExample.swf src/iBatteryExample.mxml -load-config+=battery_app.config

Again i used the +configname=airmobile directive to include the mobile SWC from the Adobe AIR SDK without defining the dependencies in an additional config file. I did, however, have an additional config file that defined the Native Extension (.ane file) to compile against as an external library:

battery_app.config

<?xml version="1.0"?>
<flex-config xmlns="http://www.adobe.com/2006/flex-config">
    <compiler>
        <external-library-path append="true">
            <path-element>ext/ibatteryextension.ane</path-element>
        </external-library-path>
    </compiler>
</flex-config>

That generated an iBatteryExample.swf which was then used alongside an application descriptor file to compile and generate the .ipa file (application installer file for iOS). We can create that using the ADT command line tool:

> /Users/todd/SDKs/flex_4.5_air_3rc1/bin/adt -package -target ipa-test-interpreter -provisioning-profile {path.to}.mobileprovision -storetype pkcs12 -keystore {path.to}.developer_identity.p12 -storepass {pass} ../release/iBatteryExample.ipa iBatteryExample-app.xml iBatteryExample.swf -extdir ../ext/

There are two things in this command that you should note. First off, you will need to replace the {path.to} and {pass} tokens to point to your iOS developer files and password, respectively. Second is the -extdir option. This defines where the application can locate the Native Extension (.ane file).

And that was pretty much it for the application. Pretty basic, but a rather quick way to get up and running to allow someone to find information about their battery on an iOS device.

Conclusion

The addition of Native Extensions for Adobe AIR to the AIR SDK opens a lot of doors not only for native device integration but also to the experience you can provide in a mobile AIR application – with the biggest takeaway (as a developer) being that we no longer have to wait and see what gets exposed to us at the device-level in future AIR SDK releases. We can just write our own native extension now.

Hopefully this article provided some insight on how to quickly get up and running in creating your own Native Extensions and how to incorporate them into your mobile AIR application. And it should be noted that though this example was iOS specific, the native library for an Native Extension for Adobe AIR is in no way restricted to that platform and you should really check out Oliver Goldman’s excellent article, Extending Adobe AIR on the Adobe DevNet.

The source discussed in this article can be found on github at http://github.com/bustardcelly/iBattery and the ibatteryextension.ane itself (if you’d like to use it in your application) can be downloaded from this link.

Posted in AIR, AS3, Flex, Flex 4.5, Native Extension for Adobe AIR.


29 Responses

Stay in touch with the conversation, subscribe to the RSS feed for comments on this post.

  1. RC says

    I downloaded a sample extension (the gyroscope) and modified all the code for what i need (i am trying to make a DatagramSocket extension for android /ios ) . the only problem is how do i compile this into the ane. i did all the code changes in eclipse, do i have to use flash builder to compile the ane. any help would be appreciated

  2. Daniel says

    Now thats impressive.

  3. todd anderson says

    As far as I know, you can’t use Flash Builder at this moment to compile an ane; there are no wizards in the latest Flash Builder release that support invoking the command line tools from the beta release to set the -target option to ane. You will have to use a CLI (terminal/console) to create the ANE with commands such as those loosely described in the README at https://github.com/bustardcelly/iBattery/tree/master/flash/lib

    Hope that helps.
    -todd

  4. Anthony says

    Hi,
    I have just release a blog post about creating a NativeAlert extension for AIR. It includes multiple buttons and dispatches ActionScript events when the user selects one of those buttons.
    the post can be found here.
    http://www.liquid-photo.com/2011/10/28/native-extension-for-adobe-air-and-ios-101/
    The source is on github and you can download the NativeAlert.ane file directly also

    Hope you guys like it.

  5. Henning says

    Hello,

    I have iOS 5.1 on my iPhone, AIR 3.1 SDK and all the native extensions including yours crashes the app once the createExtensionContext function is called to connect the AS3 code to the native code. Does anyone have a solution for this?

    Henning

  6. Mano says

    Hi,

    I’m a beginner on flex developer. Can any one provide a way for me in HOW TO DEVELOP AN ALARM APPLICATION WITH FLEX FOR IPHONE AND ANDROID. Is there any suitable examples?

    It’s urgent…
    Thanks in advance

  7. Markus says

    Question..
    There is exactly one post describing how to debug on the iOS Xcode side of things. I was wondering if you tried this approach and or what was your approach to debugging your app within Xcode?

    Debugging iOS –
    http://blogs.adobe.com/rajorshi/2011/11/18/debugging-native-extensions-for-air-ios/#more-62

    Markus

  8. bbeausej says

    This article really helped get the ball rolling for us with native extensions. Thank you!

    One thing that you forgot to mention and that is crucial is to make sure the “Enable Linking With Shared Libraries” option in your static library build settings is set to “NO”. We had an issue where any calls to NSLog in the foundation framework would cause crashes, this resolved it.

    thanks!

  9. pseudorather says

    :)

  10. Abhisek Paul says

    build script for andoird native extension:
    http://fridaymushroom.com/fm/content/ant-build-script-android-extension-flex

  11. Santanu Karar says

    HI, recently I’ve tried to do with native extension and with the iBattery example – the first day work with the XCode project did well, it did build successfully even after my small changes (i.e. adding new methods etc.). Next day when I re-visited the same XCode project, I’m starts having an unknown error – “File /Users/webspidersindiapvtltd/Library/Developer/Xcode/DerivedData/AIRExtensionC-dutrbbkegwduvqgbhxkfzjznvrza/Build/Products/Debug-iphoneos/libAIRExtensionC.a depends on itself. This target might include its own product.”

    Really doesn’t have any clue why this suddenly brought in. Any suggestion please (?)

    Thanks.

  12. Santanu Karar says

    Continue with my previous comment, I finally made it work (XCode error) by downloading another set of the XCode project from Github and put my new modification there and compile it. Not sure what got messed with the previous project. But anyway, I did my new compilation till creating a new ANE file now, imported in the AIR/mobile project and successfully launched in a device finally. The existing two functions – getBatteryLife and getBatteryState – both are working fine but my new method which I’ve added. The new method actually does nothing but only returning an int value to the actionScript. But while calling that method I only got – #Error 3500 – not sure why. I’ve re-ched that the said method reside in every places where it should have be, and I couldn’t able to found any differences! Any suggestion please (?)

  13. Sameer Jain says

    Hello Todd,

    Thank you for sharing this. I finally made an extension for a flash game ported on iOS showing advertisement from different network.

    Best,

  14. 编织袋设备 says

    Extension Example: iBattery for iOS

  15. Bhavik kama says

    Can any one Guide me about How to Call Normal Function of Objective C From FREObject Function to Native Air Application?

    Please visit this question on my StackOverFlow Account..
    http://stackoverflow.com/questions/15780349/call-normal-function-of-objective-c-from-freobject-function-to-native-air-applic

Continuing the Discussion

  1. Native Extensions examples available now : Mihai Corlan linked to this post on September 22, 2011

    [...] iBattery (iOS) – gets the battery status (unknown, unplugged, charging, or full) of an iOS device [...]

  2. iBattery native extension for Adobe AIR « Flash Platform Doc Team linked to this post on September 22, 2011

    [...] Todd Anderson just posted “iBattery”,  a great example of a native extension for Adobe AIR on his blog. [...]

  3. Adobe AIR Native Extension Example « PriyeshSheth (M)+91 9099795049 linked to this post on September 22, 2011

    [...] iBattery for iOS [...]

  4. IPhone手机Flash移动应用开发:AIR Native Extension扩展的精彩例子IBattery for IPhone | Flash006工作室 linked to this post on September 23, 2011

    [...] 原文见:http://custardbelly.com/blog/2011/09/21/air-native-extension-example-ibattery-for-ios/ 未分类 Posted by art on September 23, 2011 ← 同步博客到百度测试 [...]

  5. 开发Adobe AIR的原生扩展[优秀AIR原生扩展整理] | Flash开发者大会 linked to this post on December 12, 2011

    [...] iBattery:Todd Anderson的这个例子,向我们展示如何创建本地拓展获取IOS系统上的电池电量。http://custardbelly.com/blog/2011/09/21/air-native-extension-example-ibattery-for-ios/ [...]

  6. iOS native extension for Adobe AIR. In-app mail composer | flashsimulations.com linked to this post on December 13, 2011

    [...] Building the ActionScript library of a native extension Native Alert iOS native extension tutorial AIR Native Extension Example: iBattery for iOS as3c2dm – AIR native extension to push notifications with [...]

  7. Extending Air « Labs @ Jam3 – Toronto Web Development Reseach Blog linked to this post on January 5, 2012

    [...] This example, from Todd Anderson, shows how you can build a native extension to get battery information on iOS. [...]

  8. Adobe Native Extension for iOS Game Center – Part 2 « David Flatley linked to this post on February 6, 2012

    [...] process of ANE creation and working through the bugs were liquid-photo.com  flashsimulations.com custardbelly.com and tutsplus.com Special thanks for the great [...]

  9. 20 tips for creating Air Native Extensions for iOS | Hire Flash Developers linked to this post on March 1, 2012

    [...] AIR Native Extension Example: iBattery for iOS [...]

  10. Extending Air | Labs Blog linked to this post on March 2, 2012

    [...] This example, from Todd Anderson, shows how you can build a native extension to get battery information on iOS. [...]

  11. 给iOS开发AIR Native 扩展的20条建议 - 博客 - 伯乐在线 linked to this post on March 21, 2012

    [...] • AIR Native Extension Example: iBattery for iOS [...]

  12. iBattery | AS3 Game Gears linked to this post on May 30, 2012

    [...] iBattery is a native extension for Adobe AIR that provides access to the battery life and information on an iOS device. The extension allows you to check the following battery state: UNKNOWN (currently unplugged from recharge), UNPLUGGED (currently charging),  CHARGING and FULL. [...]

  13. 20条开发AIR Native Extension的建议-开心快乐每一天-梦想小熊小爱 linked to this post on June 28, 2012

    [...] 1. 开始 这两篇文档对初学者很有帮助,如果你不知道该如何起步,可以从阅读这两篇文档开始。在网络上也有很多好的文章,只要Google一下就行了。 ? Extending Adobe Air ? AIR Native Extension Example: iBattery for iOS [...]



Some HTML is OK

or, reply to this post via trackback.