AlarmManager 和 WakeLocks 相关查询

Inquiry related to AlarmManager and WakeLocks

我正在开发一个本机 android 应用程序,该应用程序每 30 分钟 运行 进行一次备份操作。

我为此目的使用 AlarmManager,它工作正常。这是我用来启动警报的代码:

public static void startSync(Context context) {
        alarmIntent = new Intent(context, AlarmReceiver.class);
        pendingIntent = PendingIntent.getBroadcast(context, 0, alarmIntent, 0);
        manager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
       // int interval = 3600000;
        int interval =30000 ;
        manager.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), interval, pendingIntent);

        ComponentName receiver = new ComponentName(context, SampleBootReceiver.class);
        PackageManager pm = context.getPackageManager();

        pm.setComponentEnabledSetting(receiver,
                PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
                PackageManager.DONT_KILL_APP);
        Toast.makeText(context, "Sync Started", Toast.LENGTH_SHORT).show();
    }

这是接收方法:

public class AlarmReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent arg1) {
        PowerManager pm = (PowerManager) context.getSystemService(context.POWER_SERVICE);
        PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "My Tag");
        wl.acquire();
        Intent eventService = new Intent(context, SyncInBackground.class);
        context.startService(eventService);
        wl.release();
    }
}

我注意到当我的设备不处于待机状态时,操作需要 5 秒(我通过编程计算),但当手机处于待机模式时需要 11 秒。这就是为什么我在 运行 在后台服务中执行备份操作之前使用 wake_lock,以使应用程序只需要 5 秒。

但如果手机处于待机模式,我仍然得到相同的结果...如果不处于待机模式,仍然需要 11 秒和 5 秒。

如何使我的后台服务 运行 在 5 秒而不是 11 秒内发出重复警报?

问题是 context.startService(eventService) 是一个异步操作,很可能 return 只需几毫秒。这意味着当您在 onReceive 方法中获取 WakeLock 时,您只需将其保留几毫秒,然后在服务启动前释放。

解决此问题的一种方法是在您的 BroadcastReceiver 和您尝试启动的服务之间共享唤醒锁。这就是 WakefulIntentService 的工作方式,但您也可以自己执行此操作,例如,通过创建一个具有两种方法的单例 WakelockManager,一种用于获取唤醒锁,一种用于释放唤醒锁,然后让 BroadcastReceiver 调用前者和您的服务叫后者。

此外,请记住泄漏的唤醒锁(通过获取一个但忘记释放它)可能会在电池使用方面造成严重后果。

常见错误:在 OnReceive 中获取唤醒锁没有任何作用。 AlarmManager 已经在 OnReceive 中持有一个唤醒锁。 你的方法成功完全是运气,when/if 它成功了。您必须使用 WakefulBroadcastReceiver 或使用 WakefulIntentService。 WIS 将获取一个静态唤醒锁,该锁将在 OnReceive 返回和服务启动之间激活。

在这里查看我的回答:Wake Lock not working properly 链接。