0

我正在开发一个使用 Asyntask 进行背景识别的 android 语音识别系统。我的代码如下。每次按下开始按钮以识别我的语音时,我都想调用 Asyntask 的执行,但似乎 Asyntask 只能执行一次。如果我再次调用它会发生崩溃。请不要建议每次都创建一个新的 Asyntask,因为实例化它会导致 UI 线程跳过数百帧,并且会导致用户体验缓慢。

我能做些什么来解决这个问题?

public class PocketSphinxAndroidDemo extends Activity {

    private class RecognitionTask
            extends AsyncTask<AudioRecord, Void, Hypothesis> {

        Decoder decoder;
        Config config;


        public RecognitionTask() {


            Config config = Decoder.defaultConfig();

            decoder = new Decoder(config);
        }

        protected void doInBackground(AudioRecord... recorder) {
            int nread;
            short[] buf = new short[1024];

            decoder.startUtt(null);
            while ((nread = recorder[0].read(buf, 0, buf.length)) > 0)
                decoder.processRaw(buf, nread, false, false);
            decoder.endUtt();
            return decoder.hyp();               
        }

        protected void onPostExecute(Hypothesis hypothesis) {
            if (null != hypothesis)
                speechResult.append("\n" + hypothesis.getHypstr());
            else
                speechResult.append("\n<no speech>");
        }
    }

    private static final int SAMPLE_RATE = 8000;

    static {
        System.loadLibrary("pocketsphinx_jni");
    }

    private TextView speechResult;
    private AudioRecord recorder;
    private RecognitionTask recTask;

    /**
     * Called when the activity is first created.
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        speechResult = (TextView) findViewById(R.id.SpeechResult);

        recorder = new AudioRecord(MediaRecorder.AudioSource.VOICE_RECOGNITION,
                                   SAMPLE_RATE, AudioFormat.CHANNEL_IN_MONO,
                                   AudioFormat.ENCODING_PCM_16BIT, 8192);
        recTask = new RecognitionTask();
    }

    public void onToggleRecognition(View view) {
        if (!(view instanceof ToggleButton))
            return;

        if (((ToggleButton) view).isChecked()) {
            recorder.startRecording();
            recTask.execute(recorder);
        } else {
            recorder.stop();
        }
    }
}
4

2 回答 2

1

You can use a Looper and Thread as recommended by Raghunandan, Moreover the crash you were getting is may be you are using the same object to execute your AsyncTask. If you want to call your async task again you must create a new object and then execute your AsyncTask.

Like this

 new MyAsyncTask().execute("");
于 2013-10-15T06:52:18.607 回答
0

是的..根据android doc,它只能执行一次.. http://developer.android.com/reference/android/os/AsyncTask.html。从我的经验来看,在postexecute方法之后它将被取消。所以像这样使用

new RecognitionTask().execute(recorder)

并在活动中创建那些解码器,配置变量..并将其显式传递给任务..

于 2013-10-15T08:28:21.697 回答