クマは森で用を足しますか?

アウトプットは重要です。

SELECT ITEM コマンドで二階層目のメニューを

先日から SIM ツールキット用の Java Card アプレットを書き始めたところ(下記)ですが、まとまった時間があまり取れていないと進捗しないですね。

cheerio-the-bear.hatenablog.com

前回は SET UP MENU コマンドと DISPLAY TEXT コマンドをやりましたが、今回は SELECT ITEM コマンドです。

SELECT ITEM コマンド

今後の展開を見据えて、下表のようなサブメニューを表示するために SELECT ITEM コマンドを利用します。SIM ツールキットのメインメニュー上に表示される項目を選択すると、このサブメニューが表示されるようにします。

タイトル Get Input
項目 1 Settings
項目 2 Request (sync)

DISPLAY TEXT コマンドに対する ProactiveHandler.initDisplayText() のようなヘルパーメソッドは、SELECT ITEM コマンドには用意されていないようですので、ProactiveHandler.init() と ProactiveHandler.appendTLV() を使ってコマンドを構築します。

public void init(byte type,
                 byte qualifier,
                 byte dstDevice)
public void appendTLV(byte tag,
                      byte[] value,
                      short valueOffset,
                      short valueLength)
               throws java.lang.NullPointerException,
                      java.lang.ArrayIndexOutOfBoundsException,
                      ToolkitException

上記 API の仕様については GSM 03.19 v2.0.0 Annex A を、SELECT ITEM コマンドの仕様については ETSI TS 102 223 6.6.8 をご参照ください。メニュー項目に割り当てる番号は 0 ではなく 1 から始まることに注意です。

The identifier is a single byte between '01' and 'FF'. Each item shall have a unique identifier within an Item list.

ソースコード

SELECT ITEM コマンドをサポートするために追加したコードは、ほんの十数行です。

github.com

実際に Android スマートフォン上で表示されている様子がこちら。

f:id:cheerio-the-bear:20190215211548p:plain
SELECT ITEM コマンド

unsupported field type multidimension array エラー

最初に書いたコードのままだと、ビルド後にエラーが表示されていました。ちょっと見慣れないエラーです。

error: com.github.cheeriotb.toolkit.input.InputApplet: unsupported type multidimension array of field ITEMS.
error: line 59: com.github.cheeriotb.toolkit.input.InputApplet: unsupported field type multidimension array of accessed field ITEMS of class com.github.cheeriotb.toolkit.input.InputApplet.

このエラーに関連するソースコードはここ。

    private static byte[] ITEM_SETTINGS = new byte[] { 'S', 'e', 't', 't', 'i', 'n', 'g', 's' };
    private static byte[] ITEM_REQUEST_SYNC = new byte[] { 'R', 'e', 'q', 'u', 'e', 's', 't', ' ',
            '(', 's', 'y', 'n', 'c', ')' };

    private static byte[][] ITEMS = {
        ITEM_SETTINGS,
        ITEM_REQUEST_SYNC
    };

そうでしたか。Java Card では多次元配列はサポートされていませんでしたか。Object 型の配列へと変更して難を逃れました。

    private Object[] ITEMS = {
        ITEM_SETTINGS,
        ITEM_REQUEST_SYNC
    };