Stronger Together: Developing an Organizational Strategy for Accessible Desig...
AFPS_2011
1. Flash Runtime Native Extensions
Building AIR apps with native capabilities
Rajorshi Ghosh Choudhury Syed Mohd Mehadi
Computer Scientist Lead Software Engineer
Your logo
(optional)
2. What are native extensions?
Third-party, native-code backed ActionScript API
additions to AIR applications
Flash Builder
Android SDK & NDK
AIR SDK
XCode
2
3. 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
4. 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
5. 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
6. 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();
6
7. 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
8. 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);
8
9. 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);
9
12. 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
13. 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
16. Java API List
interface FREExtension {
public static native FREObject newObject ( String
void initialize ();
className, FREObject constructorArgs[]);
FREContext createContext( String contextType); }
void dispose ();
}
public class FREBitmapData extends FREObject {
public static FREBitmapData newBitmapData (int width, int
public abstract class FREContext {
height, boolean transparent, Byte[] fillColor);
public abstract Map<String,FREFunction> getFunctions();
public int getWidth();
public FREObject getActionScriptData();
public int getHeight() ;
public void setActionScriptData( FREObject object );
public java.nio.ByteBuffer getBits();
public abstract void dispose();
public void acquire();
public void dispatchStatusEventAsync( String code,
String level );
void invalidateRect( int x , int y , int width , int height );
} }
interface FREFunction { public class FREByteArray extends FREObject {
FREObject call( FREContext ctx, FREObject[] args ); public static FREByteArray newByteArray ();
} public long getLength();
public java.nio.ByteBuffer getBytes();
public class FREObject { public void acquire();
public static FREObject newObject ( int value ); public void release();
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