Android foreground service with location updates gets killed once onHandle completed - android

i want to show persistence notification my location traction service but the service gets killed once the onHandleIndent completes, there is a timertask to get the location periodically ,
my problem is,
Its working fine if onStartCommand not returning START_STICKY. but in this case notification is not appearing.
i want my service to be running forever with persistence notification.
here is my class
public class TrackLocation extends IntentService {
public static final String START_TRACKING = "START_TRACKING";
public static final String STOP_TRACKING = "STOP_TRACKING";
private static final long MINIMUM_DISTANCE_CHANGE_FOR_UPDATES = 1;
private static final long MINIMUM_TIME_BETWEEN_UPDATES = 10000;
double totalDistance = 0;
Location locationFirstOld;
protected LocationManager locationManager;
static double n = 0;
Long s1, r1;
double plat, plon, clat, clon, dis;
Thread t1;
EditText e1;
boolean bool = true;
private String booking_id;
private FusedLocationProviderClient mFusedLocationClient;
public static boolean isTrackingEnabled;
/**
* Creates an IntentService. Invoked by your subclass's constructor.
*
*/
public TrackLocation() {
super("Distance tracking service");
}
#Override
protected void onHandleIntent(#Nullable Intent intent) {
String action = intent.getAction();
if (action.equals(START_TRACKING)) {
isTrackingEnabled = true;
booking_id = intent.getStringExtra("booking_id");
startTracking();
} else {
isTrackingEnabled = false;
}
}
#Override
public int onStartCommand(#Nullable Intent intent, int flags, int startId) {
super.onStartCommand(intent, startId, startId);
return START_STICKY;
}
private void startTracking() {
final Timer timer = new Timer();
TimerTask timerTask = new TimerTask() {
#Override
public void run() {
if (isTrackingEnabled) {
Log.d("tracking", "run: " + new Date().toString());
getLocation();
} else {
timer.cancel();
}
}
};
timer.schedule(timerTask,0,5000);
Intent notificationIntent = new Intent(this, PickaupActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 1,
notificationIntent, 0);
Notification notification = new Notification.Builder(this)
.setContentTitle("On going trip")
.setContentText("Active trips")
.setSmallIcon(R.drawable.ic_notification_auto_request)
.setContentIntent(pendingIntent)
.setTicker("Trip started")
.build();
startForeground(1337, notification);
}
private void getLocation() {
mFusedLocationClient = LocationServices.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;
}
mFusedLocationClient.getLastLocation().addOnSuccessListener( new OnSuccessListener<Location>() {
#Override
public void onSuccess(Location location) {
if (location != null) {
Log.d("", "onSuccess: " + location.getLatitude());
submitData(location);
}
}
});
}
private void submitData(Location location) {
if (locationFirstOld == null) {
locationFirstOld = location;
return;
}
// sendMyLocation(location);
// double distance = getDistance(locationFirstOld.getLatitude(), locationFirstOld.getLongitude(), location.getLatitude(), location.getLongitude());
double distance = locationFirstOld.distanceTo(location);
Log.d("distance", "submitData: " + String.valueOf(distance));
locationFirstOld = location;
sendMessageToActivity(totalDistance);
totalDistance += distance;
}
public double getDistance(double lat1, double lon1, double lat2, double lon2) {
double latA = Math.toRadians(lat1);
double lonA = Math.toRadians(lon1);
double latB = Math.toRadians(lat2);
double lonB = Math.toRadians(lon2);
double cosAng = (Math.cos(latA) * Math.cos(latB) * Math.cos(lonB-lonA)) +
(Math.sin(latA) * Math.sin(latB));
double ang = Math.acos(cosAng);
double dist = ang *6371;
return dist;
}
private void sendMessageToActivity(double distance) {
Intent intent = new Intent("DISTANCE_UPDATE");
// You can also include some extra data.
intent.putExtra("distance", distance);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
private void sendMyLocation(Location location) {
Intent intent = new Intent();
intent.putExtra("lat", location.getLatitude());
intent.putExtra("lat", location.getLongitude());
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
}

IntentService stops when it is done doing whatever it does.
Use Service instead, Service types are not stopped until the system, user or the app stops it

the service gets killed once the onHandleIndent completes
That is standard behavior for IntentService — IntentService calls stopSelf() when onHandleIntent() returns, if there are no more queued-up commands.
Do not use IntentService for this scenario. Create you own service with your own threading model, calling stopSelf() when you no longer need the service.

Related

Get location distance and speed android

Hi I am trying to fetch location in every 5 seconds and calculate the speed and total distance or the trip but it is not giving exact distance and speed, below is my code please help. TIA
public class LocationUpdater extends Service implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener{
private double latitude ;
private double longitude ;
Session session;
Context context;
LocationRequest mLocationRequest;
private static final int MILLISECONDS_PER_SECOND = 1000;
public static final int UPDATE_INTERVAL_IN_SECONDS = 5;
private static final long UPDATE_INTERVAL =
MILLISECONDS_PER_SECOND * UPDATE_INTERVAL_IN_SECONDS;
private static final int FASTEST_INTERVAL_IN_SECONDS = 10;
private static final long FASTEST_INTERVAL =
MILLISECONDS_PER_SECOND * FASTEST_INTERVAL_IN_SECONDS;
private static final int DESIRED_ACCURACY = 10;
private static final float SMALLEST_DISPLACEMENT = 10f;
/**
* Provides the entry point to Google Play services.
*/
protected GoogleApiClient mGoogleApiClient;
public LocationUpdater() {
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
context = LocationUpdater.this;
session = Session.getSession(context);
buildGoogleApiClient();
mGoogleApiClient.connect();
return START_STICKY;
}
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(context)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API).build();
}
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
#Override
public void onConnected(Bundle bundle) {
try{
mLocationRequest = LocationRequest.create();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setSmallestDisplacement(SMALLEST_DISPLACEMENT);
requestLocationUpdate();
}catch (SecurityException ex){
ex.printStackTrace();
}
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
mGoogleApiClient.connect();
}
#Override
public void onDestroy() {
super.onDestroy();
if(session.getTrip_status().equalsIgnoreCase(Utils.trip_status_started))
startService(new Intent(LocationUpdater.this,LocationUpdater.class));
}
I am able to get results but updates and not accurate and not smooth at all. Please let me know if it is the correct way of doing it or I should try something else.
Below is my location updater code
private void fetchMyLocation(){
try{
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, new LocationListener() {
#Override
public void onLocationChanged(Location location) {
if (location != null) {
latitude = location.getLatitude();
longitude = location.getLongitude();
Log.wtf("ankit","accuracy "+location.getAccuracy());
if (location.hasAccuracy() && location.getAccuracy() <= DESIRED_ACCURACY) {
// This is your most accurate location.
Log.wtf("ankit","latitude:::"+latitude);
Log.wtf("ankit","longitude:::"+longitude);
session.setCurrentLatitude(""+latitude);
session.setCurrentLongitude(""+longitude);
if(session.getTrip_status().equalsIgnoreCase(Utils.trip_status_started)){
updateDistanceAndSpeed(latitude,longitude);
} else {
UpdateLocationListner.getInstance().changeState(latitude,longitude,"");
}
}
}
}
});
}catch (SecurityException ex){
ex.printStackTrace();
}
}
and this is how i calculate speed and distance
// update speed and distance
private void updateDistanceAndSpeed(double latitude,double longitude){
long currentTimeMills = System.currentTimeMillis();
if (session.getLastLatitude().equalsIgnoreCase("")
&& session.getLastLongitude().equalsIgnoreCase("")) {
session.setLastLatitude(""+latitude);
session.setLastLongitude(""+longitude);
}else {
synchronized (this){
try{
String lat = ""+latitude;
String lng = ""+longitude;
double speed = 0;
if(!lat.equalsIgnoreCase(session.getLastLatitude())
&& !lng.equalsIgnoreCase(session.getLastLongitude())){
Location locationA = new Location("point A");
locationA.setLatitude(latitude);
locationA.setLongitude(longitude);
Location locationB = new Location("point B");
locationB.setLatitude(Double.parseDouble(session.getLastLatitude()));
locationB.setLongitude(Double.parseDouble(session.getLastLongitude()));
if(session.getDistance().equalsIgnoreCase(""))
session.setDistance("0");
Log.wtf("ankit","total distance:"+session.getDistance());
float lastDistance = Float.parseFloat(session.getDistance());
float distance[] = new float[1];
Location.distanceBetween(latitude, longitude,
Double.parseDouble(session.getLastLatitude()),
Double.parseDouble(session.getLastLongitude()), distance);
if(!session.getLastTimeStamp().equalsIgnoreCase("")){
long lastTime = Long.parseLong(session.getLastTimeStamp());
long timeDifference = currentTimeMills - lastTime;
long diffInSec = TimeUnit.MILLISECONDS.toSeconds(timeDifference);
speed = distance[0]/diffInSec;
} else {
speed = 0;
}
speed = speed*3.6;
speed = Utils.round(speed,2);
float roundDistance = Utils.round(distance[0],2);
Log.wtf("ankit","roundDistance"+roundDistance);
float final_distance = lastDistance+roundDistance;
UpdateLocationListner.getInstance().changeState(latitude,longitude,""+speed+"/"+final_distance);
session.setDistance(""+final_distance);
} else {
UpdateLocationListner.getInstance().changeState(latitude,longitude,"0/0");
}
// send speed
}catch (Exception ex){
ex.printStackTrace();
}
}
session.setLastLatitude(""+latitude);
session.setLastLongitude(""+longitude);
session.setLastTimeStamp(""+currentTimeMills);
}
}
You just need to pass latitudes and longitude
public void setLatLng(LatLng origins, LatLng destinations) {
url = "http://maps.googleapis.com/maps/api/distancematrix/json?" +
"origins=" + origins.latitude + "," + origins.longitude + "" +
"&destinations=" + destinations.latitude + "," + destinations.longitude + "" +
"&mode=driving" +
"&language=en-EN" +
"&sensor=false";
}
Handle the response of this URL here give the distance and time between two latitudes and longitude so now you need to calculate speed and for the speed you use
speed = distance / time

Run App or Method in background in Android even if App Close

I create App which Give me latitude and longitude in every 1 min.i have to update this location information to server in every 1 min.the timer run perfectly. But when I close the app or when i terminate the app from my recent open app than timer doesn't work.
How can I do this in background even if I close app?
GpsTracket.java
public class GPSTracker extends Service implements LocationListener {
private final Context mContext;
private final Handler _handler = new Handler();
private static int DATA_INTERVAL = 1 * 60 * 1000;
public static final long NOTIFY_INTERVAL =1 * 60 * 1000; // 60 seconds
// run on another Thread to avoid crash
private Handler mHandler = new Handler();
// timer handling
private Timer mTimer = null;
// 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;
private Handler handler = new Handler();
private long initial_time;
long timeInMilliseconds = 0L;
private Intent intent;
public static final String BROADCAST_ACTION = "com.example.gpstracking.AndroidGPSTrackingActivity";
#Override
public void onCreate() {
super.onCreate();
startService(new Intent(this, AndroidGPSTrackingActivity.class));
initial_time = SystemClock.uptimeMillis();
intent = new Intent(BROADCAST_ACTION);
handler.removeCallbacks(sendUpdatesToUI);
handler.postDelayed(sendUpdatesToUI, 1000);
if(mTimer != null) {
mTimer.cancel();
} else {
// recreate new
mTimer = new Timer();
}
// schedule task
mTimer.scheduleAtFixedRate(new TimeDisplayTimerTask(), 0, NOTIFY_INTERVAL);// 1 second
}
private Runnable sendUpdatesToUI = new Runnable() {
public void run() {
getLocation();
handler.postDelayed(this, 1000); // 1 seconds
}
};
public GPSTracker(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;
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(GPSTracker.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) {
}
public void notifyUser() {
NotificationManager notificationManager = (NotificationManager)this.getSystemService(Context.NOTIFICATION_SERVICE);
Intent intent = new Intent(GPSTracker.this, AndroidGPSTrackingActivity.class);
//use the flag FLAG_UPDATE_CURRENT to override any notification already there
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
Notification notification = new Notification(R.drawable.ic_launcher, "Some Text", System.currentTimeMillis());
notification.flags = Notification.FLAG_AUTO_CANCEL | Notification.DEFAULT_LIGHTS | Notification.DEFAULT_SOUND;
notification.setLatestEventInfo(this, "", "", contentIntent);
//10 is a random number I chose to act as the id for this notification
notificationManager.notify(10, notification);
}
#Override
public void onDestroy() {
super.onDestroy();
handler.removeCallbacks(sendUpdatesToUI);
}
class TimeDisplayTimerTask extends TimerTask {
#Override
public void run() {
// run on another thread
handler.post(new Runnable() {
#Override
public void run() {
// display toast
Toast.makeText(getApplicationContext(), getDateTime(),
Toast.LENGTH_SHORT).show();
}
});
}
private String getDateTime() {
// get date time in custom format
SimpleDateFormat sdf = new SimpleDateFormat("[yyyy/MM/dd - HH:mm:ss]");
return sdf.format(new Date());
}
}
#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;
}
}
AndroidGPSTrackingActivity.java
public class AndroidGPSTrackingActivity extends Activity {
Button btnShowLocation;
Geocoder geocoder;
List<Address> addresses;
private final Handler _handler = new Handler();
private static int DATA_INTERVAL = 1 * 60 * 1000;
// GPSTracker class
GPSTracker gps;
double longitude;
double latitude;
Calendar c;
SimpleDateFormat sdf;
String strDate;
Intent intent;
private Timer mTimer = null;
protected LocationManager locationManager;
private Handler handler = new Handler();
private long initial_time;
public static final long NOTIFY_INTERVAL = 60 * 1000;
public static final String BROADCAST_ACTION = "com.example.gpstracking.GPSTrackers";
String address,city,state,country,postalCode,knownName,city2;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
geocoder = new Geocoder(this, Locale.getDefault());
initial_time = SystemClock.uptimeMillis();
intent = new Intent(BROADCAST_ACTION);
handler.removeCallbacks(sendUpdatesToUI);
handler.postDelayed(sendUpdatesToUI, 1000 * 70);
if(mTimer != null) {
mTimer.cancel();
} else {
// recreate new
mTimer = new Timer();
}
// schedule task
mTimer.scheduleAtFixedRate(new TimeDisplayTimerTask(), 0, NOTIFY_INTERVAL);// 1 second
location();
btnShowLocation = (Button) findViewById(R.id.btnShowLocation);
// show location button click event
btnShowLocation.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
// create class object
location();
}
});
}
class TimeDisplayTimerTask extends TimerTask {
#Override
public void run() {
// run on another thread
handler.post(new Runnable() {
#Override
public void run() {
// display toast
location();
}
});
}
}
public void location(){
gps = new GPSTracker(AndroidGPSTrackingActivity.this);
// check if GPS enabled
if(gps.canGetLocation()){
latitude = gps.getLatitude();
longitude = gps.getLongitude();
try {
addresses = geocoder.getFromLocation(latitude, longitude, 1);
Log.d("adddd", String.valueOf(addresses));
address = addresses.get(0).getAddressLine(0);
city = addresses.get(0).getAddressLine(1);
state = addresses.get(0).getAddressLine(2);
c = Calendar.getInstance();
sdf= new SimpleDateFormat("dd/MM/yyyy hh:mm a ");
strDate = sdf.format(c.getTime());
} catch (IOException e) {
e.printStackTrace();
}
// \n is for new line
Toast.makeText(getApplicationContext(), "Your Location is - \nLat: " + latitude + "\nLong: " + longitude + address + "\n"
+city +" "+ state + "\n" + strDate
, Toast.LENGTH_LONG).show();
_handler.postDelayed(getData, DATA_INTERVAL);
}else{
// can't get location
// GPS or Network is not enabled
// Ask user to enable GPS/network in settings
gps.showSettingsAlert();
}
}
private Runnable sendUpdatesToUI = new Runnable() {
public void run() {
handler.postDelayed(this, 1000 * 60); // 1 seconds
}
};
public void notifyUser() {
NotificationManager notificationManager = (NotificationManager)this.getSystemService(Context.NOTIFICATION_SERVICE);
Intent intent = new Intent(AndroidGPSTrackingActivity.this, AndroidGPSTrackingActivity.class);
//use the flag FLAG_UPDATE_CURRENT to override any notification already there
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
Notification notification = new Notification(R.drawable.ic_launcher, "Some Text", System.currentTimeMillis());
notification.flags = Notification.FLAG_AUTO_CANCEL | Notification.DEFAULT_LIGHTS | Notification.DEFAULT_SOUND;
notification.setLatestEventInfo(this, city, state, contentIntent);
//10 is a random number I chose to act as the id for this notification
notificationManager.notify(10, notification);
}
#Override
public void onStop() {
super.onStop();
_handler.postDelayed(getData, DATA_INTERVAL);
//write your code here to start your service
}
#Override
public void onDestroy() {
startService(new Intent(this, Service.class));
super.onDestroy();
}
#Override
public void onPause() {
super.onPause();
startService(new Intent(this, GPSTracker.class));
location();
//write your code here to start your service
}
private final Runnable getData = new Runnable()
{
#Override
public void run()
{
location();
notifyUser();
}
};
}
Please Help.
You have to create Background service that extends IntentService which gives latitude and longitude in every 1 min.
You can use Timer or ScheduledExecutorService in your service to get location every 1 min.
You have created your timer in AndroidGPSTrackingActivity class instead of it create new service and move all timer related code to onStartCommand method of background service.
Start your background service in your AndroidGPSTrackingActivity. For automatic restarting of service you have to return START_STICKY in onStartCommand method of your service.
For creating Intent service refer https://developer.android.com/training/run-background-service/create-service.html
I hope it helps!

Use less battery with GPS location every 15 minutes

I'm implementing an application which need to send a location to GCM every 15 minutes. I implemented an AlarmManager which will be called every 15 minute.
Here is my class of my alarmmanager
public class LocationAlarmManager {
Context mContext = null;
public LocationAlarmManager (Context context) {
mContext = context;
}
private AlarmManager alarmManager;
private Intent gpsTrackerIntent;
private PendingIntent pendingIntent;
private static final String TAG = "LocationAlarmManager";
public void startAlarmManager() {
Log.d(TAG, "startAlarmManager");
alarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
gpsTrackerIntent = new Intent(mContext, GpsTrackerAlarmReceiver.class);
pendingIntent = PendingIntent.getBroadcast(mContext, 0, gpsTrackerIntent, 0);
alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime(),
15 * 60000, // 60000 = 1 minute
pendingIntent);
}
public void cancelAlarmManager() {
Log.d(TAG, "cancelAlarmManager");
Intent gpsTrackerIntent = new Intent(mContext, GpsTrackerAlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, gpsTrackerIntent, 0);
AlarmManager alarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
alarmManager.cancel(pendingIntent);
}
}
That one calls GpsTrackerAlarmReceiver
// make sure we use a WakefulBroadcastReceiver so that we acquire a partial wakelock
public class GpsTrackerAlarmReceiver extends WakefulBroadcastReceiver {
private static final String TAG = "GpsTrackerAlarmReceiver";
#Override
public void onReceive(Context context, Intent intent) { context.startService(new Intent(context, SmartLocationService.class));
}
}
For handling my location I implemented the following in my SmartLocationService.
public class SmartLocationService extends Service implements
GooglePlayServicesClient.ConnectionCallbacks,
GooglePlayServicesClient.OnConnectionFailedListener,
LocationListener {
private static final String TAG = "SmartLocationService";
// use the websmithing defaultUploadWebsite for testing and then check your
// location with your browser here: https://www.websmithing.com/gpstracker/displaymap.php
private String defaultUploadWebsite;
private boolean currentlyProcessingLocation = false;
private LocationRequest locationRequest;
private LocationClient locationClient;
public LocationManager locationManager;
Context context;
// flag for GPS status
public 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
public Location previousBestLocation;
private double mLastLatitudeLocation = 0;
private double mLastLongitudeLocation = 0;
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// if we are currently trying to get a location and the alarm manager has called this again,
// no need to start processing a new location.
if (!currentlyProcessingLocation) {
currentlyProcessingLocation = true;
startTracking();
}
return START_NOT_STICKY;
}
private void startTracking() {
Log.d(TAG, "startTracking");
if (GooglePlayServicesUtil.isGooglePlayServicesAvailable(this) == ConnectionResult.SUCCESS) {
locationClient = new LocationClient(this,this,this);
if (!locationClient.isConnected() || !locationClient.isConnecting()) {
locationClient.connect();
}
} else {
Log.e(TAG, "unable to connect to google play services.");
}
}
protected void sendLocationDataToWebsite(Location loc) {
MessageHandler messageHandler = new MessageHandler(SmartLocationService.this);
messageHandler.sendLocationMessage(loc); //send location to GCM
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onLocationChanged(Location location) {
if (location != null) {
Log.e(TAG, "position: " + location.getLatitude() + ", " + location.getLongitude() + " accuracy: " + location.getAccuracy());
sendLocationDataToWebsite(location);
}
}
private void stopLocationUpdates() {
if (locationClient != null && locationClient.isConnected()) {
locationClient.removeLocationUpdates(this);
locationClient.disconnect();
}
}
/**
* Called by Location Services when the request to connect the
* client finishes successfully. At this point, you can
* request the current location or start periodic updates
*/
#Override
public void onConnected(Bundle bundle) {
context = getApplicationContext();
Log.d(TAG, "onConnected");
locationRequest = LocationRequest.create();
locationRequest.setInterval(900000); // milliseconds
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationClient.requestLocationUpdates(locationRequest, this);
}
/**
* Called by Location Services if the connection to the
* location client drops because of an error.
*/
#Override
public void onDisconnected() {
Log.e(TAG, "onDisconnected");
stopLocationUpdates();
stopSelf();
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.e(TAG, "onConnectionFailed");
stopLocationUpdates();
stopSelf();
}
}
This works, but my locationservice get called more then once in my timeslot of 15 minutes. Anyone know why? Is this a good way to use less battery power (GPS)?
Thanks

Log Location Coordinates using a Service

Guys I am trying to create an app that logs your locations' coordinates using the location class and the service class, but it doesn't work !
I don't know how to start!!!
here is my sevice file:
public class LocationService extends Service {
private static final long ONE_MIN = 1000 * 60;
private static final long TWO_MIN = ONE_MIN * 2;
private static final long FIVE_MIN = ONE_MIN * 5;
private static final long MEASURE_TIME = 1000 * 30;
private static final long POLLING_FREQ = 1000 * 10;
private static final float MIN_ACCURACY = 25.0f;
private static final float MIN_LAST_READ_ACCURACY = 500.0f;
private static final float MIN_DISTANCE = 10.0f;
private static final int NOTIFICATION_ID = 1;
// Current best location estimate
private Location mBestReading;
WIWDb db;
// Reference to the LocationManager and LocationListener
private LocationManager mLocationManager;
private LocationListener mLocationListener;
private final String TAG = "LocationGetLocationActivity";
private boolean mFirstUpdate = true;
#SuppressLint("NewApi") #Override
public void onCreate() {
super.onCreate();
Log.i(TAG,"here");
db=new WIWDb(this);
// Acquire reference to the LocationManager
if (null == (mLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE)))
Toast.makeText(getBaseContext(), "Error", Toast.LENGTH_LONG).show();
// Get best last location measurement
mBestReading = bestLastKnownLocation(MIN_LAST_READ_ACCURACY, FIVE_MIN);
// Display last reading information
if (null != mBestReading) {
updateDisplay(mBestReading);
} else {
Toast.makeText(getBaseContext(),"No Initial Reading Available",Toast.LENGTH_LONG).show();
//mAccuracyView.setText("No Initial Reading Available");
}
mLocationListener = new LocationListener() {
// Called back when location changes
public void onLocationChanged(Location location) {
// Determine whether new location is better than current best
// estimate
if (null == mBestReading
|| location.getAccuracy() < mBestReading.getAccuracy()) {
// Update best estimate
mBestReading = location;
// Update display
updateDisplay(location);
if (mBestReading.getAccuracy() < MIN_ACCURACY)
mLocationManager.removeUpdates(mLocationListener);
}
}
public void onStatusChanged(String provider, int status,
Bundle extras) {
// NA
}
public void onProviderEnabled(String provider) {
// NA
}
public void onProviderDisabled(String provider) {
// NA
}
};
// Create a notification area notification so the user
// can get back to the MusicServiceClient
final Intent notificationIntent = new Intent(getApplicationContext(),
MainActivity.class);
final PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
notificationIntent, 0);
final Notification notification = new Notification.Builder(
getApplicationContext())
.setSmallIcon(android.R.drawable.ic_menu_compass)
.setOngoing(true).setContentTitle("Location tracking...")
.setContentText("Back to WIW")
.setContentIntent(pendingIntent).build();
// Put this Service in a foreground state, so it won't
// readily be killed by the system
startForeground(NOTIFICATION_ID, notification);
}
private Location bestLastKnownLocation(float minAccuracy, long maxAge) {
Location bestResult = null;
float bestAccuracy = Float.MAX_VALUE;
long bestAge = Long.MIN_VALUE;
List<String> matchingProviders = mLocationManager.getAllProviders();
for (String provider : matchingProviders) {
Location location = mLocationManager.getLastKnownLocation(provider);
if (location != null) {
float accuracy = location.getAccuracy();
long time = location.getTime();
if (accuracy < bestAccuracy) {
bestResult = location;
bestAccuracy = accuracy;
bestAge = time;
}
}
}
// Return best reading or null
if (bestAccuracy > minAccuracy
|| (System.currentTimeMillis() - bestAge) > maxAge) {
return null;
} else {
return bestResult;
}
}
#SuppressWarnings("deprecation")
private void updateDisplay(Location location) {
StringBuilder sb=new StringBuilder();
sb.append("Accuracy:" + location.getAccuracy());
//mAccuracyView.setText("Accuracy:" + location.getAccuracy());
sb.append("Time:"+ new SimpleDateFormat("MM/dd/yyyy HH:mm:ss", Locale.getDefault()).format(new Date(location.getTime())));
//mTimeView.setText("Time:"+ new SimpleDateFormat("MM/dd/yyyy HH:mm:ss", Locale.getDefault()).format(new Date(location.getTime())));
sb.append("Longitude:" + location.getLongitude());
//mLatView.setText("Longitude:" + location.getLongitude());
sb.append("Latitude:" + location.getLatitude());
//mLngView.setText("Latitude:" + location.getLatitude());
//db.insertCordsToDb(String.valueOf(location.getLongitude())+","+String.valueOf( location.getLatitude()),String.valueOf(new Date().getDate()) ,String.valueOf(location.getTime()));
db.insertCordsToDb(String.valueOf(location.getLongitude())+","+String.valueOf(lo cation.getLatitude()),new SimpleDateFormat("MM/dd/yyyy", Locale.getDefault()).format(new Date(location.getTime())) ,new SimpleDateFormat("HH:mm:ss", Locale.getDefault()).format(new Date(location.getTime())));
}
protected void onResume() {
// Determine whether initial reading is
// "good enough". If not, register for
// further location updates
if (null == mBestReading
|| mBestReading.getAccuracy() > MIN_LAST_READ_ACCURACY
|| mBestReading.getTime() < System.currentTimeMillis()
- TWO_MIN) {
// Register for network location updates
if (null != mLocationManager
.getProvider(LocationManager.NETWORK_PROVIDER)) {
mLocationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER, POLLING_FREQ,
MIN_DISTANCE, mLocationListener);
}
// Register for GPS location updates
if (null != mLocationManager
.getProvider(LocationManager.GPS_PROVIDER)) {
mLocationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER, POLLING_FREQ,
MIN_DISTANCE, mLocationListener);
}
// Schedule a runnable to unregister location listeners
Executors.newScheduledThreadPool(1).schedule(new Runnable() {
#Override
public void run() {
Log.i(TAG, "location updates cancelled");
mLocationManager.removeUpdates(mLocationListener);
}
}, MEASURE_TIME, TimeUnit.MILLISECONDS);
}
}
// Unregister location listeners
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
}
please guide to finish this application

Android locationManager - "location not changed" event

I'm building a service that will let me know if the location hasn't change in a period of time for a certain amount of metres.
Then thing is I have the event onLocationChanged on my Listener.. but I don't know how to do the opposite.. that is, send a broadcast if the location is within the distance I provided after some minutes.
This is the code I have so far
LocationService
public class LocationService extends Service {
public static final String LOC_INTENT = "com.xxx.intent.action.LOCATION";
private Thread triggerService;
protected LocationManager locationManager;
protected MyLocationListener MyLocationListener;
protected Criteria criteria;
public static final int MIN_TIME = 300000; // 5 Minutes
public static final long MIN_DISTANCE_MOTOR = 50; // 50 Metres
private SharedPreferences settings;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
settings = getSharedPreferences(getString(R.string.settings_prefsName), 0);
addLocationListener();
return START_STICKY;
}
private void addLocationListener()
{
triggerService = new Thread(new Runnable(){
public void run(){
try{
Looper.prepare();//Initialise the current thread as a looper.
locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
final String PROVIDER = locationManager.getBestProvider(criteria, true);
updateLocation(getLastBestLocation(MIN_TIME, MIN_DISTANCE_MOTOR));
MyLocationListener = new MyLocationListener();
locationManager.requestLocationUpdates(PROVIDER, MIN_TIME, MIN_DISTANCE_MOTOR, MyLocationListener);
Log.d("LOC_SERVICE", "Service RUNNING! ("+PROVIDER+")");
Looper.loop();
}catch(Exception ex){
ex.printStackTrace();
}
}
}, "LocationThread");
triggerService.start();
}
public Location getLastBestLocation(int minDistance, long minTime) {
Location bestResult = null;
float bestAccuracy = Float.MAX_VALUE;
long bestTime = Long.MIN_VALUE;
List<String> matchingProviders = locationManager.getAllProviders();
for (String provider: matchingProviders) {
Location location = locationManager.getLastKnownLocation(provider);
if (location != null) {
float accuracy = location.getAccuracy();
long time = location.getTime();
if ((time > minTime && accuracy < bestAccuracy)) {
bestResult = location;
bestAccuracy = accuracy;
bestTime = time;
}
else if (time < minTime && bestAccuracy == Float.MAX_VALUE && time > bestTime) {
bestResult = location;
bestTime = time;
}
}
}
return bestResult;
}
public static void updateLocation(Location location)
{
Context appCtx = MyApplication.getAppContext();
double latitude, longitude;
float speed;
latitude = location.getLatitude();
longitude = location.getLongitude();
speed = location.getSpeed();
Intent filterRes = new Intent();
filterRes.setAction(LOC_INTENT);
filterRes.putExtra("latitude", latitude);
filterRes.putExtra("longitude", longitude);
filterRes.putExtra("speed", speed);
appCtx.sendBroadcast(filterRes);
}
class MyLocationListener implements LocationListener
{
#Override
public void onLocationChanged(Location location)
{
if(settings.getBoolean("active", false))
updateLocation(location);
}
#Override
public void onProviderDisabled(String provider) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
}
}
Set a timer for however long you want to test this. When it goes off, check if the last location you got in onLocationChanged is older than the timer length.
EDIT
Here is how I would imagine your service looking
Service starting
requestLocationUpdates called with appropriate minimum time and minimum distance that that you will be notified after
Repeating task set where you check if an update was received (check out Timer.scheduleAtFixedRate
Service running
Perform necessary actions when your timer goes off or onLocationChanged is called
Service stopping
Remove location updates with removeUpdates
Stop your timer

Categories

Resources