安卓:为什么屏幕锁定后服务停止了?

4
我使用一个服务,在这个服务内有一个定时器,每分钟向我的TCP/IP服务器发送一条消息。
public void keepAlive() {
        timer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                try {
                    Gson gson = new Gson();
                    String message = gson.toJson(new StillAlive(Mode.STILLALIVE));
                    sendMessage(message);
                    Log.d("TCP-SEND", message);
                } catch(Exception e) {
                    Log.e("TCP1", e.getMessage());
                }
            }
        }, 60000, 60000);
    }

但是当我的手机锁屏或者我按下关闭显示器的按钮时,我的服务就停止发送这些信息了。
我不确定的是,当关闭显示器时服务是否会停止,或者只是由于某些我不知道的原因计时器停止了。
有人知道在这种情况下计时器是否会停止吗?还是服务会停止?
感激不尽! :-)

这是为了节省电池而关闭WiFi/移动数据。在移动设备上,消耗电池的不是数据量,而是天线开启的时间。如果你确实需要每分钟从服务器检查一些东西,请使用Google Cloud Messaging。Google Cloud Messaging不会增加电池使用量,但如果您使用自己的技术,即使没有检测到任何更改,也将至少消耗总电池寿命的20%。对大多数人来说,20%已经很多了,尤其是对于一个应用程序而言。请使用Google Cloud Messaging。 - Stephan Branczyk
@StephanBranczyk:我的问题是,我需要发送这些消息告诉我的TCP服务器连接仍然存在。如果可以的话,我也可以每5分钟发送一次,但我需要在已知的时间范围内发送消息。这可能吗? - progNewbie
@StephanBranczyk 我想知道WhatsApp/Telegram等应用是如何处理这个问题的。他们是否使用Google云消息传递服务? - progNewbie
WhatsApp的常见问题解答似乎暗示他们正在使用GCM。请参阅http://www.whatsapp.com/faq/en/android/20887936:“如果上述所有步骤都没有帮助,则有可能是您未收到来自Google推送通知服务的更新,或者您的Wi-Fi或移动数据设置配置不正确。” - Stephan Branczyk
@StephanBranczyk:我看到他们自己的通知系统不需要GCM,也不会消耗太多电池电量:https://twitter.com/telegram/status/478487472750755840。所以我认为一定有办法在屏幕关闭时发送信息而不浪费电池寿命。 - progNewbie
显示剩余3条评论
2个回答

3

这是因为您的设备开始休眠。强烈建议使用其他实现方式处理此类进程:AlarmManager

它看起来像这样(这是我的代码的一部分):

private static AlarmManager am;

//....
@SuppressLint("NewApi")
public static void startByAlarm(Context ctx, boolean wakeup, long nexttime, boolean autoStart)
    {
PendingIntent pi = wakeup? PendingIntent.getBroadcast(ctx, _.intentalarm, intent, PendingIntent.FLAG_CANCEL_CURRENT):
            PendingIntent.getService(ctx, _.intentalarm, intent, PendingIntent.FLAG_CANCEL_CURRENT);
am = (AlarmManager) ctx.getSystemService(Activity.ALARM_SERVICE);
int currentapiVersion = android.os.Build.VERSION.SDK_INT;
    if (currentapiVersion >= android.os.Build.VERSION_CODES.KITKAT){
        am.setExact(wakeup?AlarmManager.RTC_WAKEUP:AlarmManager.RTC, nexttime, pi);
    } else{
        am.set(wakeup?AlarmManager.RTC_WAKEUP:AlarmManager.RTC, nexttime, pi);
    }
//or am.setRepeating ...
}

谢谢您的快速回答:这意味着是一个计时器问题吗? :-) - progNewbie
@progNewbie,我发现很多手机对于长时间进程有不同的行为。是的,你可以说这是一个计时器问题。但核心问题是“电池寿命消耗”。如果你想以100%的概率ping你的服务器,你必须使用alarm manager。此外,我不知道你的代码是否在某些部分使用了timer.stop() :) - Vyacheslav

0

看一下jscharf的这个答案,它可能对你有帮助,但你必须要警惕,因为这是一个耗电量较大的任务。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接