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
2
AIR SDK
Flash Builder
Android SDK & NDK
XCode
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
3
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
4
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)
5
Accessing the native code
• 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.
6
Creating the Extension Context
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
7
Writing the native code • Extension Initializer
– Called when the first extension context is created.
• Extension Finalizer
– Called (if and) when extension is unloaded.
8
Initializing and finalizing the extension
typedef void (*FREInitializer)(
void** extDataToSet ,
FREContextInitializer* ctxInitializerToSet,
FREContextFinalizer* ctxFinalizerToSet );
typedef void (* FREFinalizer)( void** extDataToSet);
Writing the native code • Context Initializer
– Called every time a new extension context is created. – Registers native functions to be called in this context.
• Context Finalizer – Called when an extension context is disposed.
9
Initializing and finalizing the context
typedef void (*FREContextInitializer)(
void** extDataToSet , const uint8_t* ctxType, FREContext ctx,
uint32_t* numFunctionsToSet,
const FRENamedFunction** functionsToSet);
typedef void (* FREContextFinalizer)( FREContext ctx);
Initialization Sequence
10
Extension APIs • 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
Accessing ActionScript Objects from native code
Multi-threading support
• 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.DispatchStatusEventAsync()
12
Threading
Describing the Extension <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
The extension descriptor
Consuming an Extension
14
output.ane
extension library (.swc)
extension.xml
native library + library.swf +
assets
AIR application
Application.swf
output.ane Application.xml
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 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 int getAsInt (); public double getAsDouble();
public bool void setProperty( String propertyName, FREObject propertyValue );
FREObject callMethod( String methodName,
FREObject methodArgs[] );
getAsBool ();
public String getAsString();
FREObject getProperty( String propertyName ); 16
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 FREArray extends FREObject {
public static FREArray newArray (String classname, int numElements, boolean fixed);
public static FREArray newArray (int numElements);
public long getLength();
public void setLength( long length );
public FREObject getObjectAt( long index );
public void setObjectAt( long index, FREObject value );
}
Demo
17
Demo
18
AIR Part (.swf)
…
…
var asLayer : ASLayer = new ASLayer();
asLayer.VibrateDevice();
…
…
AS library (.swc)
…
Class ASLayer {
…
private var context : ExtensionContext = ExtensionContext.createExtensionContext(extID, type);
public function VibrateDevice() : void {
Context.call(“VibrateMethod”);
}
…
}
…
Native code (.a)
…
…
FREObject VibrateMethod(arguments) {
NSLog(@”*********In NativeVibrateMethod”);
AudioSeervicesPlaySystemSound( kSystemSoundID_Vibrate );
return NULL;
}
…
…
Extension
Top Related