Passing context for call to “getSystemService”

My application crashes when accessing a location service within a method which is called within a Thread. I pass the context from within a service in which the thread is running but it doesn't work.

This is the call to the LocationService within the thread which is created inside a service.

class MyService extends Service {

  @Override 
  public int onStartCommand(Intent intent, int flags, int startId) {

  Thread thread = new Thread(){
    @Override
    public void run() {

      try{
        geofix = new GeoFixer(getApplicationContext());
        geofix.startLocationObserver(); 
        ...
      }catch (....){}....

The constructor of GeoFixer takes the context and saves it in Context context.

Now inside the method startLocationObserver() I call getSystemService with this context which crashes the application.

public class GeoFixer {
  ... 
  private Context context;

  GeoFixer(Context context){
    this.context = context; 
  }

  public void startLocationObserver(){
     LocationManager locationManager = (LocationManager)     
     context.getSystemService(Context.LOCATION_SERVICE);
  // This is where it crashes
  ... }

What am I doing wrong?

EDIT: Here's the LogCat now.

ERROR/AndroidRuntime(8824): FATAL EXCEPTION: Thread-10
ERROR/AndroidRuntime(8824): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
ERROR/AndroidRuntime(8824): at android.os.Handler.<init>(Handler.java:121)
ERROR/AndroidRuntime(8824): at android.location.LocationManager$ListenerTransport$1.<init>(LocationManager.java:173)
ERROR/AndroidRuntime(8824): at android.location.LocationManager$ListenerTransport.<init>(LocationManager.java:173)
ERROR/AndroidRuntime(8824): at android.location.LocationManager._requestLocationUpdates(LocationManager.java:579)
ERROR/AndroidRuntime(8824): at android.location.LocationManager.requestLocationUpdates(LocationManager.java:446)
ERROR/AndroidRuntime(8824): at de.theapplication.GeoFixer.getNetworkLocation(GeoFixer.java:64)
ERROR/AndroidRuntime(8824): at de.theapplication.GeoFixer.startLocationObserver(GeoFixer.java:27)
ERROR/AndroidRuntime(8824): at de.theapplication.Fadenzieher$1.run(Fadenzieher.java:36)

Answers


Looking at the stack trace, looks like your startLocationObserver() method invoked the LocationManager's requestLocationUpdates(String provider, long minTime, float minDistance, LocationListener listener) method (the one without a Looper argument).

See if you can call the requestLocationUpdates() version with the Looper argument instead, passing Looper.getMainLooper().

Alternatively, see this blog post where the solution is to call Looper.myLooper().prepare().


From a quick search on Google, it seems that worker thread do not have a Looper associated with them, so your Runnable might be trying to post a message on a thread that cannot process them. Try posting the same Runnable to your UI thread and see if the error still occurs.

Source:

Android Can't create handler inside thread that has not called Looper.prepare()


Get a reference to the LocationService in onStartCommand() (main/UI thread), and pass that to your thread.

And why don't you want to use an IntentService? It takes care of running your code on a separate thread and shuts itself down when done.


Need Your Help

What happened to emacs' java?

java android emacs editor

First of all, I do not want to start a religious war here, and pardon me for telling you a little story first.

UITableView custom popping

iphone uitableview

Okay, I made an app that has a list of items as a main view, and when you select an item it pushes a detail view controller. In this detail view controller you can switch between items. I want to b...