Location Service Gps Force Closed

Location service GPS Force closed

I have implemented my own version of the GPSTracker class from http://www.androidhive.info/2012/07/android-gps-location-manager-tutorial/

Using this you can turn on the GPS and receive a callback as soon as a valid location is available. This might take a little while depending on the location of the device but will give a much more precise and reliable position.

With my implementation you can do something like this:

private GPSTracker gps;
private FirstFixListener firstFixListener;
private LocationUpdateListener locationUpdateListener;

private void sendGPStoSMS() {
gps = GPSTracker.getInstance(context);
firstFixListener = new MyFirstFixListener();
locationUpdateListener = new MyLocationUpdateListener();
gps.startUsingGPS(firstFixListener, locationUpdateListener);

}

private class MyFirstFixListener implements FirstFixListener {

@Override
public void onFirsFixChanged(boolean hasGPSfix) {
if (hasGPSfix == true) {
Location position = gps.getLocation();
// send SMS with position

// stop the gps and unregister callbacks
gps.stopUsingGPS(firstFixListener, locationUpdateListener);
}

}

}

private class MyLocationUpdateListener implements LocationUpdateListener {

@Override
public void onLocationChanged(Location location) {
// hand you each new location from the GPS
// you do not need this as you only want to send a single position

}

}

And here is my implementation of GPSTracker:

public class GPSTracker extends Service implements LocationListener {

private static final String TAG = "GPSTracker";

/**
* Register to receive callback on first fix status
*
* @author Morten
*
*/
public interface FirstFixListener {

/**
* Is called whenever gps register a change in first-fix availability
* This is valuable to prevent sending invalid locations to the server.
*
* @param hasGPSfix
*/
public void onFirsFixChanged(boolean hasGPSfix);
}

/**
* Register to receive all location updates
*
* @author Morten
*
*/
public interface LocationUpdateListener {
/**
* Is called every single time the GPS unit register a new location
* The location param will never be null, however, it can be outdated if hasGPSfix is not true.
*
* @param location
*/
public void onLocationChanged(Location location);
}

private Context mContext;

// flag for GPS status
private List<FirstFixListener> firstFixListeners;
private List<LocationUpdateListener> locationUpdateListeners;
boolean isGPSFix = false;
boolean isGPSEnabled = false;
private GPSFixListener gpsListener;

// flag for GPS status
boolean canGetLocation = false;

Location location; // location
double latitude; // latitude
double longitude; // longitude
long mLastLocationMillis;

private boolean logLocationChanges;

// Declaring a Location Manager
protected LocationManager locationManager;

/** removed again as we need multiple instances with different callbacks **/
private static GPSTracker instance;

public static GPSTracker getInstance(Context context) {
if (instance != null) {
return instance;
}
return instance = new GPSTracker(context);
}

private GPSTracker(Context context) {
this.mContext = context;
gpsListener = new GPSFixListener();
firstFixListeners = new ArrayList<GPSTracker.FirstFixListener>();
locationUpdateListeners = new ArrayList<GPSTracker.LocationUpdateListener>();
}

public boolean hasGPSFirstFix() {
return isGPSFix;
}

private void addFirstFixListener(FirstFixListener firstFixListener) {
this.firstFixListeners.add(firstFixListener);
}

private void addLocationUpdateListener(
LocationUpdateListener locationUpdateListener) {
this.locationUpdateListeners.add(locationUpdateListener);
}

private void removeFirstFixListener(FirstFixListener firstFixListener) {
this.firstFixListeners.remove(firstFixListener);
}

private void removeLocationUpdateListener(
LocationUpdateListener locationUpdateListener) {
this.locationUpdateListeners.remove(locationUpdateListener);
}

public void setLogLocationChanges(boolean logLocationChanges) {
this.logLocationChanges = logLocationChanges;
}

public Location getLocation() {
return location;
}

private Location startLocationListener() {
canGetLocation = false;

try {
locationManager = (LocationManager) mContext
.getSystemService(Service.LOCATION_SERVICE);

// getting GPS status
isGPSEnabled = locationManager
.isProviderEnabled(LocationManager.GPS_PROVIDER);

if (isGPSEnabled) {
if (location == null) {
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER, 0, 0, this);
locationManager.addGpsStatusListener(gpsListener);
if (locationManager != null) {
location = locationManager
.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (location != null) {
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
}
} else {
showSettingsAlert();
}

} catch (Exception e) {
e.printStackTrace();
}

return location;
}

public void stopUsingGPS(FirstFixListener firstFixListener,
LocationUpdateListener locationUpdateListener) {
if (firstFixListener != null)
removeFirstFixListener(firstFixListener);
if (locationUpdateListener != null)
removeLocationUpdateListener(locationUpdateListener);

stopUsingGPS();
}

/**
* Stop using GPS listener Calling this function will stop using GPS in your
* app
* */
public void stopUsingGPS() {
Log.d("DEBUG", "GPS stop");
if (locationManager != null) {
locationManager.removeUpdates(GPSTracker.this);
location = null;

if (gpsListener != null) {
locationManager.removeGpsStatusListener(gpsListener);
}

}
isGPSFix = false;
location = null;
}

public void startUsingGPS(FirstFixListener firstFixListener,
LocationUpdateListener locationUpdateListener) {
Log.d("DEBUG", "GPS start");
if (firstFixListener != null)
addFirstFixListener(firstFixListener);
if (locationUpdateListener != null)
addLocationUpdateListener(locationUpdateListener);

startLocationListener();
}

/**
* Function to get latitude
* */
public double getLatitude() {
if (location != null) {
latitude = location.getLatitude();
} else {
Log.e("GPSTracker", "getLatitude location is null");
}

// return latitude
return latitude;
}

/**
* Function to get longitude
* */
public double getLongitude() {
if (location != null) {
longitude = location.getLongitude();
} else {
Log.e("GPSTracker", "getLongitude location is null");
}

// 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 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) {
if ( location == null)
return;

this.location = location;

mLastLocationMillis = SystemClock.elapsedRealtime();
canGetLocation = true;
if (isGPSFix) {

if (locationUpdateListeners != null) {
for (LocationUpdateListener listener : locationUpdateListeners) {
listener.onLocationChanged(location);
}
}
}

}

@Override
public void onProviderDisabled(String provider) {
canGetLocation = false;
}

@Override
public void onProviderEnabled(String provider) {

}

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

@Override
public IBinder onBind(Intent arg0) {
return null;
}

private boolean wasGPSFix = false;

// http://stackoverflow.com/questions/2021176/how-can-i-check-the-current-status-of-the-gps-receiver
// answer from soundmaven
private class GPSFixListener implements GpsStatus.Listener {
public void onGpsStatusChanged(int event) {
switch (event) {
case GpsStatus.GPS_EVENT_SATELLITE_STATUS:
isGPSFix = (SystemClock.elapsedRealtime() - mLastLocationMillis) < 3000;

if (isGPSFix != wasGPSFix) { // only notify on changes
wasGPSFix = isGPSFix;
for (FirstFixListener listener : firstFixListeners) {
listener.onFirsFixChanged(isGPSFix);
}
}

break;
case GpsStatus.GPS_EVENT_FIRST_FIX:
// Do something.

break;
}
}
}
}

Force close on Android Location Permissions

requestPermissions() is asynchronous. By the time that method returns, you do not have permission yet. The user has not even been asked to grant you the permission by that time.

If you determine that you do not hold the permission, and you need to call requestPermissions(), you cannot try getting the location yet. You need to do that in onRequestPermissionsResult() at the earliest, when you are informed about whether the user granted you permission.

See this sample app to see how to request permissions and then request a location.

Background service when app is not open or closed

According to google developer recent policy you shouldnt be using
manifest based broadcast receivers , though it will not work above 26
SDK

https://developer.android.com/guide/components/broadcasts#changes-system-broadcasts

So no need to use broadcast receiver to restart service.

Use this code to restart service

Updated service class

public class LocationService extends Service {
private static final String TAG = "SERVICE";
private LocationManager mLocationManager = null;
private static final int LOCATION_INTERVAL = 0;
private static final float LOCATION_DISTANCE = 0;

private class LocationListener implements android.location.LocationListener {
Location mLastLocation;

public LocationListener(String provider) {
Log.e(TAG, "LocationListener " + provider);
mLastLocation = new Location(provider);
}

@Override
public void onLocationChanged(Location location) {

mLastLocation.set(location);
}

@Override
public void onProviderDisabled(String provider) {
Log.e(TAG, "onProviderDisabled: " + provider);
}

@Override
public void onProviderEnabled(String provider) {
Log.e(TAG, "onProviderEnabled: " + provider);
}

@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
Log.e(TAG, "onStatusChanged: " + provider);
}
}

LocationListener[] mLocationListeners = new LocationListener[]{
new LocationListener(LocationManager.GPS_PROVIDER),
new LocationListener(LocationManager.NETWORK_PROVIDER)
};

@Override
public IBinder onBind(Intent arg0) {
return null;
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e(TAG, "onStartCommand");
super.onStartCommand(intent, flags, startId);
LocationInitialize();
return START_STICKY;
}

@Override
public void onCreate() {
super.onCreate();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startMyOwnForeground();
} else {
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, "1");
Notification notification = notificationBuilder.setOngoing(true)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("My service.")
.setPriority(NotificationManager.IMPORTANCE_MIN)
.setCategory(Notification.CATEGORY_SERVICE)
.build();
startForeground(1, notification);
}
}

@RequiresApi(api = Build.VERSION_CODES.O)
private void startMyOwnForeground() {
String channelName = "My service";
NotificationChannel chan = new NotificationChannel("2", channelName, NotificationManager.IMPORTANCE_NONE);
chan.setLightColor(Color.BLUE);
chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
assert manager != null;
manager.createNotificationChannel(chan);

NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, "2");
Notification notification = notificationBuilder.setOngoing(true)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("My service")
.setPriority(NotificationManager.IMPORTANCE_MIN)
.setCategory(Notification.CATEGORY_SERVICE)
.build();
startForeground(2, notification);
}

public void LocationInitialize(){
initializeLocationManager();
try {
mLocationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER, LOCATION_INTERVAL, LOCATION_DISTANCE,
mLocationListeners[1]);
} catch (java.lang.SecurityException ex) {
Log.i(TAG, "fail to request location update, ignore", ex);
} catch (IllegalArgumentException ex) {
Log.d(TAG, "network provider does not exist, " + ex.getMessage());
}
try {
mLocationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER, LOCATION_INTERVAL, LOCATION_DISTANCE,
mLocationListeners[0]);
} catch (java.lang.SecurityException ex) {
Log.i(TAG, "fail to request location update, ignore", ex);
} catch (IllegalArgumentException ex) {
Log.d(TAG, "gps provider does not exist " + ex.getMessage());
}
}

@Override
public void onDestroy() {
Log.e(TAG, "onDestroy");
super.onDestroy();
// no need to do anything here
//Intent broadcastIntent = new Intent();
//broadcastIntent.setAction("restartservice");
//broadcastIntent.setClass(this, RestartService.class);
//this.sendBroadcast(broadcastIntent);
}

private void initializeLocationManager() {
Log.e(TAG, "initializeLocationManager");
if (mLocationManager == null) {
mLocationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
}
}

@Override
public void onTaskRemoved(Intent rootIntent) {
Intent restartServiceIntent = new Intent(getApplicationContext(), this.getClass());
restartServiceIntent.setPackage(getPackageName());

PendingIntent restartServicePendingIntent = PendingIntent.getService(getApplicationContext(), 1, restartServiceIntent, PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmService = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
alarmService.set(
AlarmManager.ELAPSED_REALTIME,
SystemClock.elapsedRealtime() + 1000,
restartServicePendingIntent);

super.onTaskRemoved(rootIntent);
}
}

Location Services App - Xcode Stop leaves location services running forever

I am not quite sure why this behavior is not expected to begin with. To stop significant location updates you must call stopMonitoringSignificantLocationChanges method. When you hit the stop button in Xcode, you just forcefully kill the app with none of your housekeeping code being executed. That means nobody tells location manager to stop doing what your app requested it to do, and when iPhone gets a new location, it launches your app to background mode and delivers that location reading to it.

I doubt you can do anything to change this behavior, as it essentially would mean teaching Xcode how to do a cleanup, which is specific for your app.

Re: "little location icon from status bar"

First of all, even if the arrow is solid, it does not necessarily mean the app keeps using GPS and aggressively drains phone battery. This arrow icon is about privacy, it is used to tell user that at least one app may learn about location change using method or methods other than or in addition to region monitoring.

Please keep in mind that the arrow is solid if one of the following services is active:

  • standard location updates with GPS
  • standard location updates without GPS
  • significant location updates
  • visit tracking

The reason I asked you which location service you use is that the last two services will resume on iPhone reboot and will not be interrupted if you kill the app. Standard location updates will not resume on phone reboot and will be cancelled on app termination.

Finding out how my location is being gathered. Force close on Location.getProvider();

Good morning this are native methods from the gps provider and you can implement them in your project...

     @Override
public void onProviderDisabled(String provider)
{
Log.e(TAG, "onProviderDisabled: " + provider);
}
@Override
public void onProviderEnabled(String provider)
{
Log.e(TAG, "onProviderEnabled: " + provider);
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras)
{
Log.e(TAG, "onStatusChanged: " + provider);// here you will see gps or network in your logcat
}
}
LocationListener[] mLocationListeners = new LocationListener[] {
new LocationListener(LocationManager.GPS_PROVIDER),
new LocationListener(LocationManager.NETWORK_PROVIDER)
};

02-24 11:28:29.722 16488-16488/com.solmoviles.tmp E/BOOMBOOMTESTGPS﹕ onProviderDisabled: gps

02-24 11:28:29.790 16488-16488/com.solmoviles.tmp E/BOOMBOOMTESTGPS﹕ onProviderDisabled: network
02-24 11:28:29.790 16488-16488/com.solmoviles.tmp E/BOOMBOOMTESTGPS﹕ onProviderDisabled: gps

EDIT here is the full code of the class where I get the location

private class LocationListener implements android.location.LocationListener{
Location mLastLocation;
public LocationListener(String provider)
{
Log.e(TAG, "LocationListener " + provider);
mLastLocation = new Location(provider);
}
@Override
public void onLocationChanged(Location location)
{
Log.e(TAG, "onLocationChanged: " + location);
mLastLocation.set(location);
}
@Override
public void onProviderDisabled(String provider)
{
Log.e(TAG, "onProviderDisabled: " + provider);
}
@Override
public void onProviderEnabled(String provider)
{
Log.e(TAG, "onProviderEnabled: " + provider);
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras)
{
Log.e(TAG, "onStatusChanged: " + provider);
}
}
LocationListener[] mLocationListeners = new LocationListener[] {
new LocationListener(LocationManager.GPS_PROVIDER),
new LocationListener(LocationManager.NETWORK_PROVIDER)
};
@Override
public IBinder onBind(Intent arg0)
{
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId)
{
Log.e(TAG, "onStartCommand");
super.onStartCommand(intent, flags, startId);
return START_STICKY;
}
@Override
public void onCreate()
{

Log.e(TAG, "onCreate");
initializeLocationManager();
try {
mLocationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER, LOCATION_INTERVAL, LOCATION_DISTANCE,
mLocationListeners[1]);
} catch (java.lang.SecurityException ex) {
Log.i(TAG, "fail to request location update, ignore", ex);
} catch (IllegalArgumentException ex) {
Log.d(TAG, "network provider does not exist, " + ex.getMessage());
}
try {
mLocationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER, LOCATION_INTERVAL, LOCATION_DISTANCE,
mLocationListeners[0]);
} catch (java.lang.SecurityException ex) {
Log.i(TAG, "fail to request location update, ignore", ex);
} catch (IllegalArgumentException ex) {
Log.d(TAG, "gps provider does not exist " + ex.getMessage());
}
}
@Override
public void onDestroy()
{
Log.e(TAG, "onDestroy");
super.onDestroy();
if (mLocationManager != null) {
for (int i = 0; i < mLocationListeners.length; i++) {
try {
mLocationManager.removeUpdates(mLocationListeners[i]);
} catch (Exception ex) {
Log.i(TAG, "fail to remove location listners, ignore", ex);
}
}
}
}
private void initializeLocationManager() {
Log.e(TAG, "initializeLocationManager");
if (mLocationManager == null) {
mLocationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
}
}

Location with GPS is not always correct and crashes without connection

  1. You are using getLastKnownLocation() to get location but You doesn't use

    locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 2000, 0, null);

The second parameter is delation between updates in milliseconds. The fourth parameter is listener, you can use it to update locations vithout any async threads, for example:

...
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 2000, 0, this);
...

public void onLocationChanged(Location arg0) {
if (arg0 != null){
double longitude = arg0.getLongitude();
double latitude = arg0.getLatitude();

...
}
}
  1. LocationManager.NETWORK_PROVIDER is no good way to recieve location because it using location recieved by another location services when device was near wifi router. If location was not recieved near some router by another services in some reasons it will not provide you correct location.

  2. There is a bug in some devices (for example Sony) when mobile data turned on and networkInfo == null. Some times it solves getting needed networkInfo directly. For Exmple:

    android.net.NetworkInfo wifi = cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
    android.net.NetworkInfo mobile = cm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);

Example:

public class MyActivity extends Activity implements LocationListener
{

...

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

...

locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);

... // do something

locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 2000, // every 2 seconds
0, this);
}

...

public void onLocationChanged(Location arg0) {
if (arg0 != null){
double longitude = arg0.getLongitude();
double latitude = arg0.getLatitude();

...
}
}

}

continuous gps tracking for every x minutes in android even if app is closed (or force closed)

There is no way to keep service running in the background if user force-closes or kills the app.

To improve chances of the service for not being killed when system running low on memory I would recommend to make it foreground. You would also need to make it foreground to avoid being suspended in Android Marshmallow (see Power-Saving Optimizations).

You can also take a look at Traccar Client open source GPS tracking app. You can either take it as a base for your app or just borrow some ideas from there.

Retrieving current position causes my Android app to force close

I'm guessing line 23 of your MainActivity is this:

Toast.makeText(MainActivity.this, "Latitude -> "+Double.toString(loc.getLatitude())

Put in a null check after this line

 Location loc = lm.getLastKnownLocation(lm.NETWORK_PROVIDER);

It is possible there is no last known location from the network provider and loc is null.

Try this:

     LocationManager lm = (LocationManager)
getSystemService(Context.LOCATION_SERVICE);

// connect to the GPS location service
Location loc = lm.getLastKnownLocation(lm.NETWORK_PROVIDER);

//Try to get it from the GPS_PROVIDER
if (loc == null)
{
loc = lm.getLastKnownLocation(lm.GPS_PROVIDER);
}

if (loc != null){
Toast.makeText(MainActivity.this, "Latitude -> "+Double.toString(loc.getLatitude())
+" Longitude is -> "+Double.toString(loc.getLongitude()), Toast.LENGTH_LONG).show();
}else{
//If it's still null there is no other way to get the last location. Display a message if you like.
Toast.makeText(MainActivity.this, "No location found", Toast.LENGTH_LONG).show();
}


Related Topics



Leave a reply



Submit