I am creating a route tracking app using a foreground service to get location data. I have sessions, and for each session I want a list of longitude and latitude coordinates. I am currently only able to store one instance of coordinates which updates every callback interval rather than creating a new set entirely. The aim is to have a list of lat and long coordinates to from which to generate a polyline of the route.
Callback method in service class:
// Location callback every
private final LocationCallback locationCallback = new LocationCallback() {
@Override
public void onLocationResult(LocationResult locationResult) {
super.onLocationResult(locationResult);
// If both locationResult and last location are not null then...
// This avoids null pointer exceptions as there are instances where last known location
// will be null
if(locationResult != null && locationResult.getLastLocation() != null){
location = locationResult.getLastLocation();
// Parse the location to the sendBroadcastMessage method to send data
// to receiver in RecordFragment classZ
sendBroadcastMessage(location);
}
}
};
Broadcaster method:
// Method to send data service to receiver in the RecordFragment class
// Location is parsed to the method
private void sendBroadcastMessage(Location location) {
if (location != null) {
Intent intent = new Intent(ACTION_LOCATION_BROADCAST);
// Add extra data to the intent
// When the intent is parsed so is the extra data
intent.putExtra(EXTRA_LATITUDE, location.getLatitude());
intent.putExtra(EXTRA_LONGITUDE, location.getLongitude());
intent.putExtra(EXTRA_SPEED, location.getSpeed());
intent.putExtra(EXTRA_BEARING, location.getBearing());
// Send the data to receiver
LocalBroadcastManager.getInstance(LocationService.this).sendBroadcast(intent);
}
}
Broadcast receiver:
/*
The data sent from the service is handled below
*/
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(
new BroadcastReceiver() {
@SuppressLint({"SetTextI18n", "DefaultLocale"})
@Override
public void onReceive(Context context, Intent intent) {
// Received data is now assigned to variables
double latitude = intent.getDoubleExtra(LocationService.EXTRA_LATITUDE, 0);
double longitude = intent.getDoubleExtra(LocationService.EXTRA_LONGITUDE, 0);
float speed = intent.getFloatExtra(LocationService.EXTRA_SPEED, 0);
float bearing = intent.getFloatExtra(LocationService.EXTRA_BEARING, 0);
// Stopwatch timer is retrieved
time = watch.getTime();
// Calculate the conversion from m/s to knots
// assign calculated value to variable
speedInKnots = speed * 1.194;
// Cast the float to double
doubleBearing = (((double) bearing));
// Calculate conversion from milli-seconds to seconds
// assign calculated value to variable
timeInSeconds = time / 1000;
// Log the location data
Log.d(TAG, "onReceive: Lat: " + latitude + ", Long: " + longitude);
Log.d("Speed_before_conversion", "onReceive: Speed before conversion " + speed);
// Update the text views displayed in record fragment
// round() method called, double value parsed to it and the number of
// decimal places after the value
mCurrent_speedTv.setText("Speed is: " + round(speedInKnots, 2) + " knots");
mBearingTv.setText("Direction: " + round(doubleBearing, 2) + "\u00B0");
mElapsedTimeTv.setText("Elapsed time: " + round(timeInSeconds, 2) + " s");
FirebaseUser user = mAuth.getCurrentUser();
String uid = user.getUid();
Log.d(TAG, "Current user uid: " + uid);
// Put info into HashMap
latLongStoreServer.put("longitude", longitude);
latLongStoreServer.put("latitude", latitude);
FirebaseDatabase database = FirebaseDatabase.getInstance();
// Path toe store user data named "Users"
DatabaseReference reference = database.getReference("Users/" + uid);
// Put data within HashMap in database
reference.child("Sessions").child(sessionID).setValue(latLongStoreServer);
}
}, new IntentFilter(LocationService.ACTION_LOCATION_BROADCAST)
);
return view;
}
Firebase database view:
Thanks in advance.
Very simple fix. Use an arraylist rather than a HashMap. I have implemented the change below.
ArrayList<Double> latLong = new ArrayList<>(); // Create an ArrayList object
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(
new BroadcastReceiver() {
@SuppressLint({"SetTextI18n", "DefaultLocale"})
@Override
public void onReceive(Context context, Intent intent) {
// Received data is now assigned to variables
double latitude = intent.getDoubleExtra(LocationService.EXTRA_LATITUDE, 0);
double longitude = intent.getDoubleExtra(LocationService.EXTRA_LONGITUDE, 0);
float speed = intent.getFloatExtra(LocationService.EXTRA_SPEED, 0);
float bearing = intent.getFloatExtra(LocationService.EXTRA_BEARING, 0);
// Stopwatch timer is retrieved
time = watch.getTime();
// Calculate the conversion from m/s to knots
// assign calculated value to variable
speedInKnots = speed * 1.194;
// Cast the float to double
doubleBearing = (((double) bearing));
// Calculate conversion from milli-seconds to seconds
// assign calculated value to variable
timeInSeconds = time / 1000;
// Log the location data
Log.d(TAG, "onReceive: Lat: " + latitude + ", Long: " + longitude);
Log.d("Speed_before_conversion", "onReceive: Speed before conversion " + speed);
// Update the text views displayed in record fragment
// round() method called, double value parsed to it and the number of
// decimal places after the value
mCurrent_speedTv.setText("Speed is: " + round(speedInKnots, 2) + " knots");
mBearingTv.setText("Direction: " + round(doubleBearing, 2) + "\u00B0");
mElapsedTimeTv.setText("Elapsed time: " + round(timeInSeconds, 2) + " s");
FirebaseUser user = mAuth.getCurrentUser();
String uid = user.getUid();
Log.d(TAG, "Current user uid: " + uid);
latLong.add(longitude);
latLong.add(latitude);
FirebaseDatabase database = FirebaseDatabase.getInstance();
// Path toe store user data named "Users"
DatabaseReference reference = database.getReference("Users/" + uid);
// Put data within HashMap in database
reference.child("Sessions").child(sessionID).setValue(latLong);
}
}, new IntentFilter(LocationService.ACTION_LOCATION_BROADCAST)
);
return view;
}