Android Native Activityによるキーボード処理 (その1)
Native Activityでのソフトウェアキーボードの利用の困難さ
Native Activity のOpenGL ESを使ったアプリケーションは、Androidが提供する様々な機能が利用できない。最も大きいのは、ソフトウェアキーボードだろう。 Androidアプリケーションで、名前の入力やURLの入力には、ソフトウェアキーボードが表示され、そこで、入力した文字や記号が入力領域(EditText)に反映される。 日本語対応のソフトウェアキーボードでは、連文節かな漢字変換をおこなったり、予測変換の文字列が表示されたりする。 候補をタップすることで、候補の文字列が入力領域にはいる。
ソフトウェアキーボードをNative Activity のOpenGL ES環境下で、表示するには、
に示されているが、NDKでイベントを扱うには、結局
の回答にあるように、
static int32_t engine_handle_input(struct android_app* app, AInputEvent* event)
{
if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_KEY)
{
lint32_t key_val = AKeyEvent_getKeyCode(event);
fprintf("Received key event: %d\n", key_val);
if*1
{
fprintf("Got a letter");
}
}
return 0;
}
となる。
AKeyEvent_getKeyCode(event); で、全てのコードが取得できればよいが、取得できるコードは、
で定義されているコードだけになるようだ。 例えば、!マークや%記号のコードは、定義されていない。これらの記号は、お使いのキーボードをご覧になれば、一目瞭然で、シフトキーを押したときのコードになる。 更に、かなや漢字などの文字列が、上記の入力処理のeventに送られてくるはずがない。
AndroidのJAVAの入力領域(EditText)とキーボードは、別のアプリケーションになっている。 しかし、その間を取り持つインターフェースは、inputconnection となっていて、両者が密接に関係している。 下記のサイトは、独自のキーボードの実装をコードベースで説明している。
上記のNewKeyboard.java中の、commitText("1", 1); で、文字列を入力領域に送っている。 この入力をNative Activity のOpenGL・ESのアプリで取得するためには、JNIを使って取得する必要がありそうだ。さて、JAVAのアプリでは,どのような記述でキーボードを表示しているか見てみる。
上記のサイトによると、JAVAのコードでは、
public class MainActivity extends AppCompatActivity {
private EditText editText;
@Override
protected void onCreate(Bundle savedInstanceState) {
...
editText = findViewById(R.id.edit_text);
...
となっていている。 ソフトウェアキーボードは、アクティビティの起動時に既に表示されている。で、自動的に入力領域(EditText)にソフトウェアキーボードで入力した文字や記号が反映される仕組みになっているようだ。 すなわちソフトウェアキーボードで入力した文字や記号は、
commitText("入力した文字や記号、文字列など", X); でどこかに送信され、アプリケーションがその情報を取得して、入力領域(EditText)に反映していることになる。 JAVAのアプリケーションプログラマは、commitTextで送信された情報を取得したり、入力領域(EditText)に表示する処理を記述する必要はない。 これらは、Android用JAVAの部品が行っている。 しかし、Native Activity のOpneGL・ESで構築されたアプリケーションでは、この一連の処理を自分で記述する必要がある。
Native Activity では、OpenGL の表示処理やイベントの入力のためのメインループがある。 このメインループは、何らかの処理を呼び出して、その処理が終了するまで、待機させることができない。 待機させると、画面の書き換えが起こらないため、フリーズしたようになる。 他のアプリケーションが、commitText を発行した時に、どのようなイベントが発生するのか、また、何かのコールバックが呼ばれるのか、ネットで検索しても記述を発見できなかった。
単純に英数字だけの入力なら、ソフトウェアキーボードを利用することができると予想する。 しかし、かなや漢字がある場合、その利用が困難になる。 記号の場合も同様で、
Input | Android NDK | Android Developersに表現されてる場合、コードが求まるが、そうでない記号は、上述のcommitTextで記号が送られてくると予想される。
GUIライブラリでのソフトウェアキーボードの実装
Androidに付属しているソフトウェアキーボードは、Native Activity のOpenGL ES環境下のアプリケーションでは、表示ができても、記号などの入力を獲得することが難しい。 更に日本語などは、実装が更にハードルが上がり、殆ど不可能に近い。 そこで、GUIライブラリ(
Android, WindowsCE KeyHoleTV - KeyHoleTV開発者のブログ)の表示機能を使ったキーボードを実装した。 実装にあたり、次の要件を満たすようにした。
(1)英字キーボードの配列は、101と同じにする。
(2)記号と数値は、Shitを押して操作するのではなく、記号や数値ボタンをタップして、記号キーボードや数値キーボードを表示する。
(3)UTF-16LEの入力機構をもち、コードで文字の入力を可能にする。
(4)ひらがな2文字までの漢字辞書を持ち、候補を表示する。
(5)ひらがな3文字以上は、連文節かな漢字変換を用いる。 連文節かな漢字変換は、ネットワークを利用したエンジンを利用する。
(6)入力領域の移動(キーボードとか重ならないように)
GUIライブラリで、実装したキーボードは、
となっている。 qが少し濃くなっているのは、WindowsCEやLinuxのナビゲーションボタンや帰ボードの矢印キーで、キーを移動させる現在選択されてるキーを示している。 また、「文字列を入れる」と表示されている入力領域は、キーボードの表示に伴い移動する。 仮名文字の入力のための「KANA」キー、全角入力のための「WIDE」キー、数値とUTF-16LEを入力する「123」キー、記号を入力する「#@」キーがある。 こらのキーをタップすることで、キーボードが変換する。 「KANA」キーをタップした時、
上記のようなキーボードになる。 かなを連続タップすることで、「あ」→「い」→「う」→「え」→「お」と入力文字が変わる。 一定時間経過すると連続タップ期間が終了して、文字が固定される。 上記の例では、2文字入力されて、その候補が表示されている。 この候補はGUIライブラリに内臓されている辞書を使っている。
「ローマ字」ボタンをタップすると、
となる。 3文字以上入力されているので、ネットのかな漢字変換のエンジンを利用した結果を表示している。
GUIライブラリは、ネット上にあるGoogleのかな漢字変換を利用している。 このかな漢字変換は、
で、CGIに元の文字列を送って、リスト形式の結果をもらって、それらを表示している。 CGIで「へんかん」という文字列を送信するためには、TCP/IPを使って、http://www.google.comに接続し、
GET /transliterate?langpair=ja-Hira|ja&text==%E3%81%B8%E3%82%93%E3%81%8B%E3%82%93
HTTP/1.1
User-Agent: kanakanji [ja]
の文字列を送信すればよい。 すると、相手からから
HTTP/1.1 200 OK
Date: xx, day month year time GMT
Pragma: no-cache
Expires: xx, day month year time GMT
Cache-Control: no-cache, must-revalidate
Content-Type: text/javascript; charset=UTF-8
X-Content-Type-Options: nosniff
Content-Disposition: attachment; filename="f.txt"
Server: Google Input Server/1.0
X-XSS-Protection: 1; mode=block
X-Frame-Options: SAMEORIGIN
Alternate-Protocol: 80:quic,p=0.Transfer-Encoding: chunkedmak
4d
"へんかん",["変換","返還","偏官","へんかん","ヘンカン"]
0
が送られてくるので、["変換","返還","偏官","へんかん","ヘンカン"]の部分を取り出して、それぞれ”変換","返還","偏官","へんかん","ヘンカン"を表示する。 ただ、文節を移動する機構を作っていないので、連文節かな漢字変換は、厳密にはできない。
英字キーボードの状態で、「WIDE」をタップすると、
となって、全角入力ができる。 キーボードに←と→がついて、全角を表している。 また、日本語入力キーボードやローマ字入力のキーボードの状態で、「123」や「#@」をタップすると、全角モードの数値や記号の入力になる。 「半角」をタップすると、全角入力が解除される。
全角入力が解除された状態で、「123」キーをタップすると、
数値・UTF-16LEキーボード
となって、数値や数値に関係する記号が入力できる。 「TAP HERE」をタップすると、UTF-16LE入力モードになる。
0ー9までの数値と、A-Fまでの記号で、16進数のUTF-16LEのコードを入力できる。 UTF-16LEのコード入力で、グリフが定義されていない場合、16進表記が入力領域に表示される。
上記の例では、009Eと入力した結果が表示されている。
全角入力が解除された状態で、「#@」キーをタップすると、記号入力になり、
となる。 三角をたっぷすると、別の記号が表示される。
なお、KeyHoleTVのダウンロード・プレミアムモジュールキーのご購入は、
まで。 また、GUIライブラリは、無償で提供していますので、メールにてお知らせください。
メールで ZIP か tar.gz でお送りします。
*1:key_val >= AKEYCODE_A && key_val <= AKEYCODE_Z