0

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)
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Ben
  • 191
  • 3
  • 13

3 Answers3

0

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:

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

Community
  • 1
  • 1
ACrazyOldMan
  • 45
  • 1
  • 5
  • It worked before in an class which extended "IntentService". This should be the same like the UI thread. So it's about Looper.prepare(). How can I fix this? Shall I just call "Looper.prepare()" in the thread's run() method? – Ben Nov 15 '11 at 02:27
  • Yes, you can try that. If that does not work, try explicitly obtaining the thread's Looper with Looper.myLooper() first. Last would be to try the application's main Looper. The Android docs for the Looper class actually explain this fairly well IMO. – ACrazyOldMan Nov 15 '11 at 06:35
0

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().

Joe
  • 14,039
  • 2
  • 39
  • 49
0

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.

Nikolay Elenkov
  • 52,576
  • 10
  • 84
  • 84
  • Thanks a lot! For me passing the Looper via requestLocationUpdates did work. I used a Service because there's a periodic action within the service & the service only get started / stopped but no other interaction happens. – Ben Nov 15 '11 at 17:30
  • If it's a periodic action, it's still a good idea to use `IntentService`. You can use `AlaramManager` to start it periodically. – Nikolay Elenkov Nov 16 '11 at 00:35