Display timer while video recording android

2019-04-16 05:33发布

问题:

I am making a video recorder and i want to have the time duration of how much time did the user have recorder the video. The time will counts upwards.

in order to calculate the time, im using thread and the calculation start when the user click the start button and it will stop when the user click the stop button.

for the timer thread im referring the tutorial from here. however my problem here is the timer is not working and i think the thread is not doing its job. below is my logcat.

Here's my code for the main activity

public class Videotest1Activity extends Activity implements 
    SurfaceHolder.Callback, OnInfoListener, OnErrorListener{

    Camera camera;
    VideoView videoView;
    SurfaceHolder holder;
    TextView msg;
    Button initBtn, startBtn, stopBtn, playBtn, stprevBtn;
    MediaRecorder recorder;

    String outputFileName;
    static final String TAG = "RecordVideo";
    int maxDuration = 7000;//7sec
    int frameRate = 1;//15

String serverIP = "172.19.117.12";
int serverPort = 2000;
Socket socket;

int mCount;
TimerThread mTimer;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_videotest1);

    videoView = (VideoView) findViewById(R.id.videoView1);
    initBtn = (Button) findViewById(R.id.initialize);
    startBtn = (Button) findViewById(R.id.button1);
    stopBtn = (Button) findViewById(R.id.button3);
    msg = (TextView) findViewById(R.id.textView1);
    playBtn = (Button) findViewById(R.id.reviewBtn);
    stprevBtn = (Button) findViewById(R.id.stprevBtn);

    mTimer= new TimerThread();
    mTimer.setOnAlarmListener(mSTimer_OnAlarm);
    mTimer.setPeriod(100);
}

public void buttonTapped(View view){
    switch(view.getId()){
    case R.id.initialize:
        initRecorder();
        break;
    case R.id.button1:
        beginRecording();
        break;
    case R.id.button3:
        stopRecording();
        break;
    case R.id.reviewBtn:
        playRecording();
        break;
    case R.id.stprevBtn:
        stopPlayback();
        break;
    }
}

@Override
public void onError(MediaRecorder mr, int what, int extra) {
    Log.e(TAG, "Record error");
    stopRecording();
    Toast.makeText(this, "Recording limit reached", 2500).show();
}

@Override
public void onInfo(MediaRecorder mr, int what, int extra) {
    Log.i(TAG, "recording event");
    if(what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED){
        Log.i(TAG, "...max duration reached");
        stopRecording();
        Toast.makeText(this, "Recording limit info", 2500).show();
    }
}

@Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {

}

@Override
public void surfaceCreated(SurfaceHolder arg0) {
    Log.v(TAG, "in surfaceCreated");

    try{
        camera.setPreviewDisplay(holder);
        camera.startPreview();
    }catch(IOException e){
        Log.v(TAG, "Could not start the preview");
        e.printStackTrace();
    }
    initBtn.setEnabled(true);
    startBtn.setEnabled(true);
    stopBtn.setEnabled(true);
}

@Override
public void surfaceDestroyed(SurfaceHolder arg0) {

}

protected void onResume(){
    Log.v(TAG, "in onResume");
    super.onResume();
    initBtn.setEnabled(false);
    startBtn.setEnabled(false);
    stopBtn.setEnabled(false);
    playBtn.setEnabled(false);
    stprevBtn.setEnabled(false);
    if(!initCamera())
        finish();
}

public boolean initCamera(){
    try{
        camera = Camera.open();
        Camera.Parameters camParam = camera.getParameters();
        camera.lock();
        holder = videoView.getHolder();
        holder.addCallback(this);
        holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        //Thread thread = new Thread(new hantarThread());
        //thread.start();
    }catch(RuntimeException re){
        Log.v(TAG, "Could not initialize the camera");
        re.printStackTrace();
        return false;
    }
    return true;
}

public void initRecorder(){
    if(recorder == null){
        Toast.makeText(this, "record null", 2500).show();           
    }
    else{
        Toast.makeText(this, "record have", 2500).show();
    }
    outputFileName = Environment.getExternalStorageDirectory() + "/videooutput.mp4";

    File outputFile = new File(outputFileName);
    if(outputFile.exists())
        outputFile.delete();//knp nk dlt?

    try{
        camera.stopPreview();
        camera.unlock();
        recorder = new MediaRecorder();
        recorder.setCamera(camera);

        recorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
        recorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
        recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
        recorder.setVideoSize(176, 144);
        recorder.setVideoFrameRate(frameRate);//15
        recorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);
        recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
        recorder.setMaxDuration(maxDuration);
        recorder.setPreviewDisplay(holder.getSurface());
        recorder.setOutputFile(outputFileName);

        recorder.prepare();
        Log.v(TAG, "MediaRecorder initialized");
        initBtn.setEnabled(false);
        startBtn.setEnabled(true);
    }catch(Exception e){
        Log.v(TAG, "MediaRecorder failed");
        e.printStackTrace();
    }
}

public void beginRecording(){
    mCount = 0;
    mTimer.start();

    recorder.setOnInfoListener(this);
    recorder.setOnErrorListener(this);
    recorder.start();               

    msg.setText("Recording");
    startBtn.setEnabled(false);
    stopBtn.setEnabled(true);
}

public void stopRecording(){
    if(recorder != null){
        recorder.setOnErrorListener(null);
        recorder.setOnInfoListener(null);
        try{
            recorder.stop();        
            mTimer.stop();
        }catch(IllegalStateException e){
            Log.e(TAG, "Got Illegal");
        }
        releaseRecorder();
        msg.setText("");
        releaseCamera();
        startBtn.setEnabled(false);
        stopBtn.setEnabled(false);
        playBtn.setEnabled(true);
    }
}

private void releaseCamera(){
    if(camera != null){
        try{
            camera.reconnect();
        }catch(IOException e){
            e.printStackTrace();
        }
        camera.release();
        camera = null;
    }
}

private void releaseRecorder(){
    if(recorder != null){
        recorder.release();
        recorder = null;
    }
}

private void playRecording(){
    MediaController mc = new MediaController(this);
    videoView.setMediaController(mc);
    videoView.setVideoPath(outputFileName);
    videoView.start();
    stprevBtn.setEnabled(true);
}

private void stopPlayback(){
    videoView.stopPlayback();
}


//----time thread---
OnAlarmListener mSTimer_OnAlarm= new OnAlarmListener() {
    @Override 
    public void OnAlarm(TimerThread source) {
        mCount++;
        msg.setText("Count="+mCount);
        if( mCount==100) source.stop();
    }
};
//----end time thread---

here is my code for TimerThread.java

  package com.example.videotest1;

import android.os.Handler;

/**
 * A class that implements a simple timer.
 * The timer does not create a separate thread, so there are no multi-threading issues in your activity.
 * The timer uses an event listener as callback when it expires ("alarm") .
 * @author Maarten Pennings 2011 September 26
 */
public class TimerThread {

    // The minimal value for the period of a timer (in milliseconds).
    public static final int MinPeriod = 10; 

    //  Interface definition for a callback to be invoked when a timer expires ("alarm").    
    public interface OnAlarmListener {
        /**
         * Callback that timer 'source' has expired ("alarm").
         * @param source  Timer that expired (when multiple timers use same listener)
         */
        void OnAlarm( TimerThread source );
    }

    protected int             mPeriod= 100;              // what is the period of the timer (in milliseconds)
    protected boolean         mEnabled= false;           // is the timer enabled?
    protected OnAlarmListener mOnAlarmListener= null;    // the listener (callback) for the alarm events
    protected Handler         mHandler= new Handler();   // handler to the thread's queue, allows us to send (timed) messages to that queue 
    protected Runnable        mMessage= new Runnable() { // The message being posted on the message queue
        @Override public void run() 
        { 
            // Call the listener (when it is set).
            if( mOnAlarmListener!=null ) mOnAlarmListener.OnAlarm(TimerThread.this);


              // Cascade, i.e. post a new delayed message to ourselves.
                // NOTE: The listener could have called stop(), this removes the mMessage message form the queue.
                // However, there is no such message, it has just

 been taken out of the queue and is currently being executed.
            // So check if the timer is still enabled before cascading (posting a new delayed message).  
            if( mEnabled ) mHandler.postDelayed(mMessage, mPeriod); 
        } 
    }; 

    /**
     * Set the period of the timer. The timer must be separately enabled before its starts generating alarm events.     
     * @param ms    the period of the timer in milliseconds
     */
    public void setPeriod( int ms ) {
        if( ms<MinPeriod ) throw new IllegalArgumentException("STimer.setPeriod called with too small period ("+ms+"<"+MinPeriod+")" );
        mPeriod= ms;
    }

    /**
     * Returns the current period of the timer.     
     * @return the current period of the timer in milliseconds
     */
    public int getPeriod( ) {
        return mPeriod;
    }

    /**
     * Enables or disables the timer for generating an alarm event every getPeriod milliseconds.     
     * @param enabled   the new state of the timer
     */
    public void setEnabled( boolean enabled ) {
        if( enabled!=mEnabled ) {
            // The enabled state really changes
            if( enabled ) {
                // Post the first message (which will post the next message and so on)
                mHandler.postDelayed(mMessage, mPeriod);  


           } else {
                // Remove any message that is in the queue
                mHandler.removeCallbacks(mMessage);
            }
            // Record the new state
            mEnabled= enabled;
        }
    }

    /**
     * Returns the current enabled/disabled state of the timer.     
     * @return the current enabled/disabled state of the timer
     */
    public boolean getEnabled() {
        return mEnabled;
    }

    /**
     * Register a callback to be invoked each time the timer period expires ("alarm").     
     * @param l   the listener object that will be called-back.
     */
    public void setOnAlarmListener( OnAlarmListener l ) {
        mOnAlarmListener= l;
    }

   // Starts the timer, i.e. a shorthand for setEnabled(true).   
    public void start( ) {
      setEnabled(true);
    }

     // Stops the timer, i.e. a shorthand for setEnabled(false).    
    public void stop( ) {
      setEnabled(false);
    }

}

and last is my OnAlarmListener.java

public class OnAlarmListener implements TimerThread.OnAlarmListener {

public void OnAlarm(TimerThread source) {
    // TODO Auto-generated method stub

}

回答1:

Consider using a CountDownTimer() ...

new CountDownTimer(1000, 1000) {

     public void onTick(long millisUntilFinished) {
         mTextField.setText("seconds remaining: " + millisUntilFinished / 1000);
     }

     public void onFinish() {
         mTextField.setText("done!");
     }
  }.start();

http://developer.android.com/reference/android/os/CountDownTimer.html