端数処理は不明。。。
RecordStoreは世の中のサンプルはindexを0から処理する物がほとんどだが
なぜかWX320KではgetRecord(0)するとExceptionが発生する?
WX320Kでは位置情報とカメラ機能の拡張は使えない。
Math.atan()の用にMicroEmulatorでは使えるが実機では使えないメソッドは
ProGuardでjarを処理するとエラーとして出てくる。
J2ME_POMでMath.atan()が使えないためローカルにコードを突っ込んであるが
薄明の計算のソースを見つけて使おうと思ったところ今度ははasin,powがないと
ProGuardでエラーが出た。面倒なのでオープンソースのMathライブラリを探して
みたところ
DFP(LGPL)と
Real(GPL)
というコードが見つかった。Realでpowの使い方は以下です。
// r = Math.pow(10, r);
String restr2 = Double.toString (r);
Real reobj = new Real(10);
Real reobj2 = new Real(restr2);
reobj.pow(reobj2);
Double reDoub = Double.valueOf(reobj.toString());
r = reDoub.doubleValue();
薄明の計算はオープンソースのコードをそのまま使うと実機で1分以上かかってし
まう。これは1分毎に24時間分チェックしていて、24×60回ループしているのが原
因のようだった。日の出・日の入りの時間が計算できていて薄明だけの計算であ
れば、それぞれの時間から天文薄明までの時間までの計算をすればよい。これに
より10秒近くまで処理時間を短縮できた。おおよそ薄明はそれぞれ2時間なので
2×2÷24で計算通りである。(日の出・日の入りに必要な計算も省きました)
上の薄明の計算に使っているJavaコードは
ここの
JAVA Scriptを移植したように見える。今時のパソコンであれば1秒程度で計算
できるのだが。
上のオプティマイズは最初すべての処理をRealベースで計算しようとしたところ、
いろいろ面倒で、部分的にRealベースなコードを試したところ逆に遅くなったので
苦肉の策です。
WX320KでフォントはSIZE_LARGE(20),SIZE_MEDIUM(16),SIZE_SMALL(12)が使えるが
SIZE_LARGEはあまり奇麗ではない感じだ。
Calendar.getInstance()とタイムゾーンを指定せずにインスタンスを取得すると
月末になると何故かCalendar.MONTHなどが狂いだす。タイムゾーンはVMの実装依
存のようだ。WX320Kには"Asia/Tokyo"などが5つあるようだ。
決め打ちでもまったく問題ないので、意味があまりないサンプルコードは下記に
なります。
String tokyoTZ;
String[] tzIDs = TimeZone.getAvailableIDs();
for (int i = 0; i < tzIDs.length; i++) {
if(tzIDs[i].compareTo("Asia/Tokyo") == 0)
tokyoTZ = tzIDs[i];
if(tzIDs[i].compareTo("JST") == 0)
tokyoTZ = tzIDs[i];
}
TimeZone tz = TimeZone.getTimeZone(tokyoTZ);
Calendar cal = Calendar.getInstance(tz);
WX320KではFileConnectionでアクセスする時のパスは"file:///data/"である。
機種依存しないためにはFileSystemRegistry.listRoots()でルートを取るのが
良さそうだ。
MascotCapsuleでのテクスチャーは256色のbmpファイルを使っている。このため
J2MEのオフスクリーンで用意したImageを直接貼る事はできない。またImageは
24bitなので減色処理した上で変換しなければならない。この時に以下のような
選択肢がある。
- パレットを意識してImageに描画して変換する
- 固定のパレットに合わせてImageを変換する
- Imageを解析してパレットを作成して変換する
J2ME環境はあまりパワーがないので、上の二つが現実的ではないだろうか。
JavaでTarフォーマットをサポートするコードはANTの中と
ここあるがどちらも
J2MEではサポートされていないクラスを使っているのでそのままでは使えない
ようだ。
WX320Kのアプリごとの「許可設定」には
- 1度だけ確認
- 起動ごとに確認
- 使用ごとに確認
- 許可しない
とあるが、1度はグレーアウトして選べない。。。
通信が必要なとき以外パケット通信の切断を行いたいのだが方法が分からない。
結局J2SEを対象にしたオープンソースJ2MEに変更するのはあきらめて、超いい加減な
TARファイルの取り込みのコードを書いた。20年くらい前にもMacでTarファイルを処理
するコードをいじった事をぼんやり思い出した。。。
MicroEmulator 2.0.3をMac OS Xで使った時のHTTPリクエストのヘッダー
GET /hotnews.rss HTTP/1.1
User-Agent: Java/1.5.0_20
Host: localhost
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Connection: keep-alive
MicroEmulator 2.0.4をMac OS X 10.6で使った時のHTTPリクエストのヘッダー
GET / HTTP/1.1
User-Agent: Java/1.6.0_29
Host: 10.0.1.34
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Connection: keep-alive
MicroEmulatorでhttpsすると200なのにgetLengthが-1になってしまう。WX320Kでは
正常に動作するのだが。。。
上記の許可設定は証明書がある物だけが、パーマネントに許可できるのかもしれな
いが、詳細はよく分からない。
下記のMascotCapsuleで回転のために3次元アフィン変換を繰り返すと誤差のためか
図形が歪んだりする。360(4096)回った時は元に戻すのが良いのかもしれない。
3Dの理解のためMascotCapsuleのAffineTransのlookAtの図解を書いてみた。
機種変更してWX341Kにしました。これ以降はWX341Kについて書きます。
bouncycastleを使ってOAuthのoauth_signatureを作る方法。動くまでに一日かかり
いろいろはまりました。まず仕様書にはPOSTを推奨とありましたが参考にしたコー
ドがGETだったので、そうなっています。あと実際にアクセスは最初のoauth_callback
だけをURLにつけて、残りとジネレートしたシグネチャーはヘッダーに入っています。
ヘッダーでは値はすべて""で囲まれてセパレターは,になっています。URLencodeは最
近の厳しい仕様でエンコードしないと駄目で大文字でとか除外文字とかひっかかりま
した。パラメータについてはキーの名前でソートしないといけません。ちょっとでも
違っているとダイジェストは全く別になりますから面倒です。
String rtoken = "xyz";
String key = "abc" + "&";
long currentSec = System.currentTimeMillis() / 1000L;
long currentMSec = System.nanoTime();
String param1 = "GET";
String param2 = "http://twitter.com/oauth/request_token";
String param3 = "oauth_callback=oob&" +
"oauth_consumer_key=" + rtoken + "&" +
"oauth_nonce=" + Long.toString(currentMSec) + "&" +
"oauth_signature_method=HMAC-SHA1&" +
"oauth_timestamp=" + Long.toString(currentSec) + "&" +
"oauth_token=&" +
"oauth_version=1.0";
String escapeStr = Util.URLencode(param1) + "&" +
Util.URLencode(param2) + "&" + Util.URLencode(param3);
System.out.println(escapeStr);
byte[] m = escapeStr.getBytes();
HMac hmac = new HMac(new SHA1Digest());
byte[] resBuf = new byte[hmac.getMacSize()];
hmac.init(new KeyParameter(key.getBytes()));
hmac.update(m, 0, m.length);
hmac.doFinal(resBuf, 0);
System.out.println(Base64Coder.encodeString(resBuf));
BAUMのHttpConnectionのヘッダーは以下の通り。FreeBSDのncコマンドでポートを
LISTENして確認。
GET / HTTP/1.1
Accept: */*
Host: hoge.jp
User-Agent: JV-Lite2WE/3.3(WILLCOM/WX341K) Profiles/MIDP-2.0 Configuration/CLDC-
1.1
Pragma: no-cache
Cache-Control: no-cache
Connection: Keep-Alive
Accept-Encoding: deflate, gzip
HttpConnectionのsetRequestPropertyでヘッダーをセットした時に256で切れてしまう。
おそらくJV-Lite2の制限事項なのではないだろうか。これだとtwitterのOAuthは
使えない。
サーバがgzipをサポートしている場合はHttpConnectionでの通信はgzipで行われて、
openInputStreamで開くInputStreamは解凍されたデータになるようだ。
上の問題の回避のために、自前でSocketはって、HTTPするコードを書いてみたが、
これでtwitterのAPIをたたいてXMLを拾うととんでもなく遅くてkXMLがIOException
を起こす。一度メモリに落としてからkXMLにかければ問題ないようだが、遅すぎて
使い物なりません。setRequestPropertyの制限どうにかしてください。WILLCOMさん
GearのUIではおそらくメモリ節約のためにインスタンス化を繰り返し行わずクラスを
使い回す事を考えて作られているように思われる。これと関係はわかないのだが
時々固まる。。。デバッグの切り口が見当たらない。
Managerのサポートの確認
getSupportedContentTypes: audio/x-pdxmidi
getSupportedContentTypes: audio/wav
getSupportedContentTypes: audio/x-tone-seq
getSupportedContentTypes: audio/x-wav
getSupportedContentTypes: audio/midi
getSupportedContentTypes: application/x-midi
getSupportedContentTypes: audio/sp-midi
getSupportedContentTypes: audio/x-midi
getSupportedContentTypes: audio/x-gpoint726
getSupportedProtocols: https
getSupportedProtocols: device
getSupportedProtocols: file
getSupportedProtocols: http
BAUMでWAVファイルの再生を試していたのだが、なかなかうまくいかなかった。
でよくよくWILLCOMのサイトを見ると以下が見つかった。
wav(G.726 量子化ビット数:2/4bit サンプリング周波数:8/16/32KHz)
通常WAVファイルはリニアPCMな16bitファイルになっているがそれではだめでWAV
ファイル中にG.726なデータを突っ込まないと駄目のようだ。SOXはCODECのサポ
ートはないので、ちょっと探してみたが適当がものがみつからなかったので、
soft-switch.orgのspandspという
ライブラリに含まれるG.726なコードを使って簡単なコマンドを
作ってみた。(g726encode.tgz spandsp
のソースをダウンロードして圧縮ファイルの中身をsrcディレクトリに入れて
make -f Makefile.g726するとコマンドが出来る。デバッグライトいろいろは
いっているので汚いです)32000Hz/1ChなWAVファイルを食わせるとG.726なWAV
を作ります。ちょっと苦戦したのはPCMなファイルを食わせてもまったくエクセ
プションなどエラーが出なかったからだ。再生のコードは下記のような感じ。
public void soundPlay(){
try {
Player myPlayer;
InputStream is = getClass().getResourceAsStream("receive.wav");
myPlayer = Manager.createPlayer(is, "audio/x-wav");
if(myPlayer == null) {
Logger.out.println("Manager.createPlayer error");
} else {
myPlayer.addPlayerListener(this);
myPlayer.realize();
myPlayer.prefetch();
myPlayer.setLoopCount(1);
VolumeControl vc=(VolumeControl)myPlayer.getControl("VolumeControl");
if(vc != null)
vc.setLevel(100);
myPlayer.setMediaTime(0);
myPlayer.start();
}
} catch (IOException ioe) {
Logger.out.println("IOException: " + ioe);
} catch (MediaException me) {
Logger.out.println("MediaException: " + me);
}
}
WX320Kのガイドを見るとNECの
μPD9995
というサウンドチップを使っているようなので
BAUMもおそらく同じなのであろう。このチップ自体にはG.726のデコーダーとか
は入っていないようなので、ホストCPUでデコードしているのかもしれない。
以下でCOM1が存在する事が分かるのだが、このCOM1はローカルポートすなわちUSB接続
されたパソコンとの接続でIrDAのポートではない。JavaアプリからIrDA使えるように
してほしい。
String ports = System.getProperty("microedition.commports");
J2MEとは関係ないがFelicaで三者間通信してブラウザを起動するコードを見つけたので
ちょっといじって、動くようにしてみた。元々のコードはlibpasoriを使っていたが
libpafeに変更してみた。libusbの古いバージョン(0.1.12)とlibpafeをダウンロード
してlibusbはconfigureしてMakefileしておいて、libpafeのtestsフォルダーに
この(browser_startup.tgz)ファイルを展開して
makeすればバイナリーができる。libusbはMakefileでinstall_name_toolしているので
システムにインストールする必要はありません。使い方は以下のような感じで、
一度実行した後には引数を空にして実行して三者間通信モードを解除してください。
% browser_startup http://www.google.co.jp/
忘れないうちに書いておくが、以下のようなコードだとLocationがNoClassDefFoundError
になり、microemulatorで起動しなくなる。
try {
if(onMicroEmulator) {
startProgress("Get current location near Mobile Point list");
MobilePoint search = new MobilePoint(this, 35.68381981, 139.77456498);
} else {
startProgress("Get current location near Mobile Point list");
Location loc = Location.deviceActive();
MobilePoint search = new MobilePoint(this, loc.convertDegree(loc.getLatitude()),
loc.convertDegree(loc.getLongitude()));
loc.deviceDeactive();
}
} catch (Exception e) {
}
以下のコードだとOKでした。
if(onMicroEmulator) {
try {
startProgress("Get current location near Mobile Point list");
MobilePoint search = new MobilePoint(this, 35.68381981, 139.77456498);
} catch (Exception e) {
}
} else {
try {
startProgress("Get current location near Mobile Point list");
Location loc = Location.deviceActive();
MobilePoint search = new MobilePoint(this, loc.convertDegree(loc.getLatitude()),
loc.convertDegree(loc.getLongitude()));
loc.deviceDeactive();
} catch (Exception e) {
}
}
Socketの使い方1
StreamConnection connection;
connection = (StreamConnection) Connector.open("socket://" + httpserver);
PrintStream output = new PrintStream(connection.openOutputStream() );
Socketの使い方2
SocketConnection sc;
sc = (SocketConnection)Connector.open("socket://" + httpserver);
sc.setSocketOption(SocketConnection.SNDBUF, 512);
sc.setSocketOption(SocketConnection.RCVBUF, 1024*8);
PrintStream output = new PrintStream(sc.openOutputStream() );
忘れないうち書いておくが、LocationのconvertDegreeでエクセプションを起こして
deviceDeactiveしないと次のdeviceActiveでエラーになる。convertDegreeで
エクセプションを起こさないように以下のようにチェックして処理にすると良い。
try {
Location loc = Location.deviceActive();
String latStr = loc.getLatitude();
String lonStr = loc.getLongitude();
double latVal = 0;
double lonVal = 0;
if(latStr.length() != 0 && lonStr.length() != 0) {
latVal = loc.convertDegree(latStr);
lonVal = loc.convertDegree(lonStr);
}
loc.deviceDeactive();
if(latVal != 0 && lonVal != 0) {
// do something
} else {
// error
}
} catch (Exception e) {
}
J2MEには正規表現のサポートがない。Stringのsplitはどっかからコードを拾って
きてソースに組み込んでいた。ちゃんとした正規表現のオープンソースのライブラリ
では
Jakarta Regexp
と
dk.brics.automatonがある。
ただし両方ともSerializableを使っているので、これを削除する必要がある。
またJakarta Regexpではjava.lang.Characterを使っていてdk.brics.automaton
ではjava.util.Setを使っていて、そのまでは使えない。java.lang.Characterについて
はRECharacter.javaという必要な部分だけ実装したコードが見つかったので、これで
置き換えて使えるようになった。
Yet Another J2ME Application
始めました。
上のプロジェクトのWEBホストから直接インストールできるようにしようとした
ところ、jarのContent-Typeがapplication/x-java-archiveとなってしまってい
たので.htaccessで以下を設定した。
AddType application/java-archive jar
WILLCOMのJAVA機種情報をみるとHONEY BEE 4/BAUM/WX340Kなどは
「CLUB AIR- EDGE経由通信」が「アプリダウン ロード元サーバ」となっている。
yaj2meappのsfのサイトで試してみたが確かにこのサイトからダウンロードした
アプリはこのサイトへのアクセスがprinではなくても出来ている。sfのホスティング
のphpでproxyの用なコードを作っておけば、prinの1500円は払わないでもすむかもし
れない。機種によってアクセス制限が「公式アプリ」や「制限なし」などになって
いるが、なぜアクセス制限が機種依存するのか不思議だ。
BAUMでネットからアプリをインストールする場合、ブラウザでjadファイルのリンク
からのjarファイルの読み込みにはJAVA接続先設定が利用されるようだ。
この時はCLUB AIR-EDGEに設定してあっても、どこのサーバからでもダウンロードは
出来る。
J2ME_POMに計算時間の表示を入れてベンチマークをとってみたところWX320Kは12秒
くらいで、BAUMは7.5秒くらいであった。Airで動いているmicroemulatorだと0.7秒
位なのだが。。。
J2ME_JSONにもアクセス時間の表示を入れたところ5秒くらいである。重い計算は
サーバのPHPに任せた方がよいのかもしれない。
pngの最適化はImageOptimが良いようです。
Hello! Worldサンプルプログラムとpreverifyパッチ
フォルダー名をJ2MESampleから適当な名前に変えてmodifyname.shに新しい名前
を引数にして実行すると関連するファイルを修正できます。
|
|
Legion of the Bouncy Castle
を使ったSHA1とRSAの
サンプルプログラム
|
|
Legion of the Bouncy Castle
を使ったYahoo!デベロッパーネットワークのOAuthの
サンプルプログラム
|
|
JZLib
を使ったGZIP処理の
サンプルプログラム
このプログラムを作っていて気がついたのだがBAUMのHttpConnectionクラスは通信は
可能な場合はgzipで行っていてopenInputStream()は解凍されたデータが返ってきます。
microemulatorではgzipを使わずに通信を行っています。これらは上記のヘッダーを
見れば分かる事でした。microemulatorではHttpConnectionでAccept-Encodingをgzip
にしてリクエストするとボディーにはgzipなデータが入ってきます。このときChunkな
データの場合は、処理済み、具体的にはデータの長さを削除したRAWデータで渡され
ます。JZLib 1.1.1はJava 1.3&MIDIP 2ではそのままコンパイルできずにコメントの
削除、Cloneの削除、無いエクセプション削除、java.ioのクラスの追加をして
コンパイルしてあります。microemulatorでは600msくらいで処理できますがBAUMでは
11sもかかります。
|
|
kXML,
XML Pull Parsing
を使ったRSS処理の
サンプルプログラム
|
|
org.json.me,
を使った
サンプルプログラム
|
|
RecordStoreをつかって端末に情報を保存する
サンプルプログラム
|
|
オープンソースのUIライブラリーの
Gear
を使った
サンプルプログラム
ビルドにはGear本体を同じフォルダーにコピーする必要があります。
ソフトキーを使えるようにいじっていたのだが、当初キーコードの問題と
思ってソースをいじったのだがうまく動かなかった。キーコード以前に
どうもNokiaなどの携帯のVMのCommand処理とWillcomのJV-Lite2では違う動
きをするようだ。とりあえずあきらめて1キーと3キーをソフトキーの代わ
りにするように処理を入れてある。Gearのメモ
|
|
月の満ち欠けの表示する
プログラム
こちらもエンジン部分とは
こちら
のオープンソースを使っています。
それとここのコードも一部
利用させてもらいました。
国内の月のページ(The Moon Age Calendar)
のデータと微妙な差があるので、エンジン部分のパラメータの調整が必要なのかも
しれません。
グラフィック表示は簡易で正確でないかもしれません。
「日と月」 の 出没時刻は
K.ShindoさんのアプレットのJAVAコード
を利用させてもらいました。計算にはRealを使っています。それぞれのオープン
ソースの出所はREADMEに書いてあります。
|
|
FileConnectionをつかって端末に保存されているファイルリストを表示する
サンプルプログラム
このサンプルはJSR75の機能を使っているのだが、MicroEmulatorでは動作
しなかった。MicroEmulatorの配布ファイルのlibディレクトリにmicroemu-jsr-75.jar
が入っているので、設定すると使えるのかもしれないが調べていない。
|
|
端末がサポートしているエンコードを確認する
サンプルプログラム
WX320KではUTF8とSJISだけがOKで他はNGになります。
|
|
MascotCapsuleを使ってモデルを表示する
サンプルプログラム
(J2ME_Planet.tgz)
HIのサンプルをベースにモデルの表示位置を変更して動かし、視点位置を
変更してモデルの大きさを変更しています。3Dプログラミング的には間違え
ているような気もするが、なんとなく思ったように動いているので勘弁して
ください。光源をいじって月の満ち欠けみたいな事をやってみたかったのだ
が出来てません。リソースはmbacファイルのみでmtraファイルを使わずにモ
デルを動かしています。上で書いたようにMacではモデルデータ(mbac)やア
ニメーションデータ(mtra)を作る事は出来ないので、サンプルのモデルをそ
のまま使っています。
|
|
MascotCapsuleで四角の面に色を貼ってY軸方向に回す
サンプルプログラム
このサンプルはソニーエリクソンのサンプルコードを参考にしている。
|
|
第5使途ではないがMascotCapsuleで正八面体に色を貼ってY軸方向
に回す
サンプルプログラム
このサンプルはソニーエリクソンのサンプルコードを参考にしている。
|
|
MascotCapsuleで四角の面にBMPのテクスチャーを貼ってY軸方向に回す
サンプルプログラム
このサンプルはソニーエリクソンのサンプルコードを参考にしている。
|
|
リンク
Copyright (C) 2009 Hiroki Mori All Rights Reserved.