My app has a widget and shows information depending on the location of the device.
I would like to get the location by using a IntentService, because it destroys itself after the job is done, however the algorythm executes the
@Override
protected void onHandleIntent(Intent intent)
method and finishes. so there is no time to listen for some locations and give the info back.
is it possible to let the LocationListener wait until the
@Override
public void onLocationChanged(Location location) {
is called?
how to use properly the Looper in the
LocationManager.requestLocationUpdates(
method?
here the entire code for the IntentService:
public class GetLocation extends IntentService {
public GetLocation() {
super("GetLocation");
// TODO Auto-generated constructor stub
}
private static final String TAG = "GetLocation";
private LocationManager mLocationManager = null;
private static final int LOCATION_INTERVAL = 1000;
private static final float LOCATION_DISTANCE = 10f;
private ResultReceiver resultReceiver;
public static final String RECEIVER = "receiver";
public static final String GPS = "gps";
private int result = Activity.RESULT_CANCELED;
public static String RESULT = "result";
Location mLastLocation;
private class LocationListener implements android.location.LocationListener {
public LocationListener(String provider) {
Log.e(TAG, "LocationListener " + provider);
mLastLocation = new Location(provider);
}
@Override
public void onLocationChanged(Location location) {
Log.e(TAG, "onLocationChanged: " + location);
mLastLocation.set(location);
result = Activity.RESULT_OK;
publishResults(new double[] { mLastLocation.getLatitude(),
mLastLocation.getLongitude() }, result);
}
@Override
public void onProviderDisabled(String provider) {
Log.e(TAG, "onProviderDisabled: " + provider);
}
@Override
public void onProviderEnabled(String provider) {
Log.e(TAG, "onProviderEnabled: " + provider);
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
Log.e(TAG, "onStatusChanged: " + provider);
}
}
LocationListener[] mLocationListeners = new LocationListener[] {
// new LocationListener(LocationManager.GPS_PROVIDER),
new LocationListener(LocationManager.NETWORK_PROVIDER) };
@Override
public IBinder onBind(Intent arg0) {
return null;
}
@Override
protected void onHandleIntent(Intent intent) {
// TODO Auto-generated method stub
Log.e(TAG, "onHandleIntent");
resultReceiver = intent.getParcelableExtra(RECEIVER);
initializeLocationManager();
try {
mLocationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER, LOCATION_INTERVAL,
LOCATION_DISTANCE, mLocationListeners[0]);
} catch (java.lang.SecurityException ex) {
Log.i(TAG, "fail to request location update, ignore", ex);
} catch (IllegalArgumentException ex) {
Log.d(TAG, "network provider does not exist, " + ex.getMessage());
}
}
@Override
public void onDestroy() {
Log.e(TAG, "onDestroy");
super.onDestroy();
if (mLocationManager != null) {
for (int i = 0; i < mLocationListeners.length; i++) {
try {
mLocationManager.removeUpdates(mLocationListeners[i]);
Log.i(TAG, "remove location listners");
} catch (Exception ex) {
Log.i(TAG, "fail to remove location listners, ignore", ex);
}
}
}
}
private void initializeLocationManager() {
Log.e(TAG, "initializeLocationManager");
if (mLocationManager == null) {
mLocationManager = (LocationManager) getApplicationContext()
.getSystemService(Context.LOCATION_SERVICE);
}
}
private void publishResults(double[] gps, int result) {
Bundle bundle = new Bundle();
bundle.putDoubleArray(GPS, gps);
bundle.putInt(RESULT, result);
resultReceiver.send(Activity.RESULT_OK, bundle);
}
}
EDIT:
I would like to add the final code for the Service that gives the coordinates to a receiver:
However, it is only the gps provider working, the network is ignored on the device (everything is activated in the settings)
public class LocationGetter extends Service {
private static final String TAG = "LocationGetter";
private LocationManager mLocationManager = null;
private static final int LOCATION_INTERVAL = 1000;
private static final float LOCATION_DISTANCE = 10f;
private ResultReceiver resultReceiver;
public static final String RECEIVER = "receiver";
public static final String GPS = "gps";
private int result = Activity.RESULT_CANCELED;
public static String RESULT = "result";
Location mLastLocation;
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
Log.e(TAG, "onStartCommand");
resultReceiver = intent.getParcelableExtra(RECEIVER);
initializeLocationManager();
try {
mLocationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER, LOCATION_INTERVAL,
LOCATION_DISTANCE, mLocationListeners[0]);
} catch (java.lang.SecurityException ex) {
Log.i(TAG, "fail to request location update, ignore", ex);
} catch (IllegalArgumentException ex) {
Log.d(TAG, "network provider does not exist, " + ex.getMessage());
}
return super.onStartCommand(intent, flags, startId);
}
private class LocationListener implements android.location.LocationListener {
public LocationListener(String provider) {
Log.e(TAG, "LocationListener " + provider);
mLastLocation = new Location(provider);
}
@Override
public void onLocationChanged(Location location) {
Log.e(TAG, "onLocationChanged: " + location);
mLastLocation.set(location);
result = Activity.RESULT_OK;
publishResults(new double[] { mLastLocation.getLatitude(),
mLastLocation.getLongitude() }, result);
}
@Override
public void onProviderDisabled(String provider) {
Log.e(TAG, "onProviderDisabled: " + provider);
}
@Override
public void onProviderEnabled(String provider) {
Log.e(TAG, "onProviderEnabled: " + provider);
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
Log.e(TAG, "onStatusChanged: " + provider);
}
}
LocationListener[] mLocationListeners = new LocationListener[] {
new LocationListener(LocationManager.GPS_PROVIDER),
new LocationListener(LocationManager.NETWORK_PROVIDER) };
private void initializeLocationManager() {
Log.e(TAG, "initializeLocationManager");
if (mLocationManager == null) {
mLocationManager = (LocationManager) getApplicationContext()
.getSystemService(Context.LOCATION_SERVICE);
}
}
private void publishResults(double[] gps, int result) {
Bundle bundle = new Bundle();
bundle.putDoubleArray(GPS, gps);
bundle.putInt(RESULT, result);
resultReceiver.send(Activity.RESULT_OK, bundle);
}
}
You had select the wrong way to go - you should use Service to listen for Location updates, because Service will not be closed after it's code have been executed.
Another way - is to subscribe some service component to Location updates via AndroidManifest.xml by defining proper IntentFilter. In this situation - it can be an IntentService, as only it's OnReceive() method will be executed.