アンドロイドOSの3.1(Honeycomb MR1)以上では、USBキーボードやBluetoothキーボードを利用できるようになっています。便利な機能なのですが、Android用と銘打った製品でもない限り、必ずしもキートップ通りの文字入力が可能とは限りません。最近のバージョン(Android 4.1)なら、ハードウェアキーのレイアウトを指定できるので、日本語106キーボードに似た配列ならば文字や数字キーはキートップ通りに入力が可能なようです。

しかし、キーボードによっては、こうした機能でカバーできないことがあります。今回は、アンドロイドのキーボードのカスタマイズをやってみましょう。ただし、このカスタマイズには、root権限が必要になります。今回は解説だけなので、記事を読むのにroot権限は必要ありませんが、次回以降の解説を実地に試すにはroot権限が必要になることをご理解ください。

Android 4.0ではBluetoothキーボードを物理キーボード(PHYSICAL KEYBOARD)として認識するが、キーレイアウトの変更はできない

Android 4.1では、物理キーボードを認識して、キーレイアウトを変更できる。キーボード名称(この写真ではBroadcom Bluetooth HID)をタップすると、レイアウト変更が可能になる

標準は、システム側で割り当てたキーキャラクタマップを使うが、ここでキーボードレイアウトを指定することもできる。ただし、現在のキーボードレイアウトには、日本語キーボード(JIS配列準拠)のレイアウト情報はふくまれていない

アンドロイドキーボードの基本的なこと

作業の前に対象などをはっきりとさせておきましょう。今回のカスタマイズの対象になるのは、USBやBluetoothで接続した物理的なキーボードに限ります。タッチキーボードには別の仕組みがあり、今回のカスタマイズの対象外です。少なくともタッチキーボードでキー表示と入力される文字が一致しないことはないはずです。また、スライド式などの内蔵キーボードには、今回の方法が応用可能ですが、必ずしもうまくいくとは限りません。また、Androidのバージョンとしては、Android 2.2(Froyo)では、同様な仕組みがあるようですが、Android 3.0(Honycomb)はすでに手元に機器がなくて確認していません。なお、Android 4.1(Jelly Bean)には、キーボードの対応表(キャラクタマップファイル。後述)をユーザーが組み込むための仕組みが入っています。

一般にキーボードは、ユーザーが押したキーに対応したコードをオペレーティングシステムがデバイスドライバ経由などで受け取り、これをアプリケーションにイベントとして伝達します。最近のGUIアプリケーションでは、キーは文字に対応しているのではなく、イベントの発生として通知され、その後、アプリケーションなどが必要に応じて文字コードへと変換します(図01)。

図1:通常キーボードなどのハードウェアはキーに対して固有のコード(PS/2スキャンコードやHIDキーコードなど)を発生する。これをシステム側でデバイスに依存しない仮想的なキーコードに変換する。このときメタキーを認識しその状態を記憶する。キーはイベントとしてアプリに渡されるがこの仕組みは通常GUIシステムが用意する

アンドロイドは、カーネルにLinuxを利用しているため、基本的な入力の仕組みは、Linuxのものを利用します。これはInput System(あるいはInput Subsystem)と呼ばれていて、USBやBluetooth、マウス、ジョイスティックなどを統一的に扱う仕組みになっています。このInput Systemがキー入力に応じて「イベント」を発生させます(図02)。

図2:Androidの場合、下の部分はLinuxのInput Systemがあり、その上にAndroidのGUIフレームワーク(ウィンドウマネージャ)がある。Input Systemからのキーイベントはアンドロイドの方式に変換されてアプリケーションに渡される。なお、アプリケーションが処理しなかったキーは、システム側で解釈され必要に応じて実行される

その後、アンドロイド側となるGUIのフレームワーク(ウィンドウマネージャ)などがこのイベントを受け取り、アンドロイドのスタイルに変換します。最終的にキー入力のイベントは、現在入力可能なアプリケーションへと渡されます。

アプリケーションでは、必要に応じてキーイベントを処理します。このとき必要ならキーイベントを文字コードに変換します。また、必要に応じてIMEを呼び出すのですが、このあたりは、アプリケーションというよりも、アプリケーションに組み込まれているシステムが用意したGUI部品(TextViewなど)が勝手に行い、アプリケーションは単純に文字入力された結果だけを受け取ることになります。

USBやBluetoothでは、キーボードを「HID」(Human Input Device)として実現しています。HIDは、単純な機器、特にユーザーが操作するようなキーボードやマウス、あるいはセンサー類をUSBで接続するときのプロトコルや情報の表現方法などを定めています。このようにすることで、オペレーティングシステム側は、デバイスごとにドライバを作る必要がなく、HIDデバイスしとてこれらを扱うことができます。具体的には、USBからレポートと呼ばれる情報を受け取るようになっていて、この中にデバイスの種類ごとに入る情報の形が決められています。USBキーボードの場合レポートには、UsageとUsage Pageと呼ばれる情報があり、これが従来のPS/2キーボードなどでいう「スキャンコード」に当たります。UsageとUsage PageはHIDの規格に含まれており、キーボードであれば、必ずこれを発生するようになっています。Bluetoothは、USBからHIDの仕組みを借りており、接続したあとUSB HIDデバイスとほとんど同じように扱うことができます。

Linux Input Systemでは、HIDキーボードのレポートをLinux key code(LKC)と呼ばれる仮想的なキーコードに変換します。Linuxでは、他のPS/2キーボードやメーカー独自のキーボードを扱う必要があり、ハードウェアをUSBに絞り込めないからです。このLinux key codeは、前述のキーイベントで押されたキーを区別するコードとして使われます。なお、PS/2キーボードなども扱うため、LKCやusageをスキャンコードと呼ぶことがありますが、あまり正しい用語ではなく、誤解される可能性があります。このためここではスキャンコードという用語は使いません。

アンドロイド側では、Linux Input Systemからのキーイベントを受け取ると、まずキーコードをAndroid独自のキーコード(Android key code:AKC)に変換します。その後、Javaで記述されたアンドロイドアプリケーション実行環境へイベントを送信します。アンドロイドのアプリケーションが受け取るのは、このAKCで表現されたキーボードイベントです。

キーコードの変換のしくみ

この仕組みには大きく2つのコード変換が関わります。1つは、LKCからAKCへの変換です。これは、キーボードでどのキーが押されたかという対応なのですが、アンドロイド側では、このとき、キーボードのシフト状態などを管理します。

HIDキーボードやPS/2キーボードなどでは、シフトキーなどの処理は、ソフトウェア側から行い、すべてのキーは、単純なスイッチでしかありません。

このような「メタキー」(シフトやコントロールキーなど他のキーと同時に押すキー)の処理は、アンドロイド側(Linux側ではなくて)で行われています。アンドロイド側では、メタキーの押し下げを認識すると、これをメタキーの状態として記憶します。アプリケーションに伝えるキーイベントにはこのメタキーの状態も含まれています。

アプリケーションなどでキーに対応する文字コードが必要な場合、メタキーの状態と折れたキーのコードを元に変換が行われます。

最初に変換を行うときにアンドロイドで使う変換情報を「キーレイアウト」といいます。キーレイアウトは、キーレイアウトファイルに保存されていて、デバイスごとに専用のキーレイアウトファイルを使うことができます。ただし、デバイスに対応するキーレイアウトファイルがない場合、Generic.klというファイルが使われます。このキーレイアウトは、一般的なキーボード(PCキーボード)を想定したものです。ただし、これはキーコードだけの変換なので、キートップの文字とはまだ無関係です。たとえば、日本語と英語のキーボードでは、記号の位置などが違っていますが、キーレイアウトの変換の段階ではそこまでは区別していません。ただし、キーボードの左下のキーがコントロールキーなのかどうかなのかという点についてはこのキーレイアウトファイルが関係します。なお、このキーレイアウトファイルは、前述のLKCをAKCに変換するものです。これによりさまざまなキーボードからのコードがアンドロイドの中でキーイベントとして意味を持つようになります。

アプリケーションがキーコード(この時点ではAKC)を文字に変換する場合に使われるのがキーキャラクタマップです。この変換情報では、押されたキーコードとその時点のメタキーの状態を元に、変換すべき文字や機能を割り付けます。一部のキーやキーとメタキーの組み合わせは、AKCのままになり、アプリケーションやシステム側で解釈されます。この情報は、キーキャラクタマップ(kcm:key charcter map)ファイルに保存されています。これも原則入力デバイスごとにファイルを対応させることができますが、汎用の変換表であるGeneric.kcmというファイルがあります。これは、US版のPCキーボード(いわゆる101キーボード)を想定したものです。

アンドロイドが持つキーレイアウトの変更機能とは、このキーキャラクタマップファイルを変更する機能です。

簡単にいうと、キーレイアウトファイルを作ることで、標準では扱っていないキーをアンドロイドに認識させることができ、さらにキーキャラクタマップファイルを変更することで、キーで入力できる文字や機能を変更できます。注意する点は、キーレイアウトファイルで、AKCが割り当てられなかったキーコードは、アプリケーション側へは伝わらず、キーキャラクタマップでは変換できないという点です。

また、キーレイアウトファイルでAKCを割り当てるためには、Linux側のデバイスドライバで、キーが認識されLKCの割り当てがおこなわれていなければなりません。つまり、LinuxのInput Systemで認識されないキーは、そもそもアンドロイド側では扱えないということです。

さて、次回は、具体的にファイルを編集するなどしてキー割り当てを変更する方法などを解説します。また、システムがキーをどのように認識しているかを調べる方法なども解説する予定です。

編集部注: 本稿は、2013年2月12日にAndorid情報のWeb専門誌「AndroWire」に掲載した記事を再構成したものです。