Native Extensions in FlashDevelop part I

Update: you might want to read the follow up article either before or after this article. There are different approaches in FlashDevelop/Air to using/referencing Native Extensions, pick whichever you like best. The follow up article can be found here.

For a project I’m currently working on I needed to include an Adobe Air Native Twitter Extension in to my mobile air project, which I am developing using FlashDevelop. I settled on using the GoViral extension from MilkManGames, and using the documentation available from their extension and from this url, I put together a full description of what I had to do in order to make it work directly from FlashDevelop (with basic twitter support).

I’m assuming you already have a working air mobile project on flashdevelop, succesfully deployed to the iPad/iPhone. If not, take care of that first and come back later.

Step 1

First, update your application descriptor, add:

ย ย ย  <extensions>
<extensionID>com.milkmangames.extensions.GoViral</extensionID>
</extensions>
before </application>

Make sure you are using air 3.1 or higher and update your application descriptor, eg:

<application xmlns=”http://ns.adobe.com/air/application/3.2“>

 

Step 2

Now that you’ve added this extension, running it through run.bat will tell you it cannot find the extension, we’ll fix that in the next steps:

1) copy the com.milkmangames.extensions.GoViral.ane file to your lib folder
2) rename it to com.milkmangames.extensions.GoViral.zip
3) extract it back to com.milkmangames.extensions.GoViral.ane
4) delete the zip
5) update the desktop-run profile in the run.bat file, by adding -extdir lib/ :
adl -screensize %SCREEN_SIZE% “%APP_XML%” “%APP_DIR%” -extdir lib/

Now try running your app again (without referring any GoViral classes yet), tada!

Step 3

Add a print/log/trace statement somewhere using GoViral.isSupported().
You’ll find it’s not working. Add the GoViral.swc or a ane-renamed-swc com.milkmangames.extensions.GoViral.ane/swc to your library folder. And try again…
It will now print false as it should.

Step 4

Create an ext folder under your project, copy the com.milkmangames.extensions.GoViral.ane into this folder.
Update your packager.bat and add -extdir ext/ to this line:

call adt -package -target %TYPE%%TARGET% %OPTIONS% %SIGNING_OPTIONS% “%OUTPUT%” “%APP_XML%” %FILE_OR_DIR%

into

call adt -package -target %TYPE%%TARGET% %OPTIONS% %SIGNING_OPTIONS% “%OUTPUT%” “%APP_XML%” %FILE_OR_DIR% -extdir ext/

Add the following code (replace the StageHelper.print with your own code or include the StageHelper class below):

try {
StageHelper.print (“GoViral:” + GoViral.isSupported());

if (GoViral.isSupported ()) {
GoViral.create();
StageHelper.print (“Tweet sheet available:” + GoViral.goViral.isTweetSheetAvailable());

if (GoViral.goViral.isTweetSheetAvailable()) {
GoViral.goViral.showTweetSheet (“This is a sheet test.”);
} else {
GoViral.goViral.showBasicTwitterPostDialog (“This is a basic test.”);
}
}

} catch (e:Error) {
StageHelper.print (“GoViral error:” + e);
}

As you might have found, but running and packaging the app takes a lot more time when including the extension, so you might want to comment the extension in your application.xml during development. Notice however the difference here between externally linking or including the classes. Externally linking will result in a class reference error, while including them will nicely return false for GoViral.isSupported. For that reason I chose to include the GoViral swc classes. HOWEVER: before you package an adhoc or appstore build MAKE sure you exclude this swc!

For those that would like to use my easy StageHelper class:

package com.innerdrivestudios.core
{
import flash.display.Stage;
import flash.events.KeyboardEvent;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;
import flash.ui.Keyboard;/**
* Provide easy stage access for non display object classes.
*
* @author J.C. Wichman, Inner Drive Studios (www.innerdrivestudios.com / info@innerdrivestudios.com),
*
*/
final public class StageHelper
{
private static var _stage:Stage = null;
private static var _textfield:TextField = null;public static function setStage (pStage:Stage):void {
_stage = pStage;
}

public static function getStage ():Stage {
return _stage;
}

public static function print (pInfo:String, pNewLine:String = “\n”):void {
_setupTextField();
_textfield.visible = true;
_textfield.appendText (pInfo + pNewLine);

_textfield.scrollV = _textfield.maxScrollV;

if (_stage.getChildIndex (_textfield) < (_stage.numChildren – 1)) {
_stage.removeChild (_textfield);
_stage.addChild (_textfield);
}
}

public static function clear():void {
if (_textfield != null) {
_textfield.text = “”;
_textfield.visible = false;
}
}

private static function _setupTextField():void {
if (_textfield != null) return;

if (_stage == null) trace (“Cannot print, stage is null in StageUtil, use setStage first”);

_textfield = new TextField();
var tf:TextFormat = new TextFormat (“_sans”);
_textfield.defaultTextFormat = tf;
_textfield.autoSize = TextFieldAutoSize.LEFT;
_textfield.multiline = true;
_textfield.wordWrap = true;
_textfield.width = _stage.stageWidth;
_textfield.height = 0;

_stage.addChild (_textfield);

_stage.addEventListener (KeyboardEvent.KEY_DOWN, StageHelper._onKeyDown);
}

public static function getTextfield():TextField {
_setupTextField();
return _textfield;
}

private static function _onKeyDown(pKeyEvent:KeyboardEvent):void {
if (pKeyEvent.keyCode == Keyboard.F1) {
_textfield.visible = !_textfield.visible;
}

if (pKeyEvent.keyCode == Keyboard.F2) {
_textfield.autoSize = TextFieldAutoSize.NONE;
_textfield.height = _stage.stageHeight / 4;
}

if (pKeyEvent.keyCode == Keyboard.F3) {
_textfield.autoSize = TextFieldAutoSize.LEFT;
}

if (pKeyEvent.keyCode == Keyboard.F4) {
clear();
}

}
}

}

18 thoughts on “Native Extensions in FlashDevelop part I

  1. Alan_Langlois

    Hi!
    First of all thx for this great summary/post!
    In my case I’m trying to implement the FB side of GoViral and using the FBConnect API.
    I’ve followed your post, after having reading the one from the Adobe website, and the one from philippe, but it sounds like if I’m missing something…

    When I build the app I’m having this error message:
    ld: framework not found Twitter
    Compilation failed while executing : ld64

    BTW, everything goes fine when I compile.

    Do you have any idea of where this error come from?

    To save some time, here is what I did so far:
    – Using the AIR SDK 3.2 + set it in the application.xml file
    – Adding the extension bloc in application.xml
    – Adding an unzipped ( com.milkmangames.extensions.GoViral.ane) version of the ane file contain in the GoViral pack in the lib folder
    – Adding the GoViralAPI.swc as an external library
    – Adding -extdir lib/ in the adl command line in the Run.bat file.
    Compile ok

    – Adding the com.milkmangames.extensions.GoViral.ane file in the “ext” folder
    – Adding -extdir ext/ in the adt command line of the Packager.bat file
    Build fails…

    cheers.

    1. Hans Wichman Post author

      Hi Alan, thanks, glad it was of some help. It sounds like you are trying to build the ipa on windows using the mac ane, or building the ipa on the mac without the correct iOs SDK installed, or with an incorrect path to the iOs SDK. If that is the case, the following might help.

      My setup is like this:
      – as above in the article for windows testing and deploying with basic twitter
      – next I added a directory next to ext called extmac
      – I’ve put everything into a dropbox which synchronizes between my pc and mac (but a network disc is just as easy ofcourse)
      – I’ve upgraded my mac to Lion, installed the latest xcode which includes the latest iOs SDK and installed the latest air sdk on the mac
      – next I made a small clumpy shell script, which I’ve stored next to the FlashDevelop PackageApp.bat

      cd /[path to project root here]/
      adt -package -target ipa-ad-hoc -storetype pkcs12 -keystore /[path to p12 file hre]/ios_dev.p12 -storepass [yourpass] -provisioning-profile apple/[yourprofile].mobileprovision dist/applebuild.ipa application.xml bin/[yourswf].swf -C bin . -C icons/ios . -extdir extmac/ -platformsdk /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.1.sdk

      You’ll have to replace the [] parts of course.

      Everytime I need a complete build, I drag the shell script on mac to the terminal and execute it. This can probably be automated, but I don’t require it that often.

      HTH,
      JC

      1. Alan_Langlois

        Hey, thx for the reply,

        Actually yes I’m developing / building on windows (only) and I’m using the ane packaged in the zip file you have from milkmangames when you buy it.

        So if I’m right, you need a mac / macos anyway to compile your ipa… shitty! ๐Ÿ™‚

        But I maybe found an alternative here: http://blogs.adobe.com/airodynamics/2012/05/18/using-platformsdk-for-ios-on-windows/

        Sounds like if the AIR 3.3 SDK now “fix” the mac need for building the app.

        I’ll try this solution and keep u posted ๐Ÿ˜‰

        Thx

        Alan

  2. Nicholas Bester

    Hey Hansa

    Great post I’m just curious about Step 2 in your instructions above. When you rename the ANE to .ZIP and extract it are you extracting it to a folder or is it a file again?

    Regards
    Nick

    1. Hans Wichman Post author

      Hi Nick,

      thanks, glad it was of help. After renaming the ane to a zip, and extracting it, it becomes a folder, eg com.milkmangames.extensions.GoViral.ane. That’s the main reason you have to rename it, since otherwise the folder blahblah.ane would clash with the filename blahblah.ane.

      HTH!
      JC

  3. Daniel

    copy the com.milkmangames.extensions.GoViral.ane file to your lib folder

    done

    rename it to com.milkmangames.extensions.GoViral.zip

    done

    extract it back to com.milkmangames.extensions.GoViral.ane (isn’t that file already renamed?)

    1. Hans Wichman Post author

      Hi Daniel,

      no, first it is a file (.ane), but you have to convert it into a directory (.ane), so thats the reason for the rename-to-zip step in between, it gets the ane file out of the way, so that the ane directory can be created. You can ofcourse copy the ane file to another directory and extract it directly to yet-another directory. Whatever works best for you.

      HTH
      JC

  4. Daniel

    Thanks for the quick response! still I can’t figure this, sometimes happens that flashdevelop changes and they don’t support new features (happened to me with molehill).

    Anyway, if you have a minute, I have the source in

    http://www.inkedchips.com/native_extension/index.html

    Problem 1
    adding will result in

    com.adobe.extensions.Vibration.ane

    An implementation for native extension ‘com.adobe.extensions.Vibration.ane’ required by the application was not found for the target platform.

    APK setup creation FAILED

    Problem 2

    I create the folder com.adobe.extensions.Vibration.ane and move the EXTRACTED com.adobe.extensions.Vibration.zip there
    adl -screensize %SCREEN_SIZE% โ€œ%APP_XML%โ€ โ€œ%APP_DIR%โ€ -extdir lib/

    If I run it for desktop it will say application descriptor not found

    If I run it for android, it will say “An implementation for native extension ‘com.adobe.extensions.Vibration.ane’ required by the application was not found for the target platform.”

    there is more… but this is what is stopping me from moving forward, I’m using flashdevelop

    Thanks in advance!

  5. Alex Rain

    Hey Hans! Thanks for a great post. But I have one queation. When I am packing the application I got this message:
    Warning: Using default implementation for native extension ‘com.milkmangames.extensions.GoViral’
    What does it mean and how can I avoid it? I know, it’s just a warning, but it seems to affect the final result

  6. Florian Matoflink

    Hi and thanks.

    I like your article, it is very clear.

    However, i’m stuck at step 2. (like Daniel in a previous post, which i read your answer but nothing seemed to solve my problem)

    It says : “An implementation for native extension ‘blahblah’ required by the application was not found for the target platform”

    I’ve tried a few things (options => external library for example) but it still doesn’t work.

    Do you have any idea ?

    Thank you.

  7. Josh

    Thanks man! It worked with their Google Play Services ANE.
    The part that gave me trouble was the part where you made the .ane to a .zip.

    For anyone not getting it:
    You rename the “com.milkmangames.extensions.GoogleGames.ane” file to “com.milkmangames.extensions.GoogleGames.zip” in flashdevelop and it should become a .zip file. Then, use windows to extract it in the same directory as the .zip file to a FOLDER called “com.milkmangames.extensions.GoogleGames.ane”. This is just so you can build the .swf in air.

  8. Tyranus

    Hi there,

    Thanks for sharing!

    I am trying to use a joystick in Windows and in AIR by using an ane called “AirControl.ane”. So i am trying to do that on desktop only. I have followed your tutorial, but, I get an error “not supported native extension profile”. I have googled but with not lucky. What I am doing wrong?
    I am using Flash Develop 4.5.1, Air 3.9 and Flex. I have try add in supported profiles extendedDesktop.

    Thanks!

Leave a Reply