Buy any Easy Native Extensions 2nd Edition package and get our $99 iOS + Android ANE Template completely free before the end of June 2015.
- step-by-step guide to making your iOS extension in under an hour
- library for data conversion between ActionScript and native code
- tutorials
- infographics
- code included
At the end of this part you will have:
An Xcode project with AIR interface and function placeholders for driving the camera which you’ll fill in the next few parts of the tutorial.
Time
8-10 miutes
Wait, have you done this first?
- Part 1: Create a test app – 15-20 minutes
- You don’t necessarily need a test app to complete this part of the tutorial, but it gives you an idea of what you’ll need from the ANE and a way of testing your code as you write it. Go on, set up your app, I’ll wait for you here.
Step 1: Create an iOS library in Xcode
In Xcode’s menu select File > New >Project, then under iOS select Framework & Library > Cocoa Touch Static Library.
Name your project and save it. I have named my project CameraLibiOS and this is what Xcode creates for me in Project Navigator:
For the iOS library we won’t need the header file CameraLibiOS.h, so feel free to delete it (Right-click > Delete). The source file CameraLibiOS.m will be the focus of our work today – read on to see why.
Step 2: Add the AIR SDK
On iOS all you need is to add the AIR SDK header, FlashRuntimeExtensions.h, to your project. I like to put the AIR SDK header under Supporting Files in Project Navigator – it doesn’t really matter where it sits in the project structure, though.
Right-click Supporting files and select Add files to “CameraLibiOS…”, then navigate to where the AIR SDK is installed on your machine, very likely here:
1 |
/Applications/Adobe Flash Builder 4.6/sdks/4.6.0/include/FlashRuntimeExtensions.h |
If you are unsure whether to check Copy items into destination group’s folder (if needed), have a look at this article: Do you need a copy of FlashRuntimeExtensions.h in your project?
Step 3: Add the Native Extension initializer and finalizer
Open CameraLibiOS.m. In this file we’ll put the code that ActionScript can call – this will be the interface of your native library.
Xcode has helpfully put a class implementation there for you:
1 2 3 4 5 |
#import "CameraLibiOS.h" @implementation CameraLibiOS @end |
Very nice of you, Xcode, but we won’t be using that – you don’t really need a class for our purposes here. Exterminate. Delete. Delete. Sorry. Couldn’t resist.
Starting with a clean slate, import the AIR SDK header first:
1 |
#import "FlashRuntimeExtensions.h" |
Next, let’s add the extension initializer:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
//------------------------------------ // // Extension initialization and finalization // //------------------------------------ void CameraLibInitializer( void * * extDataToSet, FREContextInitializer * ctxInitializerToSet, FREContextFinalizer * ctxFinalizerToSet ) { *extDataToSet = NULL; *ctxInitializerToSet = &CameraLibContextInitializer; *ctxFinalizerToSet = &CameraLibContextFinalizer; } |
If you copy and paste that function in Xcode you’ll notice that it underlines the last two lines as errors:
Semantic issue: Use of undeclared identifier ‘CameraLibContextInitializer’; did you mean ‘CameraLibInitializer’?
Semantic issue: Use of undeclared identifier ‘CameraLibContextFinalizer’; did you mean ‘CameraLibInitializer’?
Let Xcode complain and don’t allow it to think you meant ‘CameraLibInitializer’ in either case. CameraLibContextInitializer and CameraLibContextFinalizer are the names of your context initializer and finalizer functions, which you’ll add in a minute.
Before that, add your extension finalizer:
1 2 3 4 |
void CameraLibFinalizer( void* extData ) { return; } |
Step 4: Add the Context initializer and finalizer
Here you will implement CameraLibContextInitializer and CameraLibContextFinalizer that we promised Xcode a few moments ago:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
//------------------------------------ // // Context initialization and finalization // //------------------------------------ void CameraLibContextInitializer( void * extData, const uint8_t * ctxType, FREContext ctx, uint32_t * numFunctionsToSet, const FRENamedFunction ** functionsToSet ) { // Create mapping between function names and pointers in an array of FRENamedFunction. // These are the functions that you will call from ActionScript - // effectively the interface of your native library. // Each member of the array contains the following information: // { function name, as it will be called from ActionScript, // any data that should be passed to the function, // a pointer to the implementation of the function in the native library } static FRENamedFunction extensionFunctions[] = { { ( const uint8_t* ) "as_startCameraPreview", NULL, &ASStartCameraPreview }, { ( const uint8_t* ) "as_stopCameraPreview", NULL, &ASStopCameraPreview } }; // Tell AIR how many functions there are in the array: *numFunctionsToSet = sizeof( extensionFunctions ) / sizeof( FRENamedFunction ); // *functionsToSet = extensionFunctions; // Make a copy of the extension context pointer. // We'll use it to send events to AIR. g_ctx = ctx; } void CameraLibContextFinalizer( FREContext ctx ) { return; } |
The next thing that happens after you add the code above is that Xcode complains about not knowing what g_ctx, ASStartCameraPreview and ASStopCameraPreview are. Let’s fix that. First, define g_ctx at the top of your file, right after where you import FlashRunTimeExtensions.h:
1 2 3 4 5 6 |
#import "FlashRuntimeExtensions.h" // A copy of the extension context // that's passed to the extension initializer. // We'll use it for sending events to AIR: FREContext g_ctx; |
We’ll add the other missing declarations in Step 5.
Step 5: Add the AIR interface
Although you don’t know yet exactly how we’ll obtain a camera preview and pass it to ActionScript, you have two pieces of functionality you can add at this point: you’ll want native code to start and stop the camera:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
//------------------------------------ // // ActionScript interface // //------------------------------------ FREObject ASStartCameraPreview( FREContext ctx, void* funcData, uint32_t argc, FREObject argv[] ) { // ActionScript will call this function to set up and start the camera return NULL; } FREObject ASStopCameraPreview( FREContext ctx, void* funcData, uint32_t argc, FREObject argv[] ) { // ActionScript will call this function to stop the camera return NULL; } |
These two functions are placeholders. We’ll be returning to fill them in with functionality in Part 5: Start the camera from ActionScript and Part 8: Stop the camera.
Step 6: Add a way of sending events to AIR
You will need a way of telling ActionScript if something happens outside one of the functions you have just declared. Add a function that will do just that:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
//------------------------------------ // // Auxiliary functions // //------------------------------------ void sendMessage( const NSString * const messageType, const NSString * const message ) { // See Keeping your C native code reusable and independent of AIR // at http://easynativeextensions.com/keeping-your-native-code-reusable/ assert( NULL != messageType ); assert( NULL != g_ctx ); if ( NULL != message ) { FREDispatchStatusEventAsync( g_ctx, ( uint8_t * ) [ messageType UTF8String ], ( uint8_t * ) [ message UTF8String ] ); } else { FREDispatchStatusEventAsync( g_ctx, ( uint8_t * ) [ @"STATUS_EVENT" UTF8String ], ( uint8_t * ) [ messageType UTF8String ] ); } } |
Step 7: Make sure your library builds
You won’t be able to run any of this code just yet, but let’s make sure it builds OK. In Xcode select Product > Build (or press Command + B). This should produce libCameraLibiOS.a under Products:
If you get any build errors, work through them one by one. Xcode will tell you what its problem is. Alternatively, shout in the comments below and we’ll do our best to help.
What’s next?
- Part 3: Set up the AIR Library – 8-10 minutes
- Here is the table of contents for the tutorial, in case you want to jump back or ahead.
Helpful reading
If this is the first time you are writing an Xcode library to be used by AIR, here is a list of articles that will help you make sense of what we have just done:
- What goes in an ANE for iOS?
- Extension Initializer and Finalizer in C
- Extension Context Initializer and Finalizer in C
- Loading your ANE – infographic
- Unloading your ANE – infographic
-
Communication between ActionScript and native code in an ANE
Check out the DiaDraw Camera Driver ANE.
Pornphop
I try that your code but It still build fail
this is my code:
https://www.dropbox.com/s/k7e3su97sjfpdw9/doubleroboticExtension.m?dl=0
this is my project
https://www.dropbox.com/sh/ski834tfe2y1wwx/AAABNMj5p2yIvJQq31J5q54ma?dl=0
please suggest me
thank you very much
Pornphop
Radoslava
Hi Pornphop,
In doubleroboticExtension.m the context initializer and finalizer need to be defined before the extension initializer and finalizer: i.e. DRDoubleLibContextInitializer and DRDoubleLibContextFinalizer need to be above DRDoubleLibInitializer, so it can see them.
Radoslava