| MIDP メモ |
|
□MIDPとは □準備 □サンプル実行 □サンプル作成 □ネットワークを使った実行 □MIDP1.0 final specification を使う □midp.exeの機能 □イメージの描画サンプル □データの保存 □メモ □問題と思うこと |
ここでは作者がMIDPの使い方などをメモしたものを公開しています。 AtsushiさんがMIDPについて丁寧に書かれています。 KVM全般については「KVM工房」の布留川氏のページへ。 現在の携帯Java情報やMIDPを使ったゲームの公開をされているJava-Mode!
< 2000/7/6 > < 2000/9/22 > |
MIDP(Mobile Information Device Profile)とは、J2ME(Java Micro Edition)のCLDC(Connected Limited Device Configuration)に属する、主に携帯電話等を対称とした仕様(Profile)の一つです。
と書くとやる気を無くしてしまいそうなのですが、要は「携帯電話でJavaする時に使うライブラリ仕様」のことです。(^^;;
MIDPでは「MIDlet」と言うアプリケーションの形式が定義されています。これは「WebのApplet」のような感じで、ダウンロード先のVMによって実行できる形式を統一することで、様々な環境で同じ動きを実現するためにあります。
注意:MIDletが実際に携帯アプリケーションの標準になるという保証はありません。(^^;;
現在(2000/6/17)SUNのDeveloperConnectionからMIDP1.0のEarlyAccess版がダウンロードできます。(JDCへの登録無料)
http://developer.java.sun.com/developer/earlyAccess/j2me_midp/index.html
実際に開発環境を整えるにはJDK1.2以上も必要です。
JDK1.2 : http://java.sun.com/products/jdk/1.2/ja/
JDK1.3 : http://java.sun.com/j2se/1.3/ja/download-windows.html
すみませんが、JDKのクラスパスの設定等は省略します。どうしても分からない場合はメールでも下さい。
MIDPをダウンロードし適当な場所に解凍したら(例:C:\midp-ea1)イメージを掴む為に早速私の用意したサンプルを実行してみます。(注意:ここでは、ネットワークから直接ダウンロードして実行するサンプルです。)
メモ帳などで以下の内容のバッチファイル(.bat)を作り、先ほど解凍したMIDPのフォルダへコピーし実行します。
bin\midp.exe -classpath lib/midp.jar\ -transient http://www.ngy1.1st.ne.jp/~takashi/MID/sample1.jad注意:「-classpath lib/midp.jar\」と、JARファイルの最後に「\」を入れたほうがいいかも。
上手く行けば下のような画面が出ます。

では実際に作ってみます。
○ソース記述
MIDletを継承したクラスを作ります。定義しなければならないのはコンストラクタと、メソッド「startApp()」「pauseApp()」「destroyApp(boolean)」、さらにimplements CommandListenerの「commandAction(Command,Displayable)」です。
ソース内容としては以下のものとなります。(SUNのサンプルと同じ)
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class Sample1 extends MIDlet implements CommandListener {
private Command exitCommand;
private Display display;
public Sample1(){
display = Display.getDisplay(this);
exitCommand = new Command("Exit",Command.SCREEN,2);
}
public void startApp(){
TextBox textbox = new TextBox("Sample1","test",256,0);
textbox.addCommand(exitCommand);
textbox.setListener(this);
display.setCurrent(textbox);
}
public void pauseApp(){
}
public void destroyApp(boolean unconditional){
}
public void commandAction(Command command,Displayable screen){
if(command==exitCommand){
destroyApp(false);
notifyDestroyed();
}
}
}
ソースが完成したら次はコンパイルです。
例として、「C:\midp-ea1\project\sample\」以下にSample1.javaがある場合のコンパイル方法を紹介します。
set CLASSPATH=.;c:\midp-ea1\lib\midp.jar\ javac.exe Sample1.java
これでクラスファイルができました。
J2MEではjavac.exeによって作成されたクラスファイルを2段階の検証を行い安全に実行しようとします。
その1段階目はMIDPのBINフォルダにある「preverify.exe」を使って実際に実行されるより以前に検証します。
set CLASSPATH=.;c:\midp-ea1\lib\midp.jar\c:\midp-ea1\bin\preverify.exe Sample1
成功すると「c:\midp-ea1\project\sample」フォルダに「output」というフォルダが新たに作られ、その中に検証済みのクラスファイルが移されます。
|
訂正(2000/7/6) 上のままでは正常に動作しませんでした。 布留川氏からご指摘を頂きました。 正常に動作させるためには「midp.jar」の解凍が必要です。 「midp.jar」を解凍する JARを解凍するにはJDK付属の「jar.exe」を使います。 midp のlib フォルダ(c:\midp-ea1\lib)で以下のコマンドを実行すると、「javax、com、java、Meta-inf」というフォルダが解凍されます。 jar.exe xvf midp.jar これらのフォルダをそのままの位置で使う場合は、 set CLASSPATH=.;c:\midp-ea1\lib c:\midp-ea1\bin\preverify.exe Sample1 とすることで検証することができます。 解凍したフォルダを一つの新しいフォルダ(c:\midp-ea1\lib\classなど)へ移す場合は「set CLASSPATH=.;c:\midp-ea1\lib\class」などとして指定します。 |
やっとこテスト実行です。(^^;;
実行には「c:\midp-ea1\bin」にある「midp.exe」を使います。これは未だ(2000/6/17)発売されていないJava搭載携帯電話の変わりをする言わば「Java携帯エミュレータ」です。(^^;;
set CLASSPATH=.;c:\midp-ea1\lib\midp.jar\ c:\midp-ea1\bin\midp.exe Sample
で実行できます。
実際にJavaを搭載した携帯電話が発売され、MIDletが実行できるようになったら、ネットワークを使いMIDletが携帯電話にダウンロードされ、必要な時に実行されるようになります。
現在(2000/6/17)はその環境がない為、先ほどの「midp.exe」を使い、ネットワーク上のMIDletが含まれるJARファイルをダウンロードし実行することができます。(しかできません)
また、MIDletアプリケーションの指定にはJAR形式で圧縮することの他に、JADという形式のファイルを作る必要があります。
初めのネットワークサンプルの実行で言うと、「sample1.jad」がそれに当たります。
なお、JARによる圧縮方法は省略します。
JADファイルとは、Java Application Descriptor みたいな意味だと思います。(^^;;
実際はただのテキスト形式なのですが、書式としてはJARの「Manifest.mf」のような感じです。
MIDPに付属されるSUNのサンプル(HelloMIDlet)では以下のような内容になっています。
MIDlet-Name: HelloWorld MIDlet-Version: 1.0.0 MIDlet-Vendor: Sun Microsystems, Inc. MIDlet-Description: Sample Hello World MIDlet MIDlet-Info-URL: http://java.sun.com/j2me/ MIDlet-Jar-URL: http:/// /hello.jar MIDlet-Jar-Size: 1020 MicroEdition-Profile: MIDP-1.0 MicroEdition-Configuration: CLDC-1.0 MIDlet-1: HelloWorld,, HelloMIDlet
これを参考にして私が書いたのが以下のものです。
MIDlet-Name: Sample1 MIDlet-Version: 0.1 MIDlet-Vendor: musashi MIDlet-Description: MIDlet Sample1 MIDlet-Info-URL: http://www.ngy1.1st.ne.jp/~takashi/MID/ MIDlet-Jar-URL: http://www.ngy1.1st.ne.jp/~takashi/MID/Sample1.jar MIDlet-Jar-Size: 1070 MicroEdition-Profile: MIDP-1.0 MicroEdition-Configuration: CLDC-1.0 MIDlet-1: Sample1,,Sample1
JADについての詳しい情報は私もまだ分かっていないのでこれで勘弁してください。(^^;;
一応、最後の行「MIDlet-1: Sample1,,Sample1」と言うのは、このJADファイルで使用するMIDletアプリケーションの登録のようで、この下に「MIDlet-2: Sample2,,Sample2」などとすると一つのJADファイルで複数のMIDletアプリケーションを登録することができるみたいです。(未確認)
また、「MIDlet-1: Sample1,,Sample1」のSample1で囲まれた「,,」の間にアイコン用のイメージファイルへのパスを入れることで、複数MIDletアプリケーションの選択画面で、そのアイコンが使えるようです。(SUNのサンプルをみる限り)
後はJADで指定した通りにファイルをアップすることでダウンロード・実行できるようになります。
□MIDP1.0 final specification を使う
2000/9/22:MIDP1.0 final specification が公開されました。
http://java.sun.com/products/midp/の DownLoad からダウンロードが可能です。(^^;;
なお、ダウンロードには登録(register)が必要です。
「 Mobile Information Device Profile $ 0.00 」などと出ていて不安になりますが無料なのでご安心を。
ダウンロードしたら適当な場所に解凍してください。
ここでは「 C:\midp-fcs 」に解凍した場合を紹介します。
注意:以下にMIDP1.0 final specification の開発方法を記しますが、私は英語が苦手でUnixにも強くないためSUNのドキュメントやUnixのmakefileの内容はほとんど見てません。(^^;;
ので、間違った情報を書いてしまう可能性が十分にあります。
間違いに気づいた時にはご連絡くださると、とても助かります。
ソースはありますが、API Document があった方がいいのでJava2のJAVADOCで作ってみます。
ドキュメントの作成場所は「 C:\midp-fcs\html 」とします。
cd C:\midp-fcs\src\share\classes javadoc.exe -d C:\midp-fcs\html java.lang java.util javax.microedition.io javax.microedition.lcdui javax.microedition.midlet javax.microedition.rms
2000/9/23:ここでは限られたAPIのドキュメントしか生成されません。これは未確認ですが「CLDCのAPIと被っているソースは出さないよ」ってことみたいです。
もちろんEAのAPI Documentと見比べればいいのですが面倒なので、CLDCのソースを持っている方は必要なソースファイルを追加してAPI Documentを作ってみるといいかもしれません。
CLDCのSDK(ソース含む)は「 http://java.sun.com/products/cldc/ 」からダウンロードできたと思います。
Sun Community Source Licensingと書かれていますが、特に気にしなくても大丈夫だと思います。
ちなみにその時のJAVADOCはこんな感じで。
javadoc.exe -d html java.io java.lang java.util javax.microedition.midlet javax.microedition.lcdui javax.microedition.io
ついでにCLDCの日本語ドキュメントもダウンロードしてみるといいかもしれません。API Documentは日本語化されていませんが、日本語でCLDCについて詳しく解説されています。
前回のSample1.javaを今回の物に移植する場合の変更点は
「 textbox.setListener(Command) 」が「 textbox.setCommandListener(Command)」になりました。
このような変更点は他にも存在するようです。
コンパイルはEAの時と同じくJDK1.2のJAVACを使います。
ただしクラスパスは「 C:\midp-fcs\classes 」を指定します。
javac.exe -bootclasspath .;C:\midp-fcs\classes Sample1.java
前回厄介だった検証ですが、プログラム自体は変わらないもののJARの解凍をする必要が無くなりました。(^^;;
なお「 preverify.exe 」は「 C:\midp-fcs\build\win32\tools 」にWin版が存在します。
C:\midp-fcs\build\win32\tools\preverify.exe -classpath .;C:\midp-fcs\classes Sample1
実行もクラスパス以外は前回と変わりません。
C:\midp-fcs\bin\midp.exe -classpath .;C:\midp-fcs\classes Sample1
ネットワークを使った実行方法にも変更がありました。
JARファイルにもJADを含める必要があります。
これは、「ネットにあるJAD」の内容と「JARにあるJAD」とを比べて、そのバージョンなどを調べるようです。
JARファイルにJADファイルを含める。 jar.exe cvmf test.jad Test.jar *.class 実行 c:\midp-fcs\bin\midp.exe -transient JADファイルの存在するURL
「midp.exe」では標準で以下のような特徴があります。(2000/6/21)
・標準4階調モノクロ
・画面サイズ 96x100
・ヒープメモリ 300000バイト
・透明化GIFの透明色が無効
当然ながら、これらは将来発売される携帯電話に依存するもので、この状態専用のプログラムを組むと、エライコトになると思います。(^^;;
その他にパラメータを設定することで、
・2階調モノクロ化
・8Bitカラー化
・SJIS対応化
なども可能です。
やり方は、「midp.exe」の実行前に、
set SCREEN_DEPTH=8 set ENCODING=SJIS
などとすればOKです。
2000/9/23:MIDP1.0正式版での変更点
・Portable Network Graphics(PNG)サポート(透明色有効らしいダメみたい)
・String使用時はGraphics.VCENTER使用不可。
正しくはPNG以外のフォーマットは使えないようです。(−−;;
個人的に引っかかってしまった部分にこの「イメージの描画」があるのでご紹介(失敗談を語る^^;;)を。
イメージを描画するには、
Image image = Image.createImage("/image/test.gif");
などとして、描画したいGraphicsオブジェクトで通常のJava同様「drawImage()」してやればいいのですが、このImage.createImage(Path)のPathでは、「/イメージパス」はOKでも「イメージパス」はNGです。(^^;;
つまり、イメージへのパスは「必ず最初にスラッシュ「/」を付けなければならない」ということです。
いやぁ、私、こんなことの為に1時間以上悩みました・・・。(^^;;;;
イメージの描画のサンプルソースを書いておきます。
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class ImageTest extends MIDlet implements CommandListener {
private Command exitCommand;
private ImageCanvas canvas;
public ImageTest(){
exitCommand = new Command("Exit",Command.SCREEN,2);
canvas = new ImageCanvas();
}
public void startApp(){
canvas.addCommand(exitCommand);
canvas.setListener(this);
Display.getDisplay(this).setCurrent(canvas);
}
public void pauseApp(){}
public void destroyApp(boolean b){}
public void commandAction(Command c,Displayable s){
if(c==exitCommand){
destroyApp(false);
notifyDestroyed();
}
}
}
class ImageCanvas extends Canvas {
public ImageCanvas(){
}
public void paint(Graphics g){
Image image = Image.createImage("/test.gif");//スラッシュ必須^^;;
g.drawImage(image,0,0, g.TOP | g.LEFT );
}
}
ちなみに、Graphics.drawImage(Image image,int x,int y,int anchor)の「int anchor」と言うのは、「Graphicsの x , y に image の anchor 部分がくる」というような感じで、上の場合、「イメージの左上( g.LEFT | g.TOP)」が座標(0,0)に来るという意味です。
これはとても便利で、今まで(通常のJava)は画面の真中にイメージや文字を表示したい場合は、画像の大きさやフォントの大きさを気にする必要がありましたが、MIDletでは、
Graphics.drawString("game over" , screen_width /2 ,screen_height /2 , Graphics.HCENTER | Graphics.VCENTER );
としてやれば「game over」という「文字の中心」が「画面の中心」に来るように設定できます。
なお、「HCENTER:横の中心、VCENTER:縦の中心」で、「screen_width,screen_height」はCanvasのgetWidth(),getHeight()で求めることができます。
さらに言えば、Canvasはゲームを作るときに使うように設計されているそうですよ。
「Javaと言えばアプレット」な人にはちょっと新鮮な機能、データの保存について。
MIDletでは「javax.microedition.rms.RecordStore」というローカルにデータを保存する機能があります。
始めてみる時にはちょっと分かりにくいと思うので紹介を。
MIDPでは通常のファイルに当たるものを「RecordStore」というもので扱います。
例えば、「RACEGAME」というRecordStoreオブジェクト(ファイル)を開くには、
RecordStore store = RecordStore.openRecordStore("RACEGAME",true);
などとします。
さらに、このRecordStoreオブジェクト内には「recordID」と呼ばれるインデックスで分別される複数のデータを保存できます。
つまり、構造的には、
RACEGAME(RecordStore)
|
+--record1:各データ1
|
+--record2:各データ2
|
+--record3:各データ3
|
+
ってな感じになります。
「midp.exe」で実行すると、PC上にRecordStoreのファイルとそのレコードが収められたファイルが作られます。
とても単純なサンプル>kinoさん
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.microedition.rms.*;
public class RecordTest extends MIDlet implements CommandListener {
private Command exitCommand;
private String name = "RecordTest";
public RecordTest(){
exitCommand = new Command("Exit",Command.SCREEN,2);
}
public void startApp(){
String[] data = {"test1","test2","test3","test4","test5"};
RecordStore recordStore = null;
// 書き込み(追加)
try{
recordStore = RecordStore.openRecordStore(name,true);
for(int i=0;i < data.length;i++){
byte[] b = data[i].getBytes();
recordStore.addRecord(b,0,b.length);
}
recordStore.closeRecordStore();
}catch(RecordStoreException e){
e.printStackTrace();
}
// 読み込み
String allData = "";
try{
recordStore = RecordStore.openRecordStore(name,false);
for(int i=0;i < recordStore.getNumRecords();i++){
byte[] b = recordStore.getRecord(i+1);
allData += new String(b);
}
recordStore.closeRecordStore();
}catch(RecordStoreException e){
e.printStackTrace();
}
TextBox box = new TextBox("records",allData,256,0);
box.addCommand(exitCommand);
box.setListener(this);
(Display.getDisplay(this)).setCurrent(box);
}
public void pauseApp(){
}
public void destroyApp(boolean b){
// 削除
try{
RecordStore.deleteRecordStore(name);
}catch(RecordStoreException e){
e.printStackTrace();
}
}
public void commandAction(Command c,Displayable s){
if(c==exitCommand){
destroyApp(false);
notifyDestroyed();
}
}
}
destroyApp()の部分を無くせば実際にファイルとして保存されます。
・Commandのコンストラクタ
コンストラクタ最後の数値は優先度。優先度の高い順(1が最高)に左下、右下に表示される。ただし、2つ以上のコマンドが登録された場合は、片方に「MENU」というのが表示されて、そのMENUが選択されると別画面になり、画面に表示されなかったコマンドが並べられる。
・ペン入力
Canvasには「pointerPressed()」「pointerReleased()」「pointerDragged()」というメソッドがある。これはどうやらPalmのようなタッチパネルを想定してのものみたいだ。ちなみにmidp.exeでもマウス入力として試すことができる。
・日本語入力ができない
まぁ、仕方ないとも思いますが、将来的にどのように日本語を入力させるつもりなのかハッキリしてほしいですね。(^^;;
・Double,Floatが使えない
結構イタイ。いざ使えないとなると不便ですねぇ。(^^;;
・Mathが充実していない
Doubleが使えないのも原因の一つだと思いますが、あれではいったいなんのクラスなのか・・・・。
・セキュリティが甘い
と言うか、なんでもできますからねぇ。
・このまま使われるか分からない
一番の問題。(^^;;
こんなの動くかなぁ・・・・。(^^;;
一応迷路ですけど、ゴールは実装されていません。


ちなみに実行は、
set SCREEN_DEPTH=8 c:\midp-ea1\bin\midp.exe -classpath c:\midp-ea1\lib\midp.jar\ -transient http://www.ngy1.1st.ne.jp/~takashi/MID/maze.jad
MIDP final specification で実行できるようにしました。EAでは実行できませんのでご注意。
set SCREEN_DEPTH=8 c:\midp-fcs\bin\midp.exe -transient http://www.ngy1.1st.ne.jp/~takashi/MID/maze.jad
未だテストの上、かなり重いので注意!メモリを随分と使います!強制ガーベッジ有り!
| 戻る |