I am starting my background service from the MainActivity with startService(intent) which sends the location of the user to the server. I want to enable the user to stops this service (also stoping requestLocationUpdates of firing the data from the onLocationChanged method) if he does not wish it by clicking button in the Menu.
I have tried the code in the onOptionsItemSelected method but the service it still works when I click button.
How can I stop this service?
MainActivity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.route_available);
Intent i = new Intent(this, TrackingService.class);
startService(i);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.disconnect_id:
System.out.println("test onCreateOptionsMenu was invoked.");
// Stop the service when the Menu button clicks.
Intent i = new Intent(this, TrackingService.class);
stopService(i);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
Tracking Service class:
public class TrackingService extends Service {
....
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
Toast.makeText(this, "Location Updation has started", Toast.LENGTH_LONG)
.show();
Log.v("X", "Response:in onStartCommand()");
detectLocation();
stopSelf();
return START_STICKY;
}
private void detectLocation() {
// TODO Auto-generated method stub
Toast.makeText(this, "Inside detectlocation()", Toast.LENGTH_SHORT)
.show();
LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
LocationListener ll = new MyLocationListener(this);
// location updates: at least 0 meter and 60 seconds change.
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 30 * 1000, 0,
ll);
Log.v("X", "Response:After lm1.requestLocationUpdates ");
enableGPS(lm);
}
}
It looks like the way you have it coded now, your Service isn't really doing anything.
Because you have registered your MyLocationListener instance as the LocationListener, stopping the Service doesn't do anything.
Also, since you call stopSelf() in onStartCommand(), you're stopping the Service immediately every time it starts.
I would recommend making the Service the LocationListener, and don't call stopSelf() in onStartCommand()
.
Also, override onDestroy() in the Service, and explicitly call removeUpdates() in order to ensure your app releases it's request to keep the GPS radio active.
Something like this:
public class TrackingService extends Service implements LocationListener{
LocationManager lm; //make instance variable
//....
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
Toast.makeText(this, "Location Updation has started", Toast.LENGTH_LONG)
.show();
Log.v("X", "Response:in onStartCommand()");
detectLocation();
//stopSelf(); //don't stop the service here
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
lm.removeUpdates(this);
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
private void detectLocation() {
// TODO Auto-generated method stub
Toast.makeText(this, "Inside detectlocation()", Toast.LENGTH_SHORT)
.show();
lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
//LocationListener ll = new MyLocationListener(this);
// location updates: at least 0 meter and 60 seconds change.
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 30 * 1000, 0,
this);
Log.v("X", "Response:After lm1.requestLocationUpdates ");
enableGPS(lm);
}
#Override
public void onLocationChanged(Location location) {
//put your location changed code here
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
}
}
Related
RequestLocationUpdates is a method of LocationManager, receives GPS information periodically.
I think if I send from onCreate application should not be a problem because it will not overcharge the main thread, I'm right?
If I want to receive information requestLocationUpdates, even after the application closed, from where should I send it?
I think for the most part you will want to register a BroadcastReceiver. one of the broadcasts that you can watch for is when the location changes. There are a few logistical concerns with this such as how to interact with the BroadcastReceiver and how much battery your application will consume. A good summary of how to address these concerns can be found here.
Essentially you will want to make an Intent (your specific way of identfying an event you're looking for has happened) and a PendingIntent(A way to make that event interact with LocationServices).
PendingIntent launchIntent = PendingIntent.getBroadcast(context, 0, myIntent, 0);
manager.requestLocationUpdates(provider, minTime, minDistance, launchIntent);
In the end the best solution I found was to use Service, as follows:
public class GpsService extends Service implements LocationListener{
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
LocationManager LocManager =(LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
LocManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5000, 0, this);
return Service.START_STICKY;
}
public void onLocationChanged(Location location) {
Log.i("location", String.valueOf(location.getLongitude()));
Log.i("location", String.valueOf(location.getLatitude()));
}
public void onProviderDisabled(String provider) {
Log.i("info", "Provider OFF");
}
public void onProviderEnabled(String provider) {
Log.i("info", "Provider ON");
}
public void onStatusChanged(String provider, int status, Bundle extras) {
Log.i("LocAndroid", "Provider Status: " + status);
Log.i("info", "Provider Status: " + status);
}
}
And in onCreate () I launch the service:
public class PacienteApp extends Application {
#Override
public void onCreate() {
Intent intent = new Intent(this, GpsService.class);
this.startService(intent);
}
}
Using Broadcast Receiver is a good idea, but laborious as they are not allowed to use handlers within this class. And anyway you need the service to run in the background.
I am working on an app which will track user location and I have added proximity alert to do some action in that specific location. I practiced this using activity and it works fine, but in background it doesn't work. Here is an example it doesn't work. Kindly tell me a solution if any one has:
public class TrackLoc extends Service implements LocationListener{
LocationManager locationManager;
Location location;
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
#Deprecated
public void onStart(Intent intent, int startId) {
// TODO Auto-generated method stub
super.onStart(intent, startId);
locationManager=(LocationManager) getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER,
10000,
0, this);
if (locationManager != null) {
{location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
onLocationChanged(location);
}
}
hope it will helps :
public class TrackLoc extends Service implements LocationListener{
LocationManager locationManager;
Location location;
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
locationManager=(LocationManager) getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER,
10000,
0, this);
locationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER,
10000,
0, this);
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
}
#Override
public void onLocationChanged(Location location) {
// Do work with new location. Implementation of this method will be covered later.
Log.e("Location updated: ", "Lat: "+location.getLatitude()+" Long: "+location.getLongitude());
}
}
In this i replace request location code from OnStart() to onStartCommand() because of onStartCommand() is calls when another component, such as an activity, requests that the service be started, by calling startService(). Once this method executes, the service is started and can run in the background indefinitely. If you implement this, it is your responsibility to stop the service when its work is done, by calling stopSelf() or stopService().
If you need to track him just for proximity alerts use the Location APIs, in particular the Geofence API.
You can track up to 100 Geofences without burning the device's battery.
i want a background service class that which will get the user current location sends as a notification to the user if the user changes its location then the updated location will sends back to the user as a notification..even if the user close the application then also will receive the notification (the service will trace the location in background even application closed)
currently i am using this service for tracing the location which works if the application in foreground
can u pls. help me to get out of this i am struggling for 4 hours
in your activity unlike the one that you are using make your buttons start and stop the service and it will run in the background unless the user reopens the app and stops it
Intent i = new Intent(MainActivity.this,gpsservice.class);
startService(new Intent(i));
or to stop
Intent j = new Intent(MainActivity.this,gpsservice.class);
stopService(new Intent(j));
use this service
public class gpsservice extends Service{
private LocationManager locationManager;
MyLocationListener locationListenerp;
public gpsservice() {
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate() {
locationManager = (LocationManager)
getSystemService(Context.LOCATION_SERVICE);
locationListenerp = new MyLocationListener();
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER, 5000, 10, locationListenerp);
}
#Override
public void onDestroy() {
locationManager.removeUpdates(locationListenerp);
}
#Override
public void onStart(Intent intent, int startid) {
Toast.makeText(this, "location Service Started", Toast.LENGTH_LONG).show();
}
public class MyLocationListener implements LocationListener {
#Override
public void onLocationChanged(Location location) {
Toast.makeText(getApplicationContext(), "I was here", Toast.LENGTH_LONG).show();
}
#Override
public void onProviderDisabled(String s) {
}
#Override
public void onProviderEnabled(String s) {
}
#Override
public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
// TODO Auto-generated method stub
}
}
}
I have a service within an android app which implements locationListener to keep track of users changing location.
Every time the location is changed, I want to send it to the server.
So, in the onLocationChanged method I am fetching the latitude and longitude. I want to send them to the server over network. Hence, I created a new thread (as network operations are not allowed on main thread). However, I get a java.lang.NullPointerException for this thread.
What should I do?
Here's my code .....
public class SService extends Service implements LocationListener{
public class LocalBinder extends Binder {
SplashService getService() {
return SplashService.this;
}
}
#Override
public void onCreate() {
super.onCreate();
mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
//Shows notification
showNotification();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("SService", "Received start id " + startId + ": " + intent);
// Sets parameters and location providers
setLocationParam();
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
// Cancel the persistent notification.
mNM.cancel(NOTIFICATION);
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
// This is the object that receives interactions from clients. See
// RemoteService for a more complete example.
private final IBinder mBinder = new LocalBinder();
#Override
public void onLocationChanged(Location location) {
// Getting latitude of the current location
latitude = location.getLatitude();
// Getting longitude of the current location
longitude = location.getLongitude();
Log.v("SSERVICE",latitude+" "+longitude);
final SMessage sm=new SMessage("0", latitude, longitude,"");
// Creates new thread
new SThread(sm).start();
}
#Override
public void onProviderDisabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
// TODO Auto-generated method stub
}
}
i'm currently writing an app that should to the following:
The UI only contains one toggle button. If it is turned on the GPS Position shall be sent to an external server. If it is turned off, nothing shall happen.
If the Button was turned on and the app (activity) is closed the location should still be send until the Button is turned off again.
How can i achieve this ? I read a lot of threads and tutorials and on dev.google.com, but i was not able to find the best solution for my problem.
My current approach:
MainActivity.java
public void onClick(View v) {
if (onOffButton.isChecked()) {
Intent startIntent = new Intent(this, LocationService.class);
startService(startIntent);
} else {
stopService(new Intent(this, LocationService.class));
}
}
LocationService.java
public class LocationService extends Service implements LocationListener {
final public static String START_ACTION = "START_LOCATION";
final public static int NOTE_ID = 1;
private int updateRate;
private LocationManager locationManager;
private NotificationManager notifyManager;
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
// show popup message
Toast.makeText(this, getText(R.string.start_message), Toast.LENGTH_SHORT).show();
// display icon in status bar
requestLocationUpdates();
}
private void requestLocationUpdates() {
if(locationManager != null)
locationManager.removeUpdates(this);
// get location service
Criteria crit = new Criteria();
crit.setPowerRequirement(Criteria.ACCURACY_FINE);
String bestProvider = getLocationManager().getBestProvider(crit, true);
getLocationManager().requestLocationUpdates(bestProvider, updateRate * 1000,
0 /* minDist */, this);
LocationService.running = true;
}
#Override
public void onDestroy() {
super.onDestroy();
getLocationManager().removeUpdates(this);
notifyManager.cancel(NOTE_ID);
Toast.makeText(this, getText(R.string.stop_message), Toast.LENGTH_SHORT).show();
LocationService.running = false;
}
#Override
public void onLocationChanged(Location location) {
//Send Location to Server
}
#Override
public void onProviderDisabled(String provider) {
// TODO stop service, notify user
}
#Override
public void onProviderEnabled(String provider) {
requestLocationUpdates();
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
// TODO notify user
}
private LocationManager getLocationManager() {
if (this.locationManager == null)
this.locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
return this.locationManager;
}
}
I got this from a very old gps tracker i found on the Internet (i know that onStart() is deprecated and should replaced with onCommandStart()) I just want to know if the general approach is good..
Regards.
The approach looks fine. You just need to implement the call-back methods to report your location.