0

我需要定期在后台运行任务,并保持 CPU 唤醒。根据 Android文档,我为此使用了PARTIAL_WAKE_LOCK 。为了测试唤醒锁,我编写了一个 Service,它使用ScheduledThreadPoolExecutor每 2 分钟启动一个线程。该线程只是在 sdcard 中的日志文件上写入一个字符串。

然后,我执行了以下简单测试:运行应用程序并拔下设备的电源。在正确执行 2 或 3 小时后,Service 停止运行线程,并且日志文件中没有写入新字符串。

服务代码:

@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!");
}

我希望当显示器关闭时线程也会执行,但查看我的日志文件似乎并非如此。我哪里错了?

4

1 回答 1

3

在 Android 6.0+ 上,打盹模式基本上会撤消您的唤醒锁。一些制造商的 6.0 之前的设备会做类似的事情。

是否可以避免打盹模式?

用户可以将您的应用添加到电池优化白名单中。请注意,要求用户执行此操作ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS 可能会导致您的应用被 Play Store 禁止,如果那是您的分发渠道之一。

或者,用户可以一直将他们的设备放在充电器上。

如果您可以通过不那么频繁的轮询周期来解决问题,您可以尝试setAndAllowWhileIdle()setExactAndAllowWhileIdle()使用AlarmManager. 充其量,您将每 9 分钟获得一次控制权。不过,您可能无法访问 Internet。

否则,设备端每 N 分钟轮询一次的方法注定要失败。

Google 希望您使用 GCM/FCM 并避免轮询,方法是让您的服务器在需要时下推信息。我不知道这是否与您的用例有关。

于 2016-12-14T23:04:03.597 回答