如何在Android中的服务中处理位置侦听器更新?

时间:2014-02-26 08:58:55

标签: android service location google-maps-android-api-2

我正在开发一款应用程序,如果用户位于特定区域内,该应用应能持续获得准确的用户位置。 位置更新应保存在服务器(Parse.com)上,以便其他用户可以获取用户的当前位置。

流程是:

  1. 申请onCreate - >
  2. 使用LocationListener启动服务 - >
  3. onLocationChanged - >
  4. 在Parse.com上保存新位置 - >
  5. Parse.com Cloud afterSave方法向用户发送推送通知 - >
  6. 其他用户通过广播接收方获得通知 - >
  7. 在地图上更新用户标记< -
  8. 问题:

    1. 我不确定如何实现第4步,我是否应该在onLocationChanged方法内的parse中保存新位置?我应该将它传递给BroadcastReciever并将其保存在那里解析吗?或者我应该将它传递给我的CurrentUser类中的静态方法,该方法将在服务器上执行保存?

    2. 我注意到requestLocationUpdates文档说:

        

      "此方法适用于前台用例,更具体地说   用于在连接到LocationClient时请求位置。对于   后台用例,PendingIntent版本的方法是   。推荐"

      在我的情况下,我应该使用哪种方法?

    3. 我应该使用什么值来获得几乎实时的位置而不会每小时消耗超过5%的电池电量?

    4. 我的服务类:

      public class UserTracker extends Service implements
      GooglePlayServicesClient.ConnectionCallbacks,
      GooglePlayServicesClient.OnConnectionFailedListener, LocationListener{
      
      static int GEOFENCE_STATUS; 
      final static int INSIDE_GEOFENCE = 9001, OUTSIDE_GEOFENCE = 9002;
      
      static final int MINIMUM_ACCURACY = 26;
      
      final static int GEOFENCE_RADIUS = 2000;
      
      static final int NULL_LOCATION_ERROR = 7001;
      
      static final int INSIDE_INTERVAL = 10000, INSIDE_FASTEST_INTERVAL = 1000, INSIDE_SMALLEST_DISPLACEMENT = 10;
      static final int OUTSIDE_INTERVAL = 300000, OUTSIDE_FASTEST_INTERVAL = 60000, OUTSIDE_SMALLEST_DISPLACEMENT = 100;
      
      static Location eventLocation;
      
      LocationClient lc;
      
      @Override
      public void onCreate() {
          super.onCreate();
          eventLocation = new Location("Test");
          lc = new LocationClient(getApplicationContext(), this, this);
      }
      
      @Override
      public int onStartCommand(Intent intent, int flags, int startId) {
      
          double eventLat = intent.getDoubleExtra("Latitude", -1);
          double eventLon = intent.getDoubleExtra("Longitude", -1);
          if (eventLat == -1 || eventLon == -1) {
              stopSelf();
              return START_REDELIVER_INTENT;
          }
      
          eventLocation.setLatitude(eventLat);
          eventLocation.setLongitude(eventLon);
      
          lc.connect();
      
          return START_STICKY;
      }
      
      public int getGeofenceStatus(Location currentLocation) {
          if (currentLocation == null) {          
              return NULL_LOCATION_ERROR;         
          } 
          if (currentLocation.distanceTo(eventLocation) > GEOFENCE_RADIUS) {
              Log.d(TAG, "User is outside geofence");
              return OUTSIDE_GEOFENCE;
          } else {
              Log.d(TAG, "User is inside geofence");
              return INSIDE_GEOFENCE;
          }
      }
      
      public void requestLocationUpdates(int status) {
      
          GEOFENCE_STATUS = status;
      
          LocationRequest request = LocationRequest.create();
      
          switch (status) {
          case NULL_LOCATION_ERROR:
              stopSelf();
              break;
          case INSIDE_GEOFENCE:           
              request.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
              request.setInterval(INSIDE_INTERVAL);
              request.setFastestInterval(INSIDE_FASTEST_INTERVAL);
              request.setSmallestDisplacement(INSIDE_SMALLEST_DISPLACEMENT);
              break;
          case OUTSIDE_GEOFENCE:
              request.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
              request.setInterval(OUTSIDE_INTERVAL);
              request.setFastestInterval(OUTSIDE_FASTEST_INTERVAL);
              request.setSmallestDisplacement(OUTSIDE_SMALLEST_DISPLACEMENT);         
              break;
          }
          lc.requestLocationUpdates(request, this);
      }
      
      @Override
      public void onLocationChanged(Location location) {
          int newStatus = getGeofenceStatus(location);
          int accuracy = (int) location.getAccuracy(); 
      
          String message = "Geofence status: " + newStatus + 
                  "\nAccuracy: " + accuracy + 
                  "\nDistance to event: " + location.distanceTo(eventLocation);
          Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT).show();
      
          if (newStatus == INSIDE_GEOFENCE && accuracy < MINIMUM_ACCURACY) {
              Log.d(TAG, "Accuracy is good");
                          // do the save on server procees
          }
          if (GEOFENCE_STATUS != newStatus) {
              requestLocationUpdates(newStatus);
          }       
      }
      
      @Override
      public void onConnectionFailed(ConnectionResult result) {
          Log.d(TAG, "LocationClient connection failed: " + result.getErrorCode());
      }
      
      @Override
      public void onConnected(Bundle arg0) {
          Location currentLocation = lc.getLastLocation();
          requestLocationUpdates(getGeofenceStatus(currentLocation));
      }
      
      @Override
      public void onDisconnected() {
          Log.d(TAG, "LocationClient disconnected");
      }
      
      @Override
      public IBinder onBind(Intent intent) {
          return null;
      }       
      }
      

0 个答案:

没有答案