Device APIは、nexacro platformアプリケーションでデバイスの特化された機能を使用できる方法を提供します。開発者は、DeviceAPIを使用して、モバイルプラットフォーム(iOS / Android)の拡張された機能を使用することができます。
Device APIは、大きく二つの部分に分かれています。一つは、ネクサクロプロジェクトに適用するための Javaスクリプトインタフェースであり、他の部分はモバイルプラットフォーム環境で開発されたネイティブモジュールです。
この章では、入力された文字列を画面に表示する簡単な例を介して Device APIを開発及び適用する方法を紹介します。
ネイティブモジュール
iOSネイティブモジュール開発
Xcodeを使って iOSネイティブモジュールを開発する方法を説明します。提供する DeviceAPIクラスを継承して機能を実装します。
例題の開発時にテスト行った開発環境は以下のとおりです。
開発 OS:OSX 10.9.3 Xcode:Version 5.1.1 テストデバイス:iPad Mini (iOS 7.1)
プロジェクト生成
Xcodeを実行し、次のメニューからプロジェクトを生成します。
File > New > Project
デフォルトテンプレートに「Cocoa Touch static Library」を選択します。
Product Name(HelloPlugin)と必要な項目を作成した後、プロジェクトの生成を完了します。
プロジェクト環境設定
プロジェクトが生成されると Targets項目で「Hello Plugin」プロジェクトを選択し、Build Phases項目に3つのフレームワークを追加します。追加するフレームワークは以下のとおりです。
nexacro14.framework UIKit.framework Foundation.framework
ソースファイル修正
自動生成されたHello Plugin.hヘッダファイルと Hello Plugin.mソースファイルを以下のように変更します。
// HelloPlugin.h #import <Foundation/Foundation.h> #import <UIKit/UIKit.h> #import <nexacro14/DeviceAPI.h> @interface HelloPlugin : DeviceAPI { NSInteger nID; NSString *helloMsg; } @property (nonatomic) NSInteger nID; @property (nonatomic, retain) NSString * helloMsg; - (void)hello:(NSString*)lid withDict:(NSMutableDictionary*)options; @end
64bitビルド時に上の図で19行目の書式指定子の警告が発生することがあります。 64bitビルド時には、以下のソースの内容のように self.nIDを (int)self.nIDに変更してください。
// HelloPlugin.m #import "HelloPlugin.h" @implementation HelloPlugin @synthesize nID, helloMsg; //hello Method - (void)hello:(NSString*)lid withDict:(NSMutableDictionary*)options { self.helloMsg = [options objectForKey:@"helloMsg"]; self.nID = [lid integerValue]; UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil message:self.helloMsg delegate:nil cancelButtonTitle:nil otherButtonTitles:@"OK", nil]; [alert show]; //Event NSString *callbackResult = [NSString stringWithFormat:@"runCallback(\"%d\",\"_onhello\",{'eventid':\"onhello\",'msg':\"%@\"});", self.nID, self.helloMsg]; //64bit build /* NSString *callbackResult = [NSString stringWithFormat:@"runCallback(\"%ld\",\"_onhello\",{'eventid':\"onhello\",'msg':\"%@\"});", (int)self.nID, self.helloMsg]; */ [self writeJavascript:callbackResult]; } @end
ビルド
Xcodeでビルドした後 Productsフォルダに libHelloPlugin.aファイルが生成されます。Finderでも .aファイルが生成されていることを確認することができます。
アプリケーションプロジェクトに lib HelloPlugin.aファイル追加
アプリケーションプロジェクトで、既存のFrameworkを追加しながら、libHelloPlugin.aファイルも追加します。下図は、NX14という名前のアプリケーションプロジェクトに生成した libHelloPlugin.aファイルを追加した画面です。
iOSプロジェクトの開発についての説明は、管理者ガイド「アプリ開発と実行(iOS)」の内容を参照してください。
シミュレータでテストする場合は、別途の認証過程なしでテストを進めることができます。但し、実際の端末に接続するには、追加の設定が必要です。
'Code Signing' の項目の'Code Signing Identity'を以下のように適切なプロファイルとして設定します。
[管理者ガイド > アプリ開発と実行(iOS) > Code Singing]
Androidネイティブモジュール開発
Eclipseを使って Androidネイティブモジュールを開発する方法を説明します。提供する Nexacro Pluginクラスを継承して機能を実装します。
例題の開発時にテストした開発環境は以下のとおりです。
JDK(Java SE Development Kit) Eclipse Android SDK ADTプラグイン テストデバイス:LGオプティマスG(Android 4.4.2)
プロジェクト生成
Eclipseを実行して、下記のメニューからプロジェクトを生成します。
File > New > Android Application Project
Project Nameを「HelloPlugin」に指定し、新しいプロジェクトを生成します。
アンドロイド4.4(Kitkat)以上のSDKを使用時にMinumum Required SDKを3.2(Honeycomb)以下に設定すると、下位互換性を維持するためにappcompat_v7プロジェクトを自動生成します。
http://developer.android.com/tools/support-library/features.html
ただし、nexacrp platformアプリケーションの作成時には影響を受けないため、プロジェクトを作成しないことをお勧めします。このような現象を回避するにはMinumum Required SDKを4.0(IceCreamSandwich)に設定し、プロジェクトを作成した後、AndroidManifest.xmlの設定時に使用するサブバージョンを再指定することができます。
HelloPlugin.javaファイルを生成します。下図のような構造が構成されます。
ソースファイル修正
生成された HelloPlugin.javaファイルを次のように変更します。HelloPluginモジュールを生成し、paramsにメッセージを込めて Androidの Toast形式でメッセージを示します。
package com.example.helloplugin; import org.json.JSONException; import org.json.JSONObject; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.widget.Toast; import com.nexacro.Native; import com.nexacro.plugin.NexacroPlugin; import com.nexacro.plugin.NexacroPluginManager; import com.nexacro.util.Log; public class HelloPlugin extends NexacroPlugin { private static String LOG_TAG = "HelloPlugin"; private static HelloPlugin helloplugin = null; public HelloPlugin(String objectId) { super(objectId); // TODO Auto-generated constructor stub } @Override public void init(JSONObject paramObject) { // TODO Auto-generated method stub } @Override public void release(JSONObject paramObject) { // TODO Auto-generated method stub } @Override //helloメソッドが存在すると、'helloMsg'文字列値を保存します。 public void execute(String method, JSONObject paramObject) { // TODO Auto-generated method stub Log.w(LOG_TAG, "execute paramObject:" + paramObject.toString()); if (method.equals("hello")) { String msg = ""; try { JSONObject params = paramObject.getJSONObject("params"); msg = params.getString("helloMsg"); // repeatcount } catch (JSONException e) { e.printStackTrace(); } show(msg); } } //excute()メソッドに込められた変数を Toast形式で示します。 public void show(String message) { final String msg = message; new Thread(new Runnable() { @Override public void run() { new Handler(Looper.getMainLooper()).post(new Runnable() { @Override public void run() { Toast.makeText( NexacroPluginManager.getInstance() .getActivity(), msg, Toast.LENGTH_LONG) .show(); } }); } }).start(); Native.SendDeviceEvent(getObjectId(), "_onhello", "{}"); } }
jarファイル生成
Pluginで使用できるように jarファイルを生成します。
Hello Pluginプロジェクトにマウス右ボタンをクリックした後、表示されるポップアップメニューから[Export]項目を選択します。
'Export'ウィンドウから [Java > JAR file]項目を選択します。
'JAR Export'ウィンドウから HelloPluginプロジェクトの'src'フォルダのみ選択し、他の項目はすべてチェックを解除します。
アプリケーションプロジェクトに Jarファイル追加
アプリケーションプロジェクトのxmlフォルダに Plugin.xmlファイルを生成します。前に生成した Androidネイティブモジュールを使用するために、nameと classを指定します。
<?xml version="1.0" encoding="utf-8"?> <plugin-config> <plugin name="HelloPlugin" class="com.example.helloplugin.HelloPlugin"/> </plugin-config>
libhelloplugin.jarファイルを'libs'フォルダに下にドラッグします。
Androidプロジェクトの開発についての説明は、管理者ガイドの「アプリ開発と実行(Android)」の内容を参照してください。
JavaScriptのインターフェイス開発
JavaScriptのインターフェイスとして使用する Hello.jsファイルは、nexacro studioでnexacro.Helloユーザーコンポーネントを呼び出すことができるように作成します。_pHello.hello関数がこの例で使用した実際の関数の実装コードです。
JavaScriptのインターフェイスは、次のように三つの部分で構成されます。
オブジェクトの生成時に呼び出される関数
オブジェクト消滅時に呼び出される関数
ユーザーが定義した Device API機能を実行する関数
//Hello.js if (!nexacro.Hello) { nexacro.Hello = function(name, obj) { this._id = nexacro.Device.makeID(); nexacro.Device._userCreatedObj[this._id] = this; this.name = name || ""; this.enableevent = true; this._event_list = { "onhello": 1 }; var params = '""'; var jsonstr = '{"id":' + this._id + ', "div":"HelloPlugin","method":"constructor", "params":' + params + '}'; nexacro.Device.exec(jsonstr); }; var _pHello = nexacro.Hello.prototype = nexacro._createPrototype(nexacro.EventSinkObject, nexacro.Hello); _pHello._type_name = "Hello"; _pHello.destroy = function () { var params = '""'; var jsonstr; delete nexacro.Device._userCreatedObj[this._id]; jsonstr = '{"id":' + this._id + ', "div":"HelloPlugin", "method":"destroy", "params":' + params + '}'; nexacro.Device.exec(jsonstr); return true; }; _pHello.on_created = function () { }; //=============================================================== // nexacro.Hello : Methods //=============================================================== _pHello.hello = function(strHelloMsg) { var msg = strHelloMsg; var params = '{"helloMsg":"' + msg + '"}'; var jsonstr = '{"id":' + this._id + ', "div":"HelloPlugin", "method":"hello", "params":' + params + '}'; nexacro.Device.exec(jsonstr); }; //=============================================================== // nexacro.Hello : Event //=============================================================== _pHello._onhello = function(objData) { var e = new nexacro.HelloEventInfo(objData.eventid, objData.msg); this._fire_onhello(this, e); }; _pHello._fire_onhello = function(objHello, eHelloEventInfo) { if (this.onhello && this.onhello._has_handlers) { return this.onhello._fireEvent(this, eHelloEventInfo); } return true; }; //=============================================================== //nexacro.HelloEventInfo //=============================================================== nexacro.HelloEventInfo = function(strEventId, strMsg) { this.eventid = strEventId; this.msg = strMsg; }; var _pHelloEvnetInfo = nexacro._createPrototype(nexacro.Event, nexacro.HelloEventInfo); nexacro.HelloEventInfo.prototype = _pHelloEvnetInfo; _pHelloEvnetInfo._type_name = "HelloEventInfo"; delete _pHelloEvnetInfo; delete _pHello; }
実際Device APIの実装オブジェクト(Java、Objective-Cでの実装)の生成と消滅は、スクリプトで約束されたメソッド名である"constructor"と"destroy"で行われます。
ただし、現在の時点では、Android / iOS DeviceAPIのインタフェースの違いで"constructor"、"destroy"メソッドの呼び出し時にパラメータを渡すことができません。必要な値を設定するには、別のユーザーメソッドを定義して処理する必要があります。
nexacro platformプロジェクト適用
JavaScriptのインターフェースを適用するために、カスタムコンポーネントを構成し、それをnexacro platformプロジェクトに適用します。カスタムコンポーネントの作成とnexacro platformプロジェクトで使用する方法を簡単に説明します。
カスタムコンポーネント
ユーザーコンポーネントの構成
例題で使用したファイルは、特定の機能の実装のためではなく理解を助けるために作成したファイルです。下記のように4つのファイルを使用します。
モジュールファイル(*.json)
ExtDeviceAPI.json
オブジェクト情報ファイル(*.info)
Hello.info
HelloEnum.info
コンポーネントスクリプトファイル(*.js)
Hello.js
登録するモジュールとスクリプトファイルは、nexacro studioで Base Lib Pathに指定されたパス内の「component」フォルダのサブパスに位置する必要があります。
Base Lib Pathのデフォルト設定は、nexacro platformのインストールパスの下の「nexacro14lib」フォルダです。使用環境に応じて、nexacro studioオプションで別のパスに変更することができます。
Options > Environment > Base Lib Path
カスタムコンポーネントの説明は、カスタムコンポーネント 項目を参照してください。
モジュール登録
以下のような形で Ext Device API.jsonファイルを作成します。「scripts」、「objInfo」項目に指定したフォルダのパスとファイルは、[Base Lib Path > component]に指定されたフォルダの下に位置する必要があります。
{ "name": "ComComp", "version": "14.0.0.0", "description": "nexacro platform Common Component Library", "license": "", "scripts": [ "ExtDeviceAPI/Hello.js" ], "objInfo": [ "ExtDeviceAPI/Hello.info", "ExtDeviceAPI/HelloEnum.info" ] } //@ sourceURL=ExtDeviceAPI.json
Ext Device API.jsonファイルで「scripts」、「objInfo」項目に指定した「Ext Device API」フォルダを作成し、該当フォルダの下に3つのファイルを生成します。
nexacro studioで作成したExt Device API.jsonモジュールを登録します。「Project Explorer」ウィンドウで、TypeDefinition項目を右クリックし、ポップアップメニューから[Edit]項目を選択します。「Edit TypeDefinition」ウィンドウで、[Add]ボタンをクリックして ExtDeviceAPI.jsonファイルをモジュールとして登録します。
オブジェクト情報
nexacro.Helloカスタムコンポーネントは、モジュールの設定時に「Hello.info」、「Hello Enum.info」の2つのObjInfoファイルを設定しました。 「Hello.info」ファイルは、コンポーネントに必要な情報を含んでおり、「HelloEnum.info」ファイルは、Enumプロパティに関する情報を含んでいます。
Hello.info
コンポーネントに必要な情報を含んでいます。
<?xml version='1.0' encoding='utf-8'?> <MetaInfo version="1.0"> <Object id="nexacro.Hello"> <!-- define extend component based nexacro.Object --> <ObjectInfo typename="nexacro.Hello" csstypename="Hello,HelloABC[userprop='abc']" csscontrolname="HelloControl,HelloControlABC[userprop='abc']" group="Object" csspseudo="true" container="false" composite="true" tabstop="true" cssstyle="true" contents="true" formats="false" contentseditor="auto" defaultwidth="300" defaultheight="200" requirement="Runtime,HTML5" description=""/> <PseudoInfo> <Pseudo name="pushed" control="true" deprecated="false" unused="false" /> <Pseudo name="focused" control="true" deprecated="false" unused="true" /> </PseudoInfo> <ControlInfo> </ControlInfo> <PropertyInfo> <!-- define new property --> <Property name="userprop" group="Misc" type="Enum" defaultvalue="abc" readonly="false" initonly="false" hidden="false" control="false" style="false" expr="false" deprecated="false" unused="false" objectinfo="" enuminfo="enum_ext_test" unitinfo="" requirement="Runtime,HTML5" description="this is desc" /> <!-- re-define super's property --> <Property name="tooltiptext" group="Misc" type="String" defaultvalue="1111111" readonly="false" initonly="false" hidden="false" control="false" style="false" expr="false" deprecated="false" unused="false" objectinfo="" enuminfo="" unitinfo="" requirement="Runtime,HTML5" description="this is desc" /> <!-- define new style property --> <Property name="itemopacity" group="Style" type="Opacity" defaultvalue="" readonly="false" initonly="false" hidden="false" control="false" style="true" expr="false" deprecated="false" unused="false" objectinfo="nexacro.Style_opacity" enuminfo="" unitinfo="" requirement="Runtime,HTML5" description="this is desc" /> </PropertyInfo> <MethodInfo> <Method name="hello" group="" async="false" deprecated="false" unused="false" requirement="Runtime,HTML5" description="this is test method" > <Syntax text = "hello(a [, b])" > <Return/> <Arguments> <Argument name="a" type="String" in="true" out="false" option="false" variable="false" description="any string" /> <Argument name="b" type="String" in="true" out="false" option="true" variable="false" description="any string" /> </Arguments> </Syntax> </Method> </MethodInfo> <EventHandlerInfo> <!-- define event --> <EventHandler name="onhello" group="Event" deprecated="false" unused="false" requirement="Runtime,HTML5" description="this is test event" > <Syntax text="onhello(obj:Object, e:nexacro.EventInfo)" > <Return/> <Arguments> <Argument name="obj" type="Object" in="true" out="false" option="false" variable="false" description="Event Source Object" /> <Argument name="e" type="nexacro.EventInfo" in="true" out="false" option="false" variable="false" description="Event Information Object" /> </Arguments> </Syntax> </EventHandler> </EventHandlerInfo> </Object> </MetaInfo>
HelloEnum.info
Enumプロパティに関する情報を含んでいます。
<?xml version='1.0' encoding='utf-8'?> <MetaInfo version="1.0"> <!-- define enum information --> <EnumInfo id="enum_ext_test" composite="false" delimiter="" description="abc, 123" > <Enum name="abc" description="abc" /> <Enum name="123" description="123" /> </EnumInfo> </MetaInfo>
カスタムコンポーネント登録
「Edit TypeDefinition」ウィンドウを実行して「Objects」タブで、[Add]ボタンをクリックして、カスタムコンポーネント(nexacro.Hello)を追加します。
コンポーネントツールバーにHelloオブジェクトのアイコンが生成されていることを確認します。
テストフォーム作成
HelloTest.xfdl作成
nexacro studioでテストできる簡単なフォーム(HelloTest.xfdl)を新規作成します。
フォーム上に Helloオブジェクトを置くと、Invisible Objects項目に表示され Hello.infoファイルに設定した内容が Propertiesウィンドウに表示されます。Helloオブジェクトが正常に登録されていることを確認した場合は、画面の上部にボタンコンポーネントを追加します。
ボタンをコンポーネントにonclickイベントを追加し、コードを作成します。'
this.Hello00.
' と入力すると、Hello.js、Hello.infoで定義した helloメソッドがコードヒントに表示されることを確認することができます。
this.Button00_onclick = function(obj:Button, e:nexacro.ClickEventInfo) { this.Hello00.hello("Hello World"); }
onhelloイベント
Hello.infoで定義した onhelloイベントを Propertiesウィンドウから確認することができます。
helloメソッドに"Hello world"という文字列を入れて helloメソッドが実行されて、helloイベントを呼び出します。そして TextArea00オブジェクトに"onhello Event call"文字列を出力します。
//hello Method this.Button00_onclick = function(obj:Button, e:nexacro.ClickEventInfo) { this.Hello00.hello("Hello World"); } //onhello Event this.Hello00_onhello = function(obj:Hello, e:nexacro.EventInfo) { this.TextArea00.set_value("onhello Event call"); }
ユーザーが Hello Testボタンをクリックすると _onhelloイベントを呼び出すように iOSと Androidのネイティブモジュールソースを変更します。
HelloPlugin.m (iOSネイティブモジュール)
下記のように run callbackメソッドを使用して _onhelloイベントの呼び出しコードを追加した後、リビルド作業を経て libHelloPlugin.aファイルを生成します。
... //hello Method - (void)hello:(NSString*)lid withDict:(NSMutableDictionary*)options { self.helloMsg = [options objectForKey:@"helloMsg"]; self.nID = [lid integerValue]; UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil message:self.helloMsg delegate:nil cancelButtonTitle:nil otherButtonTitles:@"OK", nil]; [alert show]; //HelloTestボタンクリック時 runcallbackメソッドを使用して _onhelloイベントを呼び出す NSString *callbackResult = [NSString stringWithFormat:@"runCallback(\"%d\",\"_onhello\",{'eventid':\"onhello\",'msg':\"%@\"});", self.nID, self.helloMsg]; [self writeJavascript:callbackResult]; } @end
HelloPlguin.java (Androidネイティブモジュール)
下記のように _onhelloイベントの呼び出しコードを追加した後、libhelloplugin.jarファイルを再生成します。
... public void show(String message) { final String msg = message; new Thread(new Runnable() { @Override public void run() { new Handler(Looper.getMainLooper()).post(new Runnable() { @Override public void run() { Toast.makeText( NexacroPluginManager.getInstance() .getActivity(), msg, Toast.LENGTH_LONG) .show(); } }); } }).start(); // HelloTestボタンクリック時、_onhelloイベントを呼び出す Native.SendDeviceEvent(getObjectId(), "_onhello", "{}"); } }
実行テスト
nexacro studioで作成した Form上にある [Hello Test]ボタンをクリックすると、helloメソッドが呼び出され、メッセージが Alertの形式で表示されます。hello関数が呼び出されて onhelloイベントが発生し、TextArea領域に"hello_onhello call"という文字列が表示されることを確認することができます。
iOSデバイステスト
Androidデバイステスト