1

I follow this post What is the simplest and most robust way to get the user's current location on Android?

I have many questions about the post, but unfortunately I don't have enough reputation to reply there, so I have to create a separate post. Sorry for any inconvenience.

Copy and past the code into my app and it works on my Samsung S2, but doesn't work in the emulator (2.3).

My questions:

  1. When run in the emulator, the code never reach the onLocationChanged() methods, instead it will wait for 20 sec (timeout set by the timer1) to start run() of GetLastLocation. Why?

  2. Now, the run() method of GetLastLocation class is always called, and I got the exception above.

    (E/AndroidRuntime(436): android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.).

I guess the error occurs in my code:

    public LocationResult locationResult = new LocationResult()
    {
        @Override
        public void gotLocation(final Location location)
        {
            Log.i(LOG_TAG, "gotLocation");
            if (location == null)
            {
                Log.i(LOG_TAG, "Cannot get location");
            }
            else
            {
                Log.i(LOG_TAG, "Lat: " + location.getLatitude() + " Long:" + location.getLongitude());
                tv = (TextView) findViewById(R.id.my_text); // <<< error here!!!
                            tv.setText(lat + "," + lon);
            }
        }
    };

TextView tv is initialized in my main Activity, which calls MyLocation myLocation = new MyLocation(); and myLocation.getLocation(this, locationResult);. The design is the same with that of the post. I wonder if the run() of GetLastLocation is called in another thread? Why is this? Has anyone got the same issue?

Thanks a lot!

Community
  • 1
  • 1
Caten
  • 179
  • 1
  • 3
  • 12
  • 1
    Updating the ui component needs to be done on the UI thread. You could use an asynctask or a handler to go from the background thread you are on to the UI thread. – James Black Feb 20 '12 at 19:46

1 Answers1

1

When using an emulator, you need to set your current location to it. It can be done with a few different ways. Se them here. I think the simplest way to start testing is to use the telnet and geo commands.

As you can use findViewById I suppose you are in the inner class of some Activity. So, use the runOnUiThread method to update your views

runOnUiThread(new Runnable() {
    @Override
    public void run() {
        tv = (TextView) findViewById(R.id.my_text); 
        tv.setText(lat + "," + lon);
    }
});

In the sample code, location updates are received through a timer task, that's why it is running in a separate thread.

Moshe
  • 9,283
  • 4
  • 29
  • 38
Olegas
  • 10,349
  • 8
  • 51
  • 72
  • Thanks for the quick reply! Yes, runOnUIThread seems to be the fix! As I read the comments in that post, no one has any issues regarding the different thread, and everyone seems to get their location on the onLocationChanged(), and not to fallback to the GetLastLocation call (question 1). And even run() is executed, the location return is still null, i.e. it reaches the last line of code locationResult.gotLocation(null); when I debug. Or is there a better approach for this? – Caten Feb 20 '12 at 20:40
  • I think this is because of emulator. Try to mock your location with the ways specified. – Olegas Feb 20 '12 at 20:52
  • I spent 8 hours on that issue alone and found out someone said that it's a bug of the emulator 2.3. I compiled my project and run on 2.1 and it can get the geo fix. On the threading issue, someone mentioned to use asynctask or handle to do the UI stuff, so what are the differences between runUiThread, AsyncTask and Handle? Sorry I'm new to Android development. – Caten Feb 21 '12 at 06:25
  • Where are no differences in final result between these three methods. Each of them are suitable for some special case. `AsyncTask` is to create some reusable finite task which is running in separate thread and (maybe) doing some UI changes then. `runOnUiThread` is universal solution to change some UI but if only you are have some `Activity` instance to call this method on. `Handler` is a basic aid to access some `Thread` from another one. I think `AsyncTask` and `runOnUiThread` is using Handler "under the hood". – Olegas Feb 21 '12 at 14:40