2016年3月21日月曜日

Androidのセンサーを使う

目次へ



Androidでは、いろいろなセンサーを使うことができますが、使い方が統一されているため、一つのセンサーの使い方を覚えれば別のセンサーも同じように使えます。
メインの画面が表示されている間センサーからデータを受け取るというつもりで次のようなステップを考えました。

メイン画面のonCreateで
 1.センサーマネージャ取得
 2.センサー取得
 3.リスナインスタンス作成

メイン画面のonResumeで
 4.センサーのリスナを登録する

メイン画面のonPauseで
 5.リスナの登録を解除する


■■■■センサーマネージャ取得■■■■

センサーを使うには、SensorManagerオブジェクトが必要です。
SensorManager sm;
sm = (SensorManager) getSystemService(Context.SENSOR_SERVICE);



■■■■センサー取得■■■■

上で作成したSensorManagerオブジェクトを使って必要なセンサーを取得します。
デフォルトの加速度センサーを取り出すなら
Sensor accele;
accele = sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);

そのタイプのすべてのセンサーを取り出すなら
Listlist;
list = sm.getSensorList(Sensor.TYPE_ACCELEROMETER);


センサータイプの定数
TYPE_ALL 全てのセンサー
TYPE_ACCELEROMETER 加速度センサー
TYPE_GRAVITY 重力センサー
TYPE_GYROSCOPE ジャイロセンサー
TYPE_LIGHT 光センサー
TYPE_LINEAR_ACCELERATION 単方向加速センサー
TYPE_MAGNETIC_FIELD 地磁気センサー
TYPE_PRESSURE 圧力センサー
TYPE_PROXIMITY 近接センサー
TYPE_ROTATION_VECTOR 回転ベクトルセンサー



■■■■リスナ作成■■■■

次にセンサーのリスナを作ります。
Activity自体をimplements SensorEventListenerとすれば簡単です。
class Xx implements SensorEventListener {
    //センサ精度が変更された時呼ばれる
    public void onAccuracyChanged(Sensor sensor, int accuracy) { }

    //センサ値が変更された時呼ばれる
    public void onSensorChanged(SensorEvent event) {
        event.values[0]~[2]にセンサーの値が格納されているので
        この値を使ってプログラムを書きます
    }
}



■■■■リスナ登録■■■■

メインのActivityが表示された時にセンサーからの値を使うのなら、onResumeメソッドで次のように、リスナを登録すればよいでしょう。
smはSensorManager、acceleはSensorです。
また、第3引数はイベントの発生間隔で次のような値が指定できます。
SENSOR_DELAY_FASTEST 最も短い間隔
SENSOR_DELAY_GAME ゲームに最適。FASTESTの次に短い間隔
SENSOR_DELAY_UI user interfaceに最適。GAMEの次に短い間隔
SENSOR_DELAY_NORMAL スクリーン方向の変化などに最適。最もゆっくり
数字 ミリ秒単位で自分で設定


sm.registerListener(リスナ,accele, SensorManager.SENSOR_DELAY_NORMAL); 



■■■■リスナ登録解除■■■■

メインのActivityが隠れた時に解除するなら、onPauseメソッドで次のように登録を解除すればよいと思います。
smはSensorManagerです。
sm.unregisterListener(リスナ);






にほんブログ村 IT技術ブログ IT技術メモへ
にほんブログ村

2016年3月15日火曜日

Androidで音声認識

目次へ



Androidでは、日本語の音声認識を、簡単に使うことができます。
Intentを使い音声認識のためのActivityを起動し、認識された文字列を元のActivityで受け取るのですが、自分で書くのは、ほんの少しです。


■■■■音声認識■■■■

下のプログラムでは「開始」と書いたボタンを押すと、 RecognizerIntent.ACTION_RECOGNIZE_SPEECHを指定して、Intentのインスタンスを作成します。
このオブジェクトにputExtraメソッドを使って、いくつか情報を追加し、startActivityForResultメソッドを使って音声認識用Acyivityを起動します。
マイクの画面(これが音声認識用Activity)が表示され、話した内容を認識すると、元の画面に戻り、認識した内容をTextViewに表示します。
現在「Hello World」と表示している場所がTextViewです。

  

音声認識のActivityを表示するための部分が下のプログラムの(1)から(6)です
認識された文字列を使っているのが、(7)から
  1. まず音声認識用のActivityを指定しIntentのインスタンスを作ります。

  2. RecognizerIntent.EXTRA_LANGUAGE_MODELでは、
    RecognizerIntent.LANGUAGE_MODEL_FREE_FORM
    RecognizerIntent.LANGUAGE_MODEL_WEB_SEARCH
    のどちらかを指定しますが、LANGUAGE_MODEL_WEB_SEARCHは、Web検索の際に使います。

  3. RecognizerIntent.EXTRA_PROMPTで指定するのは、マイクの上に表示される文字列です。

  4. EXTRA_MAX_RESULTSは、認識した候補のうち、最大いくつ返すかを指定します。
    これを1にして、どうぞといった場合「どうぞ」という文字列がひとつ返ってきましたが、
    これを指定しなかった場合には「どうぞドウゾzozodmsoどうゾ」という文字列が返ってきました。

  5. Activityを起動します。
    この時リクエストコードとして、適当な数字を渡すと、戻り値を受け取る場合に、このリクエストコードで起動したActivityからの戻り値であるかを確認できます。

  6. エミュレータで実行した場合には、音声認識機能が無いため、catchが必要です。


  7. onActivityResultは(5)のstartActivityForResultでスタートしたActivityが終了した時に呼び出されるメソッドです。

  8. (5)で自分が発行したIntentであるか判断するのが、REQUEST_CODEのチェックです。

  9. 音声認識された文字列の候補をArrayListとして受け取り、全てを表示しています。
    もし、(4)で指定したように、候補を一つだけ受け取るようにしているのなら、for文など使わずに、results.get(0)を表示するだけです。





import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.os.Bundle;
import android.speech.RecognizerIntent;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;

public class MainActivity extends Activity implements View.OnClickListener {

    private static final int REQUEST_CODE = 100;

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button button1 = (Button)findViewById(R.id.button1);
        button1.setOnClickListener(this);
    }

    //button1をタップすると音声認識を行うActivityを起動する
    public void onClick(View v) {
        try {
            //--- (1)
            Intent intent = new Intent
                           (RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
            //--- (2)
            intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, 
                            RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
            //--- (3)
            intent.putExtra(RecognizerIntent.EXTRA_PROMPT, 
                              "どうぞお話しください");
            //--- (4)
            intent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 1);
            //--- (5)
            startActivityForResult(intent, REQUEST_CODE);
        //--- (6)
        } catch(ActivityNotFoundException e) {        
            Toast.makeText(this, e.getMessage(), Toast.LENGTH_SHORT).show();
        }
    }


    //--- (7)
    public void onActivityResult(int requestCode,int resultCode,Intent data){
        //--- (8)
        if(requestCode==REQUEST_CODE && resultCode==RESULT_OK) {
            String str = "";

            //--- (9)
            ArrayList results = 
                data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
            for(String s : results) {
                str += s;
            }
            TextView text = (TextView)findViewById(R.id.text1);
            text.setText(str);
        }
    }
}




■■■■音声認識によるWeb検索■■■■

もしも、音声認識後、その文字列ですぐにWeb検索を行う場合には、上のプログラムの(1)(2)を次のようにし、(7)のメソッドは削除します。
これだけで、音声認識後、Web検索へと進みます。



           //--- (1)
            Intent intent = new Intent
                           (RecognizerIntent.ACTION_WEB_SEARCH);
            //--- (2)
            intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, 
                            RecognizerIntent.LANGUAGE_MODEL_WEB_SEARCH);



にほんブログ村 IT技術ブログ IT技術メモへ
にほんブログ村