DeviceAPI開発

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)

プロジェクト生成

  1. Xcodeを実行し、次のメニューからプロジェクトを生成します。

File > New > Project

프로젝트생성

  1. デフォルトテンプレートに「Cocoa Touch static Library」を選択します。

템플릿선택

  1. Product Name(HelloPlugin)と必要な項目を作成した後、プロジェクトの生成を完了します。

프로젝트생성완료

プロジェクト環境設定

プロジェクトが生成されると Targets項目で「Hello Plugin」プロジェクトを選択し、Build Phases項目に3つのフレームワークを追加します。追加するフレームワークは以下のとおりです。

nexacro14.framework
UIKit.framework
Foundation.framework

프레임워크추가

ソースファイル修正

自動生成されたHello Plugin.hヘッダファイルと Hello Plugin.mソースファイルを以下のように変更します。

HelloPlugin.h

// 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

HelloPlugin.m

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ファイルを追加した画面です。

NX14프레임워크추가

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)

プロジェクト生成

  1. Eclipseを実行して、下記のメニューからプロジェクトを生成します。

File > New > Android Application Project

New_Project

  1. Project Nameを「HelloPlugin」に指定し、新しいプロジェクトを生成します。

New_Android_Application

アンドロイド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の設定時に使用するサブバージョンを再指定することができます。

  1. HelloPlugin.javaファイルを生成します。下図のような構造が構成されます。

New_HelloPlugin.java

ソースファイル修正

生成された HelloPlugin.javaファイルを次のように変更します。HelloPluginモジュールを生成し、paramsにメッセージを込めて Androidの Toast形式でメッセージを示します。

Toasts

http://developer.android.com/guide/topics/ui/notifiers/toasts.html

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ファイルを生成します。

  1. Hello Pluginプロジェクトにマウス右ボタンをクリックした後、表示されるポップアップメニューから[Export]項目を選択します。

Export1

  1. 'Export'ウィンドウから [Java > JAR file]項目を選択します。

Export2

  1. 'JAR Export'ウィンドウから HelloPluginプロジェクトの'src'フォルダのみ選択し、他の項目はすべてチェックを解除します。

Export3

アプリケーションプロジェクトに Jarファイル追加

  1. アプリケーションプロジェクトのxmlフォルダに Plugin.xmlファイルを生成します。前に生成した Androidネイティブモジュールを使用するために、nameと classを指定します。

Nexacro_plugins.xml

<?xml version="1.0" encoding="utf-8"?>
<plugin-config>
	<plugin name="HelloPlugin" class="com.example.helloplugin.HelloPlugin"/>
</plugin-config>
  1. libhelloplugin.jarファイルを'libs'フォルダに下にドラッグします。

Insert_libhelloplugin.jar

Androidプロジェクトの開発についての説明は、管理者ガイドの「アプリ開発と実行(Android)」の内容を参照してください。

JavaScriptのインターフェイス開発

JavaScriptのインターフェイスとして使用する Hello.jsファイルは、nexacro studioでnexacro.Helloユーザーコンポーネントを呼び出すことができるように作成します。_pHello.hello関数がこの例で使用した実際の関数の実装コードです。

JavaScriptのインターフェイスは、次のように三つの部分で構成されます。

//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つのファイルを使用します。

登録するモジュールとスクリプトファイルは、nexacro studioで Base Lib Pathに指定されたパス内の「component」フォルダのサブパスに位置する必要があります。

Base Lib Pathのデフォルト設定は、nexacro platformのインストールパスの下の「nexacro14lib」フォルダです。使用環境に応じて、nexacro studioオプションで別のパスに変更することができます。

Options > Environment > Base Lib Path

カスタムコンポーネントの説明は、カスタムコンポーネント 項目を参照してください。

モジュール登録

  1. 以下のような形で 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

  1. Ext Device API.jsonファイルで「scripts」、「objInfo」項目に指定した「Ext Device API」フォルダを作成し、該当フォルダの下に3つのファイルを生成します。

  1. 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プロパティに関する情報を含んでいます。

<?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>
<?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作成

  1. nexacro studioでテストできる簡単なフォーム(HelloTest.xfdl)を新規作成します。

  1. フォーム上に Helloオブジェクトを置くと、Invisible Objects項目に表示され Hello.infoファイルに設定した内容が Propertiesウィンドウに表示されます。Helloオブジェクトが正常に登録されていることを確認した場合は、画面の上部にボタンコンポーネントを追加します。

  1. ボタンをコンポーネントに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のネイティブモジュールソースを変更します。

...
//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
...
	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"という文字列が表示されることを確認することができます。

Result_iOS

결과화면