title: Looper.prepare exception using LocationManager in external Service
body: <p>I am getting the following exception when I try to use LocationManager within a custom class running in an external service:</p>
  
  <pre><code>*** Uncaught remote exception!  (Exceptions are not yet supported across        processes.)
  java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
          at android.os.Handler.&lt;init&gt;(Handler.java:200)
          at android.os.Handler.&lt;init&gt;(Handler.java:114)
          at android.location.LocationManager$GpsStatusListenerTransport$1.&lt;init&gt;(LocationManager.java:1464)
          at android.location.LocationManager$GpsStatusListenerTransport.&lt;init&gt;(LocationManager.java:1464)
          at android.location.LocationManager.addGpsStatusListener(LocationManager.java:1503)
          at org.poseidon_project.contexts.hardware.GPSIndoorOutdoorContext.start(GPSIndoorOutdoorContext.java:97)
          at org.poseidon_project.context.management.ContextManager.addObserverRequirement(ContextManager.java:97)
          at org.poseidon_project.context.reasoner.ContextMapper.registerIndoorOutdoorsContext(ContextMapper.java:260)
          at org.poseidon_project.context.reasoner.ContextMapper.registerContext(ContextMapper.java:197)
          at org.poseidon_project.context.ContextReasonerCore.addContextRequirement(ContextReasonerCore.java:70)
          at org.poseidon_project.context.ContextReasonerService$1.addContextRequirement(ContextReasonerService.java:74)
          at org.poseidon_project.context.IContextReasoner$Stub.onTransact(IContextReasoner.java:74)
          at android.os.Binder.execTransact(Binder.java:446)
  </code></pre>
  
  <p>Now, I have read many answer relating back to the use of Looper, with stuff like:</p>
  
  <pre><code>    Looper.prepare;
      mLocationManager.requestLocationUpdates(mProvider, mMinTime, mMinDistance, this, Looper.getMainLooper);
  </code></pre>
  
  <p>But this ends up not causing the Callback (onLocationChanged(Location location)) to be called when there is an update?</p>
  
  <p>The class implements the LocationListener, which also invokes the LocatioManager methods:</p>
  
  <pre><code>public abstract class LocationContext extends ContextObserver implements LocationListener {
  
  protected LocationManager mLocationManager;
  private int mMinTime = 3000;
  private int mMinDistance = 10;
  private String mProvider = LocationManager.GPS_PROVIDER;
  private String mIdealProvider = LocationManager.GPS_PROVIDER;
  
  
  public LocationContext (Context c) {
      super(c);
      mLocationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
  }
  
  public LocationContext (Context c, ContextReceiver cr) {
      super(c, cr);
      mLocationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
  }
  
  public LocationContext (Context c, ContextReceiver cr, int minTime, int minDistance, String name) {
      super(c, cr, name);
      mMinTime = minTime;
      mMinDistance = minDistance;
      mLocationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
  }
  
  public LocationContext (Context c, ContextReceiver cr, int minTime, int minDistance, String provider, String name) {
      super(c, cr, name);
      mMinTime = minTime;
      mMinDistance = minDistance;
      mProvider = provider;
      mIdealProvider = provider;
      mLocationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
  }
  
  @Override
  public boolean start() {
  
      //new Thread(new Runnable() {
      //  @Override
      //  public void run() {
              //Looper.prepare();
  
              mLocationManager.requestLocationUpdates(mProvider, mMinTime, mMinDistance, this);
              //handler.sendEmptyMessage(0);
              //Looper.loop();
      //  }
      //}).start();
  
  
      mIsRunning = true;
      //Looper.loop();
      return true;
  }
  
  
  @Override
  public boolean pause() {
      return stop();
  }
  
  
  @Override
  public boolean resume() {
      return start();
  }
  
  @Override
  public boolean stop() {
      mLocationManager.removeUpdates(this);
      mIsRunning = false;
      return true;
  }
  
  @Override
  public void onLocationChanged(Location location) {
      checkContext(location);
  
  }
  
  
  protected abstract void checkContext(Location location);
  
  @Override
  public void onProviderDisabled(String provider) {
      if (provider.equals(mIdealProvider)) {
          mProvider = LocationManager.GPS_PROVIDER;
  
          if (! mLocationManager.isProviderEnabled(mProvider)) {
              Intent gpsOptionIntent = new Intent (android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
              mContext.startActivity(gpsOptionIntent);
          }
      }
  
  }
  
  
  @Override
  public void onProviderEnabled(String provider) {
      if ((provider.equals(mIdealProvider)) &amp;&amp; (! provider.equals(mProvider))) {
          mLocationManager.removeUpdates(this);
          mProvider = provider;
          mLocationManager.requestLocationUpdates(mProvider, mMinTime, mMinDistance, this);
      }
  }
  
  
  @Override
  public void onStatusChanged(String provider, int status, Bundle extras) {
      // TODO Auto-generated method stub
  
  }
  
  public int getMinTime() {
      return mMinTime;
  }
  
  public void setMinTime(int mMinTime) {
      this.mMinTime = mMinTime;
  }
  
  public int getMinDistance() {
      return mMinDistance;
  }
  
  public void setMinDistance(int mMinDistance) {
      this.mMinDistance = mMinDistance;
  }
  </code></pre>
  
  <p>I don't really understand how to use the Looper in my situation. Can someone help? I understand the answer "run in UI thread" but this is a single service app, there is no UI, so I don't think I can do it in the UI thread?</p>
  
  <p>****UPDATE*****Solution Found******</p>
  
  <p>I believe I found a solution. The class in question was an abstract class, which I was extending by a few classes that did various Location based operations.</p>
  
  <p>In the LocationContext abstract class I used:</p>
  
  <pre><code> mLocationManager.requestLocationUpdates(mProvider, mMinTime, mMinDistance,this, Looper.getMainLooper());
  </code></pre>
  
  <p>And in an implementation class (for example one for analysing GPS satellite status) I placed it in a new Thread:</p>
  
  <pre><code>new Thread(new Runnable() {
          @Override
          public void run() {
              Looper.prepare();
              GPSIndoorOutdoorContext.super.start();
              mLocationManager.addGpsStatusListener(gpsListener);
              Looper.loop();
          }
      }).start();
  </code></pre>