iOS : Flash Proでネイティブ拡張(ANE)に挑戦

広告:超オススメUnity Asset
  広告:超オススメUnity Asset

Flash Professional CS6の新機能のひとつとして、ネイティブ拡張(ANE)を使ったAIRアプリケーションが作れるようになりました。ANEと言えば、Flash Builderで使っている方が多いと思いますが、ここではiOS用のみに機能を限定して、XcodeとFlash BuilderでANEを作り、Flash Professionalでそれを利用するAIR for iOSアプリを作ってみたいと思います。
Flash x ANE


AdobeのADC記事「ネイティブ拡張(Native Extensions)入門 第2回 ネイティブ拡張の開発方法 前編 (by 有川 榮一氏)」を参考に、このまんま作ってみたいと思います。ただし、iOSに機能を限定して少しシンプルにします。(これでも少しシンプルになってるのです。。)

ANEはどうやって作るか

図で書くとこんな感じ。

ANEはどうやって作るか

ANEはどうやって作るか

ここで使うそれぞれの製品とバージョンはこんな感じ。また、作業する際のコンピュータはMacを使います。

  • Xcode 4.3.3
  • Flash Builder 4.6
  • Flash Professional CS6
  • Adobe AIR SDK 3.2 (*1)

※1 このMEMOを書いている時点でAIR SDKの最新版は3.3がリリースされていますが、ここでは、Flash Pro CS6に同梱されている3.2を使うことにします。また、Flash Professional CS6では、新機能として、AIR SDKのバージョン管理がしやすくなっており、「ヘルプ>AIR SDKを管理…」から新しく追加したAIR SDKのバージョンに切り替える事ができるようになっています。

大まかな流れとしては、こんな感じ。

  1. Cocoa Touch Static Library(.a)の作成
  2. ネイティブ拡張ActionScriptライブラリ(.swc)の作成
  3. library.swfの抽出
  4. 証明書ファイル(.p12)の作成
  5. ネイティブ拡張記述ファイル(.xml)の作成
  6. ADTコマンドを使ってANEファイル(.ane)を作成
  7. Flash ProfessionalのAIR for iOS(.ipa)でANEを使用

いろいろ作業する前に、step6で使用するADT用のフォルダを準備して、これから書き出すファイルをみんなそこへ集めるようにします。(以下「ADT用のフォルダ」と書きます。)

1. Cocoa Touch Static Library(.a)の作成

iOSに機能を限定しますので、この記事中盤の図8あたりのXcodeから開始します。

  1. Xcodeを起動して、新規にプロジェクトを作成。
  2. [Framework & Library]で[Cocoa Touch Static Library]を選択。
  3. [Product Name]欄に「HelloWorldANE」と入れ、[Company Identifier]欄にここでは「com.mushikago」と入力(両方とも任意の文字列です)。
  4. FlashRuntimeExtensions.h」というファイルをプロジェクトに追加。プロジェクトのコンテキストメニューから「Add Files to “HelloWorldANE”…」を選択。
  5. Flash Pro CS6にはAIR3.2が同梱されているので「/Applications/Adobe Flash CS6/AIR3.2/include/FlashRuntimeExtensions.h」というパスにあるファイルを選択して、Destinationのチェックをつけて、プロジェクトフォルダ内にコピーしましょう。
  6. ADC記事にあるように、「GetHelloWorld」というネイティブ拡張関数、コンテキストの初期化関数、破棄関数を作ります。「HelloWorldANE.h」と「HelloWorldANE.m」がそれぞれ下記のようになるように。
    HelloWorldANE.h

    [sourcecode language=”objc”]
    #import <Foundation/Foundation.h>
    //↓これ追加するの忘れずに
    #import "FlashRuntimeExtensions.h"

    @interface HelloWorldANE : NSObject

    @end

    FREObject GetHelloWorld(
    FREContext ctx,
    void* funcData,
    uint32_t argc,
    FREObject arg[]
    );

    void ContextInitializer(
    void* extData,
    const uint8_t* ctxType,
    FREContext ctx,
    uint32_t* numFunctionsToTest,
    const FRENamedFunction** functionsToSet
    );

    void ContextFinalizer(FREContext ctx);

    void ExtInitializer(
    void** extDataToSet,
    FREContextInitializer* ctxInitializerToSet,
    FREContextFinalizer* ctxFinalizerToSet
    );
    void ExtFinalizer(void* extData);
    [/sourcecode]

    HelloWorldANE.m
    #import "HelloWorldANE.h"
    
    @implementation HelloWorldANE
    
    @end
    
    FREObject GetHelloWorld(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[]) {
        
        const char *str = "HelloWorld MUSHIKAGO!";
        
        FREObject retStr;
        FRENewObjectFromUTF8(strlen(str)+1, (const uint8_t *)str, &retStr);
        
        return retStr;
    }
    
    void ContextInitializer(void* extData, const uint8_t* ctxType, FREContext ctx,
                            uint32_t* numFunctionsToTest, const FRENamedFunction** functionsToSet) {
        *numFunctionsToTest = 1;
        FRENamedFunction* func = (FRENamedFunction*)malloc(sizeof(FRENamedFunction)*1);
        func[0].name = (const uint8_t*)"GetHelloWorld"; //ネイティブ拡張関数名
        func[0].functionData = NULL;
        func[0].function = &GetHelloWorld; //ネイティブコード関数のポインタ
        
        *functionsToSet = func;
    }
    void ContextFinalizer(FREContext ctx) {
        return;
    }
    
    void ExtInitializer(void** extDataToSet, FREContextInitializer* ctxInitializerToSet,
                        FREContextFinalizer* ctxFinalizerToSet) {
        *extDataToSet = NULL;
        *ctxInitializerToSet = &ContextInitializer;
        *ctxFinalizerToSet = &ContextFinalizer;
    }
    void ExtFinalizer(void* extData) {
        return;
    }
    
  7. Buildします。
  8. [Project > Build for > Archiving]もやっておきましょう。[libHelloWorldANE.a]上でコンテキストメニューを出して、[Show in Finder]を選ぶとlibHelloWorldANE.aが実際に書きだされているフォルダが開きますが、Build for Archivingすることで、「Release-iphoneos」ができますので、その中の「libHelloWorldANE.a」を、後に使うADT用のフォルダにコピーしておきましょう。

これでネイティブ拡張ライブラリ(.a)が準備できました。

2. ネイティブ拡張ActionScriptライブラリ(.swc)の作成

次は、ADC記事の第3回の最初から。ネイティブ拡張ActionScriptライブラリ(.swc)というAIRとネイティブ拡張ライブラリの中継役を務めるものを作ります。

  1. Flash Builderを使います。
  2. Flash Builder 4.6を起動して、ファイル>新規>Flexライブラリプロジェクト で新規プロジェクトを作成。
  3. プロジェクト名は「HelloWorldANE_ASLIB」(任意です)としました。
  4. ActionScriptクラスを作成。
  5. flash.events.EventDispatcherを継承して作ります。ここでは、パッケージ「com.mushikago」、名前「HelloWorldExtension」(パッケージ名やクラス名は任意)としました。
  6. ADC記事にあるように、「ExtensionContextインスタンスのcall関数」やそれに必要なimport、変数宣言、関数などを追加。以下のように。

    HelloWorldExtension.as

    package com.mushikago
    {
    	import flash.events.EventDispatcher;
    	import flash.events.IEventDispatcher;
    	import flash.external.ExtensionContext; //追加
    	
    	public class HelloWorldExtension extends EventDispatcher
    	{
    		private var context:ExtensionContext; //追加
    		public function HelloWorldExtension(target:IEventDispatcher=null)
    		{
    			super(target);
    			context= ExtensionContext.createExtensionContext("mushikago.ane.HelloWorld", "type"); //追加
    		}
    		
    		//追加 /////
    		public function getHelloWorld():String
    		{
    			return context.call("GetHelloWorld") as String;
    		}
    		
    		public function dispose():void
    		{
    			return context.dispose();
    		}
    		/////////////
    		
    	}
    }
    
  7. コンパイラー引数に「-swf-version 13」と入力。
  8. プロジェクトのビルド」を選択してビルド。「bin」の中の「HelloWorldANE_ASLIB.swc」を、後に使うADT用のフォルダにコピーしておきましょう。

これでネイティブ拡張ActionScriptライブラリ(.swc)が準備できました。

3. library.swfの抽出

swcを作ったついでに、ADT時に必要なlibrary.swfを抽出しておきます。ADC記事ではこの辺にさらっと書いてあります。

  1. 「HelloWorldANE_ASLIB.swc」を複製しておいて、拡張子を「.zip」に変えちゃいます。
  2. ダブルクリックして解凍すると、中に「library.swf」が入ってますので、それをADT用のフォルダにコピー。

これでlibrary.swfが準備できました。

4. 証明書ファイル(.p12)の作成

証明書ファイルは、Flash BuilderやADTコマンドでも作れますが、ここではFlash Professional CS6で作ります。

  1. Flash Professional CS6を起動し、新規ファイルで「AIR」を選択。名称未設定のままで保存する必要ありません。「ファイル>AIR 3.2 for Desktop 設定…」を選択。
  2. 署名」タブを開き、「証明書」欄の「新規」を選択。
  3. 必要な情報を入力。パスワードはADTコマンドを実行する時に使いますので忘れないように。
    名前を付けて保存」欄では、このファイルを書き出したい場所、ファイル名を選択。ここでは、「mykey.p12」としました。
  4. 「OK」を押すと、その時点で「mykey.p12」が作成されるのでADTフォルダにコピー。

これで証明書ファイル(.p12)が準備できました。

5. ネイティブ拡張記述ファイル(.xml)の作成

最後にネイティブ拡張記述ファイルを作成します。ADC記事では、ここに詳しく書かれています。テキストエディタでXMLを作成します。

  1. 「extension.xml」というファイル名(任意です)で、以下のXMLを作成。Android部分は今回コメントアウトしています。注意すべき点は、<id>です。「mushikago.ane.HelloWorld」となっているExtension IDは、「2. ネイティブ拡張ActionScriptライブラリ(.swc)の作成」のActionScriptクラス内に記述した「ExtensionContext.createExtensionContext」の第一引数の文字列と一致させてください。
    [sourcecode language=”xml”]
    <extension xmlns="http://ns.adobe.com/air/extension/3.1">
    <id>mushikago.ane.HelloWorld</id>
    <versionNumber>1.0.0</versionNumber>
    <name>
    <text xml:lang="en_US">Hello World</text>
    <text xml:lang="ja_JP">こんにちは 世界</text>
    </name>
    <platforms>
    <!–
    <platform name="Android-ARM">
    <applicationDeployment>
    <nativeLibrary>HelloWorldANE.jar</nativeLibrary>
    <initializer>example.ane.android.HelloWorldExtension</initializer>
    <finalizer>example.ane.android.HelloWorldExtension</finalizer>
    </applicationDeployment>
    </platform>
    –>
    <platform name="iPhone-ARM">
    <applicationDeployment>
    <nativeLibrary>libHelloWorldANE.a</nativeLibrary>
    <initializer>ExtInitializer</initializer>
    <finalizer>ExtFinalizer</finalizer>
    </applicationDeployment>
    </platform>
    <!–
    <platform name="default">
    <applicationDeployment/>
    </platform>
    –>
    </platforms>
    </extension>
    [/sourcecode]

これでネイティブ拡張記述ファイル(.xml)が準備できました。ADT用のフォルダにコピーしてください。

6. ADTコマンドを使ってANEファイル(.ane)を作成

いよいよ、ADTコマンドを使ってANEを作ります。ADTコマンドを使うにあたって、PATH環境変数にAIR SDKのbinディレクトリを含めておくと便利です。こちらにその方法が書いてあります。確認まで含めてざっと書いておくとこんな感じ。ターミナルで一行ずつ実行していけばいけると思います。

cd
cat >> .bash_profile
export PATH=$PATH:/Applications/Adobe\ Flash\ CS6/AIR3.2/bin

ここで、キーボードの Ctrl+Shift+D キーを押して、テキストのリダイレクトを終了します。

cat .bash_profile
echo $PATH
adt -version

ターミナルで、ADT用のフォルダに移動し、以下のADTコマンドを実行します。各ファイル名は今まで任意につけてきた名前です。「FirstHelloWorldANE.ane」という名称が出力するANEのファイル名です。

adt -package

 -storetype pkcs12

 -keystore mykey.p12

 -target ane FirstHelloWorldANE.ane extension.xml

 -swc HelloWorldANE_ASLIB.swc

 -platform iPhone-ARM library.swf libHelloWorldANE.a

※↑実際は一行です。

ADTコマンドを実行するとパスワードを聞かれますが、これは「4. 証明書ファイル(.p12)の作成」で「mykey.p12」を作成した際のパスワードです。問題なく出力されるとADT用のフォルダ内に「FirstHelloWorldANE.ane」が作成れますので、これをFlash Proで利用する際に使うフォルダ(以下、「Flash Pro用のフォルダ」)にコピーしておきます。

7. Flash ProfessionalのAIR for iOS(.ipa)でANEを使用

ANEが作成できたので、今度はそれをFlash Professional CS6で利用してみます。

  1. Flash Professional CS6を起動して、「AIR for iOS」の新規ファイルを作成。「FirstHelloWorld_FlashPro.fla」(任意)というファイル名でFlash Pro用のフォルダに保存。
  2. ファイル>ActionScript設定の「ライブラリパス」タブを選択し、「+」アイコンをクリックしてから、ANEアイコン をクリックしてANEを追加。
  3. ステージ上に「test_txt」とインスタンス名をつけたダイナミックテキストを配置。
  4. 第一フレームのフレームアクションに以下のActionScriptを記入。
    //ANE HelloWorld
    import com.mushikago.HelloWorldExtension;
    test_txt.text = "test";
    var _ane:HelloWorldExtension = new HelloWorldExtension();
    test_txt.text = _ane.getHelloWorld();
    
  5. ファイル>AIR 3.2 for iOS 設定… を開くと「iOS SDK」欄が現れています。これは通常ありませんが、ANEを追加すると現れるようです。ここに最新のiOS SDKまでのパスを入れます。iOS SDKはXcodeをインストールすると入っています。Xcode4.3.3現在では、以下のパスです。
    /Applications/Xcode.app/Contents/
    Developer/Platforms/iPhoneOS.platform/
    Developer/SDKs/iPhoneOS5.1.sdk
    

    ※↑一行です。

  6. パブリッシュ(1分ほどかかります)すると、Flash Pro用のフォルダに「.ipa」の拡張子のついたファイルが出力されています。

お疲れ様でした!ついに、AIR for iOSアプリを作成できました!
ANEを使ったファイルはムービープレビューで動作確認できませんので、iPhone構成ユーティリティやiTunesなどで実機にインストールして動作を確認してください。

「1. Cocoa Touch Static Library(.a)の作成」の「HelloWorldANE.m」で設定した「HelloWorld MUSHIKAGO!」という文字列がアプリ上に現れたら成功です。


追記(2012.10.05):まとめスライドを公開しました。

コメント

  1. […] 「iOS : Flash Proでネイティブ拡張(ANE)に挑戦」でHelloWorldなANEを作ってそれを実機で確認するところまで試し、「iOS : アプリ内課金(In-App Purchase)をXcodeでやってみる」でXcodeで作ったア […]

  2. […] iOS : Flash Proでネイティブ拡張(ANE)に挑戦 —– MUSHIKAGO APPS MEMO […]