考えてみたらAndroidネイティブで何か作るってやってなかったなぁ。そういうのはAdobe AIRでお茶を濁してたからね。 そんなわけで、Androidで遊んでみる。 うん、いかにもAndroidな「音声認識」をやってみようか。
NetBeansでAndroidプロジェクト作って、以下のようにしてみた。
eclipse用とおもいますけど差異はありません。また色が気に入らなかった問題、この後に音声合成と組み合わせたい事、あと、結果を単につないでトースターで表示するだけって部分はちょっとアレだったんで、そこには手を加えました。
package com.example.soundtest; import java.util.ArrayList; 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.HashMap; public class MainActivity extends Activity { // 文字配列の中から有意なひとつを選び出す。 // ロジック(要素が2つ以上の時): // a)全てがユニークな時は0番めのものを選ぶ。 // b)ユニークでないのがある場合、その最大値のものを選ぶ。 private String getUnique(ArrayList<String> s){ HashMap<String,Integer> map = new HashMap<String,Integer>(); int z = 0; int max = 0; String xmax = ""; String r = ""; // 配列が一件のみならその一件をセット。 if(s.size() == 1){ r = s.get(0); }else{ // ユニーク性調査 for (int i = 0; i< s.size(); i++) { if(map.get(s.get(i)) == null){ // 何も設定されていない。 z = 1; map.put(s.get(i),z); }else{ // 既にあるから加算しよう。 z = map.get(s.get(i))+1; map.put(s.get(i),z); } // 最大値が更新されていたらセット。 if(z > max){ max = z; xmax = s.get(i); } } // 最大値は1か2以上か?(ユニーク性調査) if(max < 2){ // 全部ユニークなら最初のものを。 r = s.get(0); }else{ // ユニークでないのが存在するなら最大値のものを。 r = xmax; } } return r; } // = 0 の部分は、適当な値に変更してください(とりあえず試すには問題ないですが) private static final int REQUEST_CODE = 0; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Button button = (Button) findViewById(R.id.button); // アクティビティ上のボタンを割り振る。 button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { try { // インテント作成 Intent intent = new Intent( RecognizerIntent.ACTION_RECOGNIZE_SPEECH); // ACTION_WEB_SEARCH intent.putExtra( RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM); intent.putExtra( RecognizerIntent.EXTRA_PROMPT, "はい、どうぞー (`・ω・´)ゞ"); // インテント発行 startActivityForResult(intent, REQUEST_CODE); } catch (ActivityNotFoundException e) { // このインテントに応答できるアクティビティがインストールされていない場合 Toast.makeText(MainActivity.this, "ActivityNotFoundException", Toast.LENGTH_LONG).show(); } } }); } // アクティビティ終了時に呼び出される @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { TextView vv = (TextView) findViewById(R.id.kekka); // これでアクティビティのそれと関連づけて動作させるん。 TextView vvf = (TextView) findViewById(R.id.flag); // これでアクティビティのそれと関連づけて動作させるん。 TextView vvv = (TextView) findViewById(R.id.kekka2); // これでアクティビティのそれと関連づけて動作させるん。 // 自分が投げたインテントであれば応答する if (requestCode == REQUEST_CODE && resultCode == RESULT_OK) { String resultsString = ""; String result2 = ""; // 結果文字列リスト ArrayList<String> results = data.getStringArrayListExtra( RecognizerIntent.EXTRA_RESULTS); for (int i = 0; i< results.size(); i++) { // ここでは、文字列が複数あった場合に結合しています if(i == 0){ resultsString = results.get(i); }else{ resultsString = resultsString + " " + results.get(i); } } // ユニーク調査 result2 = getUnique(results); // トーストを使って結果を表示 //Toast.makeText(this, resultsString, Toast.LENGTH_LONG).show(); // set Result if(results.size() == 1){ vv.setText(resultsString); vvf.setText(""); vvv.setText(""); }else{ vv.setText(result2); vvf.setText("複数あったので選択(オリジナルは以下)"); vvv.setText(resultsString); } } super.onActivityResult(requestCode, resultCode, data); } }
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@color/background" > <Button android:id="@+id/button" android:text="Click to start" android:layout_width="fill_parent" android:layout_height="wrap_content"/> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@color/background" > <TextView android:id="@+id/kekka" android:paddingTop="40px" android:layout_width="fill_parent" android:layout_height="wrap_content" android:textColor="@color/forground" android:gravity="center" android:text="結果" /> <TextView android:id="@+id/flag" android:paddingTop="40px" android:layout_width="fill_parent" android:layout_height="wrap_content" android:textColor="@color/forground" android:gravity="center" android:text="" /> <TextView android:id="@+id/kekka2" android:layout_width="fill_parent" android:layout_height="wrap_content" android:textColor="@color/forground" android:gravity="center" android:text="" /> </LinearLayout> </LinearLayout>
<?xml version="1.0" encoding="utf-8"?> <resources> <color name="background">#ccffcc</color> <color name="forground">#000000</color> </resources>
うん。いやぁ結構わかりやすいですねAndroid。うむ。