I'm new to Android and I'm having the following problem. I'm writing a sample application where I have an intent service that first checks all location providers to get the last known location. If none of the last known locations provides an accurate (or timely) enough location then the location manager's requestLocationUpdates method is called with a BroadcastReceiver intent. Each time the broadcast receiver's onReceive method is called it should check the location to see if it is accurate and/or timely enough. I also have a TimerTask in the intent service that eventually goes off and should check to see if an accurate and/or timely enough location update has been obtained. The problem I'm having is that I don't know how to get the location data obtained in the broadcast receiver back to the intent service. Seems like this should be an easy thing to do but I've been agonizing over this for days. The only way I can think to do it is to write the data to an SQLite db in the broadcast receiver and then read those records back in the intent service, but this seems unnecessarily complicated. Does anyone know what the right way is to get the data back to the intent service? Should I even be using a broadcast receiver for requestLocationUpdates? Is there an easier way to do this? Here is the code
public class GetLocationService extends IntentService {
public GetLocationService() {
super("something");
}
LocationManager locationManager;
long maxFixLateness;
float maxFixPosUncertainty;
boolean usableLocObtained;
Location bestLoc = null;
float bestLocScore = 0;
Intent locChangeI;
PendingIntent pLocChangeI;
#Override
final protected void onHandleIntent(Intent intent) {
maxFixLateness = 30000;
maxFixPosUncertainty = 30;
long curTime = System.currentTimeMillis();
LocationManager locationManager = (LocationManager) this
.getSystemService(Context.LOCATION_SERVICE);
// Check for a usable location fix
List<string> matchingProviders = locationManager.getAllProviders();
for (String provider : matchingProviders) {
Location location = locationManager.getLastKnownLocation(provider);
if (location != null) {
// ...some code to check if the location is accurate or timely
// enough
}
}
if (bestLoc == null) {
locChangeI = new Intent(this, HandleLocationUpdateReceiver.class);
pLocChangeI = PendingIntent.getBroadcast(this, 0, locChangeI,
PendingIntent.FLAG_UPDATE_CURRENT);
usableLocObtained = false;
locationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER, 0, 0, pLocChangeI);
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER, 0, 0, pLocChangeI);
// Call the timer that will periodically check to see if a usable
// location has been obtained.
new LocFixCheckTimer(60000, 30, 1000);
}
}
private class LocFixCheckTimer {
Timer timer;
long numChecks;
public LocFixCheckTimer(long initSearchTime, long maxRechecks,
long recheckFreq) {
numChecks = maxRechecks;
timer = new Timer();
// Wait 2 seconds before checking for a fix again
timer.schedule(new CheckLocTask(), initSearchTime, recheckFreq);
}
class CheckLocTask extends TimerTask {
public void run() {
if (numChecks > 0) {
if (usableLocObtained == true) {
// I want to use the location data obtained from the
// HandleLocationUpdateReceiver's onReceive method
// but I don't how to get that data here.
}
} else {
// Cancel the timer. We've timed-out on searching
// for a usable location fix
timer.cancel();
}
--numChecks;
}
}
}
}
Here is the broadcast receiver:
public class HandleLocationUpdateReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
Location loc = (Location) intent.getExtras().get(LocationManager.KEY_LOCATION_CHANGED);
if (loc != null)
{
double lat = loc.getLatitude();
double lon = loc.getLongitude();
// Do some checking to see how accurate and timely the location is
// here and somehow get it back to the intent service.
}
}
}
Thanks for the help!
Use a listener for sending back data to your activity or service. It is provided in this link
Related
I have to update geoFence on exit. For that I need current location at that point.
When my app is closed I don't have listener for onLocationChanged. And in order to
update geoFence I require my location. Is their any way to get current Location at Geofence.GEOFENCE_TRANSITION_EXIT
public void broadcastUpdateGeoFences() {
MainActivity.isGeoFenceAdded = false;//It tells to update geoFence
Intent intent = new Intent(Constants.RECEIVER_GEOFENCE);
intent.putExtra("done", 1);
sendBroadcast(intent);
}
Broadcast Receiver in MainActivity
private BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
if (bundle != null) {
int resultCode = bundle.getInt("done");
if (resultCode == 1) {
if(!MainActivity.isGeoFenceAdded){
updateGeoFencesOnCurrentExit();//I need current location here
}
}
}
}
};
Every thing working fine. But Unable to find a way to pass currentLocation at exit when app is closed.
private void updateGeoFencesOnCurrentExit(Location currentLocation){
locationHandler.updateGeoFences(currentLocation);
}
You can Implement LocationListener interface in your broadcast and use override method onLocationChanged like this
#Override
public void onLocationChanged(Location location) {
location.getLongitude();
location.getLatitude();
}
I wouldn't recommend using a LocationListener inside an IntentService or BroadcastReceiver, since they can be destroyed once the function (onHandleIntent or onReceive) has exited. I would use a PendingIntent with LocationManager to request a single update once you get the geofence event. I have example apps to demonstrate how to request location updates using a PendingIntent on github (https://github.com/pablobaxter/AndroidLocationExamples).
Edit:
FYI, IntentService is not wrong. You are just running the onHandleIntent logic in a background thread vs onReceive running on the main thread.
Objective: To save current locations in Service in database after exact 15 min with in service (using less battery).I use these location at various points in my app.
locationrequest = LocationRequest.create();
locationrequest.setInterval(5*60000);
locationrequest
.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
locationclient.requestLocationUpdates(locationrequest, mPendingIntent);
Problem: I'm using the above code does not request location according to set interval value.Although, I'm aware that This interval is inexact. You may not receive updates at all, or you may receive them slower than requested. You may also receive them faster than requested. Sometimes, the location is updated after 1 min , I don't want to waste processing and battery to get locations at small intervals.
public class LoginActivity extends Activity implements OnClickListener
,
GooglePlayServicesClient.ConnectionCallbacks,GooglePlayServicesClient.OnConnectionFailedListener,LocationListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.login_screen);
///my code
mIntentService = new Intent(LoginActivity.this,LocationService.class);
mIntentService.putExtra("time",String.valueOf(System.currentTimeMillis()) );
mPendingIntent = PendingIntent.getService(LoginActivity.this, 1, mIntentService, 0);
int resp =GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if(resp == ConnectionResult.SUCCESS){
locationclient = new LocationClient(this,this,this);
locationclient.connect();
}
else{
Toast.makeText(this, "Google Play Service Error " + resp, Toast.LENGTH_LONG).show();
}
#Override
public void onLocationChanged(Location location) {
// TODO Auto-generated method stub
}
#Override
public void onConnectionFailed(ConnectionResult arg0) {
// TODO Auto-generated method stub
}
#Override
public void onConnected(Bundle arg0) {
// TODO Auto-generated method stub
Log.i("fused", " onConnected " );
// mIntentService = new Intent(LoginActivity.this,LocationService.class);
// mPendingIntent = PendingIntent.getService(LoginActivity.this, 1, mIntentService, 0);
locationrequest = LocationRequest.create();
locationrequest.setInterval(5*60000);
// locationrequest
// .setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
locationclient.requestLocationUpdates(locationrequest, mPendingIntent);
// locationrequest = LocationRequest.create();
// locationrequest.setInterval(1000);//??
// locationclient.requestLocationUpdates(locationrequest, this);
}
#Override
public void onDisconnected() {
// TODO Auto-generated method stub
}
}
LocationService
public class LocationService extends IntentService {
private String TAG = this.getClass().getSimpleName();
public LocationService() {
super("Fused Location");
}
public LocationService(String name) {
super("Fused Location");
}
#Override
protected void onHandleIntent(Intent intent) {
// Log.i("fused", "onHandleIntent LocationService");
Location location = intent.getParcelableExtra(LocationClient.KEY_LOCATION_CHANGED);
if(location !=null){
String time= intent.getStringExtra("time");
Log.i("fused", "onHandleIntent LocationService " +time+"---"+ location.getLatitude() + "," + location.getLongitude());
updateTransientLocation(getApplicationContext(), location);
}
}
Also, I need to save these locations periodically in database in background only and hence cannot use requestLocationUpdates without pending intent to service.
I have refered to this for the code
Thanks.
EDIT -SOLUTION This is how my problem was solved
Code in Activity
Intent myIntent = new Intent(context,LocationReceiver.class);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, myIntent, 0);
alarmMgr.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime(),
// 120000,pi);
I removed the location Service class and added location receiver
LocationReceiver
public class LocationReceiver extends BroadcastReceiver implements
GooglePlayServicesClient.ConnectionCallbacks,
GooglePlayServicesClient.OnConnectionFailedListener, LocationListener {
SharedPreferences prefs = null;
LocationClient locationclient = null;
Context contxt;
/** For location poller NO LONGER IN USE **/
#Override
public void onReceive(Context context, Intent intent) {
contxt=context;
//Log.i("locationreciever", "in location rec");
Log.i("fused", "in location rec");
int resp = GooglePlayServicesUtil
.isGooglePlayServicesAvailable(context);
if (resp == ConnectionResult.SUCCESS) {
locationclient = new LocationClient(context, this, this);
locationclient.connect();
} else {
Log.i("fused", "loc client Google Play Service Error");
}
}
#Override
public void onLocationChanged(Location location) {
Log.i("fused", " onLocationChanged Location Request :" + location.getLatitude() + "," + location.getLongitude());
updateTransientLocation(contxt, location);
if (locationclient != null) {
if (locationclient.isConnected()) {
locationclient.removeLocationUpdates(this);
locationclient.disconnect();
}
}
}
#Override
public void onConnectionFailed(ConnectionResult arg0) {
Log.i("fused", "loc client connection failed");
}
#Override
public void onConnected(Bundle arg0) {
Log.i("fused", "loc client onConnected");
LocationRequest locationrequest = LocationRequest.create();
locationrequest
.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
locationclient.requestLocationUpdates(locationrequest, this);
}
#Override
public void onDisconnected() {
Log.i("fused", "loc client disconnected");
}
}
The best solution would be to use your current approach. You're tell the OS that you don't need locations more often, but something else might be requesting locations, in which case you might as well just accept it, now that the phone has already woken up to get a GPS fix and broadcast it to every process that's interested in a location. This way, your application may actually never have to turn on the GPS, because you're basically just using a location fix that was requested by another process more often that every 15 minutes. The keyword to search for here is the new fused location provider.
If you insist on getting a location exactly every 15 minutes, you can, instead of scheduling a location request, use an AlarmManager to schedule a job to run every 15 minutes. In your alarm manager, you can then immediately request a new single location, and then completely stop requesting new locations until your job is scheduled to run again. If you go down this route, you'll likely run into problems with your service ending before you get a result, because of the asynchronous nature of the location service. Therefore, you want to poll for a location in your alarm manager. You can use a project like CWAC LocationPoller for that
The documentation has examples of how to schedule recurring events:
https://developer.android.com/training/scheduling/alarms.html
Depending on your need, you should be think about the fact that a location may not be available every 15 minutes. Maybe the user is outside of GPS/wifi/phone range. So it may or may not be beneficial to start a task a bit early, or more often, to make sure you have a reasonable fix after your 15 minute window has elapsed.
With all that said, here's the code snippet you're actually interested in to solve your specific problem (taken directly from the CWAC locationpoller site):
1. Create a recurring alarm manager
mgr=(AlarmManager)getSystemService(ALARM_SERVICE);
Intent i=new Intent(this, LocationPoller.class);
Bundle bundle = new Bundle();
LocationPollerParameter parameter = new LocationPollerParameter(bundle);
parameter.setIntentToBroadcastOnCompletion(new Intent(this, LocationReceiver.class));
// try GPS and fall back to NETWORK_PROVIDER
parameter.setProviders(new String[] {LocationManager.GPS_PROVIDER, LocationManager.NETWORK_PROVIDER});
parameter.setTimeout(60000);
i.putExtras(bundle);
pi=PendingIntent.getBroadcast(this, 0, i, 0);
mgr.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime(),
PERIOD,
pi);
2. Create a BroadcastReceiver to receive your location data
Bundle b=intent.getExtras();
LocationPollerResult locationResult = new LocationPollerResult(b);
Location loc=locationResult.getLocation();
String msg;
if (loc==null) {
loc=locationResult.getLastKnownLocation();
if (loc==null) {
msg=locationResult.getError();
}
else {
msg="TIMEOUT, lastKnown="+loc.toString();
}
}
else {
msg=loc.toString();
}
if (msg==null) {
msg="Invalid broadcast received!";
}
From http://developer.android.com/reference/android/app/AlarmManager.html#setRepeating%28int,%20long,%20long,%20android.app.PendingIntent%29
as of API 19, all repeating alarms are inexact. If your application needs precise delivery times then it must use one-time exact alarms, rescheduling each time as described above. Legacy applications whose targetSdkVersion is earlier than API 19 will continue to have all of their alarms, including repeating alarms, treated as exact.
So you will have to do something like this:
public void startTheClock(int interval) {
Intent pingerIntent = new Intent(this, findLoc.class);
pingerIntent.setAction("start_clock");
PendingIntent pendingIntent = PendingIntent.getBroadcast(
this.getApplicationContext(),
0,
pingerIntent,
PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager alarms = (AlarmManager) this.getSystemService(
Context.ALARM_SERVICE);
alarms.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + interval,
pendingIntent);
}
And in the class that captures that intent (in this example, findLoc.java):
public class findLoc extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
callMethodThatSearchesForLocation();
startTheClock(INTERVAL);
}
}
Where interval is a constant in miliseconds.
NOTE: I actually had some problems with that because it displayed an error on setExact(..) since my minimum SDK did not support this. Which is a bit of a paradox if you want the same behaviour on SDK lower than 19 and higher or equal to 19.
I have registered my LocationManager for location updates, every 10 seconds
mgr.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 10 * 1000, 50, this);
But the onLocationChanged callback returns a location every 10 secs, which(the location) is more than 2 hours old. And that time-stamp is never changing.
The problem is:
2 hours back I was in a complete different location(home) where I used the device on a wifi. Now currently I am in some other location(office) on a different wifi where my application shows my current location as home. Same thing happened at home yesterday, when it was showing office as my current location. It got to work(started showing correct location) when I closed my app, opened FourSquare app and re-opened my app.
Complete Code:
public class LocationService extends Service implements LocationListener {
public static double curLat = 0.0;
public static double curLng = 0.0;
private LocationManager mgr;
private String best;
private Location location;
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
mgr = (LocationManager) getSystemService(LOCATION_SERVICE);
best = LocationManager.NETWORK_PROVIDER;
location = mgr.getLastKnownLocation(best);
if (location != null) {
dumpLocation(location);
mgr.requestLocationUpdates(LocationManager.GPS_PROVIDER,
10 * 1000, 50, this);
}
return START_NOT_STICKY;
}
}
private void dumpLocation(Location l) {
SimpleDateFormat s = new SimpleDateFormat("dd/MM/yyyy:hh:mm:ss",
Locale.ENGLISH);
String format = s.format(l.getTime());
//The above time is always 28/03/2013:09:26:41 which is more than 2 hrs old
curLat = l.getLatitude();
curLng = l.getLongitude();
}
#Override
public void onLocationChanged(Location location) {
dumpLocation(location);
}
#Override
public void onProviderDisabled(String provider) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
}
Being started in an Activity this way:
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
Intent i = new Intent(this, LocationService.class);
pi = PendingIntent.getService(this, 0, i,
PendingIntent.FLAG_UPDATE_CURRENT);
am.cancel(pi);
am.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime(), 10000, pi);
Permissions in manifest:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
I can get the correct location now, by opening some other location based app like Maps, Navigator, Foursquare etc.., But why my app isn't able to get a new/fresh fix from the provider.
Thank You
You are getting old location because of this line
location = mgr.getLastKnownLocation(best);
because if GPS is not enabled then it will show you the old location . So remove this code It will work like a champ
You can also refer to this library
https://github.com/nagendraksrivastava/Android-Location-Tracking-Library
On the basis of your comments I have edited the answer Okay Let me explain line by line
location = mgr.getLastKnownLocation(best); it will give you object of last know location then it will go inside if condition and it will call dumplocation and will get last location data and after that you called
mgr.requestLocationUpdates(LocationManager.GPS_PROVIDER,
10 * 1000, 50, this);
but suppose GPS provider is disabled then it will not fetch new location so you will get old location only . So either you can change it like
if(locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER))
{
locationManager.requestSingleUpdate(LocationManager.GPS_PROVIDER,new NagendraSingleLocationListener(),null);
}
else
{
locationManager.requestSingleUpdate(LocationManager.NETWORK_PROVIDER,new NagendraSingleLocationListener(),null);
}
I think because you cancel your pending intent right away, thus the requestLocationUpdate would not start update before you cancel. Why don't you sleep may be for 2 second before cancel.
From my experience android will give you a location when you request the updates even if gps has not enough sattelites to work. So even if gps is on - if you are inside or in a location that is bad (like under a bridge) android will deliver an old fix to you. Can be a very old one indeed.
The only thing I found to be working 100% is to generelly not use the first position but only remember the time. When new positions arrive you can check that the time is newer than the last. If you want to only use very precise positions you may also need to check that location.getAccuracy() is low (the lower the better).
I use gps to get my timestamps for a soap interface as the android clock can be very off sometimes and this was the only way for me to get a valid time from gps.
I have searched quite a bit and I'm not totally clueless. I have implemented a temporary solution on my end but was wondering if there is a better approach out there.
I have an app that sends a person's location after every 60 seconds to a server. On my dashboard (the main screen that will go to onPause after application starts), I have registered a LocationManager with the following code:
service = (LocationManager) getSystemService(LOCATION_SERVICE);
boolean enabled = service
.isProviderEnabled(LocationManager.GPS_PROVIDER);
if (!enabled)
{
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(intent);
}
else
{
Criteria criteria = new Criteria();
provider = service.getBestProvider(criteria, false);
service.requestLocationUpdates(provider, 10000, 50, this);
Location location = service.getLastKnownLocation(provider);
// Initialize the location fields
if (location != null)
{
onLocationChanged(location);
}
else
{
Log.d("Location: ", "No update received");
}
}
However, as I mentioned, this activity will be minimized by the user (by pressing the home button). There is a service that gets called every 60 seconds by an AlarmManager. That service accesses static variables from the Dashboard Activity (lat, lon) and sends it to the server.
My question:
If the activity goes onPause, will the requestLocationUpdates function stop? Or will it keep working?
If it keeps working, it will keep updating the two lat and lon static String objects and the service will keep getting updated values. If they stop, the service will keep getting the same old values again and again.
Also, is there a better way to approach this problem? Using a mix of GPS Provider and Network Provider? (I need fairly accurate values).
EDIT
Here's my Alarm. This code is inside Login Activity
Intent i = new Intent(con, LocationPoller.class);
i.putExtra(LocationPoller.EXTRA_INTENT, new Intent(con,
Login.class));
i.putExtra(LocationPoller.EXTRA_PROVIDER,
LocationManager.GPS_PROVIDER);
gps = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
PendingIntent pi = PendingIntent.getBroadcast(con, 0, i, 0);
gps.setRepeating(AlarmManager.RTC_WAKEUP, c.getTimeInMillis(),
10 * 1000, pi);
Log.d("Service: ",
"GPS Service started and scheduled with AlarmManager");
Here's my receiver (also within Login activity)
private class ReceiveMessages extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
Location loc = (Location) intent.getExtras().get(
LocationPoller.EXTRA_LOCATION);
String msg;
if (loc == null)
{
msg = intent.getStringExtra(LocationPoller.EXTRA_ERROR);
}
else
{
msg = loc.toString();
}
if (msg == null)
{
msg = "Invalid broadcast received!";
}
Log.d("GPS Broadcast: ", msg);
}
}
Nothing's happening :s Not getting anything on logcat which means the broadcast isn't being received.
When activity goes on pause, all registered listeners will stop. Better way to implement this is, alarm manager sent a broadcast every 60 seconds, this broadcast receiver starts a service and this service will request a location on Wakeful thread, once location information is retrieved, update the location on server.
There is an Open source library available with an example (courtesy CommonsWare), please refer below link. Its under Apache 2.0 license
Location Polling Library
Please find my sample project using above library. I have modified few things in the above library and created my own version.
Location Polling Demo Application
I've been experimenting with the Android SDK for a few weeks now, trying to achieve an accurate location from a background service.
After trying a few configurations, I currently have this on a loop:
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
criteria.setAltitudeRequired(false);
criteria.setBearingRequired(true);
criteria.setCostAllowed(true);
criteria.setPowerRequirement(Criteria.POWER_HIGH);
bestProvider = locationManager.getBestProvider(criteria, true);
lastKnownLocation = locationManager.getLastKnownLocation(bestProvider);
And then I check lastKnownLocation every now and then for a position update. I know you can listen for updates but at the moment I'm not too concerned about that right now. What I am concerned about is, (I think) I'm asking for the phone to use GPS whenever possible - instead of other methods of determining the location - an yet it still returns a latitude / longitude from a good distance away, yet when I open the maps application, it has me within a couple of meters.
Can anyone suggest where I'm going wrong here?
Setting the Criteria just establishes which provider is best to use depending on them so that doesn't really have a say on the accuracy or the validity of the location. I just set the provider to GPS straight away (If GPS is available!).
Also it doesn't seem like your giving it any requirements concerning how long you want to wait before updating based on time and distance. Here is an example of what I do using intents and broadcast receiver. It may help you.
public void beginMonitoringLocation(int minDistance) {
IntentFilter filter = new IntentFilter();
filter.addAction(MainActivity.LOCATION_UPDATE_ACTION);
this.mContext.registerReceiver(this.locationReceiver, filter);
LocationManager mLocationManager = (LocationManager) this.mContext.getSystemService(Context.LOCATION_SERVICE);
mLocationManager.addGpsStatusListener(this);
boolean enabled = mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
if (!enabled) {
Log.e("LocationManager", "GPS not enabled!!!!");
}
LocationProvider provider = mLocationManager.getProvider(LocationManager.GPS_PROVIDER); // GET THE BEST PROVIDER FOR OUR LOCATION
Log.d("LocationManager:","Location Provider:"+provider);
if ( provider == null ) {
Log.e( "LocationManager", "No location provider found!" );
return;
}
final int locationUpdateRC=0;
int flags = 0;
Intent intent = new Intent(MainActivity.LOCATION_UPDATE_ACTION);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this.mContext, locationUpdateRC, intent, flags);
// PENDING INTENT TO BE FIRED WHEN THE LOCATIONMANAGER RECEIVES LOCATION UPDATE.
// THIS PENDING INTENT IS CAUGHT BY OUR BROADCAST RECEIVER
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,0,minDistance,pendingIntent);
this._monitoringLocation = true;
}
And then in the same class I put my broadcast receiver
public BroadcastReceiver locationReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
Location location = (Location) intent.getExtras().get(LocationManager.KEY_LOCATION_CHANGED);
if (location != null) {
//Do something with it
}
}
};
The action for my intent filter is just a static reference to a constant set in my activity.
public static final String LOCATION_UPDATE_ACTION = "com.corecoders.sqlmaptrack.LOCATION_UPDATE_RECEIVED";
This worked in my case in providing me with accurate locations. You can set the distance to 0 if you want then what you will find is you get location fixes of an accuracy of 5 every second if you have a good fix of 4 satellites or more.
I hope this helps you
I have used the below code to get accurate location. Using below code you can handle enabling/disabling the GPS programmatically.
private void enableGPSTracking() {
new Thread() {
#Override
public void run() {
super.run();
try {
toggleGPS(true, getApplicationContext());
provider = LocationManager.GPS_PROVIDER;
Criteria locationCritera = new Criteria();
locationCritera.setAccuracy(Criteria.ACCURACY_FINE);
locationCritera.setAltitudeRequired(false);
locationCritera.setBearingRequired(false);
locationCritera.setCostAllowed(true); locationCritera.setPowerRequirement(Criteria.NO_REQUIREMENT);
provider = locationManager.getBestProvider(locationCritera,
true);
Intent intent = new Intent(
"com.example.gps.LOCATION_READY");
pendingIntent = PendingIntent.getBroadcast(
getApplicationContext(), 0, intent,
PendingIntent.FLAG_CANCEL_CURRENT);
// Register for broadcast intents
locationManager.requestLocationUpdates(provider, 0, 0,
pendingIntent);
} catch (Exception e) {
}
}
}.start();
}
public static void toggleGPS(boolean flag, Context context) {
try {
Intent intent = new Intent("android.location.GPS_ENABLED_CHANGE");
intent.putExtra("enabled", flag);
context.sendBroadcast(intent);
} catch (Exception e) {
}
}
to disable the GPS, simply pass false for flag value of ToggleGPS() method. Hope this helps you.