1

I'm building an Android application that records sound when a certain activity is opened. I've separated the recording functions in a service class. I've been using the answer from this question and it works. I do however have some trouble stopping the timer again!

ArrayList<Double> decibelList = new ArrayList<>();
private MediaRecorder mRecorder = null;
Timer timer = new Timer();
RecorderTask recorderTask;

public void startRecorder() {
    mRecorder = new MediaRecorder();
    mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
    mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
    mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
    timer = new Timer();
    recorderTask = new RecorderTask(mRecorder);
    timer.scheduleAtFixedRate(recorderTask, 0, 400);
    mRecorder.setOutputFile("/dev/null");

    try {
        System.out.println("--MediaRecorder started--");
        mRecorder.prepare();
        mRecorder.start();
    } catch(IllegalStateException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

private class RecorderTask extends TimerTask {
    private MediaRecorder recorder;

    public RecorderTask(MediaRecorder recorder) {
        this.recorder = recorder;
    }

    public void run() {
        mActivity.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                int amplitude = recorder.getMaxAmplitude();
                double amplitudeDb = 20 * Math.log10((double) Math.abs(amplitude));
                if (!String.valueOf(amplitudeDb).equals("-Infinity")) {
                    decibelList.add(amplitudeDb);
                }
                System.out.println("Current dB: " + amplitudeDb);
            }
        });
    }
}

public void stopRecorder() {
    if (mRecorder != null) {
        if (timer != null) {
            timer.cancel();
            timer.purge();
            timer = null;
        }
        try {
            mRecorder.stop();
            mRecorder.release();
            mRecorder = null;
        } catch (RuntimeException stopException){}
    }
}

The stopRecorder function is then executed in my onBackPressed, onPause, and onStop in my activity.

As you can see, I've tried stopping it through timer.cancel(); but it continues to run despite closing down the activity.

Community
  • 1
  • 1
  • 2
    The cancel function does not affect a running task. "If there is a currently running task it is not affected" http://developer.android.com/reference/java/util/Timer.html – Enpi Apr 04 '16 at 09:05
  • 1
    also from javaDocs `If the task is running when this call occurs, the task will run to completion, but will never run again` https://docs.oracle.com/javase/7/docs/api/java/util/TimerTask.html#cancel() – Yazan Apr 04 '16 at 09:08
  • @Enpi Right. Do you have a suggestion on how I stop my timer then? I can't seem to find a function to do so in your link. – Tobias Ettrup Mølbak Apr 04 '16 at 09:30

1 Answers1

1

Solved my problem.

It turned out my cancel actually worked, but I had accidentally started two timers! I solved the problem by adding a check if my timer was null.

public void startRecorder() {
    mRecorder = new MediaRecorder();
    mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
    mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
    mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
    mRecorder.setAudioEncodingBitRate(16);
    mRecorder.setAudioSamplingRate(44100);
    if (timer == null) {
        timer = new Timer();
        recorderTask = new RecorderTask(mRecorder);
        timer.scheduleAtFixedRate(recorderTask, 0, 400);
    }
    mRecorder.setOutputFile("/dev/null");

    try {
        System.out.println("--MediaRecorder started--");
        mRecorder.prepare();
        mRecorder.start();
    } catch (IllegalStateException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

Just in case anyone wants to use the code.

Thanks a lot for the comments! They helped me optimise my code.