通过调度制定可靠稳定的定位服务

时间:2015-05-21 14:25:19

标签: android android-service android-broadcast android-alarms android-wake-lock

我想要实现的功能:

在特定日期,服务应该开始获取位置信息并将其推送到服务器。在某个特定日期,服务应该停止。

  1. 准确起始和结束时间非常重要。
  2. 服务应该尽可能可靠,操作系统不应该杀死它。
  3. 服务的开始和结束必须是自动的,无需用户互动。
  4. 以下是我取得的成就:

    1. 我的应用程序中有一个数据库,其中包含" schedulings"。开始时间,结束时间。
    2. 我有一个ServiceScheduler类,它使用PendingIntents和WakefulBroadcastReceiver从DB读取调度并使用AlarmManager将警报设置为特定日期。
    3. WakefulBroadcastReceiver实际上启动了服务,我还有另一个BroadcastReceiver来阻止它。
    4. 我的服务是一项简单的服务,所以不是IntentService,我在startForeground模式下使用它。
    5. 我在尝试使该功能可靠且可用的过程中学到了什么:

      1. 我的ServiceScheduler应在设备重启后重新设置警报,因为警报在关闭时会被清除。
      2. 启动前台模式是最小化操作系统终止服务的可能性的好方法。
      3. 使用WakefullBroadcastReceiver而不是简单的BroadcastReceiver启动服务是必须的,以确保设备从睡眠模式唤醒。
      4. 试验:

        1. 该服务尚未100%可靠,我怀疑睡眠模式是问题的根源。
        2. 我的问题:

          1. 设备的休眠模式是否会阻止服务正常运行? - 使用"融合位置"获取位置信息的含义,将位置缓存到数据库并将一些数据推送到服务器。

          2. 服务启动后,设备是否可以返回睡眠模式?

          3. 如果我选择在服务运行期间保持设备唤醒整个时间间隔,那么在服务的onCreate上获取唤醒锁并在onDestroy上发布它是一个好习惯吗?

            < / LI>

            我的简化代码:

                public class ServiceScheduler
                {
            
                //Class for scheduling a service from a scheduling instance (read from DB)
            
                //.. much simple version just to explain
            
                    private void schedule(Scheduling scheduling){
            
                        //Intent for the ServiceStartBroadcastReceiver
                        Intent startServiceIntent = new Intent(ctx.getApplicationContext(), ServiceStartBroadcastReceiver.class);
            
                        //pending intent for the alarmManager
                        PendingIntent startPendingIntent = PendingIntent.getBroadcast(ctx.getApplicationContext(), 0, startServiceIntent, 0);
            
                        //setting alarm to start the service at the specific time
            //setExact's required API level is too high for the project
                        alarmManager.set(AlarmManager.RTC_WAKEUP, scheduling.startTime.getTime(), startPendingIntent);
            
            
                        //Intent for the ServiceStopBroadcastReceiver
                        Intent endServiceIntent = new Intent(ctx.getApplicationContext(), ServiceStopBroadcastReceiver.class);
            
                        //pending intent for the alarmManager
                        PendingIntent endPendingIntent = PendingIntent.getBroadcast(ctx.getApplicationContext(), 0, endServiceIntent, 0);
            
                        //setting alarm to stop the service at the specific time
            //setExact's required API level is too high for the project
                        alarmManager.set(AlarmManager.RTC_WAKEUP, scheduling.endTime.getTime(),endPendingIntent);
                    }
            
                }
            
            
                public class ServiceStartBroadcastReceiver extends WakefulBroadcastReceiver {
            
                //BroadcastReceiver to start the service
            
                    @Override
                    public void onReceive(Context context, Intent intent) {
            
                        Intent startServiceIntent = new Intent(context, GpsService.class);
            
                        //start in wakeful mode
                        startWakefulService(context, startServiceIntent);
            
                    }
                }
            
            
                public class ServiceStopBroadcastReceiver extends BroadcastReceiver {
            
            
                //BroadcastReceiver to stop the service
            
                    @Override
                    public void onReceive(Context context, Intent intent) {
            
            
                        //Stopping the service
                        Intent stopServiceIntent = new Intent(context, GpsService.class);
                        context.stopService(stopServiceIntent);
            
                    }
            
                }
            
            
                public class GpsService extends Service {
            
                  //Using wake lock, is it necessary?
                    private PowerManager.WakeLock wakeLock;
            
            
                    @Override
                    public void onCreate() {
            
                        PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
                        wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "locationServiceWakeLock");
            
            
                    }
            
                    @Override
                    public int onStartCommand(Intent intent, int flags, int startId) {
            
            
                          //Wake lock !? is it necessary?
                        if (!wakeLock.isHeld()) {
                            wakeLock.acquire();
                        }
            
            
                        //completing the wakefull intent which is started at ServiceStartBroadcastReceiver
                        ServiceStartBroadcastReceiver.completeWakefulIntent(intent);
            
            
                        //Which mode should i use and why as return?
                        return START_REDELIVER_INTENT;
                    }
            
                    @Override
                    public IBinder onBind(Intent intent) {
                        return null;
                    }
            
            
            
                    @Override
                    public void onDestroy() {
            
            
                       //Wake lock !? is it necessary?
                        wakeLock.release();
            
            
                    }
            
            
            
                }
            

            请告诉我您的所有建议

            我现在已经做了很长时间了,解决方案已经接近了。我已经阅读了我发现的所有文章和文档,但我仍然不确定。

0 个答案:

没有答案