1

I have developed an application as a service that handles basic HTTP requests. When the phone receives a HTTP Post request like: http ://IP:port/gps/on, it should register to the GPS listener like the following:

 lm.requestLocationUpdates(LocationManager.GPS_PROVIDER,200,0,locationListener); 

But, as this code is present inside the handler, I am getting the below error:

8.614: E/AndroidRuntime(21211): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
06-18 12:34:58.614: E/AndroidRuntime(21211):    at android.os.Handler.<init>(Handler.java:121)
06-18 12:34:58.614: E/AndroidRuntime(21211):    at android.location.LocationManager$ListenerTransport$1.<init>(LocationManager.java:183)
06-18 12:34:58.614: E/AndroidRuntime(21211):    at android.location.LocationManager$ListenerTransport.<init>(LocationManager.java:183)
06-18 12:34:58.614: E/AndroidRuntime(21211):    at android.location.LocationManager._requestLocationUpdates(LocationManager.java:661)
06-18 12:34:58.614: E/AndroidRuntime(21211):    at android.location.LocationManager.requestLocationUpdates(LocationManager.java:486)
06-18 12:34:58.614: E/AndroidRuntime(21211):    at com.example.devicecommunication.ConnectService$HttpFileHandler.registerGPS(ConnectService.java:4281)
06-18 12:34:58.614: E/AndroidRuntime(21211):    at com.example.devicecommunication.ConnectService$HttpFileHandler.handle(ConnectService.java:700)
06-18 12:34:58.614: E/AndroidRuntime(21211):    at org.apache.http.protocol.HttpService.doService(HttpService.java:243)
06-18 12:34:58.614: E/AndroidRuntime(21211):    at org.apache.http.protocol.HttpService.handleRequest(HttpService.java:187)
06-18 12:34:58.614: E/AndroidRuntime(21211):    at com.example.devicecommunication.ConnectService$WorkerThread.run(ConnectService.java:4987) 

Can you please let me know if I have to use handler/ Looper for this? And any example of how to do this. Thanks in advance!

Code to register GPS is called by a class that handles HTTP requests:

public String registerGPS(){
String gps= "";
if(!gpsSensor){
if(isGpsOn(appContext))
{
Log.d("GPS on","Using GPS Provider here"); 
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER,200,0,locationListener);
gps = "***********GPS Provider registered here *********************";
}
else
{
Log.d("GPS off","using NETWORK Provider here");
lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,200,0,locationListener);
gps = "***********Network provider registered here *********************";
}
}
gpsSensor = true;
return gps; 
}
user1741274
  • 759
  • 3
  • 13
  • 25
  • Where are you making this call? This usuall just means you need to use the UI thread and not do the operation in the background. – Rarw Jun 18 '13 at 14:45
  • Need to see more code, where have you put the requestLocationUpdates, I guess in a handler or some sort. Show more code. – Siddharth Jun 18 '13 at 14:47
  • @Rarw Hi, Thanks for the reply. I have a thread that creates a class that handles all the requests. Inside the POST handler, I need to register for GPS with listener. This is my requirement. – user1741274 Jun 18 '13 at 14:47

3 Answers3

1

The error you're getting is because you're trying to run something from a background thread that requires the main thread. The code you provided does not show me the set up of this thread but to get the location set up back to the UI/Main thread you should be able to just create a new runnable using runOnUiThread as shown below.

private Runnable runnable = new Runnable() {
public void run() {  
    runOnUiThread(new Runnable() { 
        public void run(){ 
            //set up your listener here
        } 
    }); 
}

Just another comment, that you mention GPS, UI/Main thread actions, and HTTP post it just sounds like this could be set up using an AsyncTask. I'd have to see more code but that might make your life easier if you havent looked into it alraedy.

Rarw
  • 7,645
  • 3
  • 28
  • 46
  • I think I cannot use runOnUiThread() from Service. Please let me know your suggestions – user1741274 Jun 19 '13 at 07:48
  • I don't think that statment is 100% correct. `runOnUiThread` is an `Activity` method so I'd bet you could reach it so long as you passed the appropriate context to your service. However, in case I'm wrong, [here's a post on using a runnable in a service vs an activity](http://stackoverflow.com/questions/14808640/does-a-runnable-in-a-service-run-on-the-ui-thread) and how to access the UI thread from both. – Rarw Jun 19 '13 at 12:30
0
public class LocationLog extends Thread {
    LocationManager lm;
    LocationHelper loc;
    String latString, lngString = null;

    public LocationLog(Context context, String latString, String lngString) {
        loc = new LocationHelper();
        lm = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
    }

    public void run() {
        Looper.prepare();
        lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000L, 500.0f, loc);
        Looper.loop();
    }
}

then use in your service class:

private void LocationLog() {
        new LocationLog(context, latString, lngString).start();
        Log.d(latString, getClass().getSimpleName());
        Log.d(lngString, getClass().getSimpleName());
        retrieveUserId();
        sendData(user_id);
    }
Sagar Maiyad
  • 12,655
  • 9
  • 63
  • 99
0

In my Handler for Post, I passed an extra String to my service and started the service again. In onStartCommand(), I get the extra from the intent and then call requestLocationUpdates(), so it is done on the main thread. This solved my requirement. Thanks everyone for the help!

user1741274
  • 759
  • 3
  • 13
  • 25