使WiFi在手机进入睡眠模式后仍保持前台服务活动状态

21

我希望在手机锁屏的情况下也能接收Wi-Fi数据包,但是问题在于当我锁定屏幕后,我的前台服务就停止接收数据包了。我是这样使用前台服务的:

public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
{
    var notification = new Notification.Builder(this)
        .SetContentTitle(Resources.GetString(Resource.String.app_name))
        .SetContentText(Resources.GetString(Resource.String.notification_text))
        .SetSmallIcon(Resource.Drawable.ic_stat_name)
        .SetContentIntent(BuildIntentToShowMainActivity())
        .SetOngoing(true)
        .AddAction(BuildRestartTimerAction())
        .AddAction(BuildStopServiceAction())
        .Build();


    // Enlist this instance of the service as a foreground service
    StartForeground(Constants.SERVICE_RUNNING_NOTIFICATION_ID, notification);

    /*DO THIS EVEN WHEN SCREEN IS LOCKED*/

    var powerManager = (PowerManager)GetSystemService(PowerService);
    _wakeLock = powerManager.NewWakeLock(WakeLockFlags.Partial, "WakeLockTag");
    _wakeLock.Acquire();

    var wifiManager = (WifiManager)GetSystemService(WifiService);
    _wifiLock = wifiManager.CreateWifiLock(WifiMode.FullHighPerf, "xamarin_wifi_lock");
    _wifiLock.Acquire();

    if (!powerManager.IsIgnoringBatteryOptimizations("com.xamarin.xample.foregroundservicedemo") ||
        !_wakeLock.IsHeld || !_wifiLock.IsHeld)
        throw new InvalidOperationException("OPTIMIZATIONS NOT ACTIVE");

    string msg = timestamper.GetFormattedTimestamp();
    Log.Debug(TAG, msg);
    Intent intent = new Intent(Constants.NOTIFICATION_BROADCAST_ACTION);
    intent.SetAction(Android.Provider.Settings.ActionIgnoreBatteryOptimizationSettings);
    intent.PutExtra(Constants.BROADCAST_MESSAGE_KEY, msg);
    LocalBroadcastManager.GetInstance(this).SendBroadcast(intent);
    Task.Run(() =>
    {
        using (var client = new UdpClient(12345))
        {
            while (true)
            {
                var result = client.ReceiveAsync().Result;
                Console.WriteLine($"RECEIVED: {result.Buffer.Length}");
            }
        }
    });

    return StartCommandResult.Sticky;
}

我正在做以下几件事情来确保它不会被杀掉

  1. 启动前台服务
  2. 使用StartCommandResult.Sticky
  3. 使用唤醒锁(Wake Lock)
  4. 使用WiFi锁
  5. 将WiFi睡眠策略设置为Never(我在手机设置中进行了设置)
  6. 在意图中设置ActionIgnoreBatteryOptimizationSettings
  7. 在调试时通过adb命令提示符将我的应用程序加入白名单

还有其他什么我需要注意的吗?我正在使用Android 6.0 - API 23的三星A5。

我查看了来自adb命令提示符的日志,并检查了我的服务是否实际上作为前台服务运行,并且所有锁都已保持。


全职服务在Android上即将结束,但您现在可以使用前台服务 - SushiHangover
@SushiHangover 我需要一个能够在用户关闭应用程序之前一直运行的东西,但它必须在屏幕关闭时也能工作。 - FCin
@SushiHangover,我尝试将WakeLock添加到我的前台服务中,但没有成功。你能看一下吗?我更新了我的问题。 - FCin
我相信这个答案是你要找的。在设置中有一个选项,用户可以选择不优化特定的应用程序,并禁用这些特定应用程序的Doze模式,我认为这就是答案所做的。但请注意,有人在评论中提到它会导致他们的应用程序被Google Play暂停而没有通知。如果这有帮助,请告诉我。 - Mr.O
@Mr.O 谢谢,我已经在我的手机上关闭了电池优化。这就是为什么我有这个检查:powerManager.IsIgnoringBatteryOptimizations - FCin
显示剩余2条评论
1个回答

5
你所做的非常好,一切都很好。但是!!请看devleport.android.com的文章:
Google Play政策禁止应用程序在Android 6.0+(Doze和App Standby)中请求直接豁免电源管理功能,除非应用程序的核心功能受到不利影响。
你说:
我正在使用Android 6.0-API 23的三星A5。
这意味着当手机进入睡眠状态时,您将无法保持前台服务,因为应用程序的核心功能未受到不利影响。
这就是为什么当手机进入睡眠状态时,您会注意到停止接收数据包的原因。
请查看我附加的整个链接,并使用Power Manager指南。

编辑:我现在注意到还有以下内容:

如果用户将设备未插电且静止一段时间并关闭屏幕,则设备会进入Doze模式。在Doze模式下,系统试图通过限制应用程序对网络和CPU密集型服务的访问来节省电池电量。它还防止应用程序访问网络并推迟它们的作业、同步和标准闹钟。

Doze限制:

  • 暂停网络访问。
  • 系统忽略唤醒锁。
  • 标准AlarmManager闹钟(包括setExact()和setWindow())被延迟到下一个维护窗口。
  • 如果需要设置在Doze模式下触发的闹钟,请使用setAndAllowWhileIdle()或setExactAndAllowWhileIdle()。
  • 使用setAlarmClock()设置的闹钟会正常触发——系统在这些闹钟触发前不久退出Doze模式。
  • 系统不执行Wi-Fi扫描。
  • 系统不允许同步适配器运行。
  • 系统不允许JobScheduler运行。

这将结束我对您所有查询的回答。

编辑2:

我进一步调查了一下,Xamarin.Android上有一个关于这个问题的完整帖子。

这里还有一个每10分钟唤醒手机来绕过它的解决方案here


你需要深入了解developer.android.com,因为现在唯一的可能性是尝试关闭Doze的省电功能,并调查这些应用程序并检查是否在使用它们时启用了省电模式。 - Barr J
1
一旦我回到家,我会试着玩一下这个程序,但我担心它每10分钟运行一次并且在10秒内休眠,而我需要连续流畅的数据流,没有超过500毫秒的中断。 - FCin
@Cheesebaron,我可以看到我的前台服务正在运行,如果我只是编写代码在其中打印“Hello World”,那么当我关闭屏幕时它就会工作。问题是,当我编写代码来接收wifi包时,它会在我关闭屏幕的那一刻停止。因此,看起来手机会阻止wifi,但不会停止前台服务。 - FCin
@BarrJ 你有尝试使用编辑2中提到的解决方案吗?如果有,它对你有用吗? - FreakyAli
方案2虽然可行,但被认为是一种很费力却无法达到预期效果的方法。在这个过程中,你必须处理许多事件:OnTimeEventOnStartCommandOnCreate等。我的观点是,它虽然可行,但需要进行大量的开发和测试工作。 - Barr J
显示剩余4条评论

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