Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I am developing a simple application using Google Maps V2 API just to get basics and I am facing this error:

09-09 21:21:41.154: E/AndroidRuntime(3796): FATAL EXCEPTION: Thread-441
09-09 21:21:41.154: E/AndroidRuntime(3796): java.lang.ExceptionInInitializerError
09-09 21:21:41.154: E/AndroidRuntime(3796):  at cz.vongrad.dataSourceLayer.DataMapper.loadLocation(DataMapper.java:111)
09-09 21:21:41.154: E/AndroidRuntime(3796):  at cz.vongrad.dataSourceLayer.DBFacade.loadLocations(DBFacade.java:32)
09-09 21:21:41.154: E/AndroidRuntime(3796):  at cz.vongrad.domainLayer.Controller.loadLocations(Controller.java:94)
09-09 21:21:41.154: E/AndroidRuntime(3796):  at cz.vongrad.locator.MapActivity$1.run(MapActivity.java:199)
09-09 21:21:41.154: E/AndroidRuntime(3796): Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
09-09 21:21:41.154: E/AndroidRuntime(3796):  at android.os.Handler.<init>(Handler.java:121)
09-09 21:21:41.154: E/AndroidRuntime(3796):  at android.os.AsyncTask$InternalHandler.<init>(AsyncTask.java:607)
09-09 21:21:41.154: E/AndroidRuntime(3796):  at android.os.AsyncTask$InternalHandler.<init>(AsyncTask.java:607)
09-09 21:21:41.154: E/AndroidRuntime(3796):  at android.os.AsyncTask.<clinit>(AsyncTask.java:190)
09-09 21:21:41.154: E/AndroidRuntime(3796):  ... 4 more
09-09 21:21:41.164: E/EmbeddedLogger(239): App crashed!

DataMapper:

class LoadLocations extends AsyncTask<String, Void, ArrayList<Friend>>{

        private JSONObject jSONObject;


        @Override
        protected ArrayList<Friend> doInBackground(String... args) {

            List<NameValuePair> params = new ArrayList<NameValuePair>();
            params.add(new BasicNameValuePair("user_name", args[1]));

            jSONObject = jSONParser.makeHttpRequest(args[0], "POST", params);
            Log.d(TAG, jSONObject.toString());

            ArrayList<Friend> tempFriends = new ArrayList<Friend>();

            try {
                if(jSONObject.getInt("success") == 1){

                    JSONArray jsonArray = jSONObject.getJSONArray("users");


                    for (int i = 0; i < jsonArray.length(); i++) {
                        JSONObject o = jsonArray.getJSONObject(i);

                        tempFriends.add(new Friend(o.getString("user_name"), new LatLng(o.getDouble("loc_y"), o.getDouble("loc_x")), false));
                    }

                }
            } catch (JSONException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            return tempFriends;
        }

    }

public ArrayList<Friend> loadLocation(String URL, String userName) throws InterruptedException, ExecutionException {
        return new LoadLocations().execute(URL, userName).get();

    }

MapActivity:

public class MapActivity extends Activity implements LocationSource, LocationListener {
@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
}
private Thread loadFriendLocations = new Thread()
    {

        @Override
        public void run() {
            Log.d(TAG, "LastKnownLocation: " + locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER));
            try {
                while(true) {
                    controller.loadLocations(LOAD_LOCATIONS);
                    Log.d(TAG, "Loading new locations");
                    Message msg = uIHandler.obtainMessage();
                    msg.what = ADD_MAP_PIN;
                    uIHandler.sendMessage(msg);

                    sleep(10000);                   
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    };

    final Handler uIHandler = new Handler(){
      @Override
      public void handleMessage(Message msg) {

        if(msg.what==ADD_MAP_PIN){

            for (Friend friend : controller.getFriends()) {

                    addMapPin(friend);


            }
        }
        super.handleMessage(msg);
      }
    };

The weird thing is that I can run this app on my emulator (API 16) and it runs just great but when I try to run it on a physical device (API 15), it gets this error. The AsyncTask is run in separate class, so it might cause this problem. I would appreciate any suggestions. Thanks in advance.

like image 245
Husky Avatar asked Sep 09 '13 19:09

Husky


3 Answers

I had a similar issue, problem was that I was having series of Thread from Main Thread. Actually Main UI Thread started a service, which ran on a service and subsequently started another thread, which finally had a FileObserver (another thread), I had to communicate to UI thread by popping a toast message. I tried for several hours, and tried below, it worked as a charm.

//Let this be the code in your n'th level thread from main UI thread
Handler h = new Handler(Looper.getMainLooper());
h.post(new Runnable() {
  public void run() {
    Toast.makeText(context, "Your message to main thread", Toast.LENGTH_SHORT).show();
  }
});

The main key here is the getMainLooper() function of Looper class, which will provide you the Looper against the Main UI thread.

like image 100
darthvading Avatar answered Nov 09 '22 17:11

darthvading


You cannot execute an AsyncTask from a background thread. See the "Threading Rules" section of the AsyncTask documentation.

like image 10
CommonsWare Avatar answered Nov 09 '22 17:11

CommonsWare


Do this in your do in background...

runOnUiThread(new Runnable() {
    public void run() 
    {
        if (items.equals("null")) 
        {
            Toast.makeText(getApplicationContext(), "No Event Found",Toast.LENGTH_LONG).show();
        }                   
        else {                       
        }   
    }
});
like image 4
Chaitendra Pratap Avatar answered Nov 09 '22 16:11

Chaitendra Pratap