onLocationChanged is never called by using requestLocationUpdates with GPS provider - android

I'm developing an application by using service to track user's locations and send the data to the server in the background. It's the GPS based app. When my program called requestLocationUpdates with GPS provider, the onLocationChanged is never called. However, the requestLocationUpdates works fine with network provider on my app. Please take a look at my code.
Android version: 4.1.2
Device: Galaxy nexus S
Tracker.java
private void init() {
locationListener = new MyLocationListener();
mNM = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
NOTIFICATION = R.string.local_service_started;
arrivedStatus = false;
activity = TrackerActivity.getAppActivity();
}
#Override
public void onCreate() {
super.onCreate();
init();
Log.i(tag, "Start Tracking");
showStartNotification();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("LocalService", "Received start id " + startId + ": " + intent);
tripID = intent.getExtras().getInt("tripID") + "";
locationInterval = intent.getExtras().getInt("locationInterval")
* MILLISECONDS_PER_SECOND;
//lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
// locationInterval, 0, locationListener);
getLocation();
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
Log.e("STOP_SERVICE", "Service has stopped");
mNM.cancel(R.string.local_service_started);
lm.removeUpdates(locationListener);
stopSelf();
}
private void getLocation() {
lm = (LocationManager) getApplicationContext().getSystemService(
Context.LOCATION_SERVICE);
// getting GPS status
isGPSEnabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
// getting network status
isNetworkEnabled = lm
.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if (!isGPSEnabled && !isNetworkEnabled) {
// no network provider is enabled
Log.e(tag, "Non providers are enabled");
} else {
if (isGPSEnabled) {
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER,
locationInterval, 0, locationListener);
Log.d(tag, "GPS Enabled");
}
if (isNetworkEnabled) {
if (lm == null) {
lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
locationInterval, 0, locationListener);
Log.d(tag, "Network Enabled");
}
}
}
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#SuppressWarnings("deprecation")
private void showStartNotification() {
// In this sample, we'll use the same text for the ticker and the
// expanded notification
CharSequence text = getText(R.string.local_service_started);
// Set the icon, scrolling text and timestamp
Notification notification = new Notification(R.drawable.cameral, text,
System.currentTimeMillis());
// The PendingIntent to launch our activity if the user selects this
// notification+
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
new Intent(this, TrackerActivity.class), 0);
// Set the info for the views that show in the notification panel.
notification.setLatestEventInfo(this,
getText(R.string.local_service_label), text, contentIntent);
// Send the notification.
mNM.notify(NOTIFICATION, notification);
}
/**
* private void showStopSpecification() { CharSequence text =
* getText(R.string.local_service_cancel); Notification notification = new
* Notification(R.drawable.btn_save_dialog, text,
* System.currentTimeMillis()); mNM.notify(NOTIFICATION, notification); }
*/
private void checkResult(JSONObject json) {
try {
if (json.getString(KEY_SUCCESS) != null) {
String res = json.getString(KEY_SUCCESS);
if (Integer.parseInt(res) == 1) {
Log.v(tag, "Store data successfully");
activity.findViewById(R.id.tracker_info)
.setBackgroundResource(R.color.blue4);
if (json.getInt(ARRIVED_STATUS) == 1) {
setArrivedStatus(true);
} else {
setArrivedStatus(false);
}
} else if (json.getString(KEY_ERROR).equals("1")) {
// Error in login
String error_msg = json.getString(KEY_ERROR_MSG);
Log.e(tag, error_msg);
setArrivedStatus(false);
} else {
Log.e(tag, "Something is wrong");
setArrivedStatus(false);
}
} else {
Log.e(tag, "Something is wrong");
setArrivedStatus(false);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
public void setArrivedStatus(boolean status) {
arrivedStatus = status;
}
public boolean getArrivedStatus() {
return arrivedStatus;
}
private class MyLocationListener implements LocationListener {
#Override
public void onLocationChanged(Location location) {
// TODO Auto-generated method stub
currentLat = location.getLatitude() + "";
currentLng = location.getLongitude() + "";
Log.v(tag, LOCATION_CHANGED + " lat=" + currentLat + ", lon="
+ currentLng);
try {
JSONObject json = new LogInfo().execute(
new String[] { tripID, currentLat, currentLng }).get();
checkResult(json);
if (getArrivedStatus() == true) {
Log.v(tag, "User has arrived safely");
onDestroy();
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#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 also already added the permission to my Manifest
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
Thank you

when you call this function, do you see the GPS icon on the notification bar of the device? if so, it means it tries to get a location and you're just in a place with no GPS reception.
in any case, you can use Google's way to get the location, here: https://developers.google.com/events/io/sessions/324498944
also, what is the class "Tracker"? is it a service? if so, you shouldn't let it have a reference to an activity, since it can cause memory leaks. instead use correct binding .
you should also avoid calling "onDestroy" , since calling it doesn't really close your service. instead call "stopSelf", and make sure no activity is bound to it.
if you wish, i've asked this sort of question (of getting a location via a service) a long time ago, here.

Related

Location not updated on 10 mins of interval

I want to track the user location. So I have made a code so that on every 10 mins of interval its location should be hit on server. If it is not moving also the location should hit at 10 min of interval. I set Location interval minutes for 10 min public static final long LOCATION_INTERVAL_MINUTES = 10 * 60 * 1000;
It should update the location with 10 min, but it hits randomly. I also increase the gps frequency distance from 10 to gpsFreqInDistance = 100 .Random hits are stopped but it will not updated on 10 mins of interval.
So what to do to get location at 10 min of interval.
Below is my manifiest
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" /
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
As for Android above 10version u cant use background location and foreground location simultaneously. So i comment the ACCESS_BACKGROUND_LOCATION" in my project.
public class LocationMonitoringService implements LocationListener, GpsStatus.Listener {
private static final String TAG = LocationMonitoringService.class.getSimpleName();
private Context mContext;
private LocationRepository mLocationRepository;
private ShareLocationAdapterClass mAdapter;
private SyncOfflineRepository syncOfflineRepository;
private long updatedTime = 0;
private List<UserLocationPojo> mUserLocationPojoList;
private SyncOfflineAttendanceRepository syncOfflineAttendanceRepository;
public LocationMonitoringService(final Context context) {
mContext = context;
mLocationRepository = new LocationRepository(AUtils.mainApplicationConstant.getApplicationContext());
syncOfflineRepository = new SyncOfflineRepository(AUtils.mainApplicationConstant.getApplicationContext());
syncOfflineAttendanceRepository = new SyncOfflineAttendanceRepository(AUtils.mainApplicationConstant.getApplicationContext());
mUserLocationPojoList = new ArrayList<>();
mAdapter = new ShareLocationAdapterClass();
mAdapter.setShareLocationListener(new ShareLocationAdapterClass.ShareLocationListener() {
#Override
public void onSuccessCallBack(boolean isAttendanceOff) {
if (isAttendanceOff && !syncOfflineAttendanceRepository.checkIsAttendanceIn()) {
AUtils.setIsOnduty(false);
((MyApplication) AUtils.mainApplicationConstant).stopLocationTracking();
}
}
#Override
public void onFailureCallBack() {
}
});
}
public void onStartTacking() {
LocationManager locationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
//Exception thrown when GPS or Network provider were not available on the user's device.
try {
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
criteria.setPowerRequirement(Criteria.NO_REQUIREMENT);
criteria.setAltitudeRequired(false);
criteria.setSpeedRequired(true);
criteria.setCostAllowed(false);
criteria.setBearingRequired(false);
//API level 9 and up
criteria.setHorizontalAccuracy(Criteria.ACCURACY_HIGH);
criteria.setVerticalAccuracy(Criteria.ACCURACY_HIGH);
int gpsFreqInDistance = 100;
assert locationManager != null;
locationManager.addGpsStatusListener(this);
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, AUtils.LOCATION_INTERVAL,
gpsFreqInDistance, this, null);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, AUtils.LOCATION_INTERVAL,
gpsFreqInDistance, this, null);
} catch (IllegalArgumentException | SecurityException e) {
Log.e(TAG, Objects.requireNonNull(e.getLocalizedMessage()));
Log.d(TAG, "onStartTacking: " + e.getMessage());
Log.d(TAG, "onStartTacking: " + e.getLocalizedMessage());
e.printStackTrace();
} catch (RuntimeException e) {
Log.e(TAG, Objects.requireNonNull(e.getLocalizedMessage()));
Log.d(TAG, "onStartTacking: " + e.getMessage());
e.printStackTrace();
}
}
public void onStopTracking() {
mAdapter.shareLocation();
LocationManager locationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
locationManager.removeUpdates(this);
}
/*
* LOCATION CALLBACKS
*/
//to get the location change
#Override
public void onLocationChanged(Location location) {
Log.d("okh ", "onLocationChanged: "+System.currentTimeMillis());
if (location != null) {
Log.d(TAG, String.valueOf(location.getAccuracy()));
if (!AUtils.isNullString(String.valueOf(location.getLatitude())) && !AUtils.isNullString(String.valueOf(location.getLongitude()))) {
Prefs.putString(AUtils.LAT, String.valueOf(location.getLatitude()));
Prefs.putString(AUtils.LONG, String.valueOf(location.getLongitude()));
if (Prefs.getBoolean(AUtils.PREFS.IS_ON_DUTY, false)) {
if (updatedTime == 0) {
updatedTime = System.currentTimeMillis();
Log.d(TAG, "updated Time ==== " + updatedTime);
}
if ((updatedTime + AUtils.LOCATION_INTERVAL_MINUTES) <= System.currentTimeMillis()) {
updatedTime = System.currentTimeMillis();
Log.d(TAG, "updated Time ==== " + updatedTime);
}
sendLocation();
}
}
} else {
Log.d(TAG, "onLocationChanged: no location found !!");
}
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
Log.d(TAG, "onStatusChanged" + provider + "Status" + status);
}
#Override
public void onProviderEnabled(String provider) {
Log.d(TAG, " onProviderEnabled" + provider);
}
#Override
public void onProviderDisabled(String provider) {
Log.d(TAG, " onProviderDisabled" + provider);
}
#Override
public void onGpsStatusChanged(int event) {
}
private void sendLocation() {
// mAdapter.shareLocation(getTempList());
Log.d("okh", "sendLocation: Current Time In Millies "+ System.currentTimeMillis());
try {
Calendar CurrentTime = AUtils.getCurrentTime();
Calendar DutyOffTime = AUtils.getDutyEndTime();
if (CurrentTime.before(DutyOffTime)) {
Log.i(TAG, "Before");
UserLocationPojo userLocationPojo = new UserLocationPojo();
userLocationPojo.setUserId(Prefs.getString(AUtils.PREFS.USER_ID, ""));
userLocationPojo.setLat(Prefs.getString(AUtils.LAT, ""));
userLocationPojo.setLong(Prefs.getString(AUtils.LONG, ""));
double startLat = Double.parseDouble(Prefs.getString(AUtils.LAT, "0"));
double startLng = Double.parseDouble(Prefs.getString(AUtils.LONG, "0"));
userLocationPojo.setDistance(String.valueOf(AUtils.calculateDistance(
AUtils.mainApplicationConstant.getApplicationContext(), startLat, startLng)));
// userLocationPojo.setDatetime(AUtils.getServerDateTime()); //TODO
userLocationPojo.setDatetime(AUtils.getServerDateTimeLocal());
userLocationPojo.setOfflineId("0");
if (AUtils.isInternetAvailable() && AUtils.isConnectedFast(mContext))
userLocationPojo.setIsOffline(true);
else
userLocationPojo.setIsOffline(false);
String UserTypeId = Prefs.getString(AUtils.PREFS.USER_TYPE_ID, AUtils.USER_TYPE.USER_TYPE_GHANTA_GADI);
if (AUtils.isInternetAvailable()) {
TableDataCountPojo.LocationCollectionCount count = syncOfflineRepository.getLocationCollectionCount(AUtils.getLocalDate());
if ((UserTypeId.equals(AUtils.USER_TYPE.USER_TYPE_GHANTA_GADI) || UserTypeId.equals(AUtils.USER_TYPE.USER_TYPE_WASTE_MANAGER))
&& (count.getLocationCount() > 0 || count.getCollectionCount() > 0)) {
syncOfflineRepository.insetUserLocation(userLocationPojo);
} else {
mUserLocationPojoList.add(userLocationPojo);
mAdapter.shareLocation(mUserLocationPojoList);
mUserLocationPojoList.clear();
}
} else {
if (UserTypeId.equals(AUtils.USER_TYPE.USER_TYPE_EMP_SCANNIFY)) {
Type type = new TypeToken<UserLocationPojo>() {
}.getType();
mLocationRepository.insertUserLocationEntity(new Gson().toJson(userLocationPojo, type));
} else {
syncOfflineRepository.insetUserLocation(userLocationPojo);
}
mUserLocationPojoList.clear();
}
}
else {
Log.i(TAG, "After");
syncOfflineAttendanceRepository.performCollectionInsert(mContext,
syncOfflineAttendanceRepository.checkAttendance(), AUtils.getCurrentDateDutyOffTime());
AUtils.setIsOnduty(false);
((MyApplication) AUtils.mainApplicationConstant).stopLocationTracking();
Activity activity = ((Activity) AUtils.currentContextConstant);
if (activity instanceof DashboardActivity) {
((Activity) AUtils.currentContextConstant).recreate();
AUtils.DutyOffFromService = true;
}
if (!AUtils.isNull(AUtils.currentContextConstant)) {
((Activity) AUtils.currentContextConstant).recreate();
}
}
} catch (Exception e) {
e.printStackTrace();
}
Below is the foreground service which i have used
public class ForgroundService extends Service {
private LocationMonitoringService monitoringService;
private Handler locationHandler;
private Runnable locationThread;
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate() {
// Toast.makeText(this, " MyService Created ", Toast.LENGTH_LONG).show();
Log.d("okh", "onCreate: " +System.currentTimeMillis());
monitoringService = new LocationMonitoringService(this);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Toast.makeText(this, " MyService Started", Toast.LENGTH_LONG).show();
Log.d("okh", "onCreate: " +System.currentTimeMillis());
Log.d("okh", "onStartCommand: ");
final int currentId = startId;
locationThread = new Runnable() {
public void run() {
monitoringService.onStartTacking();
}
};
locationHandler = new Handler(Looper.getMainLooper());
locationHandler.post(locationThread);
startLocationForeground();
return Service.START_STICKY;
// return Service.START_NOT_STICKY;
}
#Override
public void onDestroy() {
//Toast.makeText(this, "MyService Stopped", Toast.LENGTH_LONG).show();
locationHandler.removeCallbacks(locationThread);
monitoringService.onStopTracking();
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
{
stopForeground(STOP_FOREGROUND_REMOVE);
}
if(Prefs.getBoolean(AUtils.PREFS.IS_ON_DUTY,false))
{
Intent broadcastIntent = new Intent(this, RestarterBroadcastReceiver.class);
sendBroadcast(broadcastIntent);
}
}
private void startLocationForeground() {
if (Build.VERSION.SDK_INT >= 26) {
String channelId = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
? this.createNotificationChannel("my_service", "My Background Service")
: "";
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder((Context) this,
channelId);
Notification notification = notificationBuilder
.setOngoing(true)
.setContentText("Please don't kill the app from background. Thank you!!")
.setSmallIcon(getNotificationIcon(notificationBuilder))
.setPriority(-2)
.setCategory("service")
.build();
startForeground(101, notification);
}
}
#RequiresApi(26)
private String createNotificationChannel(String channelId, String channelName) {
NotificationChannel chan = new NotificationChannel(channelId, (CharSequence)channelName,
NotificationManager.IMPORTANCE_NONE);
chan.setLightColor(Color.BLUE);
chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
NotificationManager service = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
service.createNotificationChannel(chan);
return channelId;
}
private int getNotificationIcon(NotificationCompat.Builder notificationBuilder) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
int color = 0x008000;
notificationBuilder.setColor(color);
return R.drawable.ic_noti_icon;
}
return R.drawable.ic_noti_icon;
}
}
Why you are passing null in the last parameter? Did you try without passing that?
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, AUtils.LOCATION_INTERVAL,
gpsFreqInDistance, this, null);
First of all Google Location Services are far better than Traditional LocationManager to achieve this requirement.
https://developer.android.com/training/location/request-updates

how to add to sqlite in background

I have a Handler in my fragment that every 5 second add my location in SQLite.
What I need is to maintain this action in background when I open another fragment. How can I do this ?
Handler timerHandler = new Handler();
Runnable timerRunnable = new Runnable() {
#Override
public void run() {
long millis = System.currentTimeMillis() - startTime;
int seconds = (int) (millis / 1000);
int minutes = seconds / 60;
seconds = seconds % 60;
Point p = ls.getPoint();
String X = Double.toString(p.getX());
String Y = Double.toString(p.getY());
db = new MySQLiteHelper(getActivity());
db.addLocation(new LocationXY(1,X,Y,"111"));
clearmap();
createPolyline();
timerHandler.postDelayed(this, 5000);
}
};
Well, what do both your fragments have in common? Their Activity! So run your handler in it.
As #Piyush pointed out, you should use an AsyncTask or a Service for background processes.
Yeah, as #Piyush and #Ricardo suggest - use a service with a Timer and a LocationListener.
Then invoke timer.scheduleAtFixedRate(yourSqliteUpdateMethod, 0, 5000); to update the database. See my service class below, which contains a lot of extra stuff, but you should be able to get what you want out of it...
public class TrackService extends Service {
/**
* Edit these values to adjust the LOCATION UPDATE polling interval
*/
private static final int LOCATION_INTERVAL_SECONDS = 5;
private static final float LOCATION_DISTANCE_METERS = 10f;
// Static timer variables
private static final long ONE_SECOND_IN_MILLIESECONDS = 1000;
// Create timer and set time as zero
private static Timer timer;
private long timeAsLong = 0;
/**
* Track and submission specific variables
*/
private List<LocationTrack> trackArrayList = new ArrayList<>();
private SubmissionSession submissionSession;
private long submissionID;
private boolean originAdded;
/**
* LocationManager and listener variables
*/
private LocationManager mLocationManager = null;
private LocationListener[] mLocationListeners = new LocationListener[]{
new LocationListener(LocationManager.GPS_PROVIDER)
};
/*private LocationListener[] mLocationListeners = new LocationListener[]{
new LocationListener(LocationManager.GPS_PROVIDER),
new LocationListener(LocationManager.PASSIVE_PROVIDER)
};*/
#Override
public void onCreate() {
//Log.d("onCreate");
timer = new Timer();
initializeLocationManager();
try {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED
|| ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
mLocationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER, (LOCATION_INTERVAL_SECONDS * 1000), LOCATION_DISTANCE_METERS,
mLocationListeners[0]);
}
} catch (java.lang.SecurityException ex) {
Log.e("fail to request gps location update, ignore", ex);
} catch (IllegalArgumentException ex) {
Log.e("gps provider does not exist, " + ex.getMessage());
}
/*try {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED
|| ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
mLocationManager.requestLocationUpdates(
LocationManager.PASSIVE_PROVIDER, (LOCATION_INTERVAL_SECONDS * 1000), LOCATION_DISTANCE_METERS,
mLocationListeners[1]);
}
} catch (java.lang.SecurityException ex) {
Log.e("fail to request passive location update, ignore", ex);
} catch (IllegalArgumentException ex) {
Log.e("passive provider does not exist " + ex.getMessage());
}*/
}
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent == null) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
submissionID = prefs.getLong("SUBMISSION_ID", 0);
submissionSession = new SubmissionSession(submissionID);
trackArrayList = new Select().from(LocationTrack.class).where(Condition.column(LocationTrack$Table.SUBMISSIONID).eq(submissionID)).queryList();
originAdded = false;
timeAsLong = prefs.getLong("ELAPSED_TIME_AS_LONG", 0);
} else {
submissionID = intent.getLongExtra("SUB_ID", 0);
submissionSession = new SubmissionSession(submissionID);
// Stick in a reasonably sensible location to indicate to rest of app that a track's
// being captured - this is deleted on 1st real data point from GPS captured
trackArrayList.add(setLocationToLocationTrack(submissionSession.getLocation().getLocation()));
originAdded = true;
timeAsLong = intent.getLongExtra("START_TIME", 0);
}
// Start schedule at one second intervals, calling MainTask
timer.scheduleAtFixedRate(new TrackService.updateTimerAndBroadcastTask(), 0, ONE_SECOND_IN_MILLIESECONDS);
showNotification();
//super.onStartCommand(intent, flags, startId);
return START_STICKY;
}
/**
* This method is necessary to increase the priority of the background services. It appeared that
* some devices, when running eBird Tracks and then used camera, the Tracks service was killed
* by Android due to limited resources. Upping the priority should reduce this.
*/
private void showNotification() {
final int NOTIFICATION_FLAG = 101;
final int ICON_SCALE_DIMENSION = 128;
Intent mainIntent = getPackageManager()
.getLaunchIntentForPackage(getPackageName())
.setPackage(null)
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
Bitmap icon = BitmapFactory.decodeResource(getResources(),
R.drawable.lab_logo_square);
PendingIntent pendingMainIntent = PendingIntent.getActivity(this, 0,
mainIntent, 0);
Notification notification = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_stat_kiwi_bird1600)
.setLargeIcon(Bitmap.createScaledBitmap(icon, ICON_SCALE_DIMENSION, ICON_SCALE_DIMENSION, false))
.setContentText(getString(R.string.location_and_timer_services_running))
.setContentTitle(getString(R.string.app_name))
.setContentIntent(pendingMainIntent)
.setOngoing(true)
.build();
startForeground(NOTIFICATION_FLAG, notification);
}
#Override
public void onDestroy() {
// Need to call cancel AND purge when the user stops the list
timer.cancel();
timer.purge();
if (mLocationManager != null) {
for (int i = 0; i < mLocationListeners.length; i++) {
try {
mLocationManager.removeUpdates(mLocationListeners[i]);
} catch (Exception ex) {
Log.e("fail to remove location listeners, ignore", ex);
}
}
}
submissionSession.setTracks(trackArrayList);
super.onDestroy();
}
private void initializeLocationManager() {
if (mLocationManager == null) {
mLocationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
}
}
private class LocationListener implements android.location.LocationListener {
Location mLastLocation;
public LocationListener(String provider) {
mLastLocation = new Location(provider);
}
#Override
public void onLocationChanged(Location location) {
mLastLocation.set(location);
// Code to add existing location object of site to tracks database on initiation
// to at least give one sensible point. Necessary for assigning the submission as
// an active recording - if no GPS picked up it was being overlooked in the methods
// used to display Checklist in progress throughout app. On first real capture of
// track data, it's deleted
if (originAdded) {
LocationTrack t = trackArrayList.get(0);
t.delete();
trackArrayList.remove(0);
originAdded = false;
}
trackArrayList.add(setLocationToLocationTrack(location));
sendDistanceToSubmissionActivity(Utils.routeDistance((ArrayList) trackArrayList));
}
#Override
public void onProviderDisabled(String provider) {
//Log.d("onProviderDisabled: " + provider);
}
#Override
public void onProviderEnabled(String provider) {
//Log.d("onProviderEnabled: " + provider);
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
//Log.d("onStatusChanged: " + provider);
}
}
// Send an Intent with an action named "tracks_update".
protected void sendDistanceToSubmissionActivity(double distance) {
Intent intent = new Intent("tracks_update");
intent.putExtra("distance", distance);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
/**
* Method to create Locationtrack object and save it to SQLite
*
* #param loc
* #return
*/
protected LocationTrack setLocationToLocationTrack(Location loc) {
LocationTrack l = new LocationTrack();
l.setSubmissionID(submissionID);
l.setLat(loc.getLatitude());
l.setLon(loc.getLongitude());
l.setAccuracy(loc.getAccuracy());
l.setTime(System.currentTimeMillis());
l.setValid(-1); // -1 signifies that the track is active (0 = invalid after editing, 1 = valid)
//Log.d(l.getLat() + " " + l.getLon() + " saved()");
l.save();
return l;
}
/**
* Inner main task, adds a second onto timeAsLong, then sends to SubmissionActivity
*/
private class updateTimerAndBroadcastTask extends TimerTask {
public void run() {
timeAsLong += ONE_SECOND_IN_MILLIESECONDS;
sendDistanceToSubmissionActivity(timeAsLong);
}
// Send an Intent with an action named "timer_update".
protected void sendDistanceToSubmissionActivity(long time) {
//Log.d();
Intent intent = new Intent("timer_update");
intent.putExtra("long_time", time);
LocalBroadcastManager.getInstance(TrackService.this).sendBroadcast(intent);
}
}
}

Location service got stopped by Doze mode

I'm developing sport tracking app that uses location manager and gps provider for getting location updates every second even if the screen is off and the phone is in the pocket.
When user pressed start button in my activity I start service in foreground, display notification and register location listener.
Service starts receiving location updates and writes them into my track file.
Suddenly I get log message 'Power manager idle mode: true', the phone goes into Doze mode and my sevice stops getting any location update until the phone wakes up.
I read docs about Doze mode and see that it shouldn't affect location services, but it does in my case.
May be I'm doing something wrong. Here is the code of my service, any help is really appreciated.
public class LocService
extends Service
implements LocationListener, GpsStatus.Listener
{
private String mName;
private volatile Looper mServiceLooper;
private volatile ServiceHandler mServiceHandler;
private LocationManager locationManager;
public LocService(String name)
{
super();
mName = name;
}
private final class ServiceHandler extends Handler
{
public ServiceHandler(Looper looper)
{
super(looper);
}
#Override
public void handleMessage(Message msg)
{
if (msg != null && msg.obj != null)
{
onHandleIntent((Intent)msg.obj);
}
else
{
logMessage("msg for intent is not good");
}
}
}
#Override
public void onCreate()
{
super.onCreate();
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
{
logMessage("Enabling Doze mode listener");
IntentFilter filter = new IntentFilter();
filter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
registerReceiver(new BroadcastReceiver()
{
#Override
public void onReceive(Context context, Intent intent)
{
onDeviceIdleChanged();
}
}, filter);
}
locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
}
#TargetApi(Build.VERSION_CODES.M)
private void onDeviceIdleChanged()
{
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
if(powerManager != null)
{
logMessage("Power manager idle mode: " + powerManager.isDeviceIdleMode());
} else
{
logMessage("Power manager idle changed to ?");
}
}
protected void onHandleIntent(Intent intent)
{
//call start/stop location logging on proper intent
if(intent.getIntExtra("cmd", -1) == 1)
{
startLogging();
} else
{
stopLogging();
}
}
private void startLogging()
{
logMessage("LocationService.startLogging");
try
{
locationManager.addGpsStatusListener(this);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 500, 0, this);
logMessage("requesting gps updates");
startForeground(ONGOING_NOTIFICATION, getNotification(-1, -1, true, false));
logMessage("Sending foreground service notification");
}
catch (SecurityException ex)
{
logMessage(" SecurityException while requesting location info: " + ex);
}
}
private void stopLogging()
{
try
{
locationManager.removeUpdates(this);
stopForeground(true);
notificationManager.cancel(ONGOING_NOTIFICATION);
}
catch (SecurityException ex)
{
logMessage(" SecurityException on stopLogging with location manager: " + ex);
}
}
#Override
public void onLocationChanged(Location location)
{
//save location lat, lon directly to track file
//flush file
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras)
{
//do nothing
}
#Override
public void onProviderEnabled(String provider)
{
logMessage("Location provider enabled " + provider);
}
#Override
public void onProviderDisabled(String provider)
{
logMessage("Location provider disabled " + provider);
}
#Override
public void onGpsStatusChanged(int event)
{
try
{
logMessage(" *** onGpsStatusChanged with " + event);
GpsStatus status = locationManager.getGpsStatus(null);
int inFix = 0;
int total = 0;
for (GpsSatellite satellite : status.getSatellites())
{
if (satellite.usedInFix()) inFix++;
total++;
}
logMessage(" Sats: " + total + " in fix " + inFix);
}
catch (SecurityException sex)
{
}
catch (Exception ex)
{
}
}
#Override
public void onStart(Intent intent, int startId)
{
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
onStart(intent, startId);
return START_STICKY;
}
#Override
public void onDestroy()
{
mServiceLooper.quit();
try
{
locationManager.removeUpdates(this);
}
catch (SecurityException ex)
{
logMessage(" SecurityException on Destroy service with location manager: " + ex);
}
}
#Override
public IBinder onBind(Intent intent)
{
return null;
}
private void logMessage(String msg)
{
Log.i("LocServ", msg);
}
}
It is not a given that when ACTION_DEVICE_IDLE_MODE_CHANGED is fired, doze was either turned on or off. There are more factors that can affect idle mode.
Try to create and acquire WakeLock.
PowerManager.WakeLock getLock(Context context, String lockName) {
if (wakeLock == null) {
PowerManager mgr = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
wakeLock = mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, lockName);
}
return wakeLock;
}
//on start service
getLock(ctxt.getApplicationContext(), "lockName").acquire();
//on destroy service
#Override
public void onDestroy() {
PowerManager.WakeLock lock = getLock(this.getApplicationContext(), "lockName");
if (lock.isHeld()) {
lock.release();
}
super.onDestroy();
}

How to add and remove multiple proximity alerts in location manager

I am trying to add multiple proximity alert in location listener by giving unique requesCode to its pendingIntent but I am unable to get the alert where I set the location. And app is also crashed several times, please help
here's my code
public class LocationTrackerService extends Service implements LocationListener {
private static final long RADIUS = 1000; // in Meters
private static final long PROX_ALERT_EXPIRATION_TIME = -1;
Context context;
String msg;
LocationManager locationManager;
public final int MINIMUM_UPDATE_DISTANCE = 100;// in meters
public final int MINIMUM_UPDATE_INTERVAL = 30 * 1000;// in seconds
public static String PROX_ALERT_INTENT = "com.ginormous.transportmanagement.ProximityAlert";
LocationAlertReceiver proximityAlertReceiver;
private static final NumberFormat nf = new DecimalFormat("##.########");
IntentFilter filter;
ArrayList<LocationModel> locationdata;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
context = getApplicationContext();
getPickuppoints();
registerIntents();
//will register receiver
registerReceiver();
Log.d("TAG", "service started");
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
private void registerIntents() {
if (locationdata!=null && locationdata.size()>0) {
// TODO Auto-generated method stub
for (int j = 0; j < locationdata.size(); j++) {
LocationModel obj = locationdata.get(j);
setProximityAlert(obj);
}
}
}
private void getPickuppoints(){
Cursor cur=null;
Dbhelper db=new Dbhelper(context);
SQLiteDatabase sqldb=db.getReadableDatabase();
try {
String query="select * from "+Dbhelper.TBL_LATLONG;
cur=sqldb.rawQuery(query, null);
if(cur.getCount()>0){
locationdata=new ArrayList<LocationModel>();
for(cur.moveToFirst();!cur.isAfterLast();cur.moveToNext()){
locationdata.add(
new LocationModel(
cur.getString(cur.getColumnIndex(Dbhelper.COL_LATLONG_PICKUPID)),
cur.getString(cur.getColumnIndex(Dbhelper.COL_LATLONG_PICKUP_NAME)),
cur.getDouble(cur.getColumnIndex(Dbhelper.COL_LATLONG_LATTITUDE)),
cur.getDouble(cur.getColumnIndex(Dbhelper.COL_LATLONG_LONGITUDE)),
cur.getString(cur.getColumnIndex(Dbhelper.COL_LATLONG_ROUTEID)),
cur.getString(cur.getColumnIndex(Dbhelper.COL_LATLONG_ROUTENUMBER))));
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
cur.close();
db.close();
sqldb.close();
}
#Override
public void onLocationChanged(Location location) {
try {
if (locationManager!=null) {
// TODO Auto-generated method stub
String latt = nf.format(location.getLatitude());
String longi= nf.format(location.getLongitude());
Toast.makeText(context, latt+" : "+longi, Toast.LENGTH_LONG).show();
Log.d("TAG", "latlong details" + latt+" : "+longi);
/*Location pointLocation = new Location("POINT_LOCATION");
pointLocation.setLatitude(latlongsFixed.get(index));
pointLocation.setLongitude(77.36438);
float distance = location.distanceTo(pointLocation);
Log.d("TAG", "" + distance);*/
// Toast.makeText(context,"you are meters away from your point of interest.",
// Toast.LENGTH_LONG).show();
Singelton.getInstance().setLastKnownLocation(location);
if (Utilities.checkInternetConnection(getApplicationContext())) {
if (Singelton.getInstance().getRouteNumber() != null)
sendLongLat(latt,longi);
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
Toast.makeText(getApplicationContext(), "Exception in onLocationChanged()", Toast.LENGTH_LONG).show();
e.printStackTrace();
}
}
#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
}
#Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
if(locationManager!=null)
locationManager.removeUpdates(this);
unregisterReceiver(proximityAlertReceiver);
}
#Override
public boolean onUnbind(Intent intent) {
// TODO Auto-generated method stub
return super.onUnbind(intent);
}
public void sendLongLat(final String latti, final String longi) {
new AsyncTask<String, Void, String>() {
#Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
String msg = null;
try {
JSONObject json = new JSONObject(result);
String status = json.getString("STATUS");
if (status.equalsIgnoreCase("ok")) {
msg = "Location sent";
} else {
msg = "Something went wrong";
}
Toast.makeText(getApplicationContext(), msg,
Toast.LENGTH_LONG).show();
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
#Override
protected String doInBackground(String... params) {
// TODO Auto-generated method stub
ArrayList<String> lines = new ArrayList<String>();
Connection db = new Connection();
String routeId = Singelton.getInstance().getRouteId();
if (Utilities.checkInternetConnection(getApplicationContext())) {
try {
lines = db.putLatLong("putLatLong", "2"// route id
, longi, latti);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return lines.get(0);
}
}.execute();
}
private void setProximityAlert(LocationModel obj) {
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
if( !locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) ) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle("GPS not enabled"); // GPS not found
builder.setMessage("Please switch on the GPS of your device"); // Want to enable?
builder.setPositiveButton("Settings", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialogInterface, int i) {
context.startActivity(new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS));
}
});
builder.setNegativeButton("OK", null);
builder.create().show();
return;
}
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
MINIMUM_UPDATE_INTERVAL, MINIMUM_UPDATE_DISTANCE, this);
Intent intent = new Intent(PROX_ALERT_INTENT+"."+obj.getPickupId());//
intent.putExtra("LOCATION", obj);
PendingIntent proximityIntent = PendingIntent.getBroadcast(context, Integer.parseInt(obj.getPickupId())// unique id/request code
, intent, PendingIntent.FLAG_CANCEL_CURRENT);
locationManager.addProximityAlert(
obj.getLat(), // the latitude of the central point of the alert region
obj.getLongi(), // the longitude of the central point of the alert region
RADIUS, // the radius of the central point of the alert region, in meters
PROX_ALERT_EXPIRATION_TIME, // time for this proximity alert, in milliseconds, or -1 to indicate no expiration
proximityIntent // will be used to generate an Intent to fire when entry to or exit from the alert region is detected
);
filter = new IntentFilter(PROX_ALERT_INTENT);
}
private void registerReceiver()
{
proximityAlertReceiver=new LocationAlertReceiver();
registerReceiver(proximityAlertReceiver, filter);
}
}
And Proximity Alert receiver
public class LocationAlertReceiver extends BroadcastReceiver{
private int NOTIFICATION_ID=1000;
public static String PROX_ALERT_INTENT = "com.ginormous.transportmanagement.ProximityAlert";
private String uniqueid="";
LocationModel locaObj;
Context context;
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub\
this.context=context;
try {
LocationModel model=((LocationModel) intent.getSerializableExtra("LOCATION"));
Toast.makeText(context, "Proxmity alert receiver; id : "+model.getPickupId(),
Toast.LENGTH_SHORT).show();
removeProximityAlert(context, PROX_ALERT_INTENT+"."+model.getPickupId());
Toast.makeText(context, "proxmity removed", 1).show();
} catch (Exception e) {
// TODO: handle exception
Toast.makeText(context, "exception in Proxmity alert receiver",
Toast.LENGTH_SHORT).show();
}
/*if(intent.getExtras().getSerializable("LOCATION")!=null){
locaObj=(LocationModel) intent.getExtras().getSerializable("LOCATION");
}
String KEY=LocationManager.KEY_PROXIMITY_ENTERING;
Boolean isEntering=intent.getBooleanExtra(KEY, false);
if(isEntering){
NotificationManager notificationManager = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
Intent intent2 = new Intent(context, MainLogin.class);
PendingIntent pendingIntent = PendingIntent.getActivity(
context, 0, intent2, PendingIntent.FLAG_CANCEL_CURRENT);
Notification notification = createNotification();
notification.setLatestEventInfo(context, "Proximity Alert!",
"Location : "+locaObj.getPickupName()+",", pendingIntent);
notificationManager.notify(NOTIFICATION_ID, notification);
Log.d(getClass().getSimpleName(), "entering");
removeProximityAlert(context,locaObj.getPickupId());
//this will send the details to server
if(Utilities.checkInternetConnection(context))
new SendArrivalDetails().execute(locaObj.getPickupId());
else
Utilities.sendArrivalDetails(context, locaObj.getPickupId(),"N");
}
else
Log.d(getClass().getSimpleName(), "exiting");
*/
}
private void removeProximityAlert(Context context,String uniqueid2) {
// TODO Auto-generated method stub
try {
LocationManager locationManager=(LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
Intent intent=new Intent(PROX_ALERT_INTENT+"."+uniqueid2);
PendingIntent pendingIntent=PendingIntent.getBroadcast(context, Integer.parseInt(uniqueid2), intent, 0);
locationManager.removeProximityAlert(pendingIntent);
} catch (NumberFormatException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (Exception e) {
// TODO: handle exception
Toast.makeText(context, "error in removing promity alert for "+uniqueid2, Toast.LENGTH_SHORT).show();
}
}
private Notification createNotification() {
Notification notification = new Notification();
notification.icon = R.drawable.ic_launcher_transport;
notification.when = System.currentTimeMillis();
notification.flags |= Notification.FLAG_AUTO_CANCEL;
notification.flags |= Notification.FLAG_SHOW_LIGHTS;
notification.defaults |= Notification.DEFAULT_VIBRATE;
notification.defaults |= Notification.DEFAULT_LIGHTS;
notification.ledARGB = Color.WHITE;
notification.ledOnMS = 1500;
notification.ledOffMS = 1500;
return notification;
}
public class SendArrivalDetails extends AsyncTask<String, Void, String> {
String pickupid="";
#Override
protected String doInBackground(String... params) {
// TODO Auto-generated method stub
ArrayList<String> lines=new ArrayList<String>();
pickupid=params[0];
try {
Connection db=new Connection();
Calendar cal=Calendar.getInstance();
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
db.saveArrivalDetails("savepickuptimer", pickupid, Singelton.getInstance().getAttType(),sdf.format(cal.getTime()));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return lines.get(0);
}
#Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
try {
JSONObject jsonObject=new JSONObject(result);
String response=jsonObject.getString("STATUS");
if(response.equals("STATUS")){
Utilities.sendArrivalDetails(context, pickupid,"U");
Toast.makeText(context, "proximity arrival details sent", 1).show();
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
Toast.makeText(context, "error sending proximity arrival details", 1).show();
}
}
}
}
And permission in Menifest file are
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
You have to save all proximity region IDs(request code) and when u want to remove these region just call to remove from locationmanager . For e.g.
Intent intent = new Intent();
intent.setAction(AppConstants.BROAD_ACTION);
for(int i=0;i<countRegionIDArr.size();i++){
PendingIntent pendingIntent = PendingIntent.getBroadcast(AlertService.this, countRegionIDArr.get(i), intent, 0);
mlocManager.removeProximityAlert(pendingIntent);
}

Accessing values from service to activity Android

I have a service which tracks the user location and I am not sure how I can interact it with my activity. I need to be able to access the first available latitude & longitude values and also if there is a change, can anyone give me any tips please.
My service:
public class LocationService extends Service implements
GooglePlayServicesClient.ConnectionCallbacks,
GooglePlayServicesClient.OnConnectionFailedListener,
LocationListener {
public double latitude, longitude;
IBinder mBinder = new LocalBinder();
private LocationClient mLocationClient;
private LocationRequest mLocationRequest;
// Flag that indicates if a request is underway.
private boolean mInProgress;
private Boolean servicesAvailable = false;
public class LocalBinder extends Binder {
public LocationService getServerInstance() {
return LocationService.this;
}
}
#Override
public void onCreate() {
super.onCreate();
mInProgress = false;
// Create the LocationRequest object
mLocationRequest = LocationRequest.create();
// Use high accuracy
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
// Set the update interval to 5 seconds
mLocationRequest.setInterval(Constants.UPDATE_INTERVAL);
// Set the fastest update interval to 1 second
mLocationRequest.setFastestInterval(Constants.FASTEST_INTERVAL);
servicesAvailable = servicesConnected();
/*
* Create a new location client, using the enclosing class to
* handle callbacks.
*/
mLocationClient = new LocationClient(this, this, this);
}
private boolean servicesConnected() {
// Check that Google Play services is available
int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
// If Google Play services is available
if (ConnectionResult.SUCCESS == resultCode) {
return true;
} else {
return false;
}
}
public int onStartCommand (Intent intent, int flags, int startId)
{
super.onStartCommand(intent, flags, startId);
if(!servicesAvailable || mLocationClient.isConnected() || mInProgress)
return START_STICKY;
setUpLocationClientIfNeeded();
if(!mLocationClient.isConnected() || !mLocationClient.isConnecting() && !mInProgress)
{
appendLog(DateFormat.getDateTimeInstance().format(new Date()) + ": Started", Constants.LOG_FILE);
mInProgress = true;
mLocationClient.connect();
}
return START_STICKY;
}
/*
* Create a new location client, using the enclosing class to
* handle callbacks.
*/
private void setUpLocationClientIfNeeded()
{
if(mLocationClient == null)
mLocationClient = new LocationClient(this, this, this);
}
// Define the callback method that receives location updates
#Override
public void onLocationChanged(android.location.Location location) {
// Report to the UI that the location was updated
String msg = Double.toString(location.getLatitude()) + "," +
Double.toString(location.getLongitude());
Log.d("debug", msg);
latitude = location.getLatitude();
longitude = location.getLongitude();
// Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
appendLog(msg, Constants.LOCATION_FILE);
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
public String getTime() {
SimpleDateFormat mDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return mDateFormat.format(new Date());
}
public void appendLog(String text, String filename)
{
File logFile = new File(filename);
if (!logFile.exists())
{
try
{
logFile.createNewFile();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try
{
//BufferedWriter for performance, true to set append to file flag
BufferedWriter buf = new BufferedWriter(new FileWriter(logFile, true));
buf.append(text);
buf.newLine();
buf.close();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
public void onDestroy(){
// Turn off the request flag
mInProgress = false;
if(servicesAvailable && mLocationClient != null) {
mLocationClient.removeLocationUpdates(this);
// Destroy the current location client
mLocationClient = null;
}
// Display the connection status
// Toast.makeText(this, DateFormat.getDateTimeInstance().format(new Date()) + ": Disconnected. Please re-connect.", Toast.LENGTH_SHORT).show();
appendLog(DateFormat.getDateTimeInstance().format(new Date()) + ": Stopped", Constants.LOG_FILE);
super.onDestroy();
}
/*
* 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) {
// Request location updates using static settings
mLocationClient.requestLocationUpdates(mLocationRequest, this);
appendLog(DateFormat.getDateTimeInstance().format(new Date()) + ": Connected", Constants.LOG_FILE);
}
/*
* Called by Location Services if the connection to the
* location client drops because of an error.
*/
#Override
public void onDisconnected() {
// Turn off the request flag
mInProgress = false;
// Destroy the current location client
mLocationClient = null;
// Display the connection status
// Toast.makeText(this, DateFormat.getDateTimeInstance().format(new Date()) + ": Disconnected. Please re-connect.", Toast.LENGTH_SHORT).show();
appendLog(DateFormat.getDateTimeInstance().format(new Date()) + ": Disconnected", Constants.LOG_FILE);
}
/*
* Called by Location Services if the attempt to
* Location Services fails.
*/
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
mInProgress = false;
/*
* Google Play services can resolve some errors it detects.
* If the error has a resolution, try sending an Intent to
* start a Google Play services activity that can resolve
* error.
*/
if (connectionResult.hasResolution()) {
// If no resolution is available, display an error dialog
} else {
}
}
}
My broadcast receiver:
public class LocationLoggerServiceManager extends BroadcastReceiver {
public static final String TAG = "LocationLoggerServiceManager";
#Override
public void onReceive(Context context, Intent intent) {
// Make sure we are getting the right intent
if( "android.intent.action.BOOT_COMPLETED".equals(intent.getAction())) {
ComponentName comp = new ComponentName(context.getPackageName(), LocationService.class.getName());
ComponentName service = context.startService(new Intent().setComponent(comp));
if (null == service){
// something really wrong here
Log.e(TAG, "Could not start service " + comp.toString());
}
}else {
Log.e(TAG, "Received unexpected intent " + intent.toString());
}
}
}
In your onLocationChanged callback, you need to use sendBroadcast to notify your Activity of the change. Here is an example from an answer to another question (taken from here https://stackoverflow.com/a/4739898/826731).
In your service, you can broadcast your intent like this:
sendBroadcast(new Intent(RefreshTask.REFRESH_DATA_INTENT));
(the RefreshTask.REFRESH_DATA_INTENT variable is simply a string)
And in your activity, you need to check for that particular string:
private class DataUpdateReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(RefreshTask.REFRESH_DATA_INTENT)) {
//Do stuff - maybe update my view based on the changed DB contents
}
}
You can pass values from the service to the BroadcastReceiver as follows:
In the service
i.putExtra("Counter", counter);
In BroadcastReceiver
intent.getIntExtra("Counter", -1); // -1 is the default value

Categories

Resources