手机进入睡眠状态后,在前台服务中保持 wifi 处于活动状态
Posted
技术标签:
【中文标题】手机进入睡眠状态后,在前台服务中保持 wifi 处于活动状态【英文标题】:Keep wifi active in foreground service after phone goes to sleep 【发布时间】:2019-01-12 01:09:28 【问题描述】:我想在手机锁定时接收来自 wifi 的数据包。问题是当我锁定屏幕时,我的前台服务停止接收数据包。我正在使用这样的前台服务:
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;
我正在做以下事情来确保它没有被杀死:
-
启动前台服务
使用
StartCommandResult.Sticky
使用唤醒锁
使用 Wifi 锁
将 WifiSleepPolicy 设置为 Never
(我在手机中设置了
设置)
在意图中设置ActionIgnoreBatteryOptimizationSettings
调试时通过 adb 命令提示符将我的应用列入白名单
我还缺少什么?我正在使用带有 Android 6.0 - API 23 的三星 A5。
我从 adb 命令提示符查看了日志,并检查了我的服务实际上是作为前台服务运行的,并且所有锁都被持有。
【问题讨论】:
Android 上的全职服务即将结束,但您现在可以使用 foregrounded 服务。 @SushiHangover 我使用了前台服务,当屏幕关闭时它会在大约 1 秒后停止。 @SushiHangover 我需要一些可以在用户关闭应用程序之前工作的东西,但它必须在屏幕关闭时工作。 那么你需要在设备上申请唤醒锁(当然这并不意味着某些OEM的版本不会打瞌睡你的应用,用户可能需要在设置中手动将其列入白名单),否则使用 WorkManager 之类的东西是未来,因为它将使用 AlarmManager、JobScheduler、Firebase JobDispatcher 等……取决于 API 级别,但当然这是基于时间/任务的,而不是持续运行的服务。 @SushiHangover 我尝试将 WakeLock 添加到我的前台服务,但没有运气。你能看看吗?我更新了我的问题。 【参考方案1】:你所做的很好,一切都很好。 但是!!
让我们看看devleport.android.com的帖子:
Google Play 政策禁止应用申请直接豁免 来自 Android 6.0+ 中的电源管理功能(打盹和应用待机) 除非应用的核心功能受到不利影响。
你说:
我正在使用搭载 Android 6.0 - API 23 的三星 A5。
也就是说,当手机进入睡眠状态时,您将无法保持前台服务,因为应用的核心功能 没有 受到不利影响.
这就是为什么您注意到您在手机处于睡眠状态时停止接收数据包的原因。
请浏览我附加的整个链接以及Power Manager 指南。
编辑:我现在注意到了:
如果用户将设备不插电并静止一段时间 时间,屏幕关闭,设备进入打盹模式。在打盹模式下, 系统试图通过限制应用访问来节省电池 网络和 CPU 密集型服务。它还可以防止应用程序 访问网络并推迟他们的工作、同步和标准 警报。
打瞌睡限制:
网络访问被暂停。 系统忽略唤醒锁。 标准 AlarmManager 警报(包括 setExact() 和 setWindow()) 推迟到下一个维护时段。 如果您需要设置在打瞌睡时触发的警报,请使用 setAndAllowWhileIdle() 或 setExactAndAllowWhileIdle()。 使用 setAlarmClock() 设置的警报继续正常触发 — 系统在警报触发前不久退出打盹。 系统不执行 Wi-Fi 扫描。 系统不允许同步适配器运行。 系统不允许 JobScheduler 运行。这将结束我对您所有问题的回答。
编辑 2:
我进行了进一步调查,Xamarin.Android 中有一篇关于此问题的完整帖子。
还有一个解决方案是每 10 分钟唤醒一次手机以绕过它here。
【讨论】:
必须有一个解决方法,因为我在同一部手机上安装了能够在屏幕锁定时执行 wifi 活动的应用程序。 你将不得不在 developer.android.com 中进行更深入的挖掘,因为目前,你唯一的可能就是尝试停用 Doze 的省电功能,事实上,调查这些应用程序并检查是否使用它们时会启用省电功能。 我会尝试检查这些应用程序停用了哪些功能,但我真的不知道要寻找什么。我禁用了电池优化。我将应用程序列入白名单。还有哪些其他省电功能会导致“打瞌睡”?我的应用程序的核心也受此问题的影响。我的应用 100% 专注于通过 wifi 进行流式传输。 我回家后会玩这个,但我担心它会每 10 分钟运行一次,并在 10 秒内打瞌睡,我需要连续流而不中断超过 ~500 毫秒。 所以我试了一下,但这个解决方案只适用于超过 10 分钟后打瞌睡的手机。几秒钟后我的打瞌睡,所以不幸的是,这对我来说不是很有用。虽然我检查了isDeviceIdleMode
,它总是为我返回false
,所以也许我的手机有一些不同的模式而不是打瞌睡?以上是关于手机进入睡眠状态后,在前台服务中保持 wifi 处于活动状态的主要内容,如果未能解决你的问题,请参考以下文章