You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现App关闭后仍运行的后台Timer?附代码求正确实现

搞定App后台运行定时器的问题

嘿,我仔细看了你的代码,发现几个关键问题导致Service里的定时器没正常工作,咱们一步步把它修好:

1. 别用静态变量传参数,太不靠谱!

你现在靠page2里的静态myVariable给Service传时长,这真的不行——Fragment销毁后(比如切后台、换页面),这个变量很可能失效或者值不对。正确姿势是用Intent带参数:

在page2的startService方法里改成这样:

public void startService(int duration) {
    Intent intent = new Intent(getActivity(), MyService.class);
    intent.putExtra("TIMER_DURATION", duration); // 把时长打包进Intent
    getActivity().startService(intent);
}

然后在MyService的onStartCommand里取参数:

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    if (intent != null) {
        int duration = intent.getIntExtra("TIMER_DURATION", 0); // 给个默认值防崩溃
        if (duration > 0) {
            setParam(duration); // 终于启动定时器了!
            Toast.makeText(this, "后台定时器已启动,时长:" + duration + "ms", Toast.LENGTH_LONG).show();
        }
    }
    return START_STICKY;
}

2. 你之前根本没在Service里启动定时器!

看你原来的onStartCommand,只是弹了个Toast,完全没调用setParam方法——这就是定时器没运行的直接原因!上面的代码已经补上了这个调用。

3. 把振动和定时器逻辑补全

首先,振动需要权限,记得在AndroidManifest.xml里加:

<uses-permission android:name="android.permission.VIBRATE" />

然后把Service里的定时器和振动逻辑改得更靠谱:

private Vibrator v;

// 定时器核心方法
public void setParam(int param) {
    CountDownTimer countDownTimer = new CountDownTimer(param, 1000) {
        @Override
        public void onTick(long millisUntilFinished) {
            // 要是想给前台Fragment更改进度,得用广播或者EventBus,Service不能直接碰UI
            // 后台计时的话,这里留空或者打个日志就行
        }

        @Override
        public void onFinish() {
            // 倒计时结束,震起来!
            triggerVibration();
            // 任务完成,自己停掉Service
            stopSelf();
        }
    };
    countDownTimer.start();
}

// 振动实现
private void triggerVibration() {
    long[] pattern = {50, 1000, 500, 1000, 500, 1000, 500, 1000, 500, 1000, 500, 1000, 500, 1000, 500, 1000, 500, 1000};
    v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
    if (v != null) {
        v.vibrate(pattern, -1);
        Toast.makeText(this, "倒计时结束啦!", Toast.LENGTH_LONG).show();
    }
}

4. 应对系统杀后台的情况

Android系统资源紧张时,后台Service很容易被干掉。想让定时器尽量活下去,可以做这两点:

  • 你已经用了START_STICKY,这个不错,Service被杀死后系统会尝试重启,但重启时Intent会是null,所以咱们的代码里加了判空处理
  • Android 8.0及以上对后台Service限制很严,建议把Service改成前台Service,启动时弹个通知:

在MyService里加前台通知的代码(记得准备个通知图标):

private static final int NOTIFICATION_ID = 1001;

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    // ... 前面的参数获取和定时器启动代码 ...

    // 前台Service通知(Android 8.0+必须)
    NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "TIMER_CHANNEL")
            .setContentTitle("后台定时器")
            .setContentText("正在倒计时中...")
            .setSmallIcon(R.drawable.ic_timer_notification); // 换成你的图标资源

    // Android 8.0+需要创建通知渠道
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        NotificationChannel channel = new NotificationChannel("TIMER_CHANNEL", "定时器通知", NotificationManager.IMPORTANCE_LOW);
        NotificationManager manager = getSystemService(NotificationManager.class);
        if (manager != null) {
            manager.createNotificationChannel(channel);
        }
    }

    startForeground(NOTIFICATION_ID, builder.build());

    return START_STICKY;
}

最后,清理Fragment里的冗余代码

你在page2里也写了一个CountDownTimer,这会导致前台后台同时跑两个定时器,建议把Fragment里的setParam方法删掉,只保留启动Service的逻辑,所有计时都交给Service处理。

这样改完之后,就算把App关掉(不是强制杀死进程),Service里的定时器也会继续跑,到点就振动提醒啦!

内容的提问来源于stack exchange,提问作者jnrx gaming

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:15:13