Java 安卓:每30分钟使用计时器获取一个位置,窗口为1分钟

Java 安卓:每30分钟使用计时器获取一个位置,窗口为1分钟,java,android,timer,geolocation,Java,Android,Timer,Geolocation,我正在做我的顶点,我们正在开发一个应用程序,获取用户位置并将其绘制在地图上。我们正在尝试每x变量获取一个位置(x是用户从5、10、15、30和60分钟的选择中输入的设置),并将最佳位置发送到数据库,以便稍后共享。应用程序的基本流程是,每次用户打开应用程序时,他们都会看到地图,地图会尽快显示他们当前的位置。然后将该位置发送到数据库,以便与其他人共享。在他们获得位置后,会启动一个计时器,每隔30分钟再次获取他们的位置,然后将该位置发送到DB并再次启动计时器。每次用户访问应用程序时,计时器都需要重置,

我正在做我的顶点,我们正在开发一个应用程序,获取用户位置并将其绘制在地图上。我们正在尝试每x变量获取一个位置(x是用户从5、10、15、30和60分钟的选择中输入的设置),并将最佳位置发送到数据库,以便稍后共享。应用程序的基本流程是,每次用户打开应用程序时,他们都会看到地图,地图会尽快显示他们当前的位置。然后将该位置发送到数据库,以便与其他人共享。在他们获得位置后,会启动一个计时器,每隔30分钟再次获取他们的位置,然后将该位置发送到DB并再次启动计时器。每次用户访问应用程序时,计时器都需要重置,因为启动应用程序后,他们将立即获得自己的位置。我遇到的问题是在后台创建一个计时器,该计时器将在不在应用程序中时获取它们的位置以发送到DB。我还想实现这样的逻辑,即在我们得到他们的位置后,我们会在一小段时间内停止监听更新

我目前了解requestLocationUpdates()方法,并且已经实现了它,因此当用户访问应用程序时,他们可以从GPS和网络中获得一个位置,该位置的最短时间为60秒,距离为100英尺或30.48米。这也会在用户暂停应用程序时停止,并在用户导航回应用程序时启动。我注意到,尽管我们已经收到更新,但我们仍不断请求更新。这让我相信requestLocationUpdates在监听更新更改时会继续使用电池寿命

如何创建此逻辑以在接收到位置后停止更新,但在特定时间后开始侦听位置?阅读当前android的requestLocationUpdates方法,minTime和MindDistance只是“提示”,但它并不遵守它们。我需要locationUpdater遵守设置的参数

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    /** Session Creation and Checker */
    session = new SessionManagement(getApplicationContext());
    // Check if the user is logged in
    session.checkLogin();

    /** Setup basic session and content view */
    // Set the Content View
    setContentView(R.layout.activity_main);
    /** Start of the MapView Elements */
    // extract MapView from layout
    mapView = (MapView) findViewById(R.id.mapview);
    // Set a mapController
    mapController = mapView.getController();
    // set the map to have built in zoom controls
    mapView.setBuiltInZoomControls(true);

    /** Getting the device location */
    locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
    geoCoder = new Geocoder(this);

    isEnabled = locationManager
            .isProviderEnabled(LocationManager.GPS_PROVIDER);
    // Check if the GPS is enabled
    if (!isEnabled) {
        alert.showAlertDialog(MainActivity.this, 12);
    }

    // Retrieve a list of location providers that have fine accuracy, no
    // monetary cost, etc
    Criteria criteria = new Criteria();
    criteria.setAccuracy(Criteria.ACCURACY_HIGH);
    criteria.setAltitudeRequired(false);
    criteria.setBearingRequired(false);
    criteria.setCostAllowed(true);
    criteria.setPowerRequirement(Criteria.POWER_LOW);
    provider = locationManager.getBestProvider(criteria, true);

    // If no suitable provider is found, null is returned.
    if (provider != null) {
        provider = locationManager.getBestProvider(criteria, false);
        BCT = (session.getBCT() * 60000);
        // Initialize with last known location
        locationManager.requestLocationUpdates(provider, BCT, 31,
                locationListener);

        // Check the map settings
        if (session.isSatellite()) {
            SatelliteChecked = true;
            mapView.setSatellite(true);
        }
        if (session.isTraffic()) {
            TrafficChecked = true;
            mapView.setTraffic(true);
        }
    } else {
        alert.showAlertDialog(getApplicationContext(), 15);
        locationManager.removeUpdates(locationListener);
    }

}

// Define a listener that responds to location updates
LocationListener locationListener = new LocationListener() {
    public void onLocationChanged(Location location) {
        // Called when a new location is found by the network location
        // provider.

            Toast.makeText(getApplicationContext(), location.toString(),
                    Toast.LENGTH_LONG).show();

    }

    public void onStatusChanged(String provider, int status, Bundle extras) {

    }

    public void onProviderEnabled(String provider) {
        Toast.makeText(getApplicationContext(), provider.toUpperCase() + " enabled.", Toast.LENGTH_SHORT).show();
    }

    public void onProviderDisabled(String provider) {
        Toast.makeText(getApplicationContext(), provider.toUpperCase() + " disabled.", Toast.LENGTH_SHORT).show();
    }
};
@Override
protected void onResume() {
    super.onResume();
    BCT = (session.getBCT() * 60000);
    // when our activity resumes, we want to register for location updates
    locationManager.requestLocationUpdates(
            provider, BCT, 31, locationListener);
}

@Override
protected void onPause() {
    super.onPause();
    // when our activity pauses, we want to remove listening for location
    // updates
    locationManager.removeUpdates(locationListener);
}

您需要的是一个后台线程,用于计时器

你可以试试:

  • 使用报警管理器每x分钟安排一次。请参阅此问题的答案:
  • 将异步任务或处理程序与
    postDelayed
    一起使用x分钟,如,long)
  • 由于这是您的顶点项目,我不想给出太多的代码。但我可以更详细地解释背景线索:

    你现在的计时都是在前台完成的,这意味着除非打开应用程序,否则计时器不会滴答作响。你需要做的是在后台线程中设置计时器。这是一个由操作系统管理的线程,即使应用程序未运行,它仍在运行。由于您是为一个项目而不是为商业项目这样做的,所以我建议您使用Handler方法。像这样:

    //make instance variable of the time the user chose, say... delayInMinutes
    int delayInMinutes;
    ...
    //then whenever you want to start the timer...
    final Runnable updateLocation = new Runnable() {
        public void run() {
            //
            ... do your update location here
            //
        }
    };
    
    handler.postDelayed(updateLocation, delayInMinutes * 60 * 1000);
    

    这应该行得通

    这是一个完美的使用环境。启动IntentService,将重复报警设置为用户所需的间隔,并让IntentService处理位置更新

    这一切都是在后台为您完成的,您不需要运行任何东西