录制音频时的线程问题

时间:2011-01-30 13:15:42

标签: android multithreading

我正在尝试使用AudioRecord录制音频样本。我用了一个线程来执行录制方法。线程似乎有问题。任何想法为什么?

package com.tecmark;

import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import android.app.Activity;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.View;
import android.widget.TextView;

public class recorder extends Activity  {




    private Thread thread;
    private boolean isRecording;
    private AudioRecord recorder;
    private FileOutputStream os;
    private BufferedOutputStream bos;
    private DataOutputStream dos;
    private TextView text;

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



    }



    public void onClickPlay(View v){


    }


    public void record(){


        Log.i("inside record method", "******");

         text = (TextView)findViewById(R.id.TextView01);
         text.setText("recording");

        int audioSource = MediaRecorder.AudioSource.MIC;
        int sampleRate = 22050;
        int channel = AudioFormat.CHANNEL_CONFIGURATION_MONO;
        int encoding = AudioFormat.ENCODING_PCM_16BIT;
        int result = 0;



        File path = Environment.getExternalStorageDirectory();
        Log.v("file path", ""+path.getAbsolutePath());

        File file = new File(path, "test.wav");

        if(file.exists()){
            file.delete();
        }

        path.mkdirs();
        Log.v("file path", ""+file.getAbsolutePath());

         recorder = new AudioRecord(audioSource, sampleRate,channel,encoding,
                    AudioRecord.getMinBufferSize(sampleRate, channel,encoding));
                    Log.i("recorder", "recorder object created");

            try {
                 os = new FileOutputStream(file);
                 bos = new BufferedOutputStream(os);            
                 dos = new DataOutputStream(bos);
            } catch (Exception e1) {

                e1.printStackTrace();
            }


            int bufferSize = AudioRecord.getMinBufferSize(sampleRate,channel,encoding);
            byte[] buffer = new byte[bufferSize];

            recorder.startRecording();
            isRecording = true;

        try{  

        while (isRecording){



                 result = recorder.read(buffer, 0, bufferSize);
                 for(int a=0; a<result;a++){
                    dos.write(buffer[a]);

                    if(!isRecording){
                        recorder.stop();

                        break;
                    }

                 }

            }
            dos.flush();
            dos.close();

        }catch(Exception e) {

            e.printStackTrace();
        }

    }// end of record method




         public void onClickStop(View v){
                Log.v("onClickStop", "stop clicked");

                isRecording=false;


            }   



    public void onClickReverse(View v){
        Log.v("onClickReverse", "reverse clicked");


    } 

    public void onClickRecord(View v){

        thread = new Thread(new Runnable() {


            public void run() {
                isRecording = true;
                record();
            }
        });

        thread.start();

        isRecording = false;


    }

}//end of class

这是错误。

01-30 12:27:50.434: ERROR/AndroidRuntime(2226): Uncaught handler: thread Thread-8 exiting due to uncaught exception
01-30 12:27:50.459: ERROR/AndroidRuntime(2226): android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
01-30 12:27:50.459: ERROR/AndroidRuntime(2226):     at android.view.ViewRoot.checkThread(ViewRoot.java:2706)
01-30 12:27:50.459: ERROR/AndroidRuntime(2226):     at android.view.ViewRoot.invalidateChild(ViewRoot.java:573)
01-30 12:27:50.459: ERROR/AndroidRuntime(2226):     at android.view.ViewRoot.invalidateChildInParent(ViewRoot.java:599)
01-30 12:27:50.459: ERROR/AndroidRuntime(2226):     at android.view.ViewGroup.invalidateChild(ViewGroup.java:2396)
01-30 12:27:50.459: ERROR/AndroidRuntime(2226):     at android.view.View.invalidate(View.java:4945)
01-30 12:27:50.459: ERROR/AndroidRuntime(2226):     at android.widget.TextView.checkForRelayout(TextView.java:5366)
01-30 12:27:50.459: ERROR/AndroidRuntime(2226):     at android.widget.TextView.setText(TextView.java:2684)
01-30 12:27:50.459: ERROR/AndroidRuntime(2226):     at android.widget.TextView.setText(TextView.java:2552)
01-30 12:27:50.459: ERROR/AndroidRuntime(2226):     at android.widget.TextView.setText(TextView.java:2527)
01-30 12:27:50.459: ERROR/AndroidRuntime(2226):     at com.tecmark.recorder.record(recorder.java:54)
01-30 12:27:50.459: ERROR/AndroidRuntime(2226):     at com.tecmark.recorder$1.run(recorder.java:151)
01-30 12:27:50.459: ERROR/AndroidRuntime(2226):     at java.lang.Thread.run(Thread.java:1096)

1 个答案:

答案 0 :(得分:3)

您正在findViewById()内调用record(),但在新线程的record()方法中调用它时,run()未在UI线程中运行。正如错误所说:

  

android.view.ViewRoot $ CalledFromWrongThreadException:只有创建视图层次结构的原始线程才能触及其视图

findViewById()方法中移除对text.setText()record()的来电。相反,请在创建新主题之前尝试在onClickRecord()中设置UI元素。

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    text = (TextView)findViewById(R.id.TextView01);
}
...
public void onClickRecord(View v){
    text.setText("recording");
    thread = new Thread(new Runnable() {
        public void run() {
            isRecording = true;
            record();
        }
    });
    thread.start();
    isRecording = false;
}