Reputation: 7574
i'm trying to record an audio sample with AudioRecord. I've used a thread to carry out the recording method. there seems to be a prob with the thread. any ideas why?
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
here's the error.
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)
Upvotes: 1
Views: 3013
Reputation: 10908
You are calling findViewById()
within record()
, but record()
is not running in the UI thread as you call it within the run()
method of your new thread. As the error says:
android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views
Remove the call to findViewById()
and text.setText()
from your record()
method. Instead, try setting your UI elements in onClickRecord()
before you create the new thread.
@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;
}
Upvotes: 3