ご注意!
Google Translate API v1が2011年12月1日にサービスが終了いたします。添付のサンプルソースでは、Google Translate API v1を利用していますので、翻訳が正常に機能しない場合がございます。ご承知おきください。
Android Market公開を目指してAndroidアプリを開発する!(TextToSpeech日本語対応編)の続きです。
今、作っているAndroidアプリのベースとしたAIRアプリ、TranslatAIRには、画面が閉じられていても、OSに常駐して、クリップボードにあるテキストデータを翻訳するという機能があります。
Androidは、マルチタスクをサポートしていてバックグラウンドでの処理が可能なので、同等の機能が実装できそうです。
※ iPhoneもiOS 4から対応されましたので、同等の機能が実装できると思います。
サービスクラスを利用して、翻訳画面が閉じられても、バックグラウンドで常駐プロセスを起動させておくようにします。
常駐アプリが作成できるAndroidの“サービス”とは (2/3) – @ITを参考にして、サービスクラスを継承したクラスの大枠を作ってみました。
package jp.flashcast.translator.android.service; import jp.flashcast.translator.android.dao.TranslateDao; import android.app.Service; import android.content.Intent; import android.os.Binder; import android.os.IBinder; public class TranslateService extends Service { private TranslateDao dao; public class TranslateBinder extends Binder { public TranslateService getService() { return TranslateService.this; } } @Override public IBinder onBind(Intent intent) { return new TranslateBinder(); } @Override public void onCreate() { super.onCreate(); if (dao == null) { dao = new TranslateDao(this); } } @Override public void onDestroy() { super.onDestroy(); } @Override public void onRebind(Intent intent) { } @Override public boolean onUnbind(Intent intent) { return true; // 再度クライアントから接続された際に onRebind を呼び出させる場合は true を返す } }
アクティビティには、以下のようなコードをいくつか追加します。
まず、このサービスを開始する部分です。
Intent intent = new Intent(this, TranslateService.class); startService(intent);
アクティビティとサービスを、ServiceConnectionクラスを用いてバインドすると、
bindService(intent, connection, Context.BIND_AUTO_CREATE); binded = true;
アクティビティがサービスに接続したときと切断したときの処理を、コールバック関数のようにすることができます。
connection = new ServiceConnection() { public void onServiceConnected(ComponentName name, IBinder binder) { service = ((TranslateService.TranslateBinder)binder).getService(); } public void onServiceDisconnected(ComponentName name) { service = null; } };
また、アクティビティが終了する際に、サービスがバインドされていたら、不要なリソースが残らないようアンバインドするようにします。
@Override protected void onDestroy() { super.onDestroy(); if (binded) { unbindService(connection); } }
これらを翻訳画面のアクティビティに追加します。
TranslatAIRの場合には、WindowsのタスクトレイのアイコンやMac OS XのDockアイコンに常駐させて、それらのアイコンをクリックされたときにクリップボードの内容を翻訳するようにしました。
ですが、今回は、同じように常駐させるのが難しいので、クリップボードの内容を翻訳しにいくトリガーをどうするかが問題です。
そこで、考えたのが加速度センサーの利用です。とりあえず、携帯を振って、ある程度の加速度を検知した際に、クリップボードの内容を翻訳するようにしました。
常駐するサービスにSensorEventListenerを実装して、加速度センサーが変化したときのイベントリスナーを登録します。
manager = (SensorManager)getApplicationContext().getSystemService(SENSOR_SERVICE); List<Sensor> sensors = manager.getSensorList(Sensor.TYPE_ACCELEROMETER); if (sensors.size() > 0) { Sensor sensor = sensors.get(0); registered = manager.registerListener((SensorEventListener)this, sensor, SensorManager.SENSOR_DELAY_NORMAL); }
加速度センサーの値が変化したときのイベントリスナーはonSensorChangedです。
※ onAccuracyChangedは加速度センサーの精度が変更されたときのイベントリスナーなので、今回は何もしていません。
public void onAccuracyChanged(Sensor sensor, int accuracy) { } public void onSensorChanged(SensorEvent event) { if (!binded) { if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) { accelerations[0] = event.values[0] - accelerations[0]; accelerations[1] = event.values[1] - accelerations[1]; accelerations[2] = event.values[2] - accelerations[2]; float acceleration = Math.abs(accelerations[0]) + Math.abs(accelerations[1]) + Math.abs(accelerations[2]); if (acceleration > 40.0f) { String clipboard = ((ClipboardManager)(getApplicationContext().getSystemService(CLIPBOARD_SERVICE))) .getText().toString(); if (!clipboard.equals("")) { // 翻訳実行 if (model == null) { } model = new TranslateModel(); model.setOriginal(clipboard); model.setSrcLanguage("en"); model.setDstLanguage("ja"); model.setDt(new Date().toLocaleString()); Translate(); } accelerations[0] = 0.0f; accelerations[1] = 0.0f; accelerations[2] = 0.0f; } } } }
※ 加速度センサーの部分は、センサー(Sensor)を使用するには – 逆引きAndroid入門を参考にさせていただきました。
※ 17行目の値は、何度か試して適当な値を設定したものなので、特に意味はありません。
33行目の翻訳は、今までと同じように、別スレッドで処理します。
private void Translate() { new TranslateThread(new Handler(), this, model).start(); }
加速度センサーが変化を検知し正常に翻訳が終了すると、翻訳結果が、画面上に浮き上がります。
これで、クリップボードにコピーして、携帯を振ると、サクっと(?)翻訳できるようになりました。他の翻訳系のAndroidアプリにはあまりないと思われる機能なので、このアプリのウリにしていきたいと思います。是非、試してみてください!
サンプルソース
- TranslatorSample10:ダウンロード