Can't create handler inside thread that has not called Looper.prepare() on locationManager in service

455 views Asked by At

I is the first time I am working with the location manager and I always get the same error:

java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()

This happens when i call .requestLocationUpdates on a locationManager. I don't know how can I put this in the Main UI thread. Here is the code of the service where the error occurs:

public class TrackerService extends Service {
    private Context mContext;
    private LocListener mlocListener;
    private LocationManager mlocManager;
    private final IBinder myBinder = new MyLocalBinder();

    public void initiateTracking() {
        this.mContext = getApplicationContext();
        mlocManager = (LocationManager) this.mContext.getSystemService(Context.LOCATION_SERVICE);
        mlocListener = new LocListener();
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return;
        }
        mlocManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mlocListener);
    }

    public Boolean getGPSStatus(){
        return mlocManager.isProviderEnabled(mlocManager.GPS_PROVIDER);
    }

    public Double[] getCurrentLocation(){
        Double[] lonLat = new Double[]{mlocListener.getLon(), mlocListener.getLat()};
        Log.d("DEBUG", "getCurrentLocation: " + lonLat);
        return lonLat;
    }

    public class MyLocalBinder extends Binder {
        public TrackerService getService() {
            return TrackerService.this;
        }
    }
    @Override
    public IBinder onBind(Intent arg0) {
        return myBinder;
    }
    @Override
    public void onCreate()
    {
        isRunning = true;
    }
    @Override
    public int onStartCommand(final Intent intent, int flags, int startId) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                initiateTracking();
            }
        }).start();

        return Service.START_STICKY;
    }
    @Override
    public void onDestroy() {
        isRunning = false;
    }
}

Here is how i start my service and then bind to it:

  @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        getSupportActionBar().setDisplayShowTitleEnabled(false);

        startService(new Intent(this, TrackerService.class));
        bindService(new Intent(MainActivity.this, TrackerService.class), myConnection, Context.BIND_AUTO_CREATE);
    }
1

There are 1 answers

1
JuLes On BEST ANSWER

You can add the code to run on the main UI Thread like this:

runOnUiThread(new Runnable() {
     @Override
     public void run() {
             //your code here
           }
    });