Problem with real time location updates Android - java

So I have a Google Maps activity for my app I'm making in Android Studio and i need to get real time location updates. The goal is to make markers on the map only clickable when close enough to them.
This is the code I have at the moment:
LocationRequest locationRequest = LocationRequest.create();
locationRequest.setInterval(5000);
locationRequest.setFastestInterval(2500);
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationCallback = new LocationCallback() {
#Override
public void onLocationResult(LocationResult locationResult) {
super.onLocationResult(locationResult);
if (locationResult == null) {
return;
}
mLastKnownLocation = locationResult.getLastLocation();
LatLng lastKnownLatLng = new LatLng(mLastKnownLocation.getLatitude(), mLastKnownLocation.getLongitude());
//THIS IS AN EXAMPLE OF THE DISTANCE VALUES
distanceHala = SphericalUtil.computeDistanceBetween(lastKnownLatLng, HalA);
mFusedLocationProviderClient.removeLocationUpdates(locationCallback);
}
};
mFusedLocationProviderClient.requestLocationUpdates(locationRequest, locationCallback, null);
Later on I have some if statements to make them clickable. The problem is now that the location only updates when I just open the Map activity but not while the activity is running. So when I am out of range when I open the activity and then walk close enough, the button still isn't clickable even if I am close enough.

Related

How to update a database column based on the device's location?

I've been working on a map based app, and so far the application gets the data of markers from a Room database as a LiveData object and draws the markers on the map and gets the device's location through a FusedLocationProviderClient.
Now I have tried to create a method that would update a column in the database from 0 to 1 if the device reaches a marker, making the marker "active" and then displaying the marker's name as a toast if that marker's "active" column equals to 1.
So far I have tried to use SphericalUtil.computeDistanceBetween(LatLng1, LatLng2) < distance and if the condition is met, then it calls a method to update the column, but I have not managed to get it to work, as the devices location keeps changing and the markers come from a LiveData List object which are both checked for changes and I don't know how to use these in the computeDistanceBetween method. I have gone through the documents related to markers and other map based objects but so far I have not found a solution.
Here is the method that retrieves and draws the markers on the map.
markerViewModel.getAllMarkers().observe(this, new Observer<List<MarkerObject>>() {
#Override
public void onChanged(List<MarkerObject> markerObjects) {
for (MarkerObject markerObject : markerObjects) {
LatLng latLng = new LatLng(markerObject.getLatitude(), markerObject.getLongitude());
mMap.addMarker(new MarkerOptions()
.title(markerObject.getTitle())
.position(latLng)
.visible(true));
}
}
});
the methods that get and draw the device's location on the map.
/**
* Updates the map's UI settings based on whether the user has granted location permission.
*/
private void updateLocationUI() {
if (mMap == null) {
return;
}
getLocationPermission();
try {
if (locationPermissionGranted) {
mMap.setMyLocationEnabled(true);
mMap.getUiSettings().setMyLocationButtonEnabled(true);
} else {
mMap.setMyLocationEnabled(false);
mMap.getUiSettings().setMyLocationButtonEnabled(false);
lastKnownLocation = null;
}
} catch (SecurityException e) {
Log.e("Exception: %s", e.getMessage());
}
}
/**
* Gets the current location of the device, and positions the map's camera.
*/
public void getDeviceLocation() {
/*
* Get the best and most recent location of the device, which may be null in rare
* cases when a location is not available.
*/
try {
if (locationPermissionGranted) {
Task<Location> locationResult = fusedLocationProviderClient.getLastLocation();
locationResult.addOnCompleteListener(this, new OnCompleteListener<Location>() {
#Override
public void onComplete(#NonNull Task<Location> task) {
if (task.isSuccessful()) {
// Set the map's camera position to the current location of the device.
lastKnownLocation = task.getResult();
if (lastKnownLocation != null) {
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(
new LatLng(lastKnownLocation.getLatitude(),
lastKnownLocation.getLongitude()), DEFAULT_ZOOM));
}
} else {
Log.d(TAG, "Current location is null. Using defaults.");
Log.e(TAG, "Exception: %s", task.getException());
mMap.moveCamera(CameraUpdateFactory
.newLatLngZoom(defaultLocation, DEFAULT_ZOOM));
mMap.getUiSettings().setMyLocationButtonEnabled(false);
}
}
});
}
} catch (SecurityException e) {
Log.e("Exception: %s", e.getMessage(), e);
}
}
I have tried to reach a solution for quite a while through many trials but to no success, I really hope someone can help because I am out of ideas. Any help is well appreciated. Also I don't ask for help in just any case but with this I really am struggling, so literally any documentation or piece of info that would help would be great.
This is something I have previously used to check the distance between location objects, you can use it as it is or modify it to your needs, the code is pretty straight forward.
public final boolean isLocationCloseEnough(Location currentLocation, Location markerLocation, double distance) {
// this is where the method stores the distance between the two locations
float[] distanceInMeters = new float[1];
Location.distanceBetween(currentLocation.getLatitude(), currentLocation.getLongitude(), markerLocation.getLatitude(), markerLocation.getLongitude(), distanceInMeters);
return (double)distanceInMeters[0] < distance;
}
To be able to request location updates you need a location Request like so and request location updates
LocationRequest locationRequest = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY).setInterval(5);
LocationCallback callback = new LocationCallback() {
#Override
public void onLocationResult(LocationResult locationResult) {
// here is the location
Location lastLocation = locationResult.getLastLocation();
// do what needs to be done
}
};
public void sample() {
FusedLocationProviderClient client = LocationServices.getFusedLocationProviderClient(context);
client.requestLocationUpdates(locationRequest, callback, Looper.getMainLooper());
}
Finally when your activity or fragment pauses make sure to remove/stop the updates like so
client.removeLocationUpdates(callback)
You can find more information on LocarionRequest here, and play around with its configurations, https://developers.google.com/android/reference/com/google/android/gms/location/LocationRequest

Getting longitude and latitude from lastKnownLocation()?

I've got a activity that onCreate, it calculates the distance between your location and a event that is nearby, I've used lastKnownLocation to get the current device location and put a marker of it on a google map, but I need it to write the longitude and latitude outside of it's method to be used to calculate distances.
I've used LocationManager to get the rough coordinates but these aren't accurate enough and has a distance of 50 miles for something that's not even half a mile away. I currently have it so will overwrite longitude and latitude got from LocationManager but it does not.
I've attempted to use LocationRequest too and that hasn't helped.
LocationRequest locationRequest = LocationRequest.create();
locationRequest.setInterval(60000);
locationRequest.setFastestInterval(5000);
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
LocationCallback locationCallback = new LocationCallback() {
#Override
public void onLocationResult(LocationResult locationResult){
if(locationRequest==null){
return;
}
for(Location location : locationResult.getLocations()) {
if (location != null){
userLat=location.getLatitude();
userLng=location.getLongitude();
}
}
}
};
LocationServices.getFusedLocationProviderClient(EventLocator.this).requestLocationUpdates(locationRequest,locationCallback, null);
LocationServices.getFusedLocationProviderClient(EventLocator.this).getLastLocation().addOnSuccessListener(new OnSuccessListener<Location>() {
#Override
public void onSuccess(Location location) {
if(location!=null){
double longitude=location.getLongitude();
double latitude=location.getLatitude();
userLng=longitude;
userLat=latitude;
}
}
});
All the permissions are correct, as I said I've used getLastLocation() to place a marker.
Make sure you added location permission in manifest file
If you are using android os 6 above make sure you have location permission
Make sure you GPS service is enabled in you mobile
public Location getLocation() {
LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
if (locationManager != null) {
Location lastKnownLocationGPS = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (lastKnownLocationGPS != null) {
return lastKnownLocationGPS;
} else {
Location loc = locationManager.getLastKnownLocation(LocationManager.PASSIVE_PROVIDER);
System.out.println("1::"+loc);----getting null over here
System.out.println("2::"+loc.getLatitude());
return loc;
}
} else {
return null;
}
}
If still not working try to restart your phone and then try again.
You can create interface and implement it in the class where you need to calculate the distance
Usually GPS takes time to warm up. Your initial location reading could be from a cold GPS. In order to get a more accurate reading keep reading results until you get an accuracy reading that works for you.
Keep in mind GPS on a phone is not very accurate and would not be able to get accurate readings inside buildings or if not enough coverage is in your area at the time.
Last know position does not give you your current position, like it says it is the last know position which could have been more than a few minutes ago. Also it could've come from a cell tower reading instead of a GPS reading.
I'm using this code
lateinit var fusedLocationProviderClient: FusedLocationProviderClient
lateinit var latitude : Double
lateinit var longitude : Double
override fun onCreate() {
super.onCreate()
fusedLocationProviderClient = FusedLocationProviderClient(this)
updateLocationTracking()
}
#SuppressLint("MissingPermission")
private fun updateLocationTracking() {
if(PermissionUtility.isPermissionsGranted(this, Manifest.permission.ACCESS_FINE_LOCATION)) {
val request = LocationRequest().apply {
interval = LOCATION_UPDATE_INTERVAL
fastestInterval = FASTEST_LOCATION_INTERVAL
priority = PRIORITY_HIGH_ACCURACY
}
fusedLocationProviderClient.requestLocationUpdates(
request,
locationCallback,
Looper.getMainLooper()
)
}
}
private val locationCallback = object : LocationCallback() {
override fun onLocationResult(result: LocationResult?) {
super.onLocationResult(result)
result?.locations?.let { locations ->
for(location in locations) {
setLocationData(location)
}
}
}
}
private fun setLocationData(location : Location){
latitude = location.latitude
longitude = location.longitude
}
}
So I figured it out when I couldn't use my phone I use for debugging and used my personal phone for testing, went on the activity and the distances were correct.
Messed around with both debug phone settings and using GPS_PROVIDER and NETWORK_PROVIDER and when my phone used just GPS to get location, it got nothing. Other phone can, so think it's safe to say my debug phone's GPS is borked.
It's a old phone that, when I got a new one, I factory reset to use for debugging, as it helped with the backwards compatibility for older phones and smaller screens. I never thought if the actual hardware was faulty too after the reset.
So error was with the phone itself not the app. Guess it goes to show have two devices to test on.

How to stop properly FusedLocationProviderClient?

I use FusedLocationProviderClient within a Service.
I would like to "stop" it in a right way.
Is it good to use following code?
#Override
public void onDestroy() {
super.onDestroy();
// Stop Looper of FusedLocationProviderClient
if (locationClient != null) {
locationClient = null;
}
}
And the rest code
FusedLocationProviderClient locationClient;
protected void startLocationUpdates() {
// Create the location request to start receiving updates
mLocationRequest = new LocationRequest();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setInterval(UPDATE_INTERVAL);
mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
// Create LocationSettingsRequest object using location request
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
builder.addLocationRequest(mLocationRequest);
LocationSettingsRequest locationSettingsRequest = builder.build();
// Check whether location settings are satisfied
// https://developers.google.com/android/reference/com/google/android/gms/location/SettingsClient
SettingsClient settingsClient = LocationServices.getSettingsClient(this);
settingsClient.checkLocationSettings(locationSettingsRequest);
// new Google API SDK v11 uses getFusedLocationProviderClient(this)
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
locationClient = getFusedLocationProviderClient(this);getFusedLocationProviderClient(this).requestLocationUpdates(mLocationRequest, new LocationCallback() {
#Override
public void onLocationResult(LocationResult locationResult) {
// do work here
onLocationChanged(locationResult.getLastLocation());
}
}, Looper.myLooper());
}
just call removeLocationUpdates in onDestroy
for requestLocationUpdates, it says:
This call will keep the Google Play services connection active, so make sure to call removeLocationUpdates(LocationCallback) when you no longer need it, otherwise you lose the benefits of the automatic connection management.
just change onDestroy(); to this:
#Override
protected void onDestroy() {
super.onDestroy();
if(locationclient!=null)
locationclient.disconnect();
}

Getting the user's location in Android when the phone is locked

I am looking for a solution to get the user's location in a specific time-interval in Android API 17 (Android 4.2) and when the phone is locked.
I've already tried some different code, checked a lot tutorials and searched almost everywhere on the web. The solution might be there, but I think it's a combination of lack of experience with Android developing and interpreting the different right solutions and approaches.
At first I had some pretty basic code, which worked very well when the screen was turned on. Even in the background, the location got updated (as I could check via a Toast message with the longitude and latitude).
I used a Handler to do so:
public void locationRunnable() {
final Handler locationHandler = new Handler();
final int distanceDelay = 5000; // milliseconds
locationHandler.postDelayed(new Runnable(){
public void run() {
// code
mMap.clear();
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return;
}
mMap.setMyLocationEnabled(true);
mMap.setBuildingsEnabled(true);
mMap.getUiSettings().setMyLocationButtonEnabled(false);
LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
Criteria criteria = new Criteria();
String provider = locationManager.getBestProvider(criteria, true);
myLocation = locationManager.getLastKnownLocation(provider);
if (myLocation != null) {
latitudeCurrentPosition = myLocation.getLatitude();
longitudeCurrentPosition = myLocation.getLongitude();
}
currentPattern = shortTest;
Notification.Builder notificationBuilderChecking = new Notification.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))
.setContentTitle("Test app")
.setAutoCancel(true)
.setOnlyAlertOnce(false)
.setContentText("Getting location!")
.setPriority(Notification.PRIORITY_MAX)
.setLights(0xffffffff, 200, 200)
.setVibrate(currentPattern);
Notification notification2 = notificationBuilderChecking.build();
NotificationManager notificationMngr2 = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationMngr2.notify(NOTIFICATION_ID, notification2);
locationHandler.postDelayed(this, distanceDelay);
}
}, distanceDelay);
}
It's just a snippet and the purpose is that in the background, when the screen is locked, this will loop every 10 seconds. And it does. Even when the phone is locked, but only for about 3 times. After 3 times the timer goes up and the phone vibrates less frequent (Doze feature in the way?).
Also, the phone does vibrate, but the location isn't updated. When I unlock the phone with the app in the foreground, the location is still at the place when I locked the phone. After a while (10 seconds) it updates. I use a marker on the map to check.
Again: it works when the phone is unlocked.
Now I'm trying to use a Service, a Service (Intent Service), or a Broadcast Receiver, and start a new Thread, but I don't know how and nothing is working.
Some of the last code I have contains a not functioning Broadcast Receiver and the most recent code contains a AlarmManager:
public void getLocation(Context context) {
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, AlarmIntent.class);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, 0);
//After after 30 seconds
am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, System.currentTimeMillis(), 10000, pi);
context.getSystemService(Context.CONNECTIVITY_SERVICE);
mMap.clear();
mMap.setMyLocationEnabled(true);
mMap.getUiSettings().setMyLocationButtonEnabled(false);
LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
Criteria criteria = new Criteria();
String provider = locationManager.getBestProvider(criteria, true);
myLocation = locationManager.getLastKnownLocation(provider);
latitudeCurrentPosition = myLocation.getLatitude();
longitudeCurrentPosition = myLocation.getLongitude();
LatLng latLngCurrent = new LatLng(latitudeCurrentPosition, longitudeCurrentPosition);
mMap.moveCamera(CameraUpdateFactory.newLatLng(latLngCurrent));
mMap.animateCamera(CameraUpdateFactory.zoomTo(distZoom));
currentPattern = shortTest;
showNotification(context);
mHereIAm = mMap.addMarker(new MarkerOptions()
.position(new LatLng(latitudeCurrentPosition, longitudeCurrentPosition))
.title(weAreHere)
.draggable(false)
.icon(BitmapDescriptorFactory
.fromResource(R.drawable.marker_iconv3)));
mHereIAm.setTag(0);
mHereIAm.showInfoWindow();
}
AndroidManifest permissions:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
But at the long of 10000, Android Studio is telling me "Value will be forced up to 60000 as of Android 5.1; don't rely on this to be exact..." etc. So an AlarmManager isn't useful either.
With the last code, my app isn't even running anymore.
But still: vibrations and stuff still occur, but location updates don't.
In short:
I need some basic (at least, I think it just can't be so difficult, as the only problem is that it's not working when the screen is locked) code, that updates my location on a certain, variable interval.
Maybe I have to use a Handler/Runnable, start a new Thread, use a Service or a Broadcast Receiver. Maybe an AlarmManager may work as well, but I don't know how and which to use.
This is my first post. If anything misses or you guys need more information, please ask. I'm trying to be as precise as possible, without using to much overhead.
Edit 01
Can I use a Job Service to do so? - I've updated the API to 21, so I can make use of this service, but I don't know if that's the right solution I'm looking for? Got some great tutorials for the use of it.
Edit 02
Let me be more clear with less overhead: I am looking for a solution to get the user's current location when the device is locked: with an API, a Service, an IntentService, a BroadcastReceiver, ... - every tutorial tells me something different, even here at Stack Overflow I have troubles with finding the right solution.
I was able to use a Service as well as an Intent Service, but I cannot request any location updates, because of some errors, like:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.name.name/com.name.name.MapsActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void com.google.android.gms.maps.GoogleMap.setMyLocationEnabled(b‌​oolean)' on a null object reference - searching for a solution for this error, gives me another error later on, and on, and on... I got myself stuck in an error-loop and a lot of unnecessary code.
I hope there is a simple way to get the user's location and you guys could help me. Thanks again.
Edit 03
I've followed the instructions on this tutorial and the location is checking. See the following code:
public class LocationService extends Service implements LocationListener {
private final Context mContext;
// flag for GPS status
boolean isGPSEnabled = false;
// flag for network status
boolean isNetworkEnabled = false;
// flag for GPS status
boolean canGetLocation = false;
Location location; // location
double latitude; // latitude
double longitude; // longitude
// The minimum distance to change Updates in meters
private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 10; // 10 meters
// The minimum time between updates in milliseconds
private static final long MIN_TIME_BW_UPDATES = 1000 * 60 * 1; // 1 minute
// Declaring a Location Manager
protected LocationManager locationManager;
public LocationService(Context context) {
this.mContext = context;
getLocation();
}
public Location getLocation() {
try {
locationManager = (LocationManager) mContext
.getSystemService(LOCATION_SERVICE);
// getting GPS status
isGPSEnabled = locationManager
.isProviderEnabled(LocationManager.GPS_PROVIDER);
// getting network status
//isNetworkEnabled = locationManager
// .isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if (!isGPSEnabled && !isNetworkEnabled) {
// no network provider is enabled
} else {
this.canGetLocation = true;
// First get location from Network Provider
if (isNetworkEnabled) {
locationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
Log.d("Network", "Network");
if (locationManager != null) {
location = locationManager
.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if (location != null) {
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
}
// if GPS Enabled get lat/long using GPS Services
if (isGPSEnabled) {
if (location == null) {
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
Log.d("GPS Enabled", "GPS Enabled");
if (locationManager != null) {
location = locationManager
.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (location != null) {
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return location;
}
/**
* Stop using GPS listener
* Calling this function will stop using GPS in your app
* */
public void stopUsingGPS(){
if(locationManager != null){
locationManager.removeUpdates(LocationService.this);
}
}
/**
* Function to get latitude
* */
public double getLatitude(){
if(location != null){
latitude = location.getLatitude();
}
// return latitude
return latitude;
}
/**
* Function to get longitude
* */
public double getLongitude(){
if(location != null){
longitude = location.getLongitude();
}
// return longitude
return longitude;
}
/**
* Function to check GPS/wifi enabled
* #return boolean
* */
public boolean canGetLocation() {
return this.canGetLocation;
}
/**
* Function to show settings alert dialog
* On pressing Settings button will lauch Settings Options
* */
public void showSettingsAlert(){
AlertDialog.Builder alertDialog = new AlertDialog.Builder(mContext);
// Setting Dialog Title
alertDialog.setTitle("GPS is settings");
// Setting Dialog Message
alertDialog.setMessage("GPS is not enabled. Do you want to go to settings menu?");
// On pressing Settings button
alertDialog.setPositiveButton("Settings", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int which) {
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
mContext.startActivity(intent);
}
});
// on pressing cancel button
alertDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
// Showing Alert Message
alertDialog.show();
}
#Override
public void onLocationChanged(Location location) {
}
#Override
public void onProviderDisabled(String provider) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public IBinder onBind(Intent arg0) {
return null;
}
}
I've disabled Network location and only allowed GPS location for testing - tested both.
And my MapsActivity:
public void getLocation(){
gps = new LocationService(MapsActivity.this);
if(gps.canGetLocation()) { // gps enabled} // return boolean true/false
latitudeCurrentPosition = gps.getLatitude(); // returns latitude
longitudeCurrentPosition = gps.getLongitude(); // returns longitude
latLngCurrent = new LatLng(latitudeCurrentPosition, longitudeCurrentPosition);
Toast toastLatCur = makeText(getApplicationContext(), "Lat Current: " + latitudeCurrentPosition + "" ,Toast.LENGTH_SHORT);
toastLatCur.show();
Toast toastLongCur = makeText(getApplicationContext(), "Long Current: " + longitudeCurrentPosition + "" ,Toast.LENGTH_SHORT);
toastLongCur.show();
}
else {
gps.showSettingsAlert();
}
if(goToLocation){
mMap.moveCamera(CameraUpdateFactory.newLatLng(latLngCurrent));
goToLocation = false;
if(firstStart){
mMap.animateCamera(CameraUpdateFactory.zoomTo(distZoom));
firstStart = false;
}
}
vibrateNotification();
}
When the screen is locked, the phone vibrates as I told in vibrateNotificatoin() - works perfectly every 10 seconds. But the location doesn't get updated! So a Service is not the right way to solve this. Help!
You should use the service to perform tasks which are needed to be done even when the application is not running. Give a try.

Occasionally getting callbacks after removeLocationUpdates()

Creating my first app,
Looking for locations using the GoogleApi and the callback is working as intended. I use the location and it gets put into a database, onDestroy() I am closing the DB connection. But now I occasionally get a stack trace saying
java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase
I added a removeLocationUpdates() right before the closeDB call, and that MOSTLY solved the issue, but it still happens from time to time. It appears that I may still be getting a rogue callback after removeLocationUpdates and closeDB have been called.
Is this a typical delay? could a 500ms delay between the removeLocUpdates and the closeDB fix the issue? I'd imagine there'd be a better way, or that maybe I am simply doing something wrong with the removeLocUpdates. But the stack trace seems pretty clear that I am getting a callback as the trace shows
onLocationChanged
part way down the stack
EDIT to add Code:
onCreate():
openDB();
if (mGoogleApiClient == null) {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
//End Google Location API implementation
locationListener = new com.google.android.gms.location.LocationListener() {
#Override
public void onLocationChanged(Location location) {
//newestLocation = location;
//bestLocation = bestLocation();
//todo maybe come back and reimplement bestLocation() if needed
bestLocation = location;
getCode(null);
saveCode(null);
}};
onDestroy()
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
if (mGoogleApiClient.isConnected()) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, locationListener);
}
}
closeDB();
onConnected()
public void onConnected(#Nullable Bundle bundle) {
CharSequence text = "Google API Connected";
Toast.makeText(getApplicationContext(), text, Toast.LENGTH_SHORT).show();
LocationRequest locationRequest = new LocationRequest()
.setFastestInterval(500)
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setMaxWaitTime(3000)
.setInterval(1000);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.ACCESS_FINE_LOCATION},10);
return;
}else {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, locationRequest, locationListener);
}
return;
}
I appreciate your help on the matter

Categories