使用 PARTIAL_WAKE_LOCK 使后台线程保持活动状态
Keep alive a background thread using PARTIAL_WAKE_LOCK
我需要在后台定期 运行 一个任务,并保持清醒 CPU。根据 Android documentation 我为此目的使用了 PARTIAL_WAKE_LOCK。
为了测试唤醒锁,我编写了一个服务,它使用 ScheduledThreadPoolExecutor 每 2 分钟启动一个线程。该线程只是在 sdcard 中的日志文件上写入一个字符串。
然后,我进行了以下简单测试:运行 应用程序并拔下设备电源。正确执行 2 或 3 小时后,服务停止到 运行 线程并且没有新字符串写入日志文件。
服务代码:
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "Service onStartCommand");
PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE);
wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "WiOpp wakeLock");
wakeLock.acquire();
TestTask testTask = new TestTask(getApplicationContext());
ScheduledThreadPoolExecutor monitorPool = new ScheduledThreadPoolExecutor(1);
monitorPool.scheduleAtFixedRate(testTask, 0, 120, TimeUnit.SECONDS);
return START_STICKY;
}
TestTask 的代码:
@Override
public void run() {
//write on log file
LogManager.getInstance().logData("I am running!");
}
我希望线程在显示器关闭时也会执行,但查看我的日志文件似乎并非如此。我哪里错了?
在 Android 6.0+ 上,Doze mode 基本上会解除您的唤醒锁。一些制造商的 6.0 之前的设备做类似的事情。
Is it possible to avoid the Doze mode?
用户可以将您的应用加入电池优化白名单。请注意,如果这是您的分发渠道之一,请通过 ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
may result in your app being banned from the Play Store 要求用户执行此操作。
或者,用户可以将他们的设备一直放在充电器上。
如果轮询频率较低,您可以尝试 setAndAllowWhileIdle()
或 setExactAndAllowWhileIdle()
和 AlarmManager
。充其量,您将每 9 分钟获得一次控制。不过,您可能无法访问 Internet。
否则,设备端每 N 分钟轮询一次的方法注定要失败。
Google 希望您使用 GCM/FCM 并避免轮询,方法是让您的服务器在需要时推送信息。我不知道这是否与您的用例相关。
我需要在后台定期 运行 一个任务,并保持清醒 CPU。根据 Android documentation 我为此目的使用了 PARTIAL_WAKE_LOCK。 为了测试唤醒锁,我编写了一个服务,它使用 ScheduledThreadPoolExecutor 每 2 分钟启动一个线程。该线程只是在 sdcard 中的日志文件上写入一个字符串。
然后,我进行了以下简单测试:运行 应用程序并拔下设备电源。正确执行 2 或 3 小时后,服务停止到 运行 线程并且没有新字符串写入日志文件。
服务代码:
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "Service onStartCommand");
PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE);
wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "WiOpp wakeLock");
wakeLock.acquire();
TestTask testTask = new TestTask(getApplicationContext());
ScheduledThreadPoolExecutor monitorPool = new ScheduledThreadPoolExecutor(1);
monitorPool.scheduleAtFixedRate(testTask, 0, 120, TimeUnit.SECONDS);
return START_STICKY;
}
TestTask 的代码:
@Override
public void run() {
//write on log file
LogManager.getInstance().logData("I am running!");
}
我希望线程在显示器关闭时也会执行,但查看我的日志文件似乎并非如此。我哪里错了?
在 Android 6.0+ 上,Doze mode 基本上会解除您的唤醒锁。一些制造商的 6.0 之前的设备做类似的事情。
Is it possible to avoid the Doze mode?
用户可以将您的应用加入电池优化白名单。请注意,如果这是您的分发渠道之一,请通过 ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
may result in your app being banned from the Play Store 要求用户执行此操作。
或者,用户可以将他们的设备一直放在充电器上。
如果轮询频率较低,您可以尝试 setAndAllowWhileIdle()
或 setExactAndAllowWhileIdle()
和 AlarmManager
。充其量,您将每 9 分钟获得一次控制。不过,您可能无法访问 Internet。
否则,设备端每 N 分钟轮询一次的方法注定要失败。
Google 希望您使用 GCM/FCM 并避免轮询,方法是让您的服务器在需要时推送信息。我不知道这是否与您的用例相关。