Timer / TimerTask 運行在普通線程,**進程進入 Doze 模式或被系統回收時會暫停**。public class TimerService extends Service {
private AlarmManager alarmManager;
private PendingIntent pendingIntent;
@Override
public void onCreate() {
super.onCreate();
alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
Intent intent = new Intent(this, TimerReceiver.class);
pendingIntent = PendingIntent.getBroadcast(this, 0, intent,
PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// 每秒觸發,ELAPSED_REALTIME_WAKEUP 會喚醒 CPU
alarmManager.setRepeating(
AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + 1000,
1000,
pendingIntent
);
return START_STICKY; // 進程被殺自動重啟
}
@Override
public void onDestroy() {
alarmManager.cancel(pendingIntent);
super.onDestroy();
}
}
// BroadcastReceiver 處理計時邏輯
public class TimerReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// 更新倒計時、發送廣播通知 UI、寫入資料庫等
// 注意:onReceive 運行在主線程,耗時操作需啟動 Service/Thread
}
}
<service android:name=".TimerService"
android:foregroundServiceType="dataSync" /> <!-- Android 14+ 前台服務類型 -->
<receiver android:name=".TimerReceiver"
android:exported="false" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" /> <!-- Android 12+ -->
PeriodicWorkRequest timerWork = new PeriodicWorkRequest.Builder(
TimerWorker.class, 15, TimeUnit.MINUTES) // 最小 15 分鐘
.setConstraints(new Constraints.Builder()
.setRequiresBatteryNotLow(true)
.build())
.build();
WorkManager.getInstance(context).enqueueUniquePeriodicWork(
"timer_work", ExistingPeriodicWorkPolicy.KEEP, timerWork);
⚠️ WorkManager **最小間隔 15 分鐘**,不適合秒級倒計時,但電池友好、系統自動調度。
Timer 不適合螢幕關閉後持續運行**。請使用 AlarmManager.ELAPSED_REALTIME_WAKEUP(秒級精確)或 WorkManager(延遲容忍、省電),並聲明 WAKE_LOCK、SCHEDULE_EXACT_ALARM 權限,配合 START_STICKY 服務實現真後台計時。