In my app, I wanna use both location provider.
That means, if the gps is disabled I want my app to switch to network, and when gps is enabled to switch back it.
I'm using two LocationListener to handle those two requests.
public void onStatusChanged(String provider, int status,Bundle extras)
switch (status) {
case LocationProvider.TEMPORARILY_UNAVAILABLE:
......
break;
case LocationProvider.OUT_OF_SERVICE
.....
break;
case LocationProvider.AVAILABLE
.....
break;
}
And in the each listener ,I detect those status in the onStatusChanged().
It turns out, this method will be used in the first change(disabled network),but when I enable the network again, it shows nothing.Why was that? The listener won't detect the status all the time??
Please help me, it would be best to post you solution in code...Thanks!
This is what I do:
public class LocationActivity extends Activity implements LocationListener{
private TextView latituteField;
private TextView longitudeField;
private LocationManager locationManager;
private String provider;
private TextView outputField;
private Location location;
private ScrollView scrollView;
private Criteria criteria;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_location);
latituteField = (TextView) findViewById(R.id.lat_textView);
longitudeField = (TextView) findViewById(R.id.long_textView);
outputField = (TextView) findViewById(R.id.output_textView);
scrollView = (ScrollView) findViewById(R.id.scrollView1);
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
List<String> providers = locationManager.getProviders(criteria, true);
outputField.append("Providers available..." + "\n");
for (String provider : providers) {
outputField.append(provider + "\n");
scrollView.fullScroll(ScrollView.FOCUS_DOWN);
}
provider = locationManager.getBestProvider(criteria, true);
locationManager.requestLocationUpdates(provider, 400, 1, this);
if (provider != null) {
outputField.append("Provider " + provider + " has been selected." + "\n");
scrollView.fullScroll(ScrollView.FOCUS_DOWN);
if (location != null) {
onLocationChanged(location);
} else {
latituteField.setText("Location not available");
longitudeField.setText("Location not available");
}
} else {
outputField.append("No provider selected" + "\n");
scrollView.fullScroll(ScrollView.FOCUS_DOWN);
}
}
#Override
protected void onResume() {
super.onResume();
locationManager.requestLocationUpdates(provider, 400, 1, this);
}
protected void onPause() {
super.onPause();
locationManager.removeUpdates(this);
}
#Override
public void onLocationChanged(Location location) {
double lat =location.getLatitude();
double lng =location.getLongitude();
latituteField.setText(String.valueOf(lat));
longitudeField.setText(String.valueOf(lng));
outputField.append("New Location: " + String.valueOf(lat) + " " + String.valueOf(lng) + "\n");
scrollView.fullScroll(ScrollView.FOCUS_DOWN);
}
#Override
public void onProviderDisabled(String dProvider) {
outputField.append("Provider " + dProvider + " has been disabled." + "\n");
scrollView.fullScroll(ScrollView.FOCUS_DOWN);
provider = locationManager.getBestProvider(criteria, true);
locationManager.requestLocationUpdates(provider, 400, 1, this);
if (provider != null) {
outputField.append("Provider " + provider + " has been selected." + "\n");
scrollView.fullScroll(ScrollView.FOCUS_DOWN);
if (location != null) {
onLocationChanged(location);
} else {
latituteField.setText("Location not available");
longitudeField.setText("Location not available");
}
} else {
outputField.append("No provider selected" + "\n");
scrollView.fullScroll(ScrollView.FOCUS_DOWN);
}
}
#Override
public void onProviderEnabled(String eProvider) {
outputField.append("Provider " + eProvider + " has been enabled." + "\n");
scrollView.fullScroll(ScrollView.FOCUS_DOWN);
provider = locationManager.getBestProvider(criteria, true);
locationManager.requestLocationUpdates(provider, 400, 1, this);
if (provider != null) {
outputField.append("Provider " + provider + " has been selected." + "\n");
scrollView.fullScroll(ScrollView.FOCUS_DOWN);
if (location != null) {
onLocationChanged(location);
} else {
latituteField.setText("Location not available");
longitudeField.setText("Location not available");
}
} else {
outputField.append("No provider selected" + "\n");
scrollView.fullScroll(ScrollView.FOCUS_DOWN);
}
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
outputField.append("Provider " + provider + " status changed to: " + Integer.toString(status) + "\n");
scrollView.fullScroll(ScrollView.FOCUS_DOWN);
}
}
Your answer is here What is the simplest and most robust way to get the user's current location in Android?. In this Fedor nicely explained with example of how to switching between location provider.
Thanks.
Related
I've developed Android Wear watch face, which gets location within a Service on handheld side. I use AsyncTask code which I've got from here.
This error drains about 50% battery of the phone. And I don't know why. Please help.
Error:
W/MessageQueue: Handler (android.location.LocationManager$ListenerTransport$1) {93795ca} sending message to a Handler on a dead thread
java.lang.IllegalStateException: Handler (android.location.LocationManager$ListenerTransport$1) {93795ca} sending message to a Handler on a dead thread
at android.os.MessageQueue.enqueueMessage(MessageQueue.java:543)
at android.os.Handler.enqueueMessage(Handler.java:631)
at android.os.Handler.sendMessageAtTime(Handler.java:600)
at android.os.Handler.sendMessageDelayed(Handler.java:570)
at android.os.Handler.sendMessage(Handler.java:507)
at android.location.LocationManager$ListenerTransport.onLocationChanged(LocationManager.java:248)
at android.location.ILocationListener$Stub.onTransact(ILocationListener.java:58)
at android.os.Binder.execTransact(Binder.java:453)
My Service:
public class WeatherService extends WearableListenerService {
private void startTask() {
Log.d(TAG, "Start Weather AsyncTask");
mGoogleApiClient = new GoogleApiClient.Builder(this).addApi(Wearable.API).build();
mLocationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
// getting GPS status
isGPSEnabled = mLocationManager
.isProviderEnabled(LocationManager.GPS_PROVIDER);
// getting network status
isNetworkEnabled = mLocationManager
.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if (!isGPSEnabled && !isNetworkEnabled) {
Log.d(TAG, "no network provider is enabled");
// no network provider is enabled
} else {
this.canGetLocation = true;
Log.d(TAG, "canGetLocation" + isGPSEnabled + isNetworkEnabled);
if (isNetworkEnabled) {
mLocationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER,
0,
0, new LocationListener() {
#Override
public void onLocationChanged(Location location) {
Log.d(TAG, "onLocationChanged: " + location);
//mLocation = location;
mLocationNetwork = location;
Task task = new Task();
task.execute();
Log.v(TAG, "isNetworkEnabled onLocationChanged: " + mLocationNetwork);
if (mLocationManager != null) {
mLocationManager.removeUpdates(this);
}
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
Log.d(TAG, "onLocationChanged: " + location);
if (mLocationManager != null) {
mLocationManager.removeUpdates(this);
}
//mLocation = location;
mLocationNetwork = location;
}
#Override
public void onProviderEnabled(String provider) {
if (mLocationManager != null) {
mLocationManager.removeUpdates(this);
}
}
#Override
public void onProviderDisabled(String provider) {
if (mLocationManager != null) {
mLocationManager.removeUpdates(this);
}
}
});
Log.d("Network", "Network Enabled");
if (mLocationManager != null) {
location = mLocationManager
.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if (location != null) {
latitude = location.getLatitude();
longitude = location.getLongitude();
Log.d(TAG, "Network Enabled: lat and long: " + latitude + longitude);
Task task = new Task();
task.execute();
Log.v(TAG, "isNetworkEnabled mLocationManager != null: " + location + latitude + longitude);
}
}
}
// if GPS Enabled get lat/long using GPS Services
if (isGPSEnabled) {
if (location == null) {
mLocationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER,
0,
0, new LocationListener(){
#Override
public void onLocationChanged( Location location )
{
Log.d( TAG, "onLocationChanged: " + location );
//mLocation = location;
mLocationNetwork = location;
Task task = new Task();
task.execute();
Log.v(TAG, "isGPSEnabled onLocationChanged: " + mLocationNetwork);
if (mLocationManager != null) {
mLocationManager.removeUpdates(this);
}
}
#Override
public void onStatusChanged( String provider, int status, Bundle extras )
{
Log.d( TAG, "onLocationChanged: " + location );
//mLocation = location;
mLocationNetwork = location;
if (mLocationManager != null) {
mLocationManager.removeUpdates(this);
}
}
#Override
public void onProviderEnabled( String provider )
{
if (mLocationManager != null) {
mLocationManager.removeUpdates(this);
}
}
#Override
public void onProviderDisabled( String provider )
{
if (mLocationManager != null) {
mLocationManager.removeUpdates(this);
}
}
});
Log.d("GPS", "GPS Enabled");
if (mLocationManager != null) {
location = mLocationManager
.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (location != null) {
latitude = location.getLatitude();
longitude = location.getLongitude();
Log.d(TAG, "GPS Enabled: lat and long: " + latitude + longitude);
Task task = new Task();
task.execute();
Log.v(TAG, "isGPSEnabled mLocationManager != null: " + location + latitude + longitude);
}
}
}
}
}
}
And here is the ASyncTask:
private class Task extends AsyncTask
{
private String resp;
#Inject
IWeatherApi api;
#Override
protected Object doInBackground( Object[] params )
{
if (this.isCancelled()) {
return null;
}
try
{
Log.d( TAG, "Task Running" );
RoboGuice.getInjector( WeatherService.this.getApplicationContext() ).injectMembers( this );
if ( !mGoogleApiClient.isConnected() )
{ mGoogleApiClient.connect();
}
final DataMap config = new DataMap();
WeatherInfo infoNetwork = api.getCurrentWeatherInfo(latitude, longitude);
config.putInt( KEY_WEATHER_TEMPERATURE, infoNetwork.getTemperature() );
config.putString( KEY_WEATHER_CONDITION, infoNetwork.getCondition() );
config.putLong( KEY_WEATHER_SUNSET, infoNetwork.getSunset() );
config.putLong( KEY_WEATHER_SUNRISE, infoNetwork.getSunrise() );
config.putInt( KEY_WEATHER_WIND_SPEED, infoNetwork.getSpeed() );
config.putInt( KEY_WEATHER_WIND_DEGREE, infoNetwork.getDeg() );
config.putInt( KEY_WEATHER_TEMP_MIN, infoNetwork.getTempMin() );
config.putInt( KEY_WEATHER_TEMP_MAX, infoNetwork.getTempMax() );
config.putInt( KEY_WEATHER_HUMIDITY, infoNetwork.getHumidity() );
config.putInt( KEY_WEATHER_PRESSURE, infoNetwork.getPressure() );
Wearable.MessageApi.sendMessage(mGoogleApiClient, mPeerId, PATH_WEATHER_INFO, config.toByteArray())
.setResultCallback(
new ResultCallback<MessageApi.SendMessageResult>() {
#Override
public void onResult(MessageApi.SendMessageResult sendMessageResult) {
Log.d(TAG, "SendUpdateMessage: " + sendMessageResult.getStatus());
Log.v(TAG, KEY_WEATHER_CONDITION);
Log.v(TAG, "AsyncTask config in onResult: " + config.toString());
Log.v(TAG, "mGoogleApiClient, mPeerId, PATH_WEATHER_INFO, config.toByteArray()" + mGoogleApiClient + " " + mPeerId + " " + PATH_WEATHER_INFO + " " + config);
}
}
);
}catch (IllegalStateException e) {
e.printStackTrace();
resp = e.getMessage();
}
catch ( Exception e )
{
Log.d( TAG, "Task Fail: " + e );
}
return null;
}
}
Please help, I'm a new developer and trying to solve this problem and for now without any result.
Your error Handler on a dead thread may came from a service which die immediately when they finish. You can use IntentService to create a new thread when you call the onHandleIntent method and then kill the thread as soon as onHandleIntent method returns.
Try to create your listener somewhere else, IntentService are not safe for setting up listeners because they die. It mainly used for executing a short task outside of the main thread.
Here's a related SO ticket that may help you solve your issue: Sending message to a Handler on a dead thread when getting a location from an IntentService
I want user location. both network and GPS location. i am getting network location but GPS location is always null. here is the code that i write for that.
public class GetLocation extends Service implements LocationListener {
LocationManager locationManager;
Location networkLocation, gpsLocation;
Intent intentBroadcastLocationUpdate;
boolean gpslocationOn, networklocationOn;
Handler handler = new Handler();
Runnable runnable = new Runnable() {
#Override
public void run() {
gpsLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
networkLocation = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
broadcastLocation();
handler.postDelayed(this, 3000);
}
};
#Override
public void onCreate() {
super.onCreate();
locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
intentBroadcastLocationUpdate = new Intent("UPDATE_LOCATION");
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 10, 1000 * 60 * 1, this);
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 10, 1000 * 60 * 1, this);
networkLocation = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
gpsLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
networklocationOn = true;
gpslocationOn = true;
broadcastLocation();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
handler.postDelayed(runnable, 3000);
return START_STICKY;
}
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public void onLocationChanged(Location location) {
Toast.makeText(getApplicationContext(),
location.getProvider() + " Location Changed:" + location.getLatitude() + " , "
+ location.getLongitude(), Toast.LENGTH_LONG).show();
};
#Override
public void onProviderDisabled(String arg0) {
Toast.makeText(getApplicationContext(), arg0 + " Disabled", Toast.LENGTH_LONG).show();
}
#Override
public void onProviderEnabled(String provider) {
if (provider.equals("network")) {
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 10, 1000 * 60 * 1, this);
}
if (provider.equals("gps")) {
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 10, 1000 * 60 * 1, this);
}
Toast.makeText(getApplicationContext(), provider + " Enabled", Toast.LENGTH_LONG).show();
}
#Override
public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
}
#Override
public void onDestroy() {
super.onDestroy();
locationManager.removeUpdates(this);
handler.removeCallbacks(runnable);
}
private void broadcastLocation() {
if (gpsLocation == null && networkLocation == null) {
Toast.makeText(getApplicationContext(),
"on create Couldn't get user location", Toast.LENGTH_LONG).show();
intentBroadcastLocationUpdate.putExtra("loc", "Could not retrive location");
sendBroadcast(intentBroadcastLocationUpdate);
} else if (gpsLocation != null) {
intentBroadcastLocationUpdate.putExtra("loc", "GPS:" + gpsLocation.getLatitude() + ","
+ gpsLocation.getLongitude());
sendBroadcast(intentBroadcastLocationUpdate);
} else if (networkLocation != null) {
intentBroadcastLocationUpdate.putExtra("loc", "Net:" + networkLocation.getLatitude() + ","
+ networkLocation.getLongitude());
sendBroadcast(intentBroadcastLocationUpdate);
} else if (gpsLocation != null && networkLocation != null) {
intentBroadcastLocationUpdate.putExtra(
"loc",
"Net:" + networkLocation.getLatitude() + ","
+ networkLocation.getLongitude() + " AND GPS:"+ gpsLocation.getLatitude() + ","
+ gpsLocation.getLongitude());
sendBroadcast(intentBroadcastLocationUpdate);
}
}
}
Can anybody tell me what is wrong that i am doing? why i'm unable to get GPS location? and what is the best practice of getting GPS location?
Add these permissions in your manifest
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
Refer this tutorial
public void getMyLocation() {
LocationManager locationManager = (LocationManager) context
.getSystemService(Context.LOCATION_SERVICE);
List<String> providers = locationManager.getProviders(true);
Location l = null;
for (int i = 0; i < providers.size(); i++) {
l = locationManager.getLastKnownLocation(providers.get(i));
if (l != null)
break;
}
if (l != null) {
latitude = l.getLatitude();
longitude = l.getLongitude();
}
}
Here what I need, how can I start Android service separately?
I got service running from background (Preference.Class),
public void startService(){
Intent intent;
intent = new Intent(getBaseContext(), ForegroundService.class);
startService(intent);
intent = new Intent(getBaseContext(), PostMobileHistory.class);
startService(intent);
intent = new Intent(getBaseContext(), PostLocation.class);
startService(intent);
sharedPreferences.edit().putBoolean("serviceStatus", true).commit();
}
and start the Location Manager which run in service after from the BroadcastReceiver, but why the previous service gone, and just only Lcation Manager left?
public class LocationManager extends Service implements LocationListener{
private android.location.LocationManager locationManager;
private String previousProvider = "gps";
private float previousAccuracy = 100;
public String mobileHistory_GUID = null;
Context context = this;
#Override
public void onCreate() {
SharedPreferences sharedPreferences = context.getSharedPreferences("mobileHistory", Context.MODE_PRIVATE);
mobileHistory_GUID = sharedPreferences.getString("GUID", "DEFAULT");
Log.i("SP Mobile History GUID", mobileHistory_GUID);
startTracking();
}
public void onDestroy(){
stopTracking();
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
public void stopTracking(){
if(locationManager != null){
locationManager.removeUpdates(this);
Log.i("Location Manager", "Tracking stopped");
}
}
public void startTracking() {
//Get the location manager
locationManager = (android.location.LocationManager) getSystemService(Context.LOCATION_SERVICE);
boolean isGPSEnabled = locationManager.isProviderEnabled(android.location.LocationManager.GPS_PROVIDER);
boolean isNetworkEnabled = locationManager.isProviderEnabled(android.location.LocationManager.NETWORK_PROVIDER);
if (!isGPSEnabled && !isNetworkEnabled) {
Log.i("Provider Status", "No provider");
}
else {
if (isNetworkEnabled) {
String locationProvider = android.location.LocationManager.NETWORK_PROVIDER;
Log.i("Provider Status", "Network enabled");
// Register the listener with the Location Manager to receive location updates
locationManager.requestLocationUpdates(locationProvider, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
}
if (isGPSEnabled) {
String locationProvider = android.location.LocationManager.GPS_PROVIDER;
Log.i("Provider Status", "GPS enabled");
// Register the listener with the Location Manager to receive location updates
locationManager.requestLocationUpdates(locationProvider, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
}
}
if(locationManager != null){
Log.i("Location Manager", "Tracking started");
}
}
public void onLocationChanged(Location location) {
SharedPreferences sharedPreferences = context.getSharedPreferences("mobileHistory", Context.MODE_PRIVATE);
String mobileHistory_GUID = sharedPreferences.getString("GUID", "DEFAULT");
String location_GUID = String.valueOf(UUID.randomUUID());
if (location != null) {
String latitude = valueOf(location.getLatitude());
String longitude = valueOf(location.getLongitude());
String altitude = valueOf(location.getAltitude());
String accuracy = valueOf(location.getAccuracy());
String speed = valueOf(location.getSpeed());
String provider = location.getProvider();
float floatAccuracy = Float.valueOf(accuracy);
if(floatAccuracy <= 20 && provider.equals("gps")){
Arrays.setLocationArrayList(new Model_Location(location_GUID, mobileHistory_GUID, provider, latitude, longitude, altitude, accuracy, speed));
Log.i("Location", "GPS");
Log.i("Location", "<= 20");
Log.i("Location", latitude + " " + longitude + " " + altitude + " " + accuracy + " " + speed);
previousProvider = provider;
previousAccuracy = floatAccuracy;
}
else if(floatAccuracy > 20 && provider.equals("gps")){
previousProvider = provider;
previousAccuracy = floatAccuracy;
}
else if(floatAccuracy > 20 && floatAccuracy <= 100 && provider.equals("network")){
if(previousAccuracy > 20 && previousProvider.equals("gps")){
Arrays.setLocationArrayList(new Model_Location(location_GUID, mobileHistory_GUID, provider, latitude, longitude, altitude, accuracy, speed));
Log.i("Location", "Network");
Log.i("Location", ">= 20 && <= 50");
Log.i("Location", latitude + " " + longitude + " " + altitude + " " + accuracy + " " + speed);
}
}
else{
Log.i("Location", latitude + " " + longitude + " " + altitude + " " + accuracy + " " + speed);
}
}
}
public void onProviderDisabled(String provider) {
}
public void onProviderEnabled(String provider) {
}
public void onStatusChanged(String provider, int status, Bundle extras) {
}
}
The problem solve, I shouldn't put function in the onCreate() on service, moved to onStartCommand() and its work perfectly well...
LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
LocationListener ll = new mylocationlistener();
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, ll);
I find the onLocationChanged function is PERFECTLY working when the location is Changed with the above code.
///////CLASS mylocationlistener
private class mylocationlistener implements LocationListener {
//#Override
public void onLocationChanged(Location location) {
if (location != null) {
Log.d("LOCATION CHANGED", location.getLatitude() + "");
Log.d("LOCATION CHANGED", location.getLongitude() + "");
Toast.makeText(MainActivity.this,
location.getLatitude() + "" + location.getLongitude(),
Toast.LENGTH_LONG).show();
p = new GeoPoint((int)location.getLatitude(),(int)location.getLongitude());
// p = new GeoPoint((int)8.538754,(int)76.950620);
}
}
//#Override
public void onProviderDisabled(String provider) {
}
// #Override
public void onProviderEnabled(String provider) {
}
// #Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
}
But the Problem is that I want the variable "p" to be filled with the current location , when the program starts, that is Before the First Change Help !!
try this code:
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
// Define the criteria how to select the locatioin provider -> use
// default
Criteria criteria = new Criteria();
provider = locationManager.getBestProvider(criteria, false);
Location location = locationManager.getLastKnownLocation(provider);
// Initialize the location fields
if (location != null) {
System.out.println("Provider " + provider + " has been selected.");
onLocationChanged(location);
} else {
latituteField.setText("Location not available");
longitudeField.setText("Location not available");
System.out.println("Location not avilable");
}
}
/* Request updates at startup */
#Override
protected void onResume() {
super.onResume();
locationManager.requestLocationUpdates(provider, 400, 1, this);
}
/* Remove the locationlistener updates when Activity is paused */
#Override
protected void onPause() {
super.onPause();
locationManager.removeUpdates(this);
}
#Override
public void onLocationChanged(Location location) {
double lat = (double) (location.getLatitude());
double lng = (double) (location.getLongitude());
latituteField.setText(String.valueOf(lat));
longitudeField.setText(String.valueOf(lng));
Log.i(TAG, "Lattitude:" +lat);
Log.i(TAG, "Longitude:" +lng);
}
Before you get fix, you can use coarse location. Check this link:
http://devdiscoveries.wordpress.com/2010/02/04/android-use-location-services/
(this is about the LocationManager class in android).
Is there a way of using requestLocationUpdates, but in some way that allows it to give me results for the best active provider every time? I could pass it the result of getBestProvider, but then it will always return results from that provider, and it wouldn't work as I expect if the user turns the gps on/off.
My code is in a background service.
Is there a way of using requestLocationUpdates, but in some way that allows it to give me results for the best active provider every time?
No, though you are welcome to register separate LocationListeners for multiple providers.
I could pass it the result of getBestProvider, but then it will always return results from that provider, and it wouldn't work as I expect if the user turns the gps on/off.
Your LocationListener is notified when its provider is enabled and disabled. If your current provider is disabled, you might register a LocationListener with a backup provider.
This is what I do:
public class LocationActivity extends Activity implements LocationListener{
private TextView latituteField;
private TextView longitudeField;
private LocationManager locationManager;
private String provider;
private TextView outputField;
private Location location;
private ScrollView scrollView;
private Criteria criteria;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_location);
latituteField = (TextView) findViewById(R.id.lat_textView);
longitudeField = (TextView) findViewById(R.id.long_textView);
outputField = (TextView) findViewById(R.id.output_textView);
scrollView = (ScrollView) findViewById(R.id.scrollView1);
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
List<String> providers = locationManager.getProviders(criteria, true);
outputField.append("Providers available..." + "\n");
for (String provider : providers) {
outputField.append(provider + "\n");
scrollView.fullScroll(ScrollView.FOCUS_DOWN);
}
provider = locationManager.getBestProvider(criteria, true);
locationManager.requestLocationUpdates(provider, 400, 1, this);
if (provider != null) {
outputField.append("Provider " + provider + " has been selected." + "\n");
scrollView.fullScroll(ScrollView.FOCUS_DOWN);
if (location != null) {
onLocationChanged(location);
} else {
latituteField.setText("Location not available");
longitudeField.setText("Location not available");
}
} else {
outputField.append("No provider selected" + "\n");
scrollView.fullScroll(ScrollView.FOCUS_DOWN);
}
}
#Override
protected void onResume() {
super.onResume();
locationManager.requestLocationUpdates(provider, 400, 1, this);
}
protected void onPause() {
super.onPause();
locationManager.removeUpdates(this);
}
#Override
public void onLocationChanged(Location location) {
double lat =location.getLatitude();
double lng =location.getLongitude();
latituteField.setText(String.valueOf(lat));
longitudeField.setText(String.valueOf(lng));
outputField.append("New Location: " + String.valueOf(lat) + " " + String.valueOf(lng) + "\n");
scrollView.fullScroll(ScrollView.FOCUS_DOWN);
}
#Override
public void onProviderDisabled(String dProvider) {
outputField.append("Provider " + dProvider + " has been disabled." + "\n");
scrollView.fullScroll(ScrollView.FOCUS_DOWN);
provider = locationManager.getBestProvider(criteria, true);
locationManager.requestLocationUpdates(provider, 400, 1, this);
if (provider != null) {
outputField.append("Provider " + provider + " has been selected." + "\n");
scrollView.fullScroll(ScrollView.FOCUS_DOWN);
if (location != null) {
onLocationChanged(location);
} else {
latituteField.setText("Location not available");
longitudeField.setText("Location not available");
}
} else {
outputField.append("No provider selected" + "\n");
scrollView.fullScroll(ScrollView.FOCUS_DOWN);
}
}
#Override
public void onProviderEnabled(String eProvider) {
outputField.append("Provider " + eProvider + " has been enabled." + "\n");
scrollView.fullScroll(ScrollView.FOCUS_DOWN);
provider = locationManager.getBestProvider(criteria, true);
locationManager.requestLocationUpdates(provider, 400, 1, this);
if (provider != null) {
outputField.append("Provider " + provider + " has been selected." + "\n");
scrollView.fullScroll(ScrollView.FOCUS_DOWN);
if (location != null) {
onLocationChanged(location);
} else {
latituteField.setText("Location not available");
longitudeField.setText("Location not available");
}
} else {
outputField.append("No provider selected" + "\n");
scrollView.fullScroll(ScrollView.FOCUS_DOWN);
}
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
outputField.append("Provider " + provider + " status changed to: " + Integer.toString(status) + "\n");
scrollView.fullScroll(ScrollView.FOCUS_DOWN);
}
}
From API level 9 and onwards, this is possible, using this method:
requestLocationUpdates(long minTime, float minDistance, Criteria criteria, PendingIntent intent);
See the documentation for more information on usage.