仅当位置已更改时,才每 15 分钟将位置更新到 firebase 数据库? Android

update location to the firebase database every 15 minutes only if the location has been changed? Android

我已经使用警报管理器每 15 分钟将位置上传到 firebase 数据库,但是如果用户仍在他所在的位置(下次更新),我需要停止下一次更新,使用 fused 是可以的位置 API 或 android 中的位置管理器。这应该在应用程序被杀死或 Android 系统处于深度渗透模式(锁定)时起作用。所以我们需要后台定位权限,那也行!但它不应该一直打开位置服务,因为它会耗尽电池。所以应该停止定位服务,直到警报管理器下次启动。

这是我用的TimerService!

 public class TimerService extends BroadcastReceiver {
        public static final int REQUEST_CODE = 12346;
    
        // Triggered by the Alarm periodically (starts the service to run task)
        @Override
        public void onReceive(Context context, Intent intent) {
            Intent serviceIntent = new Intent(context, TrackingService.class);
    
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                ContextCompat.startForegroundService(context, serviceIntent);
            } else {
                context.startService(serviceIntent);
            }
        }
    }

这是 TrackingService 中的方法

private void requestLocationUpdates() {

        LocationRequest request = new LocationRequest();

        request.setInterval(10000);

        request.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        client = LocationServices.getFusedLocationProviderClient(this);
        int permission = ContextCompat.checkSelfPermission(this,
                Manifest.permission.ACCESS_FINE_LOCATION);

        if (permission == PackageManager.PERMISSION_GRANTED) {

             locationCallback = new LocationCallback() {
                @Override
                public void onLocationResult(LocationResult locationResult) {

                    Location location = locationResult.getLastLocation();
                    if (location != null) {
                     updateFirebase(location);
                    }
                }
            };

            client.requestLocationUpdates(request,locationCallback,null);
        }else{
            stopForeground(true);
            stopSelf();
        }
    }

所以我需要帮助实现一个类似这样的新方法,

tryLocationUpdate(Location location){
    if(location==stillInSamePlace){
        //Do not upload to the firebase database
    }else{
        uploadLocation();
    }
}

谁能帮帮我?

我找到了解决办法。您可以在 Shared Preferences 中保存经度和纬度,并检查用户是否走了超过 100 米。如果是,您可以更新服务器,也可以更新共享首选项。

    SharedPreferences prefs = getSharedPreferences("code", MODE_PRIVATE);
    count = prefs.getInt("location_history",0);

    storedLat = prefs.getFloat("storedLat", 0);
    storedLon = prefs.getFloat("storedLon", 0);
    storedAccu = prefs.getFloat("storedAccu", 0);

    float distance = distanceBetweenEarthCoordinates(storedLat, storedLon, (float) location.getLatitude(), (float) location.getLongitude());
                                    if (distance > 100) {
                                        Log.d("TAG", "onLocationResult: New Point" + count + "Distance: " + distance);
                                        storedLat = (float) location.getLatitude();
                                        storedLon = (float) location.getLongitude();
                                        SharedPreferences.Editor editor = getSharedPreferences("uinfo", MODE_PRIVATE).edit();
                                        editor.putFloat("storedLat", storedLat);
                                        editor.putFloat("storedLon", storedLon);
                                        count++;
                                        editor.putInt("location_history", count);
                                        editor.apply();
                                    }

distanceBetweenEarthCoordinates 方法

public static float degreesToRadians(float degrees) {
   return (float) (degrees * Math.PI / 180);
}

public static float distanceBetweenEarthCoordinates(float lat1, float lon1, float lat2, float lon2) {
        float earthRadiusKm = 6371;

        float dLat = degreesToRadians(lat2 - lat1);
        float dLon = degreesToRadians(lon2 - lon1);

        lat1 = degreesToRadians(lat1);
        lat2 = degreesToRadians(lat2);

        float a = (float) (Math.sin(dLat / 2) * Math.sin(dLat / 2) +
                Math.sin(dLon / 2) * Math.sin(dLon / 2) * Math.cos(lat1) * Math.cos(lat2));
        float c = (float) (2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)));
        return earthRadiusKm * c * 1000;
    }