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