了解服务、位置侦听器和广播接收器如何在后台获取位置



我是Android新手,正在构建一个跟踪用户距离的应用程序。它只会在用户点击按钮时开始跟踪,并在用户再次点击时停止。关于如何做到这一点,似乎有大量令人困惑的信息和方法,所以我至少对最佳实践有一个大致的了解。

public class BackgroundLocationService extends Service implements GooglePlayServicesClient.ConnectionCallbacks, GooglePlayServicesClient.OnConnectionFailedListener, LocationListener {
    IBinder mBinder = new LocalBinder();
    private LocationClient mLocationClient;
    private LocationRequest mLocationRequest;
    private boolean mInProgress;
    //Milliseconds per second
  private static final int MILLISECONDS_PER_SECOND = 1000;
  // Update frequency in seconds
  private static final int UPDATE_INTERVAL_IN_SECONDS = 30;
  // Update frequency in milliseconds
  public static final long UPDATE_INTERVAL = MILLISECONDS_PER_SECOND * UPDATE_INTERVAL_IN_SECONDS;
  // The fastest update frequency, in seconds
  private static final int FASTEST_INTERVAL_IN_SECONDS = 30;
  // A fast frequency ceiling in milliseconds
  public static final long FASTEST_INTERVAL = MILLISECONDS_PER_SECOND * FASTEST_INTERVAL_IN_SECONDS;
  private static final int TWO_MINUTES = 1000 * 60 * 2;
  public Location previousBestLocation = null;
  private Boolean servicesAvailable = false;
  public class LocalBinder extends Binder {
    public BackgroundLocationService getServerInstance() {
        return BackgroundLocationService.this;
    }
  }
  @Override
    public void onCreate() {
      super.onCreate();
      mInProgress = false;
      mLocationRequest = LocationRequest.create();
      mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
      mLocationRequest.setInterval(UPDATE_INTERVAL);
      mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
      // Check that Google Play Services are connected
      servicesAvailable = servicesConnected();
      // Create the client
      mLocationClient = new LocationClient(this, this, this);
  }//end
  private boolean servicesConnected() {
      // Check that Google Play services is available
      int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
      // If Google Play services is available
      if (ConnectionResult.SUCCESS == resultCode) {
          return true;
      } else {
          return false;
      }
  }//end
  public int onStartCommand (Intent intent, int flags, int startId) {
      super.onStartCommand(intent, flags, startId);
      if(!servicesAvailable || mLocationClient.isConnected() || mInProgress)
        return START_STICKY;
      setUpLocationClientIfNeeded();
      if(!mLocationClient.isConnected() || !mLocationClient.isConnecting() && !mInProgress) {
            mInProgress = true;
            mLocationClient.connect();
      }
      return START_STICKY;
  }//end

  private void setUpLocationClientIfNeeded() {
    if (mLocationClient == null) 
          mLocationClient = new LocationClient(this, this, this);
  }

  @Override
  public void onLocationChanged(Location location) {
      String msg = Double.toString(location.getLatitude()) + "," +Double.toString(location.getLongitude());
      Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
  }//end
  @Override
  public IBinder onBind(Intent intent) {
    return mBinder;
  }
  public String getTime() {
    SimpleDateFormat mDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    return mDateFormat.format(new Date());
  }

  @Override
  public void onDestroy(){
      // Turn off the request flag
      mInProgress = false;
      if(servicesAvailable && mLocationClient != null) {
            mLocationClient.removeLocationUpdates(this);
            // Destroy the current location client
            mLocationClient = null;
      }
      // Display the connection status
      Toast.makeText(this, DateFormat.getDateTimeInstance().format(new Date()) + ": Disconnected. Please re-connect.", Toast.LENGTH_SHORT).show();
      super.onDestroy();  
  }
  /*
   * Called by Location Services when the request to connect the
   * client finishes successfully. At this point, you can
   * request the current location or start periodic updates
   */
  @Override
  public void onConnected(Bundle bundle) {
      // Request location updates using static settings
      mLocationClient.requestLocationUpdates(mLocationRequest, this);
  }
  /*
   * Called by Location Services if the connection to the
   * location client drops because of an error.
   */
  @Override
  public void onDisconnected() {
      // Turn off the request flag
      mInProgress = false;
      // Destroy the current location client
      mLocationClient = null;
      // Display the connection status
      Toast.makeText(this, DateFormat.getDateTimeInstance().format(new Date()) + ": Disconnected. Please re-connect.", Toast.LENGTH_SHORT).show();
  }
  /*
   * Called by Location Services if the attempt to
   * Location Services fails.
   */
  @Override
  public void onConnectionFailed(ConnectionResult connectionResult) {
    mInProgress = false;
      /*
       * Google Play services can resolve some errors it detects.
       * If the error has a resolution, try sending an Intent to
       * start a Google Play services activity that can resolve
       * error.
       */
      if (connectionResult.hasResolution()) {
      // If no resolution is available, display an error dialog
      } else {
      }
  }
}

所以关于我的问题:

  • 从我的主要Activity如何开始我的服务?我该如何阻止它?
  • 我的Activity类如何知道我的Service何时收到Location更新,以便我可以更新 UI?
  • 我甚至需要BroadcastReceiver吗?
  • 有什么需要进入我的Manifest吗?

让我们按顺序回答您的问题:

  1. http://www.androidhive.info/2012/07/android-gps-location-manager-tutorial/
  2. 位置
  3. 已更改(位置位置)
  4. 否,转到 1
  5. 是的,再次,转到 1

编辑:报告回主活动

在 MainActivity 中添加如下接口:

public class MainActivity implements NewLocationsListener {
    public interface NewLocationsListener {
        public void onNewLocation(Location location);
    }
    private GPSTracker gps;
    ...
    // when your button is clicked or where ever you want to start gps
    gps = new GPSTracker(this, this);
    ...
    // and get Locations in onNewLocation
    public void onNewLocation(Location location) {
        // location reported back from gps 
    }
    // if you want gps to stop after exiting your app
    @Override
    protected void onPause() {
        if (gps != null) {
            gps.stopUsingGPS();
        }
        super.onPause();
    }
}

并添加到 GPSTracker:

private NewLocationsListener mListener;
public GPSTracker(Context context, NewLocationsListener listener) {
    this.mContext = context;
    this.mListener = listener;
    getLocation();
}

@Override
public void onLocationChanged(Location location) {
    // report back to MainActivity
    mListener.onNewLocation(location);
    canGetLocation = true;
}

Edit2:如何处理退出重新进入和方向更改的示例:

正如你所说,既然你是Android的新手,我想我不妨补充一下。

public class StrategyActivity extends Activity {
    public static final String TAG = "StrategyActivity";
    protected GPSTracker gps;
    private Button startButton;
    private boolean isStarted = false;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        startButton = (Button) findViewById(R.id.start_button);
        if (savedInstanceState != null) {
            isStarted = savedInstanceState.getBoolean("isStarted");
        }
    }

    @Override
    protected void onResume() {
        if (isStarted) {
            startStrategy();
        }
        updateOnOffButton();
        super.onResume();
    }
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        outState.putBoolean("isStarted", isStarted);
        super.onSaveInstanceState(outState);
    }
    @Override
    public void onBackPressed() {
        if (isStarted) {
            stopStrategy();
        }
        super.onBackPressed();
    }
    @Override
    protected void onPause() {
        if (isStarted) {
            killStrategy();
        }
        super.onPause();
    }
    @Override
    protected void onDestroy() {
        killStrategy();
        super.onDestroy();
    }
    public void startStopClicked(View view) {
        if (isStarted) {
            stopStrategy();
        } else {
            startStrategy();
        }
    }
    private void updateOnOffButton() {
        if (isStarted) {
            startButton.setText("Stop");
        } else {
            startButton.setText("Start");
        }
    }

    protected void killStrategy() {
        if (gps != null) {
            gps.stopUsingGPS();
        }
    }
    protected void startStrategy() {
        isStarted = true;
        gps = new GPSTracker(this);
        updateOnOffButton();
        Toast.makeText(this, "Started", Toast.LENGTH_LONG).show();
    }
    protected void stopStrategy() {
        isStarted = false;
        killStrategy();
        updateOnOffButton();
        Toast.makeText(this, "Stopped", Toast.LENGTH_LONG).show();
    }
}

最新更新