IntentService passing Location object to UI
I am putting together a test location grabber and I decided to use an intentservice to get the location so that the user can continue to fill in a form on the UI.
This test class doesn't implement the form. I just want to get the service working and get it to return a location as part of this test.
I have been checking the internet and I decided to use a handler and a Message to pass back the location object.
The trouble is I am getting the error message 'sending message to a handler on a dead thread'. I know the message should be self explanatory but I can't see what is wrong with my code.
My main and only activity code is below
package com.pengilley.locationmanagertest;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
public class LocationManagerTestService extends Activity{
EditText locationField;
Button askLocation;
Location location;
private final static String TAG = "LocationManagerTestService";
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
locationField = (EditText)findViewById(R.id.locationtext);
askLocation = (Button)findViewById(R.id.button);
askLocation.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View view) {
getLocation(getApplicationContext());
};
});
}
private void getLocation(Context context){
Intent intent = new Intent(context, LocationTest.class);
startService(intent);
Log.d(TAG,"getLocation: service request sent");
}
final Handler handler = new Handler(){
publi开发者_运维问答c void handleMessage(Message msg){
Log.d(TAG,"handleMessage start");
//receive the message from our intentservice
Bundle bundle = msg.getData();
location = (Location)bundle.getParcelable("location");
CharSequence charseq = "Latitude: " + location.getLatitude() + " Longitude: " + location.getLongitude();
locationField.setText(charseq);
}
};
}
My IntentService class is here
package com.pengilley.locationmanagertest;
import android.app.IntentService;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
public class LocationTest extends IntentService{
LocationListener locationListener;
Location lastKnownLocation;
Location goodLocation;
LocationManager locationManager;
boolean gpsEnabled;
boolean networkEnabled;
float distanceBetween;
private final static String TAG = "LocationTest";
private final float MAX_DISTANCE_BETWEEN_LOCATIONS = 20;
public static boolean LOCATION_AVAILABLE = false;
private String fieldVal;
private final Handler handler = new Handler();
public LocationTest(){
super("Location test");
}
public void setLocationManager(Context context){
Log.d(TAG,"setLocationManager start");
//setup locationlistener
locationListener = new LocationListener(){
@Override
public void onLocationChanged(Location location) {
Log.d(TAG,"onLocationChanged start");
// TODO Auto-generated method stub
//update check this location against last know location.
//If both locations are close to each other we can stop listening and pass the new location to lResult
lastKnownLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
//if no location from gps try network
if(lastKnownLocation==null){
lastKnownLocation = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
}
if(lastKnownLocation==null){
//use current location
goodLocation = location;
}else{
//check accuracy of current location
distanceBetween = location.distanceTo(lastKnownLocation);
if(distanceBetween <= MAX_DISTANCE_BETWEEN_LOCATIONS){
//good location
goodLocation = location;
}else if(lastKnownLocation.hasAccuracy()){
goodLocation = lastKnownLocation;
}
}
Log.d(TAG,"onLocationChanged: " + goodLocation.toString());
//put result into handler
Message message = Message.obtain();
Bundle bundle = new Bundle();
bundle.putParcelable("location", goodLocation);
message.setData(bundle);
handler.sendMessage(message);
Log.d(TAG,"onLocationChanged: messag sent");
}
@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 arg0, int arg1, Bundle arg2) {
// TODO Auto-generated method stub
}
};
//get location manager
locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
//check if network and gps are enabled
gpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
networkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
//request location for providers which are enabled
if(gpsEnabled){
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,0,0,locationListener);
};
if(networkEnabled){
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);
}
}
public String getFieldVal(){
return fieldVal;
}
@Override
protected void onHandleIntent(Intent intent) {
// TODO Auto-generated method stub
Log.d(TAG,"onHandleIntent start");
setLocationManager(this);
}
}
I decided to use an intentservice to get the location so that the user can continue to fill in a form on the UI.
That is not a good idea. IntentService
shuts down when onHandleIntent()
completes and there is no more work to be done. Your current implementation is leaking memory like a sieve -- you are never removing your request for updates, and every invocation of the IntentService
will register a new LocationListener
.
The trouble is I am getting the error message 'sending message to a handler on a dead thread'. I know the message should be self explanatory but I can't see what is wrong with my code.
onHandleIntent()
is executed on a background thread, a thread that is long gone by the time you try using it. Futhermore, since you never bothered to implement handleMessage()
on the Handler
, the Message
would not go anywhere, and certainly not to an activity.
精彩评论