2012年12月26日水曜日

KyoroText で使用されている技術 その7


[課題] SurfaceViewでEditorを作る。


このページにアクセスする人を増やすため、
特定のAndroid APIをネタに記事を書くことにしました。

kyorohiroが良く知っているけど、ググッても得られない情報がありました。
SurfaceView上にEditorを実現する方法です。

これを読めば、OpenGlで書かれたEditor!!なんかも簡単に作れるようになるかも知れまもせん。

[構成]

 KyoroTextから、IME関連のエッセンスを抜き取って単体アプリ化しました。
これをサンプルとして、APIの解説をします。「KyoroSampleSurfaceViewEditor」といいます。5-6回に分割してAPIを解説する予定です。

これによりにより、以下のような効能があります。
- InputConnection の使い方が理解できます。
- InputMethodServiceを理解して、android用のソフトウェアキーボードを作成できるようになります。
- また、上記の機能のテストを作成したりする際に必要な知識が手に入ります。
※ 一部だけですが..。


[サンプルコード]
https://github.com/kyorohiro/KyoroSamples
の、KyoroSampleSurfaceViewEditorです。

ソースをコピーした後で、「Eclipse->File->Import->Existing Projects into WorlSpace」
よりプロジェクトをインポートしてご利用ください。


[次回]
今回は内容の紹介だけです。
次回から、APIの解説します。




2012年12月24日月曜日

KyoroText で使用されている技術 その6


この記事を読む人はカナリ少ないです。
今読んでいる「あなた」、もしかすると「あなた」だけかもしれません。 
.. そんな、「あなた」だけがための今回の課題は、「ヒープに収まらないテキストを編集したい」です!! 


[課題]ヒープに収まらないテキストを編集したい 


KyoroTextはでっかいデータをノータイムで表示できる事を実現したアプリです。 
なので、KyoroTextで編集するデータはヒープに収まらないデータとなります。 

ヒープに収まらないデータの一部を変更/編集したい場合、どうすればよいでしょうか? 
KyoroTextでとった方法を解説します。 



[作戦] 
パパパッと思いついた作戦は、以下の2つです。 
  -a 変更したところだけ記録する。 
  -b 内部ストレージを、ヒープであるかのように使用する。適当にキャッシュして、ストレスなく扱えるように調整する。 

「-a」を実現するLogicは直ぐに思いついたのですが、「-b」を、実現するLogicは直ぐに思いつきませんでした。また、応答速度の最悪値が、良く無い場合には、うまく同期させる機能が必要になるかもしれません。 
とりあえず、簡単に実現できそうな、「-a」を実装することにしました。 


[変更点だけ記録する方法] 

  KyoroTextで採用したデータ構造はかなり単純です。 
  以下のような情報を持ったデータをListに記録しているだけです。 
   -「N行目にデーターを追加した」 
   -「N行目のデーターを削除した」 

  「テスト」と「UNDO/REDOの実装」が簡単になるように、「追加」「削除」の2つだけにしました。これだけで、編集前と変種後の差分を全て表現できます。例えば、「特定の行のテキストを置換する場合」には、以下のような感じで表せます。 
   1. 置換する行を削除する。 
   2. 置換した後のテキストを、削除した行に追加する。 


これならば、簡単に実現できそうですね!! 


具体的には、以下のような感じになりました。 改善の余地はかなりある。
https://github.com/kyorohiro/KyoroHelloAndroid/tree/master/KyoroCommon/src/info/kyorohiro/helloworld/display/widget/editview/differ


https://github.com/kyorohiro/KyoroHelloAndroid/tree/master/TestForKyoroCommon/src/info/kyorohiro/helloworld/display/widget/editview/differ


[次回のネタ]

  このブログに来る人は、特定のキーワード(APIとかフレームワーク名だとか)をGoogleした人がほとんどみたいです。より多くの人の目にとまるように、特定のキーワードが使って何か書く予定です。
  - SurfaceView上で、InputConnactionを使った簡単なサンプル
  - Robotiumを使った簡単なサンプル
  - JavaのC#への変換ついて、特定のツールの使い方
  - ..
  - .


2012年12月23日日曜日

KyoroText で使用されている技術 その5


[課題] 文字コードを自動認識させる。 


KyoroTexでは、テキストデータを表示/編集するためのツールです。 このテキストデータの扱いの難しところとして、「どの言語」なのか、「どのPFで書かれた」ものか、「どのようなツール」で書かれたデータなのかによって、データ構成が異なります。
例えば、「EUCJP」というルールに従うと、「あ」は 0xA4A2 で表せますが、「SJIS」というルールだと、0x82A0 であらわせます。 


テキストデーターを適切に読み込むには、どのようなルールで書かれたテキストデータなのかを、前もって知っている必要があります。 

しかし、テキストデータには、どのルールで書かれたものなのかが記載されていません。
KyoroTextで、どのようにしてこのルールを判定しているのかを説明します。 


[判定方法] 


  結論から書くと、jcharsetというライブラリを使用しています。「使っていますよ!」 だけだと物足りないので、文字コード(ルール)の判定する仕組みについて、さわりだけ説明します。 

文字コードの判定方法として、以下のような方法が考えられます。 
- a. テキストデータが、特定の文字コードのルールに沿ったものか確認する。 
- b. テキストデータに、含まれるバイトデータの出現率から、適当な文字コードを推測する。 
- c. テキストデータの、テキストの並びの出現率から、適当な文字コードを推測する。 
と行ったものです。 

例えば、日本語だと、改行のまえに、「。」があったり、英語表記と比較して、半角のスペースが少なかったりする。 ISO2022系の文字コードだと、文字の切り替えにESCが使用されると行った特徴を上手く利用して判定するのです。 


KyoroTextでは、自前でこれらの判定モジュールを作成することはあきらめました。  

KyoroTextで使用しているのは、Mozillaで使用されているchardatのJava版です。 


[参考] 
jchardatのPSMについて解説できたらなと考えていたのですが、PSM(Parallel State Machine)の部分が上手く理解できなかったので、あきらめました。 

もっとjchardatを知りたい方は、以下のページなどを参照してみてください。 

- http://www-archive.mozilla.org/projects/intl/UniversalCharsetDetection.html 
- http://jchardet.sourceforge.net/ 


[次回]
KyoroTextはでっかいデータをノータイムで表示できる事を実現したアプリです。
なので、KyoroTextで編集するデータはヒープに収まらないデータとなります。

メモリーに収まらないデータの一部を編集したい場合、どうすればよいでしょうか?
次回はKyoroTextで実現した解決方法について紹介します。


2012年12月20日木曜日

KyoroText で使用されている技術 その4


[課題] ひとつの画面に複数のテキストを表示したい。 

androidやiPhoneは、WindowsやMacとは異なり、ディスプレイを一つのアプリが専有してしまいます。そのため、テキストを比較したい時には、交互に表示したりしなくてはなりません。WindowsやMACに慣れた方にとって、スマートフォンに対して不満を持つ点ではないでしょうか。 
この問題を解決するために、画面を分割する機能を追加して、同時に複数のテキストを表示できるようにしました。


同時にディスプレイに表示できるのは、本当に一つのアプリだけなのでしょうか。そんな事はないだろうと考えているあなた、その考えは正しいです。残念ながら、使用したことがないので解説できませんが、「Overlay Window android」で、Googleして見てください。実現方法がわかると思います。 



[画面分割] 
画面を分割する方法として、2つ頭に浮かびました。 
  - eclipse的な方法 
  - emacs的な方法 

KyoroTextでは、emacs的な方法を採用しました。いつも、xyzzyというエディタを使用しているせいで、emacs的な方法に愛着があったのが一番の理由です。 
また、実現方法も直に思いついたので、深く検討せずに実装してしまいました。まだまだ洗練されたものでは有りませんが、簡単に構造を紹介します。 


[構造] 
KyoroTextの画面分割には、二分木を使用しています。文章で説明するのは難しいので、直接データーを構造を記述することにします。この方が直感的に理解できると思います。


1. 起動時は以下のようなリスト構造となっています。
[テキストA] 


2. 画面分割にはすると以下のような感じになります。 
[[テキストA, テキストB]] 

- --- A
 |
  --- B

3. さらに、フォーカスがテキストBにある状態で画面分割した場合は、以下のようになります。
[[テキストA, [テキストB,テキストC]]]
- --- A
 |
  --- --- B
     |
      --- C


とても単純ですね!! 簡単に実現できそうです。
後は、この構造に合わせて、UI操作を作れば良いのです。



[登場したクラス]
 Screen#separateScreen(Screen target)



[たぶん次回のネタ]

前回はRobotiumがオヌヌメですよっと宣伝しました。
RobotiumがSeleniumライクに動作させるためにどのような事をしているのか?
で、KyoroText用のテストフレームワークにどのように取り込もうとしているのか?
について、解説します。

2012年12月19日水曜日

KyoroText で使用されている技術 その3


[課題] 自動テストにどのフレームワークを使用しよう? 

作成したプログラムを検証するのに、UnitTestを書くのはもちろんのことです。しかし、加えて、ユーザー操作を必要とするシナリオも自動化したくなるかも知れません。そんな時はどうすれば良いでしょうか? Unitテストでユーザー操作のシナリオも実行できるのでしょうか? 
ユーザー操作が必要なテストは、テスターを雇ってテストを実施してもらうのはどうでしょうか? 個人で趣味で作っているような, アプリでは無理そうですね。でも、一定の品質があることを確認してからリリースしたい。そう思いませんか 

KyoroTextで採用しようとしている方法を紹介します。 


[選択できるカード] 
  そんな時は、自動人形に実施してもらえばよいのです。 今時の携帯端末は、ユーザー操作もUnitテストでかけるのです。 
  - InstrumentationTestCase 
  - Robotium 
  - NativeDriver 
  - MonkeyRunner 
などあります。 

  今回は、「InstrumentationTestCase」「Robotium」「NativeDriver」について、簡単な解説を行った後で、KyoroTextで採用した方法を紹介します。 


[Instrumentation] 
  Androidでは、ユーザー操作をプログラムで書くためのクラスが提供されています。「Robotium」「NativeDriver」もこのクラスを使用しています。 
例えば、 
  - 上下キーを押す。 
  - 画面をタップする。 
といったことができます。 


[Robotium] 
  Selenimという、ホームページをテストするためにツールを参考にしてつるられたテストツールです。Android sdk で 提供されている AndroidInstrumentationTestCaseを使用してテストシナリオをかきます。 
基本は、Android Sdkで提供されている機能を、簡単にラッピングして使い勝手を良くした。のと、SeleniumライクなApiを実現するために、ひと工夫したApiが提供されています。 

[NativeDriver] 
  Seleniumの正当な派生物でありGoogleが提供しているテストツールです。androidだけでなくiOSなどもテストターゲットにはいっています。Selenimとコンパチな開発環境を提供しており。Ruby javascriptなどのJava以外の言語でテストが書けます。 
NativeDriverは、自前のサーバーをandroid上で動作させています。Rubyやjavascriptで書かれたシナリオから送られてくるテキストデーターを逐一解釈してInstrumentationを通してandroidアプリ操作します。 

[NativeDriver と Robotiumの違い] 
   - Robotiumは、Seleniumっぽい何かだが、NativeDriverはSeleniumそのもの。 
   -  Robotiumは同一プロセス上で動作しているので、直接テスト対象のアプリのクラスにアクセスできるが、NativeDriverはSeleniumでサポートしている範囲の事のみ、アプリのクラスに直接アクセスできない。 
   -  Robotiumのコードはシンプルで量が少ないが、NaiveDrivermはSelenium化のためのコードが、多くを占めていて、コード量が多い。 




[KyoroText選択] 
KyoroTextでは、Robotiumのコードから使用したいエッセンスを取り出して。自前のテストフレームワークに追加していく方法をとっています。 
NativeDriverが、Seleniumの正当な拡張であり、なおかつ、Android OS を提供しているGoogleから出ているテストフレームワークであることを考えると。 ※ WEBアプリやIOSでも使用できる優れもの!!! 
Robotiumの存在が弱くかじる方がほとんどではないでしょうか。RobotiumにGoogleみたいなモンスター企業がバックにないぞ。大丈夫か?と考えるのが正常な人の判断です。 


私がNativeDriverを選択肢なかったのは、「NativeDriverはSeleniumの正当な派生物であるがために、融通がきかない。」という理由からです。また、Robotiumの方がコードがシンプルで量も少なく、簡単に理解できます。 


でも今後の互換性は大丈夫か、「きちんと最新の環境にすぐに対応してくれるのか?」と不安を覚えるかも知れません。「Google様がなんとかしてくれるはずだ!!」という考え方もあるでしょう。 
または、私のように、「最悪自分で何とかできなきゃダメなんだ」と考えるのもありです。 
どちらも、イケてる判断です。 

※よく、他のブログなどでは、非公開APIを使っているRobotiumの互換性は将来的には不安だ!と情報が流れていたりしますが、NativeDriverも、非公開APIを使用していますよ!! 

Google様がサポートし続けるなんて保証はありません。ならば自分が即座に対応できものを使用しようと考えました。 
ならば、シンプルで、融通がきくRobotiumがだんぜん良さそうです。 

たぶん次回のネタ

 KyoroTextは、画面を無限分割する事ができます。とても便利です。
 どのように実現したのか?分割方法としてどんな候補があったのか?
 紹介します。

2012年12月15日土曜日

KyoroText で使用されている技術 その2



続き....

大きなサイズのファイルをヒープに読み込むのは、時間がかかります。この問題に対処した結果、一部だけ読み込めば良いと考えるに至りました。


[KyoroTextの場合]


KyoroTextに適用した方法を紹介します。
※改善すべき点は多々ありますが、当時だした結論を紹介します。



[問題の整理]

結論だけ紹介するには、少し複雑で説明が難しいです。まずは、何を実現したいのか整理させてください。実現したい事はとても単純でした。
   A) ファイルからテキストを読み込んで、それを、画面に表示したい。
と、いった感じです。
   ※今回は、「ファイルに詠み込む部分」がかなり重たい処理なためひと工夫必要なわけですね。


 もう少し具体的に表現してみましょう。 例えば、「画面を表示担当」と、「ファイルからデータを読み込み担当」を別々に考えるとより理解しやすくなります。

[1] 表示担当は、ファイル担当から表示するデータをもらう。
   |  表示担当 |  -----データーください!!----> |ファイル担当|

[2] ファイル担当は、データを返す。
   |  表示担当  | <--------ホラよっと---------  |ファイル担当|

かなり、簡単になりました!!


[KyoroTextの解決方法]

KyoroText採用した方法として、「ホラよっと返すデーター」を直ぐに表示側に渡せない場合には、「Loading....」と、テキストを返すようにしました。これで、どんなに時間がかかっても表示するデーターに困ることがなくなります。

あとは、「ホラよっと、返すデーター」が、なるたけ、ファイルから読み込んだデーターになるように調整すれば良いだけになります。
※指定された行周辺のデーターを、キャッシュしておけば、スムーズに表示できそうですね!!


[登場したクラス]
登場したクラスとメソッドは以下
// 画面にテキストを表示する
Viewer# drawMultiLineText()
    
// 指定された行のデーターを返す。キャッシュがなければ、「Loading....」と、テキストを返す
FileReader#getLine(int index)



[その3のネタ]

では、どのようにして、テキストデーターをキャッシュすると、良い感じになるでしょうか。
いくつかアプローチ方法が考えられます。次回、別の課題として紹介する予定です。
- 知識面の話では、「文字コードごとの可能な戦略について」説明します。
- 話のネタとしては、「KyoroText以外のアプリが採用している方法」「KyoroTextが採用している方法の欠点」について説明します。

つづく..


2012年12月13日木曜日

KyoroText で使用されている技術 その1の次

続き...

[共有メモリから取得]
 Dalvikは、アプリごとに使用しているJavaヒープをカウントしており、一定量以上のヒープを取得できないようになっています。しかし、Nativeヒープにはその制限は適用されていません。
 そこで、Androidで大きめのヒープが必要な場合は、Nativeヒープを取得することが考えられます。
 一つは、native側で mallocしてあげる。一つは、android.os.MemoryFileを使用すると良いです。

[KyoroTextの対処]
 ここまで、説明しておいて何ですが、KyoroTextでは、Nativeヒープを使用する方法は取りませんでした。Javaヒープだけで、済ませていまいます。

その2に続きます。

KyoroText で使用されている技術 その1



 数十回に渡って、KyoroText で使用されている技術について、紹介していきたいと思います。
※ androidとj2seで、自作Editorを作成する方法を紹介します。
    以下ような内容を含んでいます。
      - androidにて、InputConnectionより確定文字、未確定文字、キーイベントを取得する方法
      - j2seにて、未確定文字、確定文字を取得する方法。
  


[はじめに]
  私は今「Kyoro Text」というアプリを作成しています。その際に、「試行錯誤したこと」や、「得たノウハウ」をまとめていきたいと考えています。
  当初、Text Editorという、文字の表示と編集するだけのアプリに、悪戦苦闘するとは、考えていませんでした。
  皆さんも、たかだかEditor程度と思いでしょう。 たかだかEditorと言う認識で正しいのかも知れません。 間違いなのかもしれません。この判断をくだすための材料を提供したいと思います。


[進め方] 
  この文章を読んで頂いている皆様は、多分、androidやJ2SEでEditorを作るのに必要なAPIだとか、その使い方だとかを知りたくてこの文章を読んでいるのではないでしょうか?
残念ながら, あなたのご期待に沿う事は出来ないかも知れません。
  モチロン、apiの使い方にもついて、触れる事は多々あると思います。しかし、apiの使い方をメインに説明しようとは考えてません。
  Editorを作成するにあたり、どのような課題があって、それをどのように克服したのかを説明します。
  残念ながら、優れた対処方法はほとんどありませんが、試行錯誤の結果を物語として楽しんでいただけたらと思います。


[課題一覧]
  - Androidで、PC等で編集したテキストを表示するには、ヒープが足りない。
  - ..
  - ..
  - ..



[課題] Androidで、PC等で編集したテキストを表示するには、ヒープが足りない。

  KyoroTextが対象としていた端末はLowSepcなものが有り。 使用可能なJavaヒープが少ないため、Javaヒープ上にデータをすべて読み込んでから表示する事が困難でした。

  また、Fileから、データを読み込む速度も重要な要素です。 Fileからデータを読み込む速度は高機能を歌っている端末だからといって早いわけではなく。古い型のものの方が早かったりしました。
このため、 最新の端末なのにタカダカ数千キロバイト程度のテキストを読み込むのにカナリ待たされたりする事があるわけです。

  これらの状況をふまえて、ユーザーにストレスを与えないように、即座に画面に表示して上げるようにする必要がありました


[androidのメモリ]

  本当に使えるメモリはそんなに少ないのか?という疑問から解決していきましょう。
 端末には、数メガのヒープを確保してもありあまる程のようりょうがあります。
  これを特別な方法で取得できないのでしょうか?
  結論から言うとデキます。なので、この特殊な方法を使用するという手もあります。

簡単に紹介しましょう。
  - malloc
  - MemoryFile
  - ByteBuffer.alllocateDirect

続く.. 中途半端なところで、ごめんなさい!!


[PS]

来年初頭に、KyoroTextの安定版をだす予定です。
そこで、「KyoroTextを紹介するページをつらないとなぁ~」と考えました。
機能の紹介だけだと、平凡な感じがしました。
そこで、KyoroTextを作成するにあたり悪戦苦闘した事を、記事にすることにしまた。

この記事が第一回目となります。
たぶん何度も書き直します。



2012年12月4日火曜日

ショート問題解決 IMEなんかに処理を渡したくない。CTLが押されたら自前で処理したい

KyoroText (自作 Android Editor)ネタです。
来年まとめる予定ですが、こまめに、Android IMEについて情報だししていきます。

* IMEなんかに処理を渡したくない。CTLが押されたら自前で処理したい
 ※ EmacsライクなEditorにしたい場合、IMEがジャマですよね!!

そんな時は、dispatchKeyEventPreIme() で trueを 返すとよい。