0

I made a code which allow me to record the audio from the microphone. Strange thing is that when I click my button it appears to have some kind of lag, the button remains visually pressed for half a second and then starts it method. is there a reason for this, and how could I solve this?

What I am having right now:

private void onRecord(boolean start) {
        if (start) {
            startRecording();
        } else {
            stopRecording();
        }
    }

private void startRecording() {
        mRecorder = new MediaRecorder();
        mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
        mRecorder.setOutputFile(mFileName);
        mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);

        try {
            mRecorder.prepare();
        } catch (IOException e) {
            Log.e(LOG_TAG, "prepare() failed");
        }

        mRecorder.start();
    }

    private void stopRecording() {
        mRecorder.stop();
        mRecorder.release();
        mRecorder = null;
    }
public void onClick(View v) {

        switch (v.getId()) {
case R.id.bRecord:

            if (mStartRecording) {
                mRecordButton.setText("Stop Recording");
                onRecord(true);
                mStartRecording = false;

            } else {
                mRecordButton.setText("Start Recording");
                mStartRecording = true;
                onRecord(false);

            }

            break;
}

EDIT Thanks for the help, I decided to work with a service but am struggling a little bit. I created:

public class RecordService extends IntentService {

    private MediaRecorder mRecorder = null;
    private String mFileName;
    private static final String LOG_TAG = "RecordService";

    public RecordService() {
        super("RecordService");
        // TODO Auto-generated constructor stub
    }

    @Override
    protected void onHandleIntent(Intent intent) {

        mFileName = Environment.getExternalStorageDirectory().getAbsolutePath();
        mFileName += "/audiorecordtest.3gp";

        mRecorder = new MediaRecorder();
        mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
        mRecorder.setOutputFile(mFileName);
        mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);

        try {
            mRecorder.prepare();
        } catch (IOException e) {
            Log.e(LOG_TAG, "prepare() failed");
        }

        mRecorder.start();

    }
}

and

case R.id.bRecord:

            if (mStartRecording) {
                mRecordButton.setText("Stop Recording");
                //onRecord(true);
                Intent service = new Intent(myContext, RecordService.class);
                myContext.startService(service); 
                mStartRecording = false;

            } else {
                mRecordButton.setText("Start Recording");
                mStartRecording = true;
                onRecord(false);

            }

            break;

Having a question about this, how can I now stop this service (= stop recording) (by clicking f.e. the button again) and communicate an idea back to the activity? I tried to add a stop function in the service but it is not seem to work when I call service.stop() to stop it..

Matthias Vanb
  • 923
  • 5
  • 14
  • 32

2 Answers2

3

My guess is that since you're starting the recording in the same thread as the UI, the UI doesn't respond until all the code in startRecording() has finished executing. You might want to consider calling onRecord in its own thread.

Anand
  • 7,654
  • 9
  • 46
  • 60
1
  • You could use AsyncTask for short Operations (a few seconds at the most.)
  • Use Service for long running Operations

Attention: AsyncTask takes care of the thread handling for you. If you write a Service, you have to spawn your own thread otherwise it will run on the UI thread.

One of several ways to do it:

Service:

@Override       
protected void onHandleIntent(Intent intent) {

    //your recorder code

    //get the messenger from intent
    Bundle extras = intent.getExtras();
    if (extras != null) {
       Messenger messenger = (Messenger) extras.get("MESSENGER");
       try {
          //send a message back to the activity
          messenger.send(...);
       } catch (android.os.RemoteException e1) {
          Log.w(getClass().getName(), "Exception sending message", e1);
       }
    }
}

Activity:

Definition of the handler

private Handler handler = new Handler() {
    public void handleMessage(Message message) {
      //do something with the message from the service 
    };
};

The code to start the service

Intent intent = new Intent(this, YourService.class);
Messenger messenger = new Messenger(handler);
intent.putExtra("MESSENGER", messenger);
startService(intent);
faceman
  • 1,318
  • 11
  • 20
  • Thanks, never used this but I will quickly read it and try it, will get back to let you know if I solved it! – Matthias Vanb Mar 05 '13 at 08:15
  • 2
    @MatthiasVanb As the [document](http://developer.android.com/reference/android/os/AsyncTask.html) says: *AsyncTasks should ideally be used for short operations (a few seconds at the most.)* I think you need a [`Service`](http://developer.android.com/reference/android/app/Service.html). –  Mar 05 '13 at 08:18
  • Mm, ok. I am a beginner so now it's really difficult for me to know which one is best :D But The recording itself can be of course longer than a few seconds.. it will be most of the time... – Matthias Vanb Mar 05 '13 at 08:26
  • Ok, I'll try it out and come back here :) – Matthias Vanb Mar 05 '13 at 08:28
  • I read about services and set up one, but I am struggling a bit with stopping the service and send back an idea. I updated my original question, maybe you know how I can handle the stop/send id back? – Matthias Vanb Mar 05 '13 at 09:55
  • @LaiVung you have any idea maybe? – Matthias Vanb Mar 05 '13 at 11:29
  • There are several questions on SO about how to communicate with a service: such as [Ways to communicate with a service](http://stackoverflow.com/a/2463746/1108036), another way is the use a broadcast [Send/Receive Broadcast](http://stackoverflow.com/a/4739898/1108036) – faceman Mar 05 '13 at 11:43
  • @MatthiasVanb There are several service examples in `[Android SDK]/samples`. I hope they would be useful for you. And all information which @faceman provided are useful too. –  Mar 05 '13 at 12:46
  • Thanks to both of you very much, really! Just one question, I tried to stop the service (=stop recording) by calling myContext.stopService(service); I also handled in the OnDestroy method of the service the correct things (=mRecorder.stop(); mRecorder.release(); mRecorder = null; super.onDestroy();). But I doubt if this is the correct way since it is not working (crash) – Matthias Vanb Mar 05 '13 at 12:59
  • 1
    @MatthiasVanb I hope [`Log`](http://developer.android.com/tools/debugging/debugging-log.html) can help you debug the code. If you couldn't solve it, feel free to post new question with details. If I can help, I will do. :-) –  Mar 06 '13 at 00:34
  • Ok, I'll be searching for myself first, i'll get back if I really can't get it fixed, or if I do of course @LaiVung – Matthias Vanb Mar 06 '13 at 07:33
  • @LaiVung I have to rebuild it transforming the IntentService to a Service. Once I executed it I noticed it stopped automatically when the onHandleIntent is processed, and so it stops recording... :s Or am i Wrong? I start myRecorder.start(); but it stops itself even if it is still recording.. – Matthias Vanb Mar 06 '13 at 08:26
  • I rebuild it to a Service, but I get that button lag again... :s is there a way to keep my IntentService going as long as I want to record and until I really call the stopService method – Matthias Vanb Mar 06 '13 at 08:40
  • 1
    @MatthiasVanb You're right with the `IntentService`, _When all requests have been handled, the IntentService stops itself_. If you want to use a `Service` you have to spawn your own thread otherwise the Service runs on the UI thread. – faceman Mar 06 '13 at 09:02
  • @faceman Tnx! If I perform Thread t = new Thread(){ public void run(){ Intent intent = new Intent(getApplicationContext(), RecordService.class); Messenger messenger = new Messenger(handler); intent.putExtra("MESSENGER", messenger); startService(intent); } }; t.start(); in my activity, it still has that lag... although I start the service in its own thread... or am i wrong? – Matthias Vanb Mar 06 '13 at 09:12
  • 1
    @MatthiasVanb Please update your question with the actual problem. 1. You should spawn your thread within your `Service` and not start your Service from another thread. 2. Refer to the android reference for correct thread creation. – faceman Mar 06 '13 at 09:30
  • 1
    I used Runnable r = new Runnable() { //code here }; Thread t = new Thread(r); t.start(); both in the onStartCommand and onDestroy methods of my Service to either start or stop recording, the button lag is gone! Thank faceman and LaiVung, you prevented me from getting bald! – Matthias Vanb Mar 06 '13 at 11:03