仅当位置已更改时,才每 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;
}
我已经使用警报管理器每 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;
}