Adobe
Products

Top destinations

  • Adobe Creative Cloud
  • Creative Suite
  • Adobe Marketing Cloud
  • Acrobat
  • Photoshop
  • SiteCatalyst
  • Students
  • Elements family

Adobe Creative Cloud

  • What is Adobe Creative Cloud?
  • Design
  • Web
  • Photography
  • Video
  • Students
  • Teams
  • Enterprise
  • Educational institutions

Design and photography

  • Photoshop
  • Illustrator
  • InDesign
  • Adobe Muse
  • Lightroom

Video

  • Adobe Premiere
  • After Effects

Web development and HTML5

  • Edge Tools & Services [opens in a new window]
  • Dreamweaver
  • Gaming [opens in a new window]

Adobe Marketing Cloud

  • What is Adobe Marketing Cloud?
  • Digital analytics
  • Social marketing
  • Web experience management
  • Testing and targeting
  • Media optimization

Analytics

  • SiteCatalyst
  • Adobe Discover
  • Insight

Social

  • Adobe Social

Experience Manager

  • CQ
  • Scene7

Target

  • Test&Target
  • Recommendations
  • Search&Promote

Media Optimizer

  • AdLens
  • AudienceManager
  • AudienceResearch

Document services

  • Acrobat
  • EchoSign [opens in a new window]
  • FormsCentral [opens in a new window]
  • SendNow [opens in a new window]
  • Acrobat.com [opens in a new window]

Publishing

  • Digital Publishing Suite

  • See all products
Business solutions

By business need

  • Digital analytics
  • Digital publishing
  • Document management
  • Media optimization
  • Social marketing
  • Testing and targeting
  • Video editing and serving
  • Web development [opens in a new window]
  • Web experience management
  • See all business needs

By industry

  • Broadcast
  • Education
  • Financial services
  • Government
  • Publishing
  • Retail
  • See all industries
Support & Learning

I need help

  • Products
  • Adobe Creative Cloud
  • Adobe Marketing Cloud
  • Forums [opens in a new window]

I want to learn

  • Training and tutorials
  • Certification [opens in a new window]
  • Adobe Developer Connection
  • Adobe Design Center
  • Adobe TV [opens in a new window]
  • Adobe Marketing Center
  • Adobe Labs [opens in a new window]
Download
  • Product trials
  • Adobe Flash Player
  • Adobe Reader
  • Adobe AIR
  • See all downloads
Company
  • Careers at Adobe
  • Investor Relations
  • Newsroom
  • Privacy
  • Corporate Social Responsibility
  • Customer Showcase
  • Contact us
  • More company info
Buy
  • For personal and professional use
  • For students, educators, and staff
  • For small and medium businesses
  • Volume Licensing
  • Special offers
  • Adobe Marketing Cloud sales [opens in a new window]
Search
 
Info Sign in
Why sign in? Sign in to manage your account and access trial downloads, product extensions, community areas, and more.
Welcome,
My Adobe
My orders
My information
My preferences
My products and services
Sign out
My cart
Privacy My Adobe
Adobe
Products Sections Buy   Search  
Solutions Company
Help Learning
Sign in Sign out Privacy My Adobe
Preorder Estimated Availability Date. Your credit card will not be charged until the product is shipped. Estimated availability date is subject to change. Preorder Estimated Availability Date. Your credit card will not be charged until the product is ready to download. Estimated availability date is subject to change.
Qty:
Purchase requires verification of academic eligibility
Subtotal
Promotions
Estimated shipping
Tax
Calculated at checkout
Total
Review and Checkout
Adobe Developer Connection / Adobe AIR Developer Center /

Building a native extension for iOS and Android – Part 3: Building the iOS library

by Nathan Weber

Nathan Weber
  • digitalprimates.net

Content

  • Creating the iOS library
  • iOS problems and pitfalls
  • Where to go from here

Created

27 August 2012

Page tools

Share on Facebook
Share on Twitter
Share on LinkedIn
Bookmark
Print
ActionScriptAdobe AIRFlash BuilderiOSmobilenative extensions
Was this helpful?
Yes   No

By clicking Submit, you accept the Adobe Terms of Use.

 
Thanks for your feedback.

Requirements

Prerequisite knowledge

This series of tutorials is designed for developers with an intermediate to advanced understanding of ActionScript 3 and building Adobe AIR applications. Familiarity with Flash Builder, Java, Objective-C, and Xcode will also be helpful. If you have not already done so, read Part 1 and Part 2 of this tutorial series before proceeding.

 

Additional required other products

  • Volume native extension

User level

Intermediate

Required products

  • Flash Builder (Download trial)
  • Adobe AIR SDK

Sample files

  • IOSVolumeLib folder in system-volume-native-extension.zip

In the previous tutorial—Building a native extension for iOS and Android – Part 2: Developing the ActionScript library—you created the main and default libraries in ActionScript. If you are going to develop an AIR native extension to use with iOS, you also have to create an iOS library.

The iOS project is the part that, in my opinion, is the hardest. There are plenty of mistakes that are easy to accidentally make. This tutorial can help you avoid these common mistakes.

Creating the iOS library

Follow these steps to create the iOS library for your native extension:

  1. Open Xcode and make a new project. In the New Project dialog box, select iOS > Framework & Library on the left, and then click Cocoa Touch Static Library.
  2. After you create the project. You'll see a .h file and a .m file named after your project. You don't need the .h file so you can delete that. Next, empty the .m file since the default code isn't needed anymore.
  3. Click on the project in the bar on the left side and search for "prototype" in the Build Settings. Toggle the value of "Missing Function Prototypes" to No. This is just to suppress warnings.
  4. Download the Adobe AIR SDK if you haven't already. Navigate to AIR_SDK_DIR/include and locate the file named FlashRuntimeExtensions.h. To include this file in your project, drag it into Xcode and drop it onto your project in the left side bar. (This doesn't actually copy the file though, so if you delete or move the original, then Xcode won't find it anymore.)
  5. Open the main .m file and add the following line to the top of the file:
#import "FlashRuntimeExtensions.h"

Now you can access the AIR runtime classes and set up the architecture for the extension.

  1. In the main .m file create a method named VolExtContextInitializer() . This method is called when the extension context is created in AIR. In this method you need to create a collection of functions that the main ActionScript library will call. Because you haven't defined these methods in the native code yet you'll need to revisit this later. Here's an example:
void VolExtContextInitializer(void* extData, const uint8_t* ctxType, FREContext ctx, uint32_t* numFunctionsToTest, const FRENamedFunction** functionsToSet){ *numFunctionsToTest = 0; FRENamedFunction* func = (FRENamedFunction*) malloc(sizeof(FRENamedFunction) * *numFunctionsToTest; *functionsToSet = func; }

Note: When naming the ContextInitializer function you should choose a unique name. If multiple native extensions are used in the same application, functions with the same name will conflict and the native extensions will not work properly. It's a good idea to incorporate the name of the extension into the name of the function.

  1. Create another method to serve as the initialize method. The name of this method must match the initializer node in the iPhone-ARM platform of the extension.xml file. This method will set which methods to call when doing the actual initialization.
void VolumeExtensionInitializer(void** extDataToSet, FREContextInitializer* ctxInitializerToSet, FREContextFinalizer* ctxFinalizerToSet){ *extDataToSet = NULL; *ctxInitializerToSet = &VolExtContextInitializer; }
  1. Now you need to build out the concrete implementations of the methods that the ActionScript code is going to call. For this native extension, you need one named init() and one named setVolume() .

Each method will accept the same parameters. The main properties you're worried about are the FREContext , which is the extension context, and the collection of FREObject instances, which are the parameters passed to the native function. Each FREObject is a C representation of an ActionScript object. Objects cannot be passed directly between ActionScript and native code, so any time you deal with an object it will be of type FREObject .

The FREObject class is a wrapper, so you have to pull the value out using methods on FREObject . See the following code for an example:

FREObject setVolume(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[]){ double newVolume; FREGetObjectAsDouble(argv[0], &newVolume); [[MPMusicPlayerController applicationMusicPlayer] setVolume: newVolume]; return NULL; }

The code above won't compile as is. You'll need to add the following import statements:

#import <MediaPlayer/MediaPlayer.h> #import <AudioToolbox/AudioToolbox.h>
  1. Once these methods are created you'll need to go back to the initializer method and add in some code so that AIR can call them:
void VolExtContextInitializer(void* extData, const uint8_t* ctxType, FREContext ctx, uint32_t* numFunctionsToTest, const FRENamedFunction** functionsToSet){ *numFunctionsToTest = 2; FRENamedFunction* func = (FRENamedFunction*) malloc(sizeof(FRENamedFunction) * *numFunctionsToTest; func[0].name = (const uint8_t*) "init"; func[0].functionData = NULL; func[0].function = &init; func[1].name = (const uint8_t*) "setVolume"; func[1].functionData = NULL; func[1].function = &setVolume; *functionsToSet = func; }

Compare this code to the initial code for VolExtContextInitializer above to see the changes.

See the completed code in the IOSVolumeLib folder in the sample files for this article for init() and other functions.

Dispatching an event to ActionScript

There will be times when you'll want the AIR project to know that something has happened in the native code. You've already set up listeners on the extensionContext when you created the ActionScript librarybut now you need to dispatch the event.

The FREDispatchStatusEventAsync() method is used to send an event back to ActionScript. Dispatching the event is straightforward; you give the method the extensionContext ( FREContext instance), a code string, and a level string. See the Native C API Reference for FREDispatchStatusEventAsync() for details on these parameters.

The tricky part is that the native iOS code is likely using the iOS versions of the objects, but AIR deals with the native C objects. For example, iOS code uses objects of type NSString to represent Strings, while the AIR extensions use uint8_t* (an array of characters). You'll have to do some conversion, but it isn't terribly hard. Here's an example:

void dispatchVolumeEvent(float volume, FREContext ctx) { if (ctx == NULL) { return; } NSNumber *numVolume = [NSNumber numberWithFloat:volume]; NSString *strVolume = [numVolume stringValue]; NSString *eventName = @”volumeChanged”; const uint8_t* volumeCode = (const uint8_t*) [strVolume UTF8String]; const uint8_t* eventCode = (const uint8_t*) [eventName UTF8String]; FREDispatchStatusEventAsync(ctx, eventCode, volumeCode); }

Note: See the completed code to understand how this method is used in the volume extension.

Generating the compiled library

When you've finished coding the library, follow these steps to build it:

  1. Click the project on the left hand side of the screen and then click the Build Settings tab.
  2. Search for "products path". The compiled library will be placed in the directory specified in the Per-configuration Build Projects Path setting.

To change the directory just double-click the current path and type a new path.

Note: Later, I'll cover the files required when building the native extension. At that point you'll create a directory to hold the file that Xcode is going to generate, and you should set the Per-configuration Build Projects Path value to be that directory.

  1. Next, search for "Architectures". Be sure that the value for Architectures is "armv7".
  2. Search for "deployment" and set the "iOS Deployment Target" to the minimum version of iOS that you are supporting. Unless you have particular version requirements, iOS 4.0 should be fine.
  3. In the top bar click Product and then click Edit Scheme. While debugging you should leave Build Configuration set to Debug, but when you are ready to build the final native extension, set the value to Release.
  4. To build the library press Cmd+b (You may want to use completed code from the sample files). When the library is built, you'll find a .a file in the directory that you specified .

A note about debugging

Debugging native extensions isn't the easiest thing to do, but both IDEs for iOS and Android provide a way to log messages to a console. You won't be able to set breakpoints but you can see log statements from the native code.

When using NSLog(NSString) statements the output will show up in the console available through the Xcode Organizer when the AIR application using the extension is running on the device and the device is plugged in via a USB port.

To open the console:

  1. While Xcode is running, choose Window > Organizer.
  2. Find your device in the left-hand list and click the arrow to expand its contents.
  3. Select the Console option. Output from your NSLog statements will show up here.

iOS problems and pitfalls

This section outlines several potential problems that you may encounter when building your iOS library.

Ensuring support for iOS 4.* devices

By default Xcode sets the deployment target to match the SDK you are using. Xcode now only comes with the iOS 5.0 SDK, so by default your library project targets 5.0.

To remedy this, click the project name in the bar on the left side. In Build Settings search for "deployment" and set iOS Deployment Target to 4.0.

You'll have to take this one step further by adding an XML file specifying the minimum required iOS version when packaging the native extension. See Using External Frameworks And Libraries below for more information.

Compiling on a Mac

I do my development on a Windows PC. So, naturally, after I built my first native extension on the Mac (since Xcode is only available for OS X), I tried to compile a test application using the native extension on my PC. This would generally crash with AIR 3.2. Sometimes compiling would fail. Often the application just didn't work as expected, or would crash for no apparent reason. I had tried this prior to creating the Volume extension and the test extension was pretty basic but it just didn't work when compiling from a Windows PC. Especially coupled with the next few pitfalls, you may find it difficult or impossible to compile the builds on anything but a Mac.

Note: AIR 3.3 has been released since this tutorial was first written. The new version of AIR is compiling against iOS 5 which should ease development on Windows to an extent. However, I still recommend doing any final release IPA builds from an OS X machine with the iOS SDK (Xcode) installed.

Using more than one native extension

Using more than one native extension in the same application can lead to some unnecessary headaches if you aren't careful. If the ContextInitializer() function specified in the extension's initializer function (the one specified in the extension.xml file initializer node) shares the same name as the ContextInitializer of a different native extension only the first native extension loaded will work.

That being said, you should name the internal initializer functions in a unique way. Appending the name of your extension is an easy way to accomplish this. Here's an example:

void MySuperUniqueContextInitializer(void* extData, const uint8_t* ctxType, FREContext ctx, uint32_t* numFunctionsToTest, const FRENamedFunction** functionsToSet){ ... return; } void MySuperUniqueContextFinalizer(FREContext ctx){ return; } void VolumeExtensionInitializer(void** extDataToSet, FREContextInitializer* ctxInitializerToSet, FREContextFinalizer* ctxFinalizerToSet){ *extDataToSet = NULL; *ctxInitializerToSet = &MySuperUniqueContextInitializer; *ctxFinalizerToSet = &MySuperUniqueContextFinalizer; }

Using an external iOS SDK when packaging the IPA

The AIR SDK has a specific version of the iOS SDK bundled with it. For AIR 3.2 it is iOS 4.0 and for AIR 3.3 it is iOS 5.1. If you are using features that are included in the iOS SDK that the AIR SDK is bundled with you'll be OK.

However, if you want to use features from a new iOS SDK or if you want to use features that are not included in the default libraries that the AIR SDK includes, you'll need to specify an external iOS SDK to use for compiling.

Note: Even within the iOS SDK that the AIR SDK includes, not all libraries are supported. This is covered in more detail below in Using External Frameworks And Libraries.

Follow these steps to set up an external iOS SDK on OS X.

  1. In Flash Builder, right-click your Flex project and select properties.
  2. Select Flex Build Packaging > Apple iOS.
  3. Click the Native Extensions tab.
  4. >For the Apple iOS SDK, type the location of the SDK. The default location (on my Snow Leopard machine) is /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk

If you are compiling via the command line, you can use the –platformsdk option to specify the location; for example:

adt -package -target ipa-app-store -provisioning-profile ./myProfile.mobileprovision -storetype pkcs12 -keystore ./Certificates.p12 -storepass XXX myApp.ipa myApp-app.xml Main.swf -extdir ext/ -platformsdk /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/

Using external frameworks and libraries

AIR doesn't link in shared iOS frameworks or libraries, even some of the ones included with the iOS SDK. Here is a list of frameworks that AIR links in by default:

  • CoreFoundation
  • UIKit
  • MobileCoreServices
  • CoreGraphics
  • SystemConfiguration
  • AudioToolbox
  • CFNetwork
  • QuartzCore
  • CoreLocation
  • CoreMedia
  • CoreVideo
  • AVFoundation
  • Foundation
  • OpenGLES
  • Security

If you want to use any other library or framework you have to list them in an XML file, which gets compiled with the native extension. One reason this is required is because Xcode links in external libraries at compile time of the main application. So when you build a library project in Xcode the resulting .a file doesn't contain any code from referenced libraries or frameworks.

If the frameworks are not included with the iOS SDK by default, you must copy them into the iOS SDK folder. (You can also specify custom directories to search for frameworks in the XML file; however you have to specify the path as relative to a path known by the packager, so I find it easier to just copy the libraries and frameworks into the iOS SDK directory.)

Inside of the iOS SDK directory, copy the library or framework files into either the System/Library/Frameworks folder or the usr/lib folder.

Create an XML file with the following structure:

<platform xmlns="http://ns.adobe.com/air/extension/3.1"> <sdkVersion>4.0</sdkVersion> <linkerOptions> <option>-ios_version_min 4.0</option> <option>-framework Twitter</option> <option>-liconv</option> </linkerOptions> </platform>

This file does two important things. First it specifies the version of iOS that you support (in this case, it is 4.0). Secondly, it tells the compiler which frameworks it should look for to compile into the native extension. If referencing a framework (you can tell it's a framework because the folder will be Name.framework ) use the option value –framework name . If it is a library (you can tell it's a library because the file will be a *.dylib) then use the option value –lname .

When compiling the native extension, use the –platformoptions option to specify the location of the XML file; for example:

adt -package -target ane myextension.ane extension.xml -swc mySwc.swc -platform iPhone-ARM library.swf libmylib.a -platformoptions myplatformoptions.xml

See Rajorshi Ghosh's post on this topic for more information.

Using entitlements

As of AIR 3.1 you can specify custom entitlements for your application by listing them in the app descriptor file; for example:

<iPhone> <!-- A list of plist key/value pairs to be added to the application Info.plist --> <InfoAdditions> <![CDATA[ ... ]]> </InfoAdditions> <!-- A list of plist key/value pairs to be added to the application entitlements --> <Entitlements> <![CDATA[ <key>keychain-access-groups</key> <array> <string>...</string> ... </array> ... ]]> </Entitlements> </iPhone>

Rajorshi's post also includes an example of this.

Using attached devices

When using an attached device, such as a barcode scanner, you have to specify an entitlement in the app descriptor file.

Here's the information from the iOS documentation:

To declare the protocols your app supports, you must include the UISupportedExternalAccessoryProtocols key in your app's Info.plist file. This key contains an array of strings that identify the communications protocols that your app supports. Your app can include any number of protocols in this list and the protocols can be in any order. The system does not use this list to determine which protocol your app should choose; it uses it only to determine if your app is capable of communicating with the accessory. It is up to your code to choose an appropriate communications protocol when it begins talking to the accessory.

As explained in the last section, you can add the UISupportedExternalAccessoryProtocols entitlement to your application descriptor file.

Where to go from here

The iOS library is now complete. If you are going to use the native extension on Android devices, read the next tutorial in this series—Building a native extension for iOS and Android – Part 4: Building the Android library. Otherwise continue to the final tutorial in the series— Building a native extension for iOS and Android – Part 5: Building the ANE file.

Creative Commons License
This work is licensed under a Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 Unported License.

More Like This

  • Developing cross-platform Adobe AIR applications
  • Performance-tuning Adobe AIR applications
  • Using Badger for Adobe AIR applications
  • Building a native extension for iOS and Android – Part 2: Developing the ActionScript library
  • Creating your first Adobe AIR application on Android
  • Using web fonts with Adobe AIR 2.5
  • Signing Adobe AIR applications
  • Using push notifications in AIR iOS apps
  • Building Lupo: A case study in building commercial AIR applications
  • Using the Push Notifications native extension for iOS

Products

  • Adobe Creative Cloud
  • Creative Suite
  • Adobe Marketing Cloud
  • Acrobat
  • Photoshop
  • Digital Publishing Suite
  • Elements family
  • SiteCatalyst
  • For education

Download

  • Product trials
  • Adobe Reader
  • Adobe Flash Player
  • Adobe AIR

Support & Learning

  • Product help
  • Forums

Buy

  • For personal and professional use
  • For students, educators, and staff
  • For small and medium businesses
  • Volume Licensing
  • Special offers

Company

  • News room
  • Partner programs
  • Corporate social responsibility
  • Career opportunities
  • Investor Relations
  • Events
  • Legal
  • Security
  • Contact Adobe
Choose your region United States (Change)
Choose your region Close

North America

Europe, Middle East and Africa

Asia Pacific

  • Canada - English
  • Canada - Français
  • Latinoamérica
  • México
  • United States

South America

  • Brasil
  • Africa - English
  • Österreich - Deutsch
  • Belgium - English
  • Belgique - Français
  • België - Nederlands
  • България
  • Hrvatska
  • Česká republika
  • Danmark
  • Eastern Europe - English
  • Eesti
  • Suomi
  • France
  • Deutschland
  • Magyarország
  • Ireland
  • Israel - English
  • ישראל - עברית
  • Italia
  • Latvija
  • Lietuva
  • Luxembourg - Deutsch
  • Luxembourg - English
  • Luxembourg - Français
  • الشرق الأوسط وشمال أفريقيا - اللغة العربية
  • Middle East and North Africa - English
  • Moyen-Orient et Afrique du Nord - Français
  • Nederland
  • Norge
  • Polska
  • Portugal
  • România
  • Россия
  • Srbija
  • Slovensko
  • Slovenija
  • España
  • Sverige
  • Schweiz - Deutsch
  • Suisse - Français
  • Svizzera - Italiano
  • Türkiye
  • Україна
  • United Kingdom
  • Australia
  • 中国
  • 中國香港特別行政區
  • Hong Kong S.A.R. of China
  • India - English
  • 日本
  • 한국
  • New Zealand
  • 台灣

Southeast Asia

  • Includes Indonesia, Malaysia, Philippines, Singapore, Thailand, and Vietnam - English

Copyright © 2013 Adobe Systems Incorporated. All rights reserved.

Terms of Use | Privacy | Cookies

Ad Choices

Reviewed by TRUSTe: site privacy statement