android - 同时运行多个定时器并保持定时器运行,即使用户已经关闭了android上的应用程序
问题描述
我需要同时启动多个计时器,并且在关闭应用程序后它们应该继续工作。为了继续计时器,我编写了一个服务,但如果应用程序被终止,它只会重新启动一个计时器。另外,重新启动应用程序后mCountDownTimer.cancel()
不起作用
服务代码
public class MyService extends Service {
IBinder mBinder = new LocalBinder();
MyCountDownTimer myCountDownTimer = new MyCountDownTimer();
public class LocalBinder extends Binder {
public BroadcastService getServerInstance() {
return BroadcastService.this;
}
}
private static final String CHANNEL_ID = "Timer" ;
@Override
public void onCreate() {
super.onCreate();
myCountDownTimer.onCreate();
}
@Override
public IBinder onBind(Intent intent) {
createNotificationChannel();
myCountDownTimer.onBind(intent);
return mBinder;
}
public void startTimer(Integer leftTime, String id) {
myCountDownTimer.startTimer(leftTime, id);
}
public void pauseTimer(String id) {
myCountDownTimer.pauseTimer(id);
}
public void resumeTimer(String id) {
myCountDownTimer.resumeTimer(id);
}
public void resetTimer(Integer timeLeft, String id) {
myCountDownTimer.resetTimer(timeLeft, id);
}
private void createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
int importance = NotificationManager.IMPORTANCE_DEFAULT;
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, "Timer", importance);
channel.setDescription("Notification channel for timers");
NotificationManager notificationManager = getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel);
}
}
}
myCountDownTimer
class MyCountDownTimer {
SharedPreferences pref;
SharedPreferences.Editor editor;
NotificationCompat.Builder builder = null;
NotificationManagerCompat notificationManagerCompat;
private static final String CHANNEL_ID = "Timer" ;
private int notificationId = 1;
private CountDownTimer mCountDownTimer;
private String mTimerId;
private long mTimeLeftInMillis;
private enum timerStatus { RUNNING, PAUSED, FINISHED, INITED }
private timerStatus mTimerRunning = timerStatus.INITED;
private static String TIMER_STATUS = "timerStatus";
private static String TIMER_ID = "timerId";
private static String TIMER_LEFT_TIME = "timerLeftTimer";
public void onCreate() {
notificationManagerCompat = NotificationManagerCompat.from(getApplicationContext());
pref = getApplicationContext().getSharedPreferences("MyPref", 0);
editor = pref.edit();
String timerIdFromStorage = pref.getString(TIMER_ID, "we");
Integer timerLeftFromStorage = pref.getInt(TIMER_LEFT_TIME, 0);
String timerStatusFromStorage = pref.getString(TIMER_STATUS, "INITED");
if(timerIdFromStorage != ""){
mTimerId = timerIdFromStorage;
}
if(timerLeftFromStorage > 0) {
mTimeLeftInMillis = timerLeftFromStorage;
if(timerStatusFromStorage.equals("RUNNING")){
startTimer((int) mTimeLeftInMillis, timerIdFromStorage);
}
}
}
public void onBind(Intent intent) {
Integer timeLeft = intent.getIntExtra("TIMER_TIME", 0);
String timerId = intent.getStringExtra("TIMER_ID");
Integer timerLeftFromStorage = pref.getInt(TIMER_LEFT_TIME, 0);
mTimerId = timerId;
if(timerLeftFromStorage <= 0) {
mTimeLeftInMillis = timeLeft;
}
updateCountDownText();
}
public void startTimer(Integer leftTime, String id) {
if (!id.equals(mTimerId)) {
mCountDownTimer.cancel();
mTimerRunning = timerStatus.INITED;
mTimerId = id;
mTimeLeftInMillis = leftTime;
}
runTimer();
}
public void pauseTimer(String id) {
if(id.equals(mTimerId)){
mCountDownTimer.cancel();
mTimerRunning = timerStatus.PAUSED;
updateCountDownText();
}
}
public void resumeTimer(String id) {
if(id.equals(mTimerId)){
startTimer((int) mTimeLeftInMillis,id);
}
}
public void resetTimer(Integer timeLeft, String id) {
if(id.equals(mTimerId)){
mTimeLeftInMillis = timeLeft;
updateCountDownText();
}
}
private void runTimer() {
mCountDownTimer = new CountDownTimer(mTimeLeftInMillis, 1000) {
@Override
public void onTick(long millisUntilFinished) {
mTimeLeftInMillis = millisUntilFinished;
updateCountDownText();
}
@Override
public void onFinish() {
mTimerRunning = timerStatus.FINISHED;
editor.putString(TIMER_STATUS, String.valueOf(timerStatus.FINISHED));
editor.apply();
}
}.start();
mTimerRunning = timerStatus.RUNNING;
Intent notificationIntent = new Intent(getApplicationContext(), MainActivity.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), 0, notificationIntent, 0);
builder = new NotificationCompat.Builder(getApplicationContext(), CHANNEL_ID)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("Timer")
.setContentText("...")
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setContentIntent(pendingIntent);
notificationManagerCompat.notify(notificationId, builder.build());
}
private void updateCountDownText() {
int minutes = (int) (mTimeLeftInMillis / 1000) / 60;
int seconds = (int) (mTimeLeftInMillis / 1000) % 60;
String timeLeftFormatted = String.format(Locale.getDefault(), "%02d:%02d", minutes, seconds);
editor.putString(TIMER_ID, mTimerId);
editor.putString(TIMER_STATUS, mTimerRunning.toString());
editor.putInt(TIMER_LEFT_TIME, (int) mTimeLeftInMillis);
editor.apply();
Intent intent_ = new Intent(getApplicationContext(), ExecutableTask.class);
intent_.putExtra("TIME_LEFT", String.valueOf(mTimeLeftInMillis));
intent_.putExtra("TIMER_STATUS", mTimerRunning.toString());
intent_.putExtra("TIMER_ID", mTimerId);
getApplicationContext().sendBroadcast(intent_);
if(builder != null) {
builder.setContentText(timeLeftFormatted);
notificationManagerCompat.notify(notificationId, builder.build());
}
}
}
解决方案
推荐阅读
- java - 弹簧靴 2 倍。休息api。将失败的字符串转换为日期
- javascript - 如何在数组中设置推送对象的属性?
- python - 使用 python-docx + python-docx-template 创建的 Word .docx 导致错误
- ios - QLPreviewController 中的注解
- ios - addPeriodicTimeObserver 保留 AVPlayer 实例
- vba - 如何处理手动选择的电子邮件?
- lua - 如何使用lua删除所有redis键
- php - Laravel Botman:无法获取 Facebook Messenger 用户
- java - 使用 Spring Boot 从 http 链接获取值
- node.js - Node-SOAP-Server 未返回预期结果