【问题标题】:Periodic call in android every 90 seconds, even when app is closed每隔 90 秒在 android 中进行定期调用,即使在应用程序关闭时也是如此
【发布时间】:2016-10-20 07:12:51
【问题描述】:

要求是每 90 秒记录一次位置并将其写入数据库(sqlite),如果网络可用则调用 api,即使应用程序已关闭。 这将是实现这一目标的最佳方法? 我应该启动意图服务吗?或者我应该和警报经理一起去。我在某处读到,只有在持续时间超过 10 分钟时才应使用警报管理器。

【问题讨论】:

  • 使用已启动的服务
  • 您可以尝试使用普通的服务和处理程序。处理程序每​​ 90 秒执行一次必要的任务,并且处理程序可以在服务内部,如果它以“START_STICKY”标志启动,它将在后台运行;

标签: android performance


【解决方案1】:

我建议使用 AlarmManager,因为即使设备处于睡眠状态,它也可以运行。 请注意,对于 API v > 19,警报传递是不准确的,您必须使用 setExact api 来实现。 见

注意:从 API 19 开始,传递给此方法的触发时间被视为不精确:在此时间之前不会发送警报,但可能会延迟并在一段时间后发送。操作系统将使用此策略在整个系统中“批量”发出警报,从而最大限度地减少设备需要“唤醒”的次数并最大限度地减少电池使用量。一般来说,安排在不久的将来的警报不会被推迟,只要安排在很远的将来的警报。 使用新的批处理政策,交货订购保证不像以前那么强大。如果应用程序设置了多个警报,则这些警报的实际交货顺序可能与其请求的交货时间顺序不匹配。如果您的应用程序有严格的排序要求,那么您可以使用其他 API 来获得必要的行为;参见 setWindow(int, long, long, PendingIntent) 和 setExact(int, long, PendingIntent)。

【讨论】:

    【解决方案2】:

    Alarm Manager 将是您的理想选择。注册的警报在设备休眠时会保留,但如果关闭并重新启动,则会被清除。 因此,您可以使用它以 90 秒的间隔运行您的作业。它可能会在设备重新启动后第一次打破间隔。

    【讨论】:

      【解决方案3】:

      我发现的另一种方法是使用 Firebase 作业调度程序。对于在 marshmallow 或更高版本上运行的设备来说,这是最佳选择。它易于集成和定制。 https://github.com/firebase/firebase-jobdispatcher-android

      【讨论】:

        【解决方案4】:

        服务是可以执行长时间运行的应用程序组件 后台操作,不提供用户界面。

        https://developer.android.com/guide/components/services.html

        警报管理器适用于您希望拥有 应用程序代码在特定时间运行,即使您的应用程序是 当前未运行。 只要闹钟响起,闹钟管理器就会持有 CPU 唤醒锁 接收者的 onReceive() 方法正在执行。这保证了 在您处理完广播之前,手机不会休眠。

        https://developer.android.com/reference/android/app/AlarmManager.html

        使用服务。

        【讨论】:

          【解决方案5】:

          您使用 Intent 服务和 Broadcastreceiver 组件,因为这些组件只会持续侦听,即使您关闭应用程序也是如此。

          如果您想每 90 秒获取一次信息,请使用警报管理器。

          AlarmManager manager = (AlarmManager) (context)
                          .getSystemService(Context.ALARM_SERVICE);
                  Intent alarmIntent = new Intent(context, YourAlarmReceuver.class);
          
                  //alarmIntent.putExtra("syncData", favoritesArrayList);
          
          
                  PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0,
                          alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
                  manager.setInexactRepeating(AlarmManager.RTC_WAKEUP,
                          System.currentTimeMillis(), 90*1000, pendingIntent);
          

          你的接收器类是这样的

          public class SyncAlarmReceiver extends BroadcastReceiver {
          
              @Override
              public void onReceive(Context context, Intent intent) {
          
                Intent stIntent = new Intent(context,
                              YourService.class);
                  context.startService(stIntent);
          
                 }
          

          你的 Intent 服务类是这样的

          public class DataSyncService extends IntentService {
          
          
              public DataSyncService() {
                  super(DataSyncService.class.getName());
                  // TODO Auto-generated constructor stub
              }
          
          @Override
              protected void onHandleIntent(Intent intent) {
          
                   //write your logic here 
                  // get the location and update the database
              }
          
          }
          

          您应该也实例化警报管理器启动完成。

          【讨论】:

          • 这将无法可靠地工作。没有为Service 提供WakeLock,因此设备可以在执行之前返回睡眠状态。
          • 警报管理器应该可以工作,即使设备处于睡眠模式。但是如果设备重新启动,那么它会丢失所有警报,为此我们需要在启动完成时实例化警报管理器。
          • 是的,AlarmManager 可以工作,因为在onReceive() 期间保证WakeLock,但设备可以在onReceive() 完成后立即进入睡眠状态。这就是为什么你必须为Service 提供一个WakeLock,要么手动,要么使用WakefulBroadcastReceiver 辅助类。
          • 正如@earthw0rmjim 所说,这里应该使用WakefulBroadcastReceiver。
          • 另外,setInexactRepeating() 是这里最糟糕的选择。警报将不准确,并且它们不适用于 Doze。
          猜你喜欢
          • 2019-01-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-04-14
          • 2019-03-08
          相关资源
          最近更新 更多