Dropbox

春節前から上海の南京東路にあるノキア旗艦店にてNOKIA E7-00が展示されていました。先日、華南の同志とおもいっきりいじり倒してきましたので、その時の印象です(写真は、同志の撮影たものを無断使用 🙂 )。

まだ販売予定は世界数カ国ですので、今の時点で実機に触れるのは限られ場所と思います。という恵まれた状況にありながら自分の興味の中心にあることだけひたすらテストしていましたのでレビューになってないです。予めお断りしておきます。

[ キーボードはイケテます ] キーボードの開閉は、見たとおりで片手でディスプレイをスライドすれば気持よく開きます。この辺りはノキア、問題なしです。キーの押し込んだ時の感触が適度で携帯端末としては十分に優秀です。

[ サクサクとは言えないか ] 普段iPod Touchを使っているせいか画面の反応は少し鈍くも感じましたが、許容範囲でしょう。アプリケーションによってサクサクだったり鈍かったりしていたような気がします。徐々に良くなっていくことでしょう。

[ カメラは残念 ] Eシリーズでありながら写真の編集アプリが内蔵されていました。顔だけ変形させたりスタンプを押したりするお遊び系アプリです。その反面、搭載されているカメラはフルフォーカスと称する自動焦点の無いものです。このため、紙の書類を撮影しても文字が読めるほどに焦点は合いませんし、細かない部品を撮ろうにもマクロは効きません。最近のノキアはNシリーズのみがCarl Zeissブランドのオートフォーカス・カメラが搭載されていて、他のシリーズは全て自動焦点が有りません。ビジネス・ユーザーだってCarl Zeissじゃなくて良いので自動焦点なカメラが欲しいと思うのですけどね。

[ MIDPはどうやろ? ] さて、ここからが私の本題であるMIDP (Javaアプリ)関連の話になります。

Read the rest of this entry

iPhone/iPad universal binaryのサンプル・コード

練習で作ったiPhoneとiPadの両方で走るuniversal binaryのテスト・プロジェクトを公開いたします。自分自身のテンプレートとして使うために極力シンプルなものにしましたので、容易に読み解く事が出来ると思います。細かいところまで正しいコードを書いているとは限りませんが大きな方針は間違ったものでは無いと思います。

[ コードの権利 ]
コードの大半はXcodeが作り出したものです。また、ごく標準的なものですので、私自身が権利を主張するようなものは何もありません。また、無保証での提供となります。ご自身の責任においてご利用ください。

[ プロジェクトの概要 ]
iPhoneで起動するとTableViewを表示し、クリックによりTextViewにNavigationコントロールにより遷移する標準的なiPhoneアプリ(DrillDownって言うの?)です。同じbianryをiPadで実行するとSplitViewにて同様の動作を行ないます。簡単なプログラムですが、実際のアプリケーションで行うようにデータはUIとは別の共通クラスにより提供するようにしています。

[ プロジェクト作成の概要 ]
Xcode 3.2.3 SDK 4.0.1を使用して作成しました。プロジェクト自体を公開していますので、全てはそれを見て頂ければ良いのですが、どうやってiPhoneプロジェクトからuniversalなプロジェクトに変更していったのかなどを理解いただくため大きなステップを紹介いたします。

< iPhoneアプリの作成 >
– 新規プロジェクトをiPhone用のNavaigation-based Applicationとして作成します。
– TableViewをタップした後に表示するTextView用のクラスとnibを’DetailViewController’として作成。ごく一般的な内容なので詳細はプロジェクトを参照ください。
– データを供給するクラス’MyEngineを作成。RootViewControllerに組み込みます。
ここまででiPhoneアプリとしては完成です。

< Universal Binary化 >
– ターゲット UniTest2を選びプロジェクト, 現在のターゲットを iPad 用にアップグレードする。この時’One Universal application’を選択する。
– UniTest2AppDelegateクラスのUINavigationControllerのプロパティをコメントアウトし代わりにUIViewControllerクラスのプロパティを作成します。元のMainWindow.xibの該当接続を貼り直します。
-> 起動時にiPhoneかiPadかでinfo.plistを参照しMainWindow.xibかMainWindow-iPad.xibが選択されま す。ただしWindowにviewを割付るのはAppDelegateクラスの中なので、ここの接続を正しく行う必要があります。
– 内容を表示するためのTextViewを含んだクラスおよびnibを’DetailViewController-iPad’という名前で作成する。’Targeted for iPad’オプションを忘れないように。このクラスはUIPopoverControllerDelegateとUISPlitViewControllerDelegateになります。クラス名はDetailViewController_iPadに成っているので注意。
– TableViewControllerのサブクラスとしてRootViewController-iPadというファイル名でクラスを作成します(クラス名はRootViewController_iPadになってしまうのでファイル名は別の方が良かったかも)。これはUISplitViewのtable部分のcontrollerになります。
– iPadで最初に表示されるviewを含むMainWindow-iPad.xibを作成します。MainWindow-iPadという名前はinfo.plistで既定値として指定されているものです。これにSplit View Controllerを追加し各種接続を行ないます。

MIDPで画面の回転

KKJConvのプログラム内でランドスケープ、ポートレイトの切り替え(すなわち画面の回転)が出来ないものかと調査してみました。APIドキュメントを眺めていただけでは分からなかったのですが本家Sunのフォーラムに、そのものズバリの答えが書いてありました。それを読んでいただければ内容は分かるのですが、自分自身のメモ代わりにもなるので簡単に解説を書いておきます。

自前でバッファーを用意します。大きさは画面を横向きにしたものにします。そこに通常通りGraphicsクラスを使用して画面の描画を行います。その後 drawRegion メソッドで本物の画面に回転方向を指定して内容を転送するだけです。

私のテストプログラムでは、Canvasクラスを継承したもののクラス変数としてバッファーを定義、

Image imgBuff;

コンストラクターで領域を確保します。

imgBuff = Image.createImage(iWidth, iHeight);

iWidthは実画面のHieght, iHeightは実画面のWidthが入っているものとします。paintメソッドにて、このimgBuffに描画して最後に実画面に反映します。

public void paint(Graphics real_g)
{
    Graphics g = imgBuff.getGraphics();
    // g に対して通常のdrawを行う
    real_g.drawRegion(imgBuff, 0, 0, iWidth, iHeight,
    Sprite.TRANS_ROT90, 0, 0, Graphics.LEFT|Graphics.TOP);
}

jQueryを利用してwebページ要素内の座標を得る方法

モバイル以外のプログラミングについて書くのは初めてかも。

簡単だと思って始めたらハマってしまうのはプログラミングには、よく有ることですがwebプログラミングでは、その可能性が高くなります。ドキュメントで良く分からない場合は、Google先生に頼れば実例が見つかるものですがwebプログラミングの場合、その検索結果を見ても混沌とした状況に陥る場合があります。今回は、その一例です。備忘録として書き残しておきます。

webページの中にイメージ等を表示して、その中をクリックしたりマウスを動かしたりしたときに、そのマウスの位置をイメージ内部の相対的な座標として得る方法です。マウスをクリックしたり動かした時のイベントをjavascriptで得る場合IEを除いては要素内では無く、ウインドウなどを基準とした座標が返って来ます。ただしwebブラウザーによって扱いが様々なのが現状です。

では、イメージなどの要素の位置が得られれば、イベントで得られたマウスの位置との差分を取れば目的は達成できる訳ですが、要素=オブジェクトが複雑にweb画面上に構成されていると生のjavascriptだとかなり面倒なコーディングが必要となります。

こういった事をなるべく簡単に処理するために幾つかのjavascriptライブラリが公開されています。その一つであるjQueryを使用したところ、かなり簡単に処理することができました。

<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$('img#test').click(function(e){
var x = e.pageX - $('img#test').position().left;
var y = e.pageY - $('img#test').position().top;
alert("X=" + x + " Y=" + y);
});
});
</script>

上のようなコードがヘッダー部分にあったとして<img id="test"で始まるイメージの内部をクリックするとイメージ内部の相対的な座標が表示されます。

5800XMでMIDPアプリを動かすのは一部難があります。というのもハードウェア・キーを省略し徹底的にタッチ・スクリーンを活用するようになっているからです。MIDPアプリに対しては組み込み済みJVMが提供するバーチャルなキーボードが使えるのですがキーが限られたものになっています。ナビキー+αではKKJConvは言うに及ばずPiClipなども動かせません。ちなみに現行の5800XMではApplication Managerで設定することにより2種類のバーチャル・キーボードとキーボード無しの状態がMIDPアプリに対して選択可能です。

ではMIDPアプリ側から5800XMに対応するための方法を探ってみようと考えてみました。MIDP2.0のCanvasクラスにはpointerPressed(int x, int y), pointerReleased(int x, int y), pointerDragged(int x, int y)といったタッチ・インターフェースにも使えそうなコールバック・メソッドが備わっています(必ずしもタッチとは限らなくて他のポインティング・デバイスも対象と思います) 。また、それらのイベントが有効かどうかを調べるboolean hasPointerEvents()というメソッドもあります。

と、いうことで簡単なテストプログラムで試してみました。

public void pointerReleased(int x, int y)
{
    iPointX = x;
    iPointY = y;
    this.repaint();
}

えらく単純な部分だけの紹介ですが、これに加えてpaintルーチンの中でiPointXとiPointYの数値を画面に出すようにしておくとタッチした場所に応じたx, yが分かるというものです。

Nokia S605thエミュレーターで試してみると、ちゃんとタッチ・イベントを拾うことが出来ました。余談ですが以前はS60エミュレーターとMIDPのエミュレーターは別でしたが5thからは一つのエミュレーターで両方のテストが出来ます。MIDPのテストは、エミュレーターのFile/OpenでJARファイルを選び、実機同様にインストールを行います。

これで低レベルなタッチ・イベントが取得出来ることは確認できました。ゲームやアプリ独自のバーチャル・キーボードなどは、これで作成出来ますね。ってKKJConv Virtual Keyboardは期待しないでね (^_^;)

標準UIの提供する部品については何もしなくても概ねタッチすると反応するみたいです。ということで10キーなどに操作を頼っている部分だけタッチ・イベントの取得で代替すれば何とかなりそうです。今後S605thデバイスがメジャーになってくると対応するMIDPアプリも増えてくるものと期待します。

S60 5thのタッチイベント・プログラミング

タイトルは何だか偉そうですがListBoxを少し試してみただけです。

5800XMを入手して最初に導入してみたのはptsNotesです。互換性に問題がある旨のメッセージが出ますが導入することは出来ます。色々と問題は有りますが、ごく基本的な動作は可能です。メインのリストをタッチしてノートを開くことも出来ました。これは、予めタッチで発生するイベントを組み込んでいたからです。

void CPtsNotesMainList::HandleListBoxEventL(CEikListBox* aListBox, TListBoxEvent aListBoxEvent)
    {
    if ((aListBoxEvent == MEikListBoxObserver::EEventEnterKeyPressed)||
        (aListBoxEvent == MEikListBoxObserver::EEventItemClicked))
        {
        // ノートを開く処理
        }
    }

みたいな感じで書いていました。このプログラムはS60 3rdMRというSDKで作成していますがEEventItemClickedというイベントが5800XMの画面タッチで捕らえられていることが確認できました。

S60 5thの流儀ではダブルクリックで文書を開く方が良いようですしptsNotesではリストのアイテムを洗濯すると画面の一部に内容のプレビューを表示する機能も働かせたいです。そこで、下のように変更してみました。

void CPtsNotesMainList::HandleListBoxEventL(CEikListBox* aListBox, TListBoxEvent aListBoxEvent)
    {
    if ((aListBoxEvent == MEikListBoxObserver::EEventEnterKeyPressed)||
        (aListBoxEvent == MEikListBoxObserver::EEventItemDoubleClicked))
        {
         // ノートを開く処理
        }
    else if (aListBoxEvent == MEikListBoxObserver::EEventItemClicked)
        {
        // プレビューの処理
        }
    }

ということで、何となくタッチイベントも処理できるようにはなりました。しかしながら、他に不可解な問題が散見されているので、実行ファイル自体はS60 5thのSDKを使ってビルドしないとダメかも知れません。少なくともS603rdのAPIに定義されているイベントが、そのまま使用できるのでソースコードは手を加えることなく共用出来そうです。

E90でキー入力で不思議な点があるとは最初から感じていたのですがE71で少しテストをする機会を得て、その正体が分かりました。たまたま、そのE71の入力が中国簡体字になっていたので気づいたのですが一部の記号キーからユニコード(UTF-16LE)の記号(文字幅が全角相当の記号)が入力されていました。私のE90も同様で簡体字入力にすると一部の記号キー(全てではないのが何とも)UTF-16LEで入力されます。

これで不都合なのは+JやKKJConvなどで一部の記号や句読点、長音が入力出来ない点です。実はE90の場合はCtlキーを併用すると入力出来ていたので、あまり深くは考えていませんでした。まさかUTF-16LEのコードが発生しているとは思いませんでした。

以下E90で入力される主なUTF-16LEな記号キーです。

記号 / キーコード
! / 0xFF01
” / 0xFF02
, / 0xFF0C
– / 0xFF0D
. / 0xFF0E

MIDPから見たキーコードですが+Jで同じキーが入力出来ていないのでNativeな環境でも同じと推測されます。他にもあるかも、、、

KKJConvでは、これらのコードは今のところ捨てられています。対応するASCIIコードの記号にマッピングするのが適当な処理と思われますので、その方向で対処しようと考えています。

Python と SQlite3 の組み合わせは良いかも

Pyhton使いの人には今更な話ではありますが、、、

とあるアプリーケーションの都合でSQLeit3のデータベースを作り込むことになり、 最初は手慣れたPerlを使うつもりでした。ところが私の開発環境であるMac OS X Leopard上でCPANがうまく動かず必要なモジュールが組み込めませんでした(ソースを取ってきてもperl Makefile.plでエラー、CPANの不具合と根は同じかも)。で、調べてみると最近のPythonには標準でSQLite3のモジュールが付いているとのこと。因みにPythonはMac OS Xに標準で組み込まれています。

斯くして、にわかPythonプログラマーは誕生しました。といっても、テキストファイルを読み込み必要な部分を切り出してSQLite3のDBに仕立てるだけなので、サンプルコードに手を少しいれただけで出来上がりました。

もともとS60でのPythonが元気が良くて興味を持っていたのでPythonチュートリアルという教科書を一つだけ持っていました。これも、軽く流した程度です(訳者まえがきに、読者のレベルにより、どの辺りを読めば良いかのガイドがあるのが親切です)。後はグーグル先生のおかげで必要な情報は得られました。まだ、自分の必要とした部分しか資料も読んでいませんが、それがスクリプト言語らしい使い方かもしれません。

SQLiteも手軽で良いです。ちゃんとしたSQLが使えますが、他のDBエンジンと違いサーバーが動いているわけではありません。Pythonなどの処理系の中だけで動くものです。それだけに単独で使用する場合には余計な手間が必要なくお手軽に使えます。有る程度まとまったデータを保管するときに、今までだとフォーマットを工夫して自前でファイルに保管していましたがSQLiteを使うとコード量がかなり減らせそうな気がします。

余談ですが、Pythonチュートリアルの表紙の蛇の絵が家内に不評で表紙を裏返して使っています。

iPhone アプリの開発にあたって読んだ本 Objective-C 2.0

実は、まだ一行もコードは書いていません。そんな状態で何かを人に勧めるなどおこがましいのですがObjective-Cの解説書の紹介です。もっとも選択肢の少ない状態ですので、私がお勧めなどしなくても良いのも事実です(はっきりとブログネタ切れと言え>自分)。

iPhoneとMac OS XのプログラミングにはObjective-Cという物を使います。始める前からC++と違うので面食らうみたいなことは聞かされていました。実際、本を読み始めると頭がくらくらするほどです。 細かいことは書きませんが全く別世界です。

iPhone SDKをダウンロードした人は、おそらくサンプル・プロジェクトを眺める所から始めると思います。ここで有る程度の知識が無いとmainを読むことさえままなりません。とりあえが何かしらObjective-Cのドキュメントを読むことをお勧めします。

ADCのiPhoneのページにもObjective-C: A Primerという文書がありますが、これでは全然足りません。その中にリンクされている”The Objective-C 2.0 Programing Language”くらいを読み通す必要があると思います。これは英語ですしボリュームもかなりあるので、日本語で読める本が楽で良いです。実のところ本屋さんでObjectve-Cに書かれた本は、上の写真のObjective-C 2.0しか見かけませんでしたので他の本との比較は出来ませんが、とても分かりやすい本だと思います。これからiPhoneのプログラムを書こうという人は購入を検討して損はありません。

サイモンのソースコード更新しました

昨年、初めてのS60 3rdプログラムとして公開した簡単なゲーム「サイモン」のソースコードの改訂版を普通的生活工作室のサイモンのページにアップロードしました。

機能的な変更はありません。ソースコードを見直してサンプルとして不適切な部分を変更したものです。したがってバイナリーの方は変更していません(ソースのZIPには含まれています)。

主な変更点は、

  • ローカル変数にもかかわらず変数名の最初がiで始まるものがあった(iで始まるのはクラス変数です)ので変更。
  • タイマーの停止でActive ObjectのDoCancel()を呼んでいた。これは禁止事項です。代わりにCancel()を呼ぶようにした。
  • FsSessionを新たにオープンする代わりにCCoEnv::Static()->FsSession();を使用。

です。もし、S60 3rdのサンプルコードとして、これを利用される場合には新しいsimon120.zipをご利用ください。