You are on page 1of 18

Flash Runtime Native Extensions

Building AIR apps with native capabilities


Rajorshi Ghosh Choudhury

Syed Mohd Mehadi

Computer Scientist

Lead Software Engineer

Your logo
(optional)

What are native extensions?


Third-party, native-code backed ActionScript API
additions to AIR applications
Flash Builder
Android SDK & NDK
XCode

AIR SDK

Who needs them anyway


Adobe AIR is awesome

Allows you to create cross platform applications


Rapid multiscreen development
A large feature set (Accelerometer, Geolocation, Gestures and more)

But

No access to some device specific capabilities (Contacts, Bluetooth, etc)


Waits for a native feature to mature before providing access to it
Porting existing native applications to AIR might be a pain

Bridging the gap

Provides access to device specific features


Native developers can reuse existing code
AS API set can be extended
Same interface can be used on different platforms

Anatomy of an extension
A set of ActionScript classes
Associated native code for one or more target
devices
A descriptor that contains deployment information
A signature to ensure secure delivery (optional)

Accessing the native code

Creating the Extension Context

A context object binds the ActionScript and native halves of


an extension.
Calls to native functions happen within a context.
There may be multiple extension context objects.
import flash.external.ExtensionContext;
...
var ctx : ExtensionContext =
ExtensionContext.createExtensionContext(com.sample.myExtension", basicType");
var str : String = ctx.call(myNativeFunction") as String;
...
ctx.dispose();

Writing the native code

Use either C or Java APIs


APIs are mostly cross-platform
Can be multi-threaded
Compiled into static or dynamic libraries depending on
target platform

Writing the native code

Initializing and finalizing the extension

Extension Initializer
Called when the first extension context is created.
typedef void (*FREInitializer)(
void** extDataToSet ,
FREContextInitializer* ctxInitializerToSet,
FREContextFinalizer* ctxFinalizerToSet );

Extension Finalizer
Called (if and) when extension is unloaded.
typedef void (* FREFinalizer)(
void** extDataToSet);

Writing the native code

Initializing and finalizing the context

Context Initializer
Called every time a new extension context is created.
Registers native functions to be called in this context.
typedef void (*FREContextInitializer)(
void** extDataToSet ,
const uint8_t* ctxType,
FREContext
ctx,
uint32_t* numFunctionsToSet,
const FRENamedFunction** functionsToSet);

Context Finalizer
Called when an extension context is disposed.
typedef void (* FREContextFinalizer)(
FREContext
ctx);

Initialization Sequence

10

Extension
APIs
Accessing ActionScript Objects from native code
Manipulate ActionScript types in native code

FREResult

FRENewObject(const uint8_t* className,


uint32_t argc,
FREObject[] argv,
FREObject* object,
FREObject* thrownException );

Get/Set properties of ActionScript objects

FREResult FREGetObjectProperty( FREObject object,


const uint8_t* propertyName,
FREObject* propertyValue,
FREObject* thrownException );
FREResult FRESetObjectProperty( FREObject object,
const uint8_t* propertyName,
FREObject propertyValue,
FREObject* thrownException );

Call methods of ActionScript objects

FREResult FRECallObjectMethod(FREObject object,


const uint8_t* methodName,
uint32_t argc,
FREObject[] argv,
FREObject* result,
FREObject* thrownException);

11

Multi-threading support

Threading

Native libraries may be multi-threaded


Native calls are serialized
All functions in the API except one can be called only from a
thread on which a registered function is in progress.
Only function that can be called from any thread is
FREDispatchStatusEventAsync()/FREContext.DispatchStatusEventAsy
nc()

12

Describing
the
Extension
The extension descriptor
<extension xmlns="http://ns.adobe.com/air/extension/2.5">
<id>com.sample.myExtension</id>
<version>1</version>
<platforms>
<platform name="Android-ARM">
<applicationDeployment>
<nativeLibrary>MyExtension.jar</nativeLibrary>
<initializer>com.example.MyExtension</initializer>
</applicationDeployment>
</platform>
<platform name="MacOS-x86">
<applicationDeployment>
<nativeLibrary>MyExtension.framework</nativeLibrary>
<initializer>InitMyExtension</initializer>
<finalizer>FiniMyExtension</finalizer>
</applicationDeployment>
</platform>
<!-- Hypothetical example of a possible Digital Home platform -->
<platform name="Samsung-MIPS">
<deviceDeployment/>
</platform>
<!-- Optional default impl -->
<platform name="default">
<applicationDeployment/>
</platform>
</platforms>
</extension>

13

Consuming an Extension
extension.xml

extension
library (.swc)

native library +
library.swf +
assets

output.ane

Applicati
on.xml

Application.s
wf

output.ane

AIR application

14

C API List
FREResult FREGetContextNativeData( FREContext ctx, void** nativeData );
FREResult FRESetContextNativeData( FREContext ctx, void* nativeData );
FREResult FREGetContextActionScriptData( FREContext ctx, FREObject *actionScriptData );
FREResult FREGetObjectType( FREObject object, FREObjectType *objectType );
FREResult FREGetObjectAsInt32 ( FREObject object, int32_t *value );
FREResult FREGetObjectAsUint32( FREObject object, uint32_t *value ); FREResult FREGetObjectAsDouble( FREObject object,
double *value ); FREResult FREGetObjectAsBool ( FREObject object, bool *value );
FREResult FRENewObjectFromInt32 ( int32_t value, FREObject *object );
FREResult FRENewObjectFromUint32( uint32_t value, FREObject *object );
FREResult FRENewObjectFromDouble( double value, FREObject *object );
FREResult FRENewObjectFromBool ( FREBool value, FREObject *object );
FREResult FREGetObjectAsUTF8( FREObject object, uint32_t* length, const uint8_t** value );
FREResult FRENewObjectFromUTF8( uint32_t length, const uint8_t* value , FREObject* object );
FREResult FRENewObject( const uint8_t* className , uint32_t argc , FREObject[] argv , FREObject* object , FREObject*
thrownException );
FREResult FREGetObjectProperty( FREObject object , const uint8_t* propertyName , FREObject* propertyValue , FREObject*
thrownException );
FREResult FRESetObjectProperty( FREObject object , const uint8_t* propertyName , FREObject propertyValue , FREObject*
thrownException );
FREResult FRECallObjectMethod ( FREObject object , const uint8_t* methodName , uint32_t argc , FREObject[] argv ,
FREObject* result , FREObject* thrownException );
FREResult FREAcquireBitmapData( FREObject object , FREBitmapData* descriptor );
FREResult FREInvalidateBitmapDataRect( FREObject object, uint32_t x , uint32_t y , uint32_t width , uint32_t height );
FREResult FREReleaseBitmapData( FREObject object );
FREResult FREAcquireByteArray( FREObject object , FREByteArray* byteArray );
FREResult FREReleaseByteArray( FREObject object );
FREResult FRESetArrayLength( FREObject arrayOrVector, uint32_t length );
FREResult FREGetArrayLength( FREObject arrayOrVector, uint32_t* length );
FREResult FRESetArrayElementAt( FREObject arrayOrVector, uint32_t index , FREObject value );
FREResult FREGetArrayElementAt( FREObject arrayOrVector, uint32_t index , FREObject* value );
FREResult FREDispatchStatusEventAsync( FREContext ctx , const uint8_t* code , const uint8_t* level );
15

Java API List


interface FREExtension {
void initialize ();
FREContext createContext( String contextType);
void dispose ();
}
public abstract class FREContext {
public abstract Map<String,FREFunction> getFunctions();
public FREObject getActionScriptData();
public void setActionScriptData( FREObject object );
public abstract void dispose();
public void dispatchStatusEventAsync( String code,
String level );
}
interface FREFunction {
FREObject call( FREContext ctx, FREObject[] args );
}

public static native FREObject newObject ( String


className, FREObject constructorArgs[]);
}
public class FREBitmapData extends FREObject {
public static FREBitmapData newBitmapData (int width, int
height, boolean transparent, Byte[] fillColor);
public int getWidth();
public int getHeight() ;
public java.nio.ByteBuffer getBits();
public void acquire();
void invalidateRect( int x , int y , int width , int height );
}
public class FREByteArray extends FREObject {
public static FREByteArray newByteArray ();
public long getLength();
public java.nio.ByteBuffer getBytes();
public void acquire();
public void release();
}

public class FREObject {


public static FREObject newObject ( int value );
public static FREObject newObject ( double value );
public static FREObject newObject ( boolean value );
public static FREObject newObject ( String value );
public class FREArray extends FREObject {
public int getAsInt (); public double getAsDouble();
public static FREArray newArray (String classname, int
public bool void setProperty( String propertyName, FREObject
numElements, boolean fixed);
propertyValue );
public static FREArray newArray (int numElements);
FREObject callMethod( String methodName,
public long getLength();
FREObject methodArgs[] );
public void setLength( long length );
getAsBool ();
public FREObject getObjectAt( long index );
public String getAsString();

public void setObjectAt( long index, FREObject value );

FREObject getProperty( String propertyName );

16

Demo

17

Demo
Extension

AIR Part (.swf)

AS library (.swc)

Native code (.a)

Class ASLayer {

var asLayer : ASLayer = new ASLayer();

FREObject VibrateMethod(arguments) {

asLayer.VibrateDevice();

private var context : ExtensionContext =


ExtensionContext.createExtensionContext(extID,
type);

public function VibrateDevice() : void {


Context.call(VibrateMethod);
}

NSLog(@*********In NativeVibrateMethod);
AudioSeervicesPlaySystemSound(
kSystemSoundID_Vibrate );
return NULL;
}

18

You might also like