Mobile Ingormation Device Prefile (JSR-37) JCP Specification Java 2 Platform, Micro Edition, 1.0a


3 Architecture

3.2 Architecture

MIDP APIs
本仕様で定義されるAPIのセット
OEM-secific APIs
デバイス独自の機能を実現するOEM(original equipment manufacturer)によって 与えられるクラス。
アプリケーションタイプ詳細
MIDPMIDPとCLDC仕様内のAPIのみを使ったもの。
OEM-SpecificOEM-specific classも使ったもの。
NativeJavaで書かれておらず、ネイティブシステムソフトウェア上。

7 Persistent Storage

7.2 Record Store

レコードストアはプラットフォーム依存の場所につくられ、MIDletsからは見えない。 レコードストアの名前空間はMIDlet suiteの粒度に制御される。 MIDlet suite中のMIDletsは複数のレコードストアを作成でき、 異なる名前を付けられる。 MIDlet suiteが削除されたとき、全てのレコードストアも削除されなければならない。 これらのAPIはMIDlet suite自身のレコードストアを触ることだけでき、 異なるMIDlet suiteのMIDlets間で共有しているレコードには触れない。 MIDlet suite内のMIDletsはお互いに直接レコードストアにアクセスできる。

レコードストア名はケースセンシティブでユニコードキャラクタ32文字。 レコードストア名はMIDlet suite内で唯一。 他のMIDlet suite内のMIDletレコードストアと同じ名前は良い。

このAPIではロック操作は与えられていない。レコードストアの実装は 個々のレコードストア操作はアトミック、同期、順序であり、 このため複数のアクセスで悪影響は起きない。 しかし、MIDletがレコードストアにアクセスする複数のスレッドを使っていたら、 アクセスをするのはMIDletの責任であり、予期しない結果が起きるかもしれない。 たとえば、あるMIDletでふたつのスレッドが両方ともRecordStore.setRecord()を同じレコードに対して同時に呼んだとき、レコードストアはこの呼び出しを適当に 順序化し、データベースに悪影響は出ない。 しかし、片方の書き込みがほかの書き込みを続けて上書きしてしまうため、 問題になるかもしれない。 同様に、あるプラットフォームでレコードストアの透過的な同期か、下からのアクセスが許されているとき、 MIDletsと同期エンジン間のレコードストアに対するアクセスを排他的にするのは プラットフォームの責任である。

レコードストアAPIはタイムスタンプにロング整数を使い、フォーマットは System.currentTimeMillis()。 レコードストアは最後に変更されたときのタイムスタンプを持つ。 またバージョンも持ち、レコードストアの内容を変更するたびにインクリメントされる 整数。 アプリケーションと同様に同期エンジンにも役立つ。

7.3 Records

DataInputStreamDataOutputStreamByteArrayInputStramByteArrayOutputStreamで異なるデータ型をバイト配列に入れたり出したり できる。

レコードは整数値recordIDで識別される。 レコードストアに最初に作られるレコードのrecordIDは1で、続きは1ずつ 増える。 MIDletsはRecordEnumerationクラスを使うことで他のインデクスを作る。


8 Applications

8.2 MIDP MIDlet Suite

MIDPアプリケーションはMIDP仕様で決められている機能のみをつかうべき。

MIDlet suiteの要素は

アプリケーション管理ソフトウェアは集合的にデバイス特有の機能について言及する のに使う。MIDletをインストール、スタート、ストップ、削除する環境を与える。 エラーハンドリングと必要ならユーザとの相互作用に責任がある。

ひとつ以上のMIDletsはひとつのJARファイルにパッケージされているかもしれない。 各MIDletはMIDletクラスと必要な他のクラスを拡張するクラスで成り立つ。 JARファイル内のマニフェストはMIDlet、名前、アイコンを実装する 各MIDletのクラスを指示する。 MIDletはアプリケーション管理ソフトウェアによって起動されるもの。 MIDlet suiteが呼ばれると、JVMはどのクラスか実行されるかが必要。 MIDletの新たなインスタンスはアプリケーション管理ソフトウェアに作成され、 MIDletを直接スタート、停止、破壊するのに使う。

MIDlets間でデータや他の情報を共有するのは個々のAPIと実装による。 例えば、あるMIDlet suiteに関連づけられたレコードストアをMIDlet間で共有する ときにつかうメソッドをレコード管理システムAPIは特定する。

8.3 MIDP Execution Environment

アプリケーション管理ソフトウェアはアプリケーションを起動させ、 以下を利用可能にする。 CLDCとJVMはマルチスレッド、ロックと同期、バイトコードの実行、メソッドの ディスパッチ(スケジュール)などを行う。 ひとつのVMは全てのポリシー、名前づけ、リソース管理を行う。 デバイスが複数のVMをサポートしていたら、それぞれのスコープ、名前づけ、リソース 管理ポリシーを持つ。 CLDCクラスはMIDlet suiteクラスに取って代わられてはいけない。

MIDPはMIDP APIを実装するクラスを与える。 MIDPクラスはMIDPlet suiteクラスに取って代わられてはいけない。

ひとつのJARファイルは全てのMIDletのクラスを含む。 MIDletはJARファイル、MIDP、CLDC内のクラスのメソッドをロードし、呼び出す。 これら3つのスコープ内の全てのクラスはJARファイルのMIDletの実行時環境に 共有される。 これらのクラスを通じてアクセス可能なすべての状態は実行中のJavaクラスを利用可能 である。 すべてのMIDlets、MIDP、CLDCのオブジェクトを含むひとつの空間がある。 通常のJavaのロックと同期プリミティブは並行問題を避けるために必要なときに 使われる。 各ライブラリは並行をどのように扱うか、MIDletがマルチスレッド環境でどのように 安全に実行すべきかを特定する。

MIDletのクラスファイルは実行のみに利用可能で、リソースとしてや再利用のための 引用はできない。 CLDCの実装はJARファイルの内容を合った方法で保存、解釈できる。

JavaクラスファイルでないJARからのファイルは メソッドjava.lang.Class.getResourceAsStreamから利用可能である。 たとえば、マニフェストはこのように使う。

MIDletデスクリプタファイルの内容は、 javax.microedition.midlet.MIDlet.getAppPropertyメソッドで利用可能 である。

8.4 MIDlet Suite Packaging

JARファイル JARマニフェストはアプリケーション管理ソフトウェアに使用される、MIDletを指示、 インストールするための属性を定義し、 アプリケーションデスクリプタには見られない属性をデフォルトとする。

MIDlet Attributes
属性名詳細
MIDlet-NameMIDletの名前
MIDlet-VersionMIDletのバージョンナンバ。major.minor.micro
MIDlet-VenderMIDlet suiteを与える組織
MIDlet-IconJARファイル内のPNGファイル。アイコン
MIDlet-DescriptionMIDlet suiteの説明
MIDlet-info-URLMIDlet suiteの情報のあるURL
MIDlet-< n > JARファイル内のn番目のMIDletの名前、 アイコン、クラスはコンマで区切られる。値nの最小値は1で連続した値をとる。
  1. 名前はMIDletを指示するために使う。
  2. アイコンはJARファイル内のPNGの名前。
  3. クラスはMIDletクラスを拡張したクラスの名前。パブリックな コンストラクタを持たなければならない。
MIDlet-Jar-URLJARファイルのあるURL
MIDlet-Jar-SizeJarファイルのバイト数
MIDlet-Data-SizeMIDletに要求される不変データの最小バイト数。 デバイスはポリシーによって付加的なストレージを必要とするかもしれない。 デフォルトは0
MicroEdition-Profile必要なJ2MEプロファイルで、システムプロパティmicroedition.profilesと同じフォーマットの値。例えば、MIDP-1.0。
MicroEdition-ConfigurationJ2MEコンフィグレーション、システム プロパティmicroedition.configurationと同じフォーマットの値。 例えば、CLDC-1.0。

MIDlet-Versionタグがなければ、0.0.0と見なされ、非ゼロバージョンはより新しい バージョンと考えられる。

8.4.1 JAR Manifest

マニフェストはJARファイルの内容の情報を与える。 JARファイルフォーマットの情報はここ。 マニフェストの属性は"MIDlet-"で始まり、アプリケーションデスクリプタとダブってないものは必要なときにMIDletに渡される。

マニフェストは以下の属性を含まなければならない。

以下の属性を含むかもしれない マニフェストの例。
MIDlet-Name: CardGames
MIDlet-Version: 1.1.9
MIDlet-Vender: CardsRUS
MIDlet-1: Solitaire, /Solitare.png, com.cardsrus.org.Solitare
MIDlet-2: JacksWild, /JacksWild.png, com.cardsrus.org.JacksWild
MicroEdition-Profile: MIDP-1.0
MicroEdition-Configuration: CLDC-1.0

8.4.2 MIDlet Classes

MIDletに必要な全てのJavaクラスはJARファイル内に標準の構造で置かれ、 これはディレクトリとファイル名で修飾したクラス名に基づく。 例えば、クラスcom.sum.microedition.TestはJARファイル内では com/sun/microedition/Test.classという名前になる。

8.5 Application Descriptor

アプリケーションデスクリプタはMIDletを管理するためにアプリケーション管理 ソフトウェアに使われ、MIDlet自身にコンフィグレーション特定の属性のために 使われる。 各JARファイルにはアプリケーションデスクリプタがある。 デスクリプタはアプリケーション管理ソフトウェアに、MIDlet suiteのJARファイルが すべてロードされる前にMIDletがデバイスに合っているかを検証させる。 またコンフィグレーション特定属性(パラメータ)がJARファイルを変更することなく MIDletに合わせる。

アプリケーション管理ソフトウェアにあるファイルがアプリケーションデスクリプタで あると認識指せるために、ファイルの拡張子とMIMEタイプが定義されている。

前もって定義された属性はアプリケーション管理ソフトウェアが MIDletを指示、扱い、インストールするために特定される。 デスクリプタ内の全ての属性はMIDletから利用可能。 アプリケーション特定の属性は"MIDlet-"から始まらない。 これはMIDletに与えられる。 属性名はケースセンシティブで正確にマッチしなければならない。 MIDletはメソッドMIDlet.getAppPropertyで属性を名前で扱う。

アプリケーションデスクリプタは以下の属性を含まなければならない。

以下も含むかも。 必須属性のMIDlet-Name,MIDlet-Version,MIDlet-Vendorはデスクリプタとマニフェスト で同じでなければならない。 もし異なれば、JARはインストールされるべきではない。 他の属性は同じである必要はないため、 マニフェストとデスクリプタが同じ属性を含んでいても、 その値は異なるかもしれない。 この場合、デスクリプタの値がマニフェストの値を上書きする。

一般的に、アプリケーションデスクリプタのフォーマットは属性名、コロン、属性値、 キャリッジリターン。 スペースは無視される。属性の順番は任意。

アプリケーションデスクリプタは転送や保存のためエンコードされるかもしれず、 パース前にユニコードにデコードされなければならない。 例えば、ISO8859-1エンコードファイルは適切なエンコードの java.io.InputStreamReaderと透過な方法で読まれる必要があるかも。 サポートされていれば、HTTPを使って扱われるデスクリプタは標準HTTP content negotiation mechanismが必要で、 ユニコードにデコードするためのコンテントエンコードヘッダや コンテントタイプパラメータのようなもの。

BNF for parsing Application Descriptors

appldesc: *attrline
attrline: attrname ":" WSP attrvale wsp newline

attrname: 1*< any Unicode char except CTLs or separators >
attrvale: *valuechar | valuechar *(valuechar | WSP) valuechar
valuechar: < any valid Unicode character, excluding CTLs and WSP >

newline: CR LF | LF
CR = < Unicode carriage return (0x000D) >
LF = < Unicode linefeed (0x000a) >

WSP: 1*( SP | HT )
SP = < Unicode space (0x0020) >
HT = < Unicode horizontal-tab (0x0009) >
CTL = < Unicode characters 0x0000 - 0x001F and 0x007F >

separators = "(" | ")" | "<" | ">" | "@"
            | "," | ";" | ":" | "'" | <">
            | "/" | "[" | "]" | "?" | "="
            | "{" | "}" | SP | HT
アプリケーションデスクリプタの例
MIDlet-Name: CardGames
MIDlet-Version: 1.1.9
MIDlet-Vender: CardsRUS
MIDlet-Jar-URL: http://www.cardsrus.com/games/cardgames.jar
MIDlet-Jar-Size: 7378
MIDlet-Data-Size: 256

8.6 Application Lifecycle

各MIDletはMIDletクラスを拡張しなければならない。 MIDletクラスは順序正しくMIDletのスタート、ストップ、クリーンアップを する。MIDletはアプリケーションデスクリプタからアプリケーション管理ソフトウェア と通信するために引数を要求できる。 MIDlet suiteはpublic static void main()メソッドを含んではならない。 存在しても、アプリケーション管理ソフトウェアに無視されるべきである。 アプリケーション管理ソフトウェアはMIDletを開始するために、CLDCによって必要な 最初のクラスを与える。

MIDletがデバイスにインストールされるとき、クラス、リソースファイル、引数、 不変のストレージはデバイス上に保持される。 MIDletsはデバイスのアプリケーション管理ソフトウェアによってユーザに利用できる。

MIDletを実行するとき、MIDletのプライマリクラスのインスタンスが パブリックの無引数のコンストラクタを用いて作られ、 MIDletの状態に従ってMIDletのメソッドが呼ばれる。 MIDletは状態を変化させるか、アプリケーション管理ソフトウェアにMIDlet メソッドを用いて状態変化を知らせることができる。 MIDletが終わるか、アプリケーション管理ソフトウェアによって終了するとき、 破壊され、リソースは再利用できる、これには生成したオブジェクトやクラスが 含まれる。 MIDletはSystem.exitを呼び出してはならない、これはMIDletに呼ばれると SecurityExceptionを投げる。

Javaクラスの普通の状態はロードされたクラスによって影響をうけない。 どのクラスへの参照は状態をロードされるようにし、普通の静的な初期化が起る。

javax.microedition.midletパッケージのクラス
クラス説明
MIDletアプリケーション管理ソフトウェアがスタート、ストップ、破壊できるようにMIDletによって拡張されている。
MIDletStateChangeException アプリケーションが変化要求をできないときに投げられる。


9 User Interface

9.1 Overview

以下のUIに関係した要求が重要。 デバイスの能力と上記要求から、JavaUI(AWT)の単純なサブセットでないようにした。 理由は

9.2 Structure of the MIDP UI API

ハイレベルとローレベルのふたつがある。

ハイレベルAPIはビジネスアプリケーション用で、MID上で実行。 ポータビリティのため、ハイレベルAPIは高度な抽象化とルックアンドフィールの 制御。

ハイレベルAPIを使う場合には、実装がデバイスとネイティブUIの適合を行う。

ローレベルAPIは、ほとんど抽象化を行わない。 アプリケーションが正確な配置と要素の制御をローレベル入力イベントを行う。 特別な、デバイス特定の点にアクセスする必要もある。ゲームなど。

ローレベルAPIを使えば、アプリケーションは以下のことができる。

ローレベルAPIを使うアプリケーションはポータビリティは保証されていない。 具体的なキーを参照するかわりにアプリケーションゲームイベント機構を使うべきで、 アプリケーションはディスプレイのサイズを尋ねて、調節すべきである。

9.2.1 Class Hierarchy

スクリーンはデバイス特定のグラフィクスレンダリングをカプセル化する。 一度に見えるスクリーンはひとつ。 アプリケーションに渡されるより高度なイベントでスクリーンはユーザの行う イベントを扱う。

スクリーンの実装方法はデバイスごとで異なるため、アプリケーション側で 気をつければ、ポータビリティが保証される。単純なほうがうれしい。

3つのカテゴリ。

ローレベルCanvas以外は、各スクリーンはTickerを付加できる。

クラスDisplayは各実行中のMIDletのインスタンスで、 デバイスのディスプレイ能力の情報を扱うメソッドを与える ディスプレイマネージャとして動作する。 ScreenDisplayのメソッドsetCurrent()を呼び出す ことで視覚化される。

9.2.2 Class Overview

ほとんどのアプリケーションはListTextBoxAlertの ような前もって定義された構造体を利用すると予想される。 これらのクラスは以下の方法で使用される。 特別なクラスFormは前もって定義された構造が十分でないスクリーンの場合に 定義される。たとえば、アプリケーションがふたつのTextFieldsか ひとつのTextFieldをもち、単純なChoiceGroupをもつような場合。 Formは任意の要素の結合の生成を許すが、開発者はディスプレイサイズが 限られており、単純なFormのみを作ることを忘れんな。

Formは近い関係のUI要素を少し含むときに使われる。 これらの要素はItemのサブクラスで、ImageItem, StringItem, TextField, ChoiceGroup, Gaugeである。 クラスImageItem, StringItemForm, Alertでのある種の操作を 実現する便利なクラス。 もし要素がスクリーンにすべて入らなければ、実装はフォームをスクロールできるよう にするか、新しいスクリーンをポップアップするか拡張できるようにしろ。

9.2.3 Interplay with Application Maneger

APIの他のリソースと同様に、ユーザインターフェースはMIDPアプリケーション管理の 原理に基づいて制御されるべき。 UIは以下のアプリケーション管理ソフトウェアからの条件に従う。 アプリケーションマネージャは以下のMIDletイベントにアプリケーションが従うと 仮定している。
startApp
最初のスクリーンではアプリケーションはsetCurrentを呼ぶかもしれ ない。アプリケーションマネージャはディスプレイをstartApp()が リターンするときに可視化する。startApp()pauseApp()が 呼ばれる間に複数回呼ばれうることに注意。初期化は起こらず、 アプリケーションはsetCurrent()で不意に他のスクリーンに スイッチすべきでない。
pauseApp
アプリケーションはスレッドで停止するかもしれない。また、アプリケーション が再起動する際に他のスクリーンを始めるなら、新しいスクリーンは setCurrent()でセットされるべき。
destroyApp
アプリケーションがオブジェクトを消去する。

9.3 Event Handling

ユーザの動作でイベントがおこり、実装はアプリケーションに一致するコールバックで イベントを知らせる。 4種類のUIコールバックがある。 全てのUIコールバックはシリアル化され、パラレルには起こらない。 (タイマイベントはUIイベントとは考えない。このためタイマコールバックはUIイベント コールバックと並行に起こる。しかしTimerTaskオブジェクトと同じ タイマコールバックは互いにシリアル化される。) さもなければ、UIコールバックは前のUIコールバックがリターンするやいなや呼ばれる 。 callSerially()を呼ぶことでrun()を呼ぶことは再描画要求が 満されたあとに行われると実装は保証する。

9.3.1 Abstract Commands

MIDPアプリケーションはCommandsを定義し、実装はこれらを抽象的な ボタンやメニュー、あるいはデバイスに適切な機能によって明らかにする。

コマンドはクラスDisplayableのメソッドaddCommandとともに Displayable(Canvas or Screen)にインストールされる。

デバイスのネイティブなスタイルはある種のコマンドを標準的な場所に置くかもしれ ない。 Commandクラスはアプリケーションが意味的に実装と通信できるようにし、 これらの標準的な配置が効果をもちうる。

Commandオブジェクトは3つのコンストラクタパラメータを持つ。

Label
ユーザにヒントを示す
CommandType
コマンドの意味。BACKだったら、元の状態に戻る。 多くの電話のデザインにはポリシーがあるので、それに基づいた実装をする。
Priority
実装がデバイスの能力にあうようにする。
選択ボタンを押すのがアプリケーションにコマンドの通知を普通は行わない場合、 型IMPLICITListは例外である。 それから暗黙のコマンドの通知、SELECT_COMMANDが通知される。

9.3.2 High-Level API for Events

ハイレベルAPIでのイベントのハンドリングはリスナモデルに基づく。 ScreenCanvasはコマンドのリスナを持つ。 リスナになろうとするあるオブジェクトは以下のひとつのメソッドを持つ インターフェースCommandListenerを実装すべき。
void commandAction(Command c, Displayable d);
ScreenCanvasCommandを付加しているか、 登録されたリスナがあればアプリケーションはこれらのイベントを得る。 リスナモデルのユニキャスト版は適合し、このためScreenCanvas は一度にひとつのリスナを持てる。

Form内のItemの状態変化のためのリスナインターフェースが ある。インターフェースItemStateListener内に定義されているメソッド

void itemStateChanged(Item item);
Gauge, ChoiceGroup, TextFieldの相互作用の値が変化するときに呼ばれる。それぞれの変化の後にリスナが呼ばれるとは予期されない。 しかし、もしアイテムの値が変化していたら、他のアイテムのために呼ばれる前か、 コマンドがフォームのコマンドリスナに届けられる前に、リスナは呼ばれる。 変化リスナは少なくともフォームフィールドから焦点がはずれた後に呼ばれるよう 提案される。 フィールドの値が実際に変化した後にリスナは呼ばれるべき。

9.3.3 Low-Level API for Events

ローレベルグラフィクスとイベントはローレベルキーイベントを扱う以下のメソッドを 持つ。
public void keyPressed(int keyCode);
public void keyReleased(int keyCode);
public void keyRepeated(int keyCode);
keyRepeatedは全てのデバイスで利用できるわけではない。 アプリケーションはCanvasの以下のメソッドを呼ぶことでリピート操作が できるかどうかチェックできる。
public static boolean hasRepeatEvents();
APIは標準的なキーコードITU-I(0-9,*,#)を要求するが、キーパッドレイアウトは 要求しない。 実装は付加的なキーを与えるかも知れないが、これらのキーに依存する アプリケーションはポータブルではない。

さらに、クラスCanvasは抽象ゲームイベントを扱うメソッドを持つ。 実装は全てのキーイベントをデバイスのあうキーに割り当てる。 APIは抽象キーイベントのセットを定義する。UP,DOWN,LEFT,RIGHT,FIRE,GAME_A,GAME_B, GAME_C,GAME_D.

アプリケーション以下の呼び出しでは抽象キーイベントへのキーイベントのマップを 得る。

public static int getGameAction(int keyCode);
アプリケーションのロジックがこのメソッドの返り値に基づくとき、 アプリケーションはキーパッドのデザインにかかわらずポータブルに実行できる。

抽象キーイベントのマップには以下も使える。

public static int getkeyCode(int gameAction);
ここでgameActionは論理的なUP,DOWN,LEFT,RIGHT,FIREなど。 キーと抽象イベントのマップはゲームの実行中に変化しないと仮定する。

キー割り当ての例

ローレベルAPIはポインタイベントもサポートするが、全てのデバイスに以下の 入力機能があるわけではないので、以下のコールバックメソッドは デバイスによっては扱われない。

public void pointerPressed<(int x, int y);
public void pointerReleased(int x, int y);
public void pointerDragged(int x, int y);
クラスCanvasの以下のメソッドでポインタが利用可能かどうかチェックできる。
public static boolean hasPointerrEvents();
public static boolean hasPointerMotionEvents();

9.3.4 Interplay of High-Level Commands and the Low-Level API

ローレベルイベントと描画に使うクラスCanvasは、Displayableの サブクラスで、アプリケーションはCommandsを付加できる。 これはゲーム中にScreenのセットアップオプションにジャンプするのに 役に立つ。 ほかの例は地図ベースのナビゲーションアプリケーションで、キーは地図内を 動くのに用いられ、コマンドはより高レベルの動作に使われる。

Canvasとローレベルイベント機能が使われるとき、相互動作ができない デバイスもある。この場合は、実装はなにかのキーでコマンドモードにスイッチできる 方法を与えるかもしれない。 この場合、実行中のCanvasはメッセージshowNotify(), hideNotify()を受け取る。

9.4 Graphics and Text in Low-Level API

9.4.1 The Redrawing Scheme

全てのScreenで再描画は自動的に行われるが、Canvasでは 行われない。 このため、ローレベルAPIを利用する開発者は再描画方法を理解しなければならない。

ローレベルAPIでは、Canvasの再描画は非同期に行われるので 複数の再描画要求は最適化のためひとつの呼び出しで実装されるかもしれない。 これはクラスCanvasのメソッドrepaint()を呼ぶことで再描画要求 をする。 実際の描画はメソッドpaint()で行われる。これはCanvasの サブクラスで与えられる。そしてrepaint()と同期する必要はない。 これは後で起こるかも知れず、複数の再描画要求はひとつのpaint()呼び出し を起こすかも知れない。 アプリケーションは消去と再描画要求をserviceRepaints()で行える。

再描画の例。

9.4.2 Drawing Model

描画操作はピクセルの置き換えだけ。目的のピクセル値はレンダリングに 用いられているグラフィクスオブジェクトに特定される現在のピクセル値で 置き換えられる。 ラスターオプス(受像域)やアルファブレンディングのようなピクセル値の結合は 容易でない(?)。

24ビットカラーモデルは赤、緑、青にそれぞれ8ビットずつ与える。 すべてのデバイスが24ビットカラーをサポートしているわけではないので、 アプリケーションが要求する色をデバイスの表現できる色にマップする。 デバイスの特性を得るのにDisplayクラスを用い、これはどの色が利用可能で どれくらいの明確なグレイレベルが利用可能かを得る。 これでデバイス独立を妥協することなくアプリケーションがデバイスにあった 振る舞いが可能となる。

グラフィクスは直接スクリーンかオフスクリーンイメージバッファに描かれる。 これはグラフィクスオブジェクトの起源に基づく。 ディスプレイに描かれるオブジェクトはCanvasオブジェクトの paint()メソッドに渡される。 これはディスプレイに描かれるグラフィクスオブジェクトを得る唯一の方法。 さらに、アプリケーションはpaint()メソッドの持続時間の間だけ この方法を使うかもしれない。

オフスクリーンイメージバッファに描かれるグラフィクスオブジェクトは そのイメージのgetGraphics()メソッドを呼ぶことで得られる。 これらのオブジェクトはアプリケーションに無限に保持されるかもしれず、 これらのオブジェクトに対する要求はいつでも起こりうる。

クラスGraphicsはsetBackgroundとsetForeground呼び出しのかわりに 色のセットのためメソッドsetColor()のみを持つ。 これは描画エリアの後ろは明示的なfillRect()呼び出しで描かれなければ ならないから。

9.4.3 Coordinate System

座標(0,0)は画面の左上。x,y座標はそれぞれ右、下に増加。 アプリケーションの水平と垂直の距離は実際のデバイスディスプレイ上の距離と一致。 デバイスの画面が正方形と著しく異なる場合、UIの実装は座標変換が必要。 座標システムの原点を変更するのが簡単。座標は整数で指定。

座標システムはピクセル間の位置を表し、ピクセル自身ではない。 このため、ディスプレイの左上の最初のピクセルは座標(0,0)(1,0)(0,1)(1,1)の 間にある。

アプリケーションはCanvasの以下のメソッドで利用可能な描画エリアを 尋ねる。

public static final int getWidth();
public static final int getHeight();

9.4.4 Font Support

要求されたフォントに最も似たフォントは実装に依存する。

システム内の各フォントは個々に実装されている。 新しいFontオブジェクトのインスタンスを作るかわりにスタティックな getFont()メソッドを呼ぶ。 これはフォントに使い方に関係するごみの生成を除去する。

Fontクラスはフォントにアクセスする呼び出しを与える。 以下の属性はFontクラスからのフォント要求に使われる。

Size
SMALL,MEDIUM,LARGE
Face
PROPORTINAL,MONOSPACE,SYSTEM
Style
PLAIN,BOLD,ITALIC,UNDERLINED

9.4.5 Drawing Text and Images

デフォルトでは、テキストの描画は標準のベースラインのかわりにアンカーポイント に基づく。 アンカーポイントはテキストを置くときの計算量を最小にするために使われる。 例えば、テキストをセンターに置く場合、アプリケーションはstringWidth()charWidth()を呼ぶ必要があり、それから引き算、割り算で 正確な位置を計算する。

テキストを描画するメソッド

public void drawString(String text, int x, int y, int anchor);
テキストは現在のフォアグラウンドとバックグラウンドの色で、 現在のフォントでアンカーポイント(x, y)に描かれる。 アンカーポイントの定義はローカルに垂直定数(TOP,BOTTOM)と結合された 水平定数(LEFT,HCENTER,RIGHT)のどれか。 垂直方向のセンタリングはAPIには定義されていない。 テキストの例。

9.5 A Note on Concurrency

UI APIはスレッドセーフ(?)にデザインされた。 メソッドはコールバックTimerTasksから呼ばれるか、アプリケーションの 作ったスレッドから呼ばれる。 また、実装は一般的にアプリケーションから見えるオブジェクトにはロックしない。 すなわちアプリケーションはオブジェクトのロックによって同期を行う。 ひとつ例外があり、クラスCanvasserviceRepaints()。 このメソッドは直ちにメソッドpaint()を呼ぶが、 異なるスレッドにする。 serviceRepaints()が呼ばれたときにpaint()が アプリケーションにロックされたオブジェクトの同期をとろうとすると、 デッドロックに陥る。 アプリケーションプログラマはserviceRepaints()が呼ばれるときには ロックをするべきでない。 また、paint()を用いたオブジェクトのロックによる同期は いつもエラーになる。

UI APIは他のUIツールキットに似たイベントの同期のための機能を持つ。 クラスDisplayのメソッドcallSerially()で、 アプリケーションはイベントの操作を連続して行う。 CallSerially()sericeRepaints()と同じ効果を持つ。

CallSerially()sericeRepaints()の例。

9.6 Implementation Notes

ListとChoiceGroupの実装は要素の選択のキーボードショートカットを含むかもしれない が、アプリケーションプログラムにはこれらのショートカットの使用は見えない。

UI要素のいくつかの実装、スクリーンやアイテム、はネイティブ要素に基づく。 Javaオブジェクトがこれ以上必要ないとき使用中のリソースは解放されるのは 実装による。 ひとつとしてはKVMのコレクタのフックである。


APPENDIX A Implementation Notes

A.2 Implementation

A.2.1 Application Management

アプリケーション管理ソフトウェアは、MIDlet管理ソフトウェアというほうが適切。

MIDlet管理ソフトウェアの機能を述べるため、MIDletsの異なるクラスを定義する。

A.2.1.1 Classes of MIDlets
すくなくともふたつのクラスがある。
クラス説明
Permanent 少なくとも一部は、不揮発性のメモリに置かれる。 多くの機能を取り扱う。何度もダウンロードせずに繰り返し実行。
System 少なくとも一部は、不揮発性のメモリに置かれる。 小さいか、大きい。 デバイス特定の機能を実現する。
Permanentクラスは、利用可能なMIDletの選択に使う。 選択後、MIdlet管理ソフトウェアがMIDletの検索、インストールをする (不変ストレージに書き込む)。再検索は不要で繰り返し使える。

Systemクラスは、Permanentクラスの特別な場合。 MIDの製造者に作成され、デバイス特定の機能を実現。 デバイスの非公開な機能にアクセス。 すなわち、ある意味で、他のMIDletクラスよりも特別な状態で操作する。 システムクラスMIDletは検索やインストールで特別な制約があるかもしれない。

MIDは本節で述べたMIDletのクラスをサポートするかどうかわからない。 ターゲットデバイスの限界を認める以外、開発者はMIDletクラスの区別をする必要は ない。

MID管理ソフトウェアが行えなければならない操作がある。
操作説明
Retrieval MIDletをソースから取ってくる。メディア認証、交渉、検索。
Installation MIDにMIDletをインストール。検証、変更。
Launching MIdletの呼び出し。点検、呼び出し。
Version Manegament MIdletを新しいバージョンにアップグレード。点検、バージョン管理。
Removal 以前にインストールしたMIDletの削除。点検、削除。
MIDletが起動される前、MIdletソースから取ってこなければならない。 MIDは複数のメディアを持つ、例えばシリアルケーブル、赤外線ポート、 無線ネットワーク。 この場合、MIDlet管理ソフトウェアはメディア認証をサポートしなければならない。 取ってくるメディアを選択後、MIDlet管理ソフトウェアは交渉ステップに入る。 ここでは、MIDとMIDletソースが情報を交換する。 この情報にはMIdのキャパシティ(利用可能なメモリ量など)やMIDletのサイズ、コスト など。 デバイスにインストールすることができるなら、取ってくるステップ。 デバイス内にインストール。

MIDPの実装は、MIDletがMIDのセキュリティポリシーを犯さないかを検証する必要が ある。たとえば、MIDletが信頼できるソースから持ってこられたかどうかを 「コードサイン」機能で確認する。 次にMIDletを一般的な形からデバイス特定の内部表現に変形。 この変形は永続的なストレージに書き込むのと同じくらい単純で、 実際にMIDletを不揮発性メモリから直接実行できるようにする。

インストール後、MIDletは起動可能。これは点検ステップを行う。 MIDletを選択、呼び出す。 呼び出しはMIDletをKVMに入れる。この時点で、8章「アプリケーション」で述べた APIがMIDletの制御に使われる。

インストール後のある時点で、新しいバージョンのMIDletが利用可能になる。 アップグレードするために、MIDlet管理ソフトウェアはなんのMIDletがインストール されているかを追跡し(認証)、バージョンナンバをチェックする(バージョン管理)。 この情報を用いて、古いバージョンのMIDletをアップグレードする。

削除。これは前の点検後のステップと少し異なり、MIDlet管理ソフトウェアは インストールされたMIDletのイメージと関係のあるリソースを削除する。 これは7節「永続的なストレージ」に述べたAPIを用いて作られたレコード も含む。

A.2.1.2 Installation, Upgrade, and Removal
アプリケーション管理ソフトウェアはデバイス上のMIDletの完全性と安全性に 責任を持つ。ユーザにデバイスのアプリケーションモデルを与え、 エラーを扱う。

アプリケーション管理ソフトウェアはMIDletのインストールやアップグレードを アプリケーションデスクリプタと一致するJARファイルによる。

MIDlet suiteをアプリケーションデスクリプタかJARファイルでインストール したいとき、アプリケーション管理ソフトウェアは現在インストールされている MIDletのひとつかどうかチェックする。 JARファイルはマニフェストのMIDlet名とMIDletベンダ属性によって唯一とされる。 これらの値がマッチしたら、同じということになる。 この場合はMIDletバージョンが新しければ、ダウンロード、インストールの前に ユーザに確認する。

MIDlet suiteの更新がなんらかの理由で失敗したら、古いバージョンがそのまま 残ることを確認すべき。 更新が成功したら、古いバージョンは削除される。 更新プロセスの一部として、MIDlet suiteのストレージは更新されるアプリケーション が使うために保護される。

MIDlet suiteが削除されるとき、全ての要素、ストレージ、リソースは デバイスから削除されるべき。

MIDP実装はRMSパーマネントストレージ(?)内でデータフォーマットの更新に 責任はない。 更新されたMIDletが異なるデータフォーマットを持っている場合、 データの更新はMIDletの責任。