サンプルプログラムを確認

プロジェクトの構成

RTMonAndroidSample
+--assets
+--bin
+--gen
+--libs
|   +--armeabi                                         // NDKライブラリ
|   |   +--libCosNaming.so
|   |   +--libOpenRTM_on_Android.so
|   |   +--libRTC_on_Android.so
|   |   +--libRtORB.so
|   +--RTM.jar                                         // JAVAライブラリ
+--res                                                         // リソース
|   +--drawable-hdpi
|   |   +--rtm_logo.png
|   |   +--title_logo.png
|   +--drawable-ldpi
|   |   +--rtm_logo.png
|   |   +--title_logo.png
|   +--drawable-mdpi
|   |   +--rtm_logo.png
|   |   +--title_logo.png
|   +--layout
|   |   +--main.xml
|   |   +--toast.xml
|   +--layout-land
|   |   +--main.xml
|   +--values
|       +--arrays.xml
|       +--strings.xml
+--src                                                 // ソースプログラム
|   +--jp
|       +--co
|           +--sec
|               +--rtc
|                   +--sample
|                   |   +--RTMonAndroidSample.java
|                   +--RTMonAndroidImpl.java
|                   +--RTMonAndroidProfile.java
+--AndroidManifest.xml                         // マニフェスト

RTMonAndroidSample.javaの説明

メインとなるクラスです。アプリが起動すると最初にonCreateが呼ばれます。[START RTC], [STOP RTC]ボタンをここで監視しています。

@Override
public void onCreate(Bundle savedInstanceState) {
        .
        .
        /**
         *      START RTC ボタン
         */
        myStartButton.setOnClickListener(new View.OnClickListener() {
                public void onClick(View v) {
                        if (nameServerConnectTask == null) {
                                connectNameServer();            // NameServerへの接続
                        }
                }
        });

        /**
         *      STOP RTC ボタン
         */
        myStopButton.setOnClickListener(new View.OnClickListener() {
                public void onClick(View v) {
                        if (rtcService != null) {
                                rtcService.stopRTC();
                                rtcService = null;

                        }
                        releaseService();
                }
        });
}

[START RTC] が押されたら、TextViewにより指定されたネームサーバーへ接続を開始します。

/**
 * NameServerへの接続
 */
private void connectNameServer() {
        SpannableStringBuilder sb = (SpannableStringBuilder)myEditText.getText();
        nameServer = sb.toString();
        saveNameServerAddress(nameServer);              // この時点でのネームサーバーアドレスを保存しておく

        nameServerConnectTask = new NameServerConnectTask(this);
        nameServerConnectTask.setListener(new NameServerConnectListenerImpl()); // NameServer接続完了リスナーを登録
        nameServerConnectTask.setIpAddress(nameServer);
        nameServerConnectTask.setRetryCount(5);
        nameServerConnectTask.execute();                // ネームサーバーへの接続を開始する
}

NameServerConnectTaskのリスナーとして、NameServerConnectListenerImplを登録します。

private class NameServerConnectListenerImpl implements NameServerConnectListener {
        .
        .
        .
        public void onConnected() {
                Intent intent = new Intent(RTMonAndroidSample.this, RTCService.class);
                startService(intent);
                serviceConnection = new RtcServiceConnection();
                bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
        }

接続が成功したら、RTCService クラスを起動します。同時に RtcServiceConnection クラスをバインドします。 バインドが成功すると RtcServiceConnection.onServiceConnected が呼ばれます。

ここで、RTCService に対して コンポーネントのコンフィグレーション等を渡します。 RTMonAndroidImplクラスもここで起動します。

private class RtcServiceConnection implements ServiceConnection {
        public void onServiceConnected(ComponentName className, IBinder service) {
                rtcService = ((RTCService.RTCServiceBinder) service).getService();

                // プロパティーを設定する
                rtcService.setProfiles(
                                RTMonAndroidProfile.DefaultNameServer,  RTMonAndroidProfile.Name,
                                RTMonAndroidProfile.ImplementationId,   RTMonAndroidProfile.Type,
                                RTMonAndroidProfile.Description,                RTMonAndroidProfile.Version,
                                RTMonAndroidProfile.Vendor,                             RTMonAndroidProfile.Category,
                                String.valueOf(RTMonAndroidProfile.execute_rate));

                rtcService.setLongConfig(RTMonAndroidProfile.ConfigName1, 0);
                rtcImpl = new RTMonAndroidImpl(RTMonAndroidSample.this, rtcService);
                SpannableStringBuilder sb = (SpannableStringBuilder)myEditText.getText();       // EditTextに入力された文字
                rtcService.startRTC(sb.toString(), context.getPackageName());           // START RTC
        }

RTMonAndroidImpl.javaの説明

RTMonAndroidImpl クラスは RTCBaseを継承したクラスです。 RTCBaseを継承することで、RTMで発生する各イベントをここで受け取ります。

/**
 * 初期化処理.コンポーネントライフサイクルの開始時に一度だけ呼ばれる.
 */
@Override
public int onInitialize() {
        Logger4RTC.debug(TAG, "onInitialize");
        myRTC.showToast("onInitialize");
        return ReturnCode.RTC_RTC_OK;
}
/**
 * 非アクティブ状態からアクティブ化されるとき1度だけ呼ばれる.
 */
@Override
public int onActivated() {
        Logger4RTC.debug(TAG, "onActivated");
        myRTC.showToast("onActivate");
        return ReturnCode.RTC_RTC_OK;
}
/**
 * アクティブ状態時に周期的に呼ばれる.
 */
@Override
public int onExecute() {
        Logger4RTC.debug(TAG, "onExecute");
        ioControl();
        return ReturnCode.RTC_RTC_OK;
}
/**
 * アクティブ状態から非アクティブ化されるとき1度だけ呼ばれる.
 */
@Override
public int onDeactivated() {
        Logger4RTC.debug(TAG, "onDeactivated");
        myRTC.showToast("onDectivate");
        return ReturnCode.RTC_RTC_OK;
}
/**
 * エラー状態に入る前に1度だけ呼ばれる.
 */
@Override
public int onAborting() {
        Logger4RTC.debug(TAG, "onAborting");
        myRTC.showToast("onAborting");
        return ReturnCode.RTC_RTC_OK;
}
/**
 * エラー状態からリセットされ非アクティブ状態に移行するときに1度だけ呼ばれる.
 */
@Override
public int onReset() {
        Logger4RTC.debug(TAG, "onReset");
        myRTC.showToast("onReset");
        return ReturnCode.RTC_RTC_OK;
}
/**
 * エラー状態にいる間周期的に呼ばれる.
 */
@Override
public int onError() {
        Logger4RTC.debug(TAG, "onError");
        myRTC.showToast("onError");
        return ReturnCode.RTC_RTC_OK;
}
/**
 * コンポーネントライフサイクルの終了時に1度だけ呼ばれる.
 */
@Override
public int onFinalize() {
        Logger4RTC.debug(TAG, "onFinalize");
        myRTC.showToast("onFinalize");
        return ReturnCode.RTC_RTC_OK;
}

このクラスではInPortとOutPortの管理も行っています。

まずはInPortの処理を見ていきましょう。 InPortを生成し RTCService に対して、addInPort で登録します。 addInPortすることでInPortのデータが取り出し可能になります。 ポート名は RTMonAndroidProfile.java で定義されている InPort1 を使います。

private void initInPort(){
        String pName = RTMonAndroidProfile.InPort1;
        TimedLong tm = new TimedLong();
        inPortLong = new InPort<TimedLong>(pName, tm);
        rtcService.addInPort(inPortLong);

次にOutPortの処理です。 InPortと同じ様に、OutPortを生成し RTCService に対して、addOutPort で登録します。 addOutPortすることでデータの出力が可能になります。 ポート名は RTMonAndroidProfile.java で定義されている OutPort1 を使います。

private void initOutPort(){
        String pName = RTMonAndroidProfile.OutPort1;
        TimedLong tm = new TimedLong();
        outPortLong = new OutPort<TimedLong>(pName, tm);
        rtcService.addOutPort(outPortLong);

入力ポートに新しいデータがあるかは、InPort.isNew()で確認します。 読み込みは InPort.read()で行います。なお読み込み時にエラーが発生すると、IOExceptionが発生します。適宜キャッチして処理してください。 出力ポートへの書き込みは、OutPort.write()で行います。

private void ioControl(){
        try{
                if (inPortLong.isNew()){                                // 入力ポートに新しいデータが入ったか確認する。
                        TimedLong tl = inPortLong.read();         // データをinPortから取り出す。
                        int n = tl.getData();
                        tl.setData(n*5);
                        outPortLong.write(tl);                                          // データをoutPortに書き出す。
                        str = tl.getTm().toString() +" | "+n;
                        myRTC.textDraw(str);            // 画面表示
                }
        }
        catch (IOException e){          // InPortの読み出しでExceptionが発生する可能性があるので、ここでキャッチ
        }

上記コードでは、入力データを文字列に変換し、RTMonAndroidSample.textDrawで画面にも表示しています。

RTMonAndroidProfile.javaの説明

 コンポーネントのコンフィグレーション等をまとめて定義するクラスです。

 初回起動時にデフォルトで表示するネームサーバーのアドレスや、コンポーネントの コンフィグレーション、実行レート、ポート名などを定義しています。

public class RTMonAndroidProfile {
        public static final String DefaultNameServer    = "192.168.3.3";                // host[:port]
        public static final String Name                 = "SampleDevelop";
        public static final String ImplementationId     = "SampleDevelop_instance";
        public static final String Type                 = "DataFlowComponent";
        public static final String Description          = "Sample RTC on Android oppose to ConsoleIN and ConsoleOut";
        public static final String Version              = "1.0";
        public static final String Vendor               = "Systems Engineering Consultants Co.,LTD. (SEC)";
        public static final String Category             = "Sample";

        public static final float execute_rate          = 5F; // 秒間何回処理をするか (wait = 1.0 / execute_rate * 1000000 usec)

        //
        // コンポーネントのコンフィグレーションを定義
        //
        public static final String ConfigName1          = "S_multiple_coefficient";
        public static final String ConfigName2          = "S_float_sample";
        public static final String ConfigName3          = "S_string_sample_1";
        public static final String ConfigName4          = "S_string_sample_2";

        //
        // コンポーネントのデータポートを定義
        //
        // << in port >>
        public static final String InPort1              = "S_in_port_1";

        // << out port >>
        public static final String OutPort1             = "S_out_port_1";
}