android - 实现倒计时工作的服务

时间:2016-09-27 17:47:56

标签: android service countdown

所以我现在有一个带有CountDownTimer的代码。但是我需要把它放在服务上以便在后台运行。 我不知道怎么做,我试过没有成功。

这是我的CountDown类

public class CountDown {

//Interface a ser implementada por um listener
public interface CountDownListener {
    //Chamado quando o valor de secondsLeft é alterado,
    //quando for decrementado ou incrementado.
    void onChange(long timeLeft);
    //Chamado quando o contador chegar ao fim.
    void onEnd();
}

private long fromSeconds;
private long secondsLeft;
private CountDownListener listener;
private boolean isCounting = false;

//Valor em milissegundos de um segundo.
private static final long ONE_SECOND = 1000;
private static final int MSG = 1;

//Constrói o contador com o valor inicial de segundos.
public CountDown(long fromSeconds){

    this.fromSeconds = fromSeconds;
    handler = new CountDownHandler(this);
}

//Inicia a contagem, a partir do valor inícial.
public synchronized void start(){
    if(isCounting){
        return;//ou talvez lançar uma excepção
    }
    isCounting = true;
    secondsLeft = fromSeconds;
    handler.sendMessage(handler.obtainMessage(MSG));
}

//Pára a contagem.
public synchronized void stop(){
    if(!isCounting){
        return;//ou talvez lançar uma excepção
    }
    isCounting = false;
    handler.removeMessages(MSG);
}

//Retoma a contagem.
public synchronized void resume(){
    if(isCounting || secondsLeft == 0){
        return;//ou talvez lançar uma excepção
    }
    isCounting = true;
    handler.sendMessageDelayed(handler.obtainMessage(MSG), ONE_SECOND);
}

//Incrementa o valor do contador.
public synchronized long increaseBy(long fromSeconds){
    secondsLeft += fromSeconds;
    return secondsLeft;
}

//true se o contador estiver contando.
public boolean isCounting(){
    return isCounting;
}

//Guarda um listener.
public void setCountDownListener(CountDownListener listener){
    this.listener = listener;
}

//Método para formatar um valor em segundos em algo tipo "mm:ss" ou "HH:mm:ss".
public static String secondsToString(long seconds, String format){
    return DateFormat.format(format, seconds * ONE_SECOND).toString();
}

private final Handler handler;

//Handler para controlar o contador
private static class CountDownHandler extends Handler
{

    private final WeakReference<CountDown> countDownWeakReference;

    private CountDownHandler(CountDown countDownInstance) {
        countDownWeakReference = new WeakReference<>(countDownInstance);
    }

    @Override
    public void handleMessage(Message msg) {

        CountDown countDown = countDownWeakReference.get();
        if(countDown == null){
            return;
        }

        synchronized (countDown) {

            //Guarda o instante em que inicia o processamento.
            long tickStart = SystemClock.elapsedRealtime();

            //Se tiver sido parado sai.
            if(!countDown.isCounting){
                return;
            }

            //Notifica o listener com o segundos que faltam para terminar.
            if (countDown.listener != null) {
                countDown.listener.onChange(countDown.secondsLeft);
            }

            //O contador chegou ao fim, notifica o listener.
            if (countDown.secondsLeft == 0) {
                countDown.isCounting = false;
                if (countDown.listener != null) {
                    countDown.listener.onEnd();
                }
            } else {
                //decrementa o contador.
                countDown.secondsLeft--;

                //Obtém o tempo para o próximo decremento.
                //Leva em conta o tempo gasto no processamento,
                //principalmente o eventualmente gasto pela implementação
                // do método onChange() no listener.
                long delay = ONE_SECOND - (SystemClock.elapsedRealtime() - tickStart);

                //Se o tempo gasto for superior a um segundo, ajusta-o para o próximo.
                //Se o tempo gasto no método onChange() for próximo ou
                // superior a um segundo ele só será chamado no próximo.
                while(delay < 0){
                    countDown.secondsLeft--;
                    delay += ONE_SECOND;
                }
                //Garante o término se o tempo for excedido
                if(countDown.secondsLeft < 0){
                    countDown.listener.onEnd();
                }else {
                    //Agenda o próximo decremento.
                    sendMessageDelayed(obtainMessage(MSG), delay);
                }
            }
        }
    }
};}

第二节课

 public CountDownBehavior(long alarmTime, String displayFormat){

    //Valor em segundos no qual deve ser chamado onAlarm().
    this.alarmTime = alarmTime;
    //Formato da string passada ao displayTimeLeft().
    this.displayFormat = displayFormat;
}

@Override
public void onChange(long timeLeft) {
    //Aqui é implementado o comportamento que queremos ter enquanto
    //o CountDown "conta".

    //Deve informar quando chegar a altura de accionar o alarma.
    if(timeLeft == alarmTime)
    {
        onAlarm();
    }
    //Informa o valor actual do contador, com o formato indicado por displayFormat.
    displayTimeLeft(CountDown.secondsToString(timeLeft, displayFormat));

}

//Metodos a implementar em resposta ao comportamento.
protected abstract void onAlarm();
protected abstract void displayTimeLeft(String timeLeft);}

最重要的是来自MyActivity

   @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    textView = (TextView)findViewById(R.id.textView);

    createNotification();

    //Cria o contador com 1 minuto
    countDown = new CountDown(TIME);

    //Cria e atribui um CountDownBehavior ao contador
    countDown.setCountDownListener(new CountDownBehavior(ALARM, "mm:ss") {
        @Override
        public void onEnd() {
            mBuilder.mActions.clear();
            mBuilder.setOngoing(false);
            mBuilder.setContentText("Seu tempo acabou.");
            mNotifyMgr.notify(mNotificationId, mBuilder.build());
            //mNotifyMgr.cancel(mNotificationId);
        }

        @Override
        protected void onAlarm() {
            alarmMethodwithCount();
        }

        @Override
        protected void displayTimeLeft(String timeLeft) {
            mBuilder.setContentText(timeLeft + " restante");
            mNotifyMgr.notify(mNotificationId, mBuilder.build());
            textView.setText(timeLeft);
        }
    });

    alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
    countDown.start();
    alarmMethod();
}

1 个答案:

答案 0 :(得分:0)

根据您帖子中提供的信息,您是否考虑过使用IntentService而不是服务?这是一个很好的链接https://developer.android.com/training/run-background-service/create-service.html。您的应用程序的serviceIntent可以在计时器到期时发送广播。您的UI线程将实现广播侦听器并更新UI。