0

I am trying to obtain GPS co-ordinates via a handler. Below is the code :

final Thread ObainGpsBackground = new Thread(new Runnable() {

            @Override
            public void run() {
                     try{
                         String SetServerString = "";
                         //Obtaining GPS co-ordinates :
                         LatLong obj_latLong = new LatLong(getActivity());
                         addressList = obj_latLong.getListAddressFromGeocoder(getActivity());

                         //Setting the addressList.getLatitude() into a variable "SetServerString"
                         for (Address address : addressList) {
                             SetServerString = String.valueOf(address.getLatitude());
                             threadMsg(SetServerString);
                         }
                         //Obtaining GPS co-ordinates :
                     }
                     catch(Throwable t){
                    Log.i("Exception","Getting GPS exception : "+t);
                }
            }
        });

Somehow the code is always navigating towards the catch block. All I get this error :

I/Exception: Getting GPS exception : java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()

Here is the handler :

    private void threadMsg(String setServerString) {
        if (!setServerString.equals("") && !setServerString.equals("0")) {
            Message msgObj = handler.obtainMessage();
            Bundle b = new Bundle();
            b.putString("message", setServerString);
            msgObj.setData(b);
            handler.sendMessage(msgObj);
        }
    }

    private final Handler handler = new Handler() {

        public void handleMessage(Message msg) {

            String aResponse = msg.getData().getString("message");

            if ((null != aResponse)) {

                // ALERT MESSAGE
//                alert_attendance(getResources().getString(R.string.warning), getResources().getString(R.string.ects));
                Toast.makeText(getActivity(), "Response: "+aResponse, Toast.LENGTH_SHORT).show();
            }
            else
            {

                // ALERT MESSAGE
                alert_attendance(getResources().getString(R.string.warning), getResources().getString(R.string.unableToFindLocation));
//                Toast.makeText(getBaseContext(), "Not Got Response From Server.", Toast.LENGTH_SHORT).show();

            }
        }
    };

Seen various posts. Somehow not able to figure it out. How to exactly implement looper.prepare() ? Any ideas ?

TechFrk
  • 185
  • 2
  • 2
  • 15

1 Answers1

0

This is happening because no Looper was created and prepared by the Thread, and Handler requires Looper so it can receive messages. Without seeing the full code it's tough to pin it down, but in essence what is happening is when your Handler is being created (when loading whatever class it is a member of - looks like threadMsg), that is happening on your custom thread.

If you intend for this to update your UI, I'd suggest updating your Activity or Fragment code to expose a public method to provide updates based on GPS. Even better encapsulation would be to have your GPS background worker define an interface to callback something when an event happens:

public interface GpsEventListener {
    void gpsEventReceived(int type, String data);
}

Have your Activity or Fragment implement this interface and have them create the Handler which will run on the main thread:

public class MyGpsActivity extends Activity implements ThreadMsg.GpsEventListener, Handler.Callback {
    ...
    private Handler handler = new Handler(this);

    public boolean handleMessage(Message msg) {
        /*  do work here  */
    }

    public void gpsEventReceived(int type, String data) {
        Message msg = Message.obtain(handler, type, data);
        msg.sendToTarget();
    }
}

Be very careful about starting/stopping your background thread and interacting with the main thread. The Thread object is not lifecycle aware, so when your Activity or Fragment gets paused you can no longer update UI components and you'll want to stop your background worker.

I'd also suggest using asynchronous notifications of the GPS data rather than polling like this. Otherwise you are going to use a lot of CPU and battery.

Larry Schiefer
  • 15,687
  • 2
  • 27
  • 33