当Android屏幕关闭时,会丢失TCP连接。

3

我的Android应用程序通过前台服务启动并保持TCP连接。活动使用StartService()来启动服务。同时,该服务在自己的进程中启动。

以下是服务的OnStartCommand

// Code is in C# using Xamarin but regular Java/Android answers are acceptable
public override StartCommandResult OnStartCommand (Intent intent, StartCommandFlags flags, int startId)
{
    base.OnStartCommand (intent, flags, startId);

    ...

    var ongoingNotification = new Notification (Resource.Drawable.icon, "Service running");
    var pendingIntent = PendingIntent.GetActivity (this, 0, new Intent (this, typeof(MainActivity)), 0);
    ongoingNotification.SetLatestEventInfo (this, "Service", "The service is running.", pendingIntent);
    StartForeground ((int)NotificationFlags.ForegroundService, ongoingNotification);
    return StartCommandResult.RedeliverIntent;
}

当手机屏幕开启时,无论我的应用程序是否打开或未打开活动,连接都很好。然而,在我关闭屏幕不到30秒后,我总是会失去TCP连接。我的应用程序会自动重新连接,因此我会恢复连接,但在屏幕关闭时它将持续断开连接。我重新打开屏幕后,它就没问题了,即使我的应用程序中没有打开任何活动。
这可能与Android生命周期有关,但我不知道原因。根据我写入手机文本文件的调试消息(当IDE的调试器附加时,问题不会发生),服务似乎正在按照预期运行,但连接却不稳定。
我还测试了开发者选项中选择“不保留活动”和不选两种情况,但结果没有改变。所以至少与Activity Lifecycle无关。
为什么Android在屏幕关闭时会丢失我的TCP连接?

你有没有获取到 WiFi 锁定?还是在使用移动设备? - 323go
测试是在wifi上完成的,但应用程序可以使用wifi或移动网络。我没有使用wifi锁定(因为在你提到它之前我不知道它)。在移动设备上进行了快速测试后,似乎移动设备和wifi出现了相同的问题。 - Jeremy K
1
此时您可以选择获取WakeLock或定期唤醒您的应用程序(通过AlarmManager),然后获取WakeLock并进行后台更新。我建议采用后者以最大化电池寿命。您唤醒的频率取决于您的应用程序需要执行多少后台传输。理想情况下,您应该让服务器发送推送通知,然后您的服务通过轮询请求做出响应。 - 323go
如果这确实是解决方案,我会尝试一下,但我感觉我必须始终在我的应用程序上保持WakeLock。由于手动保持活动状态和必需的数据发送/接收,我的服务非常频繁地发送和接收数据,因此连接最多每10-15秒就会被使用。我不明白为什么它会在连接正在使用时关闭连接。 - Jeremy K
1
为了保持电池寿命,它已关闭。在Android中,用户(和可用性)是主要关注点,而不是您的应用程序。请注意,永久唤醒锁定可能会使手机变得无用,因为它会降低电池寿命。 - 323go
1
希望永久的唤醒锁不是最终解决方案,但对于基本测试来说已经足够了,以查看它是否能正常工作。我需要进行一些测试,定期唤醒我的应用程序,并查看是否可以找到保持稳定连接的方法。 - Jeremy K
1个回答

2

我通过在服务运行时获取一个部分WakeLock来解决了这个问题。

private PowerManager.WakeLock mWakeLock;

public override void OnCreate ()
{
    PowerManager pm = (PowerManager) GetSystemService(Context.PowerService);
    mWakeLock = pm.NewWakeLock (WakeLockFlags.Partial, "PartialWakeLockTag");
    mWakeLock.Acquire();
}

public override void OnDestroy ()
{
    mWakeLock.Release();
}

如果我将来实现了更加省电的方案,我会更新这个答案。


有没有在IOS中实现相同功能的方法? - Ahmed Shamel

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