Android 谨慎使用Timer定时器

来源:互联网 发布:ubuntu搭建php7 编辑:程序博客网 时间:2024/05/09 20:13
在Android应用开发过程中,设置完Timer后,在Timer消息还没有到来之前,跳到设置里面把时间或者日期往前设置,会发现Timer永远来不了了。
经过源码分析发现:Timer是以系统时间System.currentTimeMillis()(从January 1, 1970 00:00:00算起)为基准,当我们设置了Timer之后,相当于系统会在System.currentTimeMillis()+delayLen (delayLen:Timer多久会来消息)之后给我们发Timer消息。而设置了时间和日期,System.currentTimeMillis()就会改变。从而造成System.currentTimeMillis()+delayLen 已经过时了,这样Timer再了来不了了。

同理把时间或日期向后设置会造成过很久时间才会来Timer消息。因此在用到定时器功能能要谨慎使用Timer,最好用ScheduledExecutorService来实现。

Android4.4源码中的录音文件中,采用获取当前时间来显示已录音的时间,测试发现,修改系统时间后,录音时间的显示就全乱了,(真是佩服咱公司的测试,这都能发现)。

Android中的SystemClock类之前不知道还有这个类,涨见识了。

修改后的核心代码如下:

</pre><pre name="code" class="java">
public class Recorder implements OnCompletionListener, OnErrorListener {            private ScheduledExecutorService service = Executors.newScheduledThreadPool(1);;    private TimerTask mTimerTask;    private ScheduledFuture mScheduled;        long mSampleStart = 0;       // time at which latest record or play operation started    int mSampleLength = 0;      // length of current sample    File mSampleFile = null;    int mSamplePlayLength = 0;    MediaRecorder mRecorder = null;    MediaPlayer mPlayer = null;    public Recorder() {    }    public int progress() {        if (mState == RECORDING_STATE) {            return mSampleLength;        } else if (mState == PLAYING_STATE) {           return mSamplePlayLength;        }        return 0;    }    public int sampleLength() {        return mSampleLength ;    }    public String getStartRecordingTime() {        return mTime;    }    /**     * Resets the recorder state. If a sample was recorded, the file is deleted.     */    public void delete() {        stop();        if (mSampleFile != null)            mSampleFile.delete();        mSampleFile = null;        mSampleLength = 0;        signalStateChanged(IDLE_STATE);    }    /**     * Resets the recorder state. If a sample was recorded, the file is left on disk and will     * be reused for a new recording.     */    public void clear() {        stop();        mSampleFile = null;        mSampleLength = 0;        signalStateChanged(IDLE_STATE);    }    public void startRecording(int outputfileformat, String extension,                   Context context, int audiosourcetype, int codectype) {        stop();        if (mSampleFile != null) {            delete();        }        File sampleDir = new File(mStoragePath);        if (!sampleDir.exists()) {            sampleDir.mkdirs();        }        if (!sampleDir.canWrite()) // Workaround for broken sdcard support on the device.            sampleDir = new File("/sdcard/sdcard");        try {            SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DATE_FORMAT);            String time = simpleDateFormat.format(new Date(System.currentTimeMillis()));            mTime = time;            if (extension == null) {                extension = ".tmp";            }            StringBuilder stringBuilder = new StringBuilder();            stringBuilder.append(SAMPLE_PREFIX).append(time).append(extension);            String name = stringBuilder.toString();            mSampleFile = new File(sampleDir, name);            if (!mSampleFile.createNewFile()) {                mSampleFile = File.createTempFile(SAMPLE_PREFIX, extension, sampleDir);            }        } catch (IOException e) {            setError(SDCARD_ACCESS_ERROR);            return;        }        mRecorder = new MediaRecorder();        mRecorder.setAudioSource(audiosourcetype);        //set channel for surround sound recording.        if (mChannels > 0) {            mRecorder.setAudioChannels(mChannels);        }        if (mSamplingRate > 0) {            mRecorder.setAudioSamplingRate(mSamplingRate);        }        mRecorder.setOutputFormat(outputfileformat);        try {            mRecorder.setAudioEncoder(codectype);        } catch(RuntimeException exception) {            stopTimer();            setError(UNSUPPORTED_FORMAT);            mRecorder.reset();            mRecorder.release();            if (mSampleFile != null) mSampleFile.delete();            mSampleFile = null;            mSampleLength = 0;            mRecorder = null;            return;        }        mRecorder.setOutputFile(mSampleFile.getAbsolutePath());        // Handle IOException        try {            mRecorder.prepare();        } catch(IOException exception) {            stopTimer();            setError(INTERNAL_ERROR);            mRecorder.reset();            mRecorder.release();            if (mSampleFile != null) mSampleFile.delete();            mSampleFile = null;            mSampleLength = 0;            mRecorder = null;            return;        }        // Handle RuntimeException if the recording couldn't start        Log.e(TAG,"audiosourcetype " +audiosourcetype);        try {            mRecorder.start();        } catch (RuntimeException exception) {            stopTimer();            AudioManager audioMngr = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);            boolean isInCall = ((audioMngr.getMode() == AudioManager.MODE_IN_CALL) ||                    (audioMngr.getMode() == AudioManager.MODE_IN_COMMUNICATION));            if (isInCall) {                setError(IN_CALL_RECORD_ERROR);            } else {                Intent intent = new Intent("android.intent.soundrecorder.ACTION_RECORDER_CAPTURE");                context.sendBroadcast(intent);            }            mRecorder.reset();            mRecorder.release();            if (mSampleFile != null) mSampleFile.delete();            mSampleFile = null;            mSampleLength = 0;            mRecorder = null;            return;        }        startTimer(true);        //mSampleStart = System.currentTimeMillis();        setState(RECORDING_STATE);    }    public void pauseRecording() {        if (mRecorder == null) {            return;        }        try {            mRecorder.pause();        } catch (RuntimeException exception) {            stopTimer();            setError(INTERNAL_ERROR);            Log.e(TAG, "Pause Failed");        }        stopTimer();        //mSampleLength = mSampleLength + (System.currentTimeMillis() - mSampleStart);        setState(PAUSE_STATE);    }    public void resumeRecording() {        if (mRecorder == null) {            return;        }        try {            mRecorder.start();        } catch (RuntimeException exception) {            setError(INTERNAL_ERROR);            Log.e(TAG, "Resume Failed");        }        startTimer(true);        //mSampleStart = System.currentTimeMillis();        setState(RECORDING_STATE);    }    public void stopRecording() {        if (mRecorder == null)            return;        try {            mRecorder.stop();        }catch (RuntimeException exception){            setError(INTERNAL_ERROR);            Log.e(TAG, "Stop Failed");        }        mRecorder.reset();        mRecorder.release();        mRecorder = null;        mChannels = 0;//        if (mState == RECORDING_STATE) {//            mSampleLength = mSampleLength + (System.currentTimeMillis() - mSampleStart);//        }        stopTimer();        setState(IDLE_STATE);    }    public void startPlayback() {        stop();        mSamplePlayLength = 0;        mPlayer = new MediaPlayer();        try {            mPlayer.setDataSource(mSampleFile.getAbsolutePath());            mPlayer.setOnCompletionListener(this);            mPlayer.setOnErrorListener(this);            mPlayer.prepare();            mPlayer.start();        } catch (IllegalArgumentException e) {            setError(INTERNAL_ERROR);            mPlayer = null;            return;        } catch (IOException e) {            setError(SDCARD_ACCESS_ERROR);            mPlayer = null;            return;        }        //mSampleStart = System.currentTimeMillis();        startTimer(false);        setState(PLAYING_STATE);    }    public void stopPlayback() {        mSamplePlayLength = 0;        if (mPlayer == null) // we were not in playback            return;        mPlayer.stop();        mPlayer.release();        mPlayer = null;        stopTimer();        setState(IDLE_STATE);    }    public void stop() {        stopRecording();        stopPlayback();    }    public boolean onError(MediaPlayer mp, int what, int extra) {        stop();        setError(SDCARD_ACCESS_ERROR);        return true;    }    public void onCompletion(MediaPlayer mp) {        stop();    }    private void setState(int state) {        if (state == mState)            return;        mState = state;        signalStateChanged(mState);    }    private void signalStateChanged(int state) {        if (mOnStateChangedListener != null)            mOnStateChangedListener.onStateChanged(state);    }    private void setError(int error) {        if (mOnStateChangedListener != null)            mOnStateChangedListener.onError(error);    }    public void setStoragePath(String path) {        mStoragePath = path;    }    /***     *      * @param flag if flag is true,it will record the file length, or it will     *             record the length the recorder file already played.      */    private void startTimer(final boolean flag) {        if (mTimerTask == null) {            mTimerTask = new TimerTask() {                @Override                public void run() {                    if (flag) {                        mSampleLength++;                    } else {                        mSamplePlayLength++;                    }                }            };        }        if (service != null && mTimerTask != null)            mScheduled = service.scheduleAtFixedRate(mTimerTask,0,1,TimeUnit.SECONDS);    }    private void stopTimer() {        if (mScheduled != null) {            mScheduled.cancel(true);            mScheduled = null;        }        if (mTimerTask != null) {            mTimerTask.cancel();            mTimerTask = null;        }    }}


0 0
原创粉丝点击