如何使用android中的服务组件制作倒计时器?

时间:2016-08-31 04:13:00

标签: java android

我正在尝试构建一个应用程序,其中操作栏具有倒数计时器视图。我成功了,但是,当我关闭应用程序并重新打开时,倒计时重新启动。我需要的是倒计时不应该停止,直到它完成它的时间,即使我关闭或最小化应用程序。我试过这段代码:

  final long[] timer = {2700000};
      getMenuInflater().inflate(R.menu.menu_main, menu);
      final MenuItem  counter = menu.fi`enter code here`ndItem(R.id.counter);
      new CountDownTimer(timer[0], 1000) {

        public void onTick(long millisUntilFinished) {
            long millis = millisUntilFinished;
            String  hms =  (TimeUnit.MILLISECONDS.toHours(millis))+":"+(TimeUnit.MILLISECONDS.toMinutes(millis) -TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis)))+":"+ (TimeUnit.MILLISECONDS.toSeconds(millis) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis)));

            counter.setTitle(hms);
            timer[0] = millis;

        }

        public void onFinish() {
            counter.setTitle("done!");
        }
    }.start();
    return true;

2 个答案:

答案 0 :(得分:1)

先生。 donnfelker在他的bootstrap android演示中写了倒数计时器服务。给定链接是开源Android bootstrap ,您将找到此服务类。会告诉你如何做到这一点。

public class TimerService extends Service {

@Inject protected Bus eventBus;
@Inject NotificationManager notificationManager;

private boolean timerRunning = false;
private boolean timerStarted;
private long base;
private long currentRunningTimeInMillis;
private long pausedBaseTime;
private boolean isPaused;

public static final int TICK_WHAT = 2;
private NotificationCompat.Builder b;
private String messageFormat;

@Override
public IBinder onBind(Intent intent) {
    return null;
}

@Override
public void onCreate() {
    super.onCreate();

    BootstrapApplication.component().inject(this);

    // Register the bus so we can send notifications.
    eventBus.register(this);

}

@Override
public void onDestroy() {

    // Unregister bus, since its not longer needed as the service is shutting down
    eventBus.unregister(this);

    notificationManager.cancel(TIMER_NOTIFICATION_ID);

    Timber.d("Service has been destroyed");

    super.onDestroy();
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {

    if (!timerStarted) {

        timerStarted = true;

        startTimer();

        // Run as foreground service: http://stackoverflow.com/a/3856940/5210
        // Another example: https://github.com/commonsguy/cw-android/blob/master/Notifications/FakePlayer/src/com/commonsware/android/fakeplayerfg/PlayerService.java
        startForeground(TIMER_NOTIFICATION_ID, getNotification(getString(R.string.timer_running)));
    }

    return START_NOT_STICKY;
}

@Produce
public TimerTickEvent produceTickEvent() {
    updateNotification(getTimerRunningMessage(currentRunningTimeInMillis));
    return new TimerTickEvent(currentRunningTimeInMillis);
}

@Produce
public TimerPausedEvent produceTimerIsPausedEvent() {
    return new TimerPausedEvent(isPaused);
}

@Subscribe
public void onStopEvent(StopTimerEvent stopEvent) {

    timerHandler.removeMessages(TICK_WHAT);
    stopSelf();
}

@Subscribe
public void onPauseEvent(PauseTimerEvent pauseEvent) {
    pauseTimer();
}

/**
 * Pauses the active running timer and updates the notification in the status bar.
 */
private void pauseTimer() {

    updateNotification(getString(R.string.timer_is_paused));

    timerHandler.removeMessages(TICK_WHAT);
    pausedBaseTime = SystemClock.elapsedRealtime() - base;
    timerRunning = false;
    isPaused = true;

    produceTimerIsPausedEvent();
}

@Subscribe
public void onResumeTimerEvent(ResumeTimerEvent resumeTimerEvent) {
    startTimer();
}

private void startTimer() {
    startChronoTimer();
    notifyTimerRunning();
}

private void startChronoTimer() {
    base = SystemClock.elapsedRealtime();

    // If coming from a paused state, then find our true base.
    if (pausedBaseTime > 0)
        base = base - pausedBaseTime;

    isPaused = false;

    updateRunning();
}

/**
 * Starts the generic timer.
 */
private void updateRunning() {
    if (timerStarted != timerRunning) {
        if (timerStarted) {
            dispatchTimerUpdate(SystemClock.elapsedRealtime());
            timerHandler.sendMessageDelayed(Message.obtain(timerHandler, TICK_WHAT), 1000);
        } else {
            timerHandler.removeMessages(TICK_WHAT);
        }
        timerRunning = timerStarted;
    }
}

private Handler timerHandler = new Handler() {
    public void handleMessage(Message m) {
        if (timerRunning) {
            dispatchTimerUpdate(SystemClock.elapsedRealtime());
            sendMessageDelayed(Message.obtain(this, TICK_WHAT), 1000);
        }
    }
};

private void dispatchTimerUpdate(long now) {

    currentRunningTimeInMillis = now - base;
    Timber.d("Elapsed Seconds: " + currentRunningTimeInMillis / 1000);

    eventBus.post(produceTickEvent());

}


private void notifyTimerRunning() {
    updateNotification(getTimerRunningMessage(currentRunningTimeInMillis));
    produceTimerIsPausedEvent();
}

private String getTimerRunningMessage(long millis) {
    if(Strings.isEmpty(messageFormat)) {
        messageFormat = getString(R.string.timer_running);
    }

    return String.format(messageFormat, TimeUtil.formatTime(millis));
}


private void updateNotification(String message) {
    notificationManager.notify(TIMER_NOTIFICATION_ID, getNotification(message));

}

/**
 * Creates a notification to show in the notification bar
 *
 * @param message the message to display in the notification bar
 * @return a new {@link Notification}
 */
private Notification getNotification(String message) {
    final Intent i = new Intent(this, BootstrapTimerActivity.class);

    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, i, 0);

    if(Strings.notEmpty(message)) {
        return getNotificationBuilder(message, pendingIntent)
                .setContentText(message)
                .build();
    } else {
        return getNotificationBuilder(message, pendingIntent).build();
    }
}

/**
 * Resuse the same notification builder.
 * @param message
 * @param pendingIntent
 * @return
 */
private NotificationCompat.Builder getNotificationBuilder(String message, PendingIntent pendingIntent) {
    if(b == null) {
        b = new NotificationCompat.Builder(this)
                .setContentTitle(getString(R.string.app_name))
                .setSmallIcon(R.drawable.ic_stat_ab_notification)
                .setContentText(message)
                .setAutoCancel(false)
                .setOnlyAlertOnce(true)
                .setOngoing(true)
                .setWhen(System.currentTimeMillis())
                .setContentIntent(pendingIntent);
    }
    return b;
}

}

答案 1 :(得分:0)

如果你想参加活动。请查看以下演示

<强> MainActivity:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/base"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="10dp"
    android:background="@color/white"
    android:orientation="horizontal"
    android:weightSum="10">


    <EditText
        android:id="@+id/foodName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="64dp"
        android:layout_marginRight="64dp"
        android:hint="Food name"
        android:inputType="textCapWords"
        android:textColor="@color/colorPrimaryDark"
        android:textColorHint="@color/colorPrimaryDark"
        android:textSize="32sp"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true" />

</RelativeLayout>

<强>布局:

<activity
        android:name=".activity.MainActivity"
        android:configChanges="orientation|screenSize">
</activity>

<强>清单:

default