开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜