Android: requestLocationUpdates throws exception - android

I'm trying to get periodically the user position via GPS in Android and send the data to a remote DB, but I get the exception: Can't create handler inside thread that has not called Looper.prepare().
The method that retrieves the position is in a remote service, and it's pretty basic:
private void dumpLocationLog() {
LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
Looper.myLooper().prepare();
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000L, 500.0f ,this);
retrieveUserId();
sendData(user_id);
}
I tried calling Looper.myLooper().prepare(); but it still does not work.
I guess I have to implement a Looper here but I don't know how as I'm still pretty newbie with Android.
This is the full code of my service:
public class LocationLoggingService extends Service {
String latString, lngString;
Double latitude, longitude;
Date durationDate;
String user_id;
public String username;
private Handler serviceHandler;
private Task myTask = new Task();
#Override
public IBinder onBind(Intent i) {
Log.d(getClass().getSimpleName(), "onBind()");
username = i.getStringExtra("username");
return myRemoteLocationServiceStub;
}
private IMyRemoteLocationLoggingService.Stub myRemoteLocationServiceStub = new IMyRemoteLocationLoggingService.Stub() {
public void dumpLocationLog() throws RemoteException {
LocationLoggingService.this.dumpLocationLog();
}
};
#Override
public void onCreate() {
super.onCreate();
Log.d(getClass().getSimpleName(), "onCreate()");
}
#Override
public void onDestroy() {
super.onDestroy();
serviceHandler.removeCallbacks(myTask);
serviceHandler = null;
Log.d(getClass().getSimpleName(), "onDestroy()");
}
#Override
public void onStart(Intent intent, int startId) {
username = intent.getStringExtra("username");
super.onStart(intent, startId);
serviceHandler = new Handler();
serviceHandler.postDelayed(myTask, 1000L);
Log.d(getClass().getSimpleName(), "onStart()");
}
class Task implements Runnable {
public void run() {
try {
myRemoteLocationServiceStub.dumpLocationLog();
} catch (RemoteException e) {
e.printStackTrace();
}
serviceHandler.postDelayed(this, 5000L);
Log.i(getClass().getSimpleName(), "Calling the dumpLocationLog");
}
}
public void retrieveUserId() {
ArrayList<NameValuePair> postParameters = new ArrayList<NameValuePair>();
postParameters.add(new BasicNameValuePair("username", username));
String response = null;
try {
response = CustomHttpClient.executeHttpPost(
"http://10.0.2.2/science/getUserId.php", postParameters);
String res = response.toString();
res = res.replaceAll("\\s+", "");
if (!res.equals("0")) {
Log.d(getClass().getSimpleName(),
"Successfully retrieved user_id");
user_id = res;
} else {
Log.d(getClass().getSimpleName(), "Error retrieving user_id");
}
} catch (Exception e) {
}
}
private void sendData(String user_id) {
ArrayList<NameValuePair> postParameters = new ArrayList<NameValuePair>();
postParameters.add(new BasicNameValuePair("user_id", user_id));
postParameters.add(new BasicNameValuePair("latitude", latString));
postParameters.add(new BasicNameValuePair("longitude", lngString));
String response = null;
try {
response = CustomHttpClient.executeHttpPost(
"http://10.0.2.2/science/sendLocationData.php",
postParameters);
String res = response.toString();
res = res.replaceAll("\\s+", "");
if (res.equals("1")) {
Log.d(getClass().getSimpleName(), "Insertado en DB!");
} else {
Log.d(getClass().getSimpleName(), "Error insertando en la DB");
}
} catch (Exception e) {
}
}
LocationListener myLocationListener = new LocationListener () {
#Override
public void onLocationChanged(Location location) {
if (location != null) {
android.os.Debug.waitForDebugger();
latitude = location.getLatitude();
longitude = location.getLongitude();
latString = Double.toString(latitude);
lngString = Double.toString(longitude);
Log.d("Location: ", getClass().getSimpleName());
Log.d(latString, getClass().getSimpleName());
Log.d(lngString, getClass().getSimpleName());
}
}
#Override
public void onProviderDisabled(String provider) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
};
private void dumpLocationLog() {
LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000L, 500.0f, myLocationListener);
retrieveUserId();
sendData(user_id);
}
public static String create_datestring(String timestring)
throws java.text.ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss",
Locale.US);
Date dt = null;
Calendar c = Calendar.getInstance();
try {
dt = sdf.parse("2011-03-01 17:55:15");
c.setTime(dt);
System.out.println(c.getTimeInMillis());
System.out.println(dt.toString());
} catch (ParseException e) {
System.err.println("There's an error in the Date!");
}
return dt.toString();
}
}
Thanks a lot in advance!

The proper way to use the message looper is described in its doc with a code sample here

Well finally the solution is:
Class LoggingService.java (this is my service):
private void dumpLocationLog() {
new DumpLocationLog(context, latString, lngString).start();
Log.d(latString, getClass().getSimpleName());
Log.d(lngString, getClass().getSimpleName());
retrieveUserId();
sendData(user_id);
}
Then in DumpLocationLog.java:
public class DumpLocationLog extends Thread {
LocationManager lm;
LocationHelper loc;
String latString, lngString = null;
public DumpLocationLog(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 finally the LocationHelper for the LocationListener interface:
public class LocationHelper implements LocationListener {
public String latString, lngString;
public Double latitude, longitude;
#Override
public void onLocationChanged(Location location) {
if (location != null) {
latitude = location.getLatitude();
longitude = location.getLongitude();
LocationLoggingService.latString = Double.toString(latitude);
LocationLoggingService.lngString = Double.toString(longitude);
}
}
#Override
public void onProviderDisabled(String provider) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
}
It works like a charm but I have realized, that when listening for locations, it's creating threads non-stop and never closing the former ones; I mean that every time it checks for location, it creates a new thread and after X minutes, there are hundreds of threads.
Anybody knows why?

What I was suggesting you do was
class DumpLocationLog extends Thread
{
public void run()
{
LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000L, 500.0f ,/* FIXME this */);
retrieveUserId();
sendData(user_id);
}
}
Then, from wherever you had been calling dumpLocationLog(), use runOnUiThread(new DumpLocationLog()) instead.

You can use this approach:
class DumpLocationLog extends Thread
{
public void run()
{
Looper.prepare();
mLooper = Looper.myLooper();
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000L, 500.0f ,mLooper);
retrieveUserId();
sendData(user_id);
Looper.loop();
}
public void stop()
{
mLooper.quit();
}
}

Related

How can I add a timer to get GPS location?

I am a beginner, and I have 2 question :-
I with below code get gps location now want add a timer to code for any 10 Min get gps and save file GPS.json
How can share file gps.json for use in other class this project ?
My code don't problem i tested and for save string used Json format.
Please help me
MyLocationListener class
private class myLocationListener implements LocationListener{
#Override
public void onLocationChanged(Location location) {
// TODO Auto-generated method stub
if(location!=null){
locManager.removeUpdates(locListener);
String longitude = "Longitude: " +location.getLongitude();
String latitude = "Latitude: " +location.getLatitude();
String altitiude = "Altitiude: " + location.getAltitude();
String ACRY ="ACR:" + location.getAccuracy();
try {
JSONObject jsonObject = new JSONObject();
JSONArray jsonArray = new JSONArray();
JSONObject record = new JSONObject();
record.put("longitude", longitude);
record.put("latitude", latitude);
record.put("altitiude", altitiude);
record.put("ACRY", ACRY);
jsonArray.put(record);
jsonObject.put("location", jsonArray);
File root = new File(Environment.getExternalStorageDirectory() + "/Android/test/data");
File gpxfile = new File(root((" Gps.json")));
FileOutputStream fileOutputStream = new FileOutputStream(gpxfile);
byte[] in = (jsonArray.toString().getBytes() );
fileOutputStream.write(in);
fileOutputStream.close();
} catch (Exception e) {
Toast.makeText(context,e.getMessage(),Toast.LENGTH_SHORT).show();
e.printStackTrace();
}
}
}
#Override
public void onProviderDisabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
// TODO Auto-generated method stub
}
}
I prvoide some you can change according your needs.
public void turnGPSOn() {
String provider = Settings.Secure.getString(getContentResolver(),
Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
if (!provider.contains("gps")) {
final Intent poke = new Intent();
poke.setClassName("com.android.settings",
"com.android.settings.widget.SettingsAppWidgetProvider");
poke.addCategory(Intent.CATEGORY_ALTERNATIVE);
poke.setData(Uri.parse("3"));
sendBroadcast(poke);
}
}
private class MyTimerTask extends TimerTask {
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
// code to get and send location information
locManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
if (!locManager
.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
turnGPSOn();
}
try {
locManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER, 1000, 10,
locationListener);
} catch (Exception ex) {
turnGPSOff();
}
}
});
}
}
private void updateWithNewLocation(Location location) {
String latLongString = "";
try {
if (location != null) {
Log.e("test", "gps is on send");
latitude = Double.toString(location.getLatitude());
longitude = Double.toString(location.getLongitude());
Log.e("test", "location send");
locManager.removeUpdates(locationListener);
latLongString = "Lat:" + latitude + "\nLong:" + longitude;
Log.w("CurrentLocLatLong", latLongString);
} else {
latLongString = "No location found";
}
} catch (Exception e) {
}
}
private final LocationListener locationListener = new LocationListener() {
public void onLocationChanged(Location location) {
updateWithNewLocation(location);
}
public void onProviderDisabled(String provider) {
updateWithNewLocation(null);
}
public void onProviderEnabled(String provider) {
}
public void onStatusChanged(String provider, int status, Bundle extras) {
}
};
Calling the timer :
long gpsTimeInterval=2000;
void startTimer()
{
myTimer = new Timer();
myTimerTask = new MyTimerTask();
myTimer.scheduleAtFixedRate(myTimerTask, 0,
gpsTimeInterval);
}
and i hope you add internet permission into android manifest file.

Values are not updating in thread

i have made a background service which fetches value to database every 40 seconds but here longitude and latitude values are not updating, while in GPSTracker service, the values are updating every 30 second. This Service only fetches the first value of coordinates it get..
BackService.java:
public class BackService extends Service {
static double latitude,longitude;
GPSTracker gpsTracker;
private static final String DATA_URL = "http://"+Userstate.IP+"/spytracem/enter_loc.php";
public BackService() {
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
gpsTracker = new GPSTracker(getApplicationContext());
if (gpsTracker.canGetLocation()) {
longitude = gpsTracker.getLongitude();
latitude = gpsTracker.getLatitude();
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Runnable r = new Runnable() {
#Override
public void run() {
for (int a = 0; a < 10; a++) {
if (!getSharedPreferences(Userstate.STATESAVE,Context.MODE_PRIVATE).getBoolean(Userstate.status,false))
{
long futuretime = System.currentTimeMillis() + 40000;
while (System.currentTimeMillis() < futuretime) {
synchronized (this) {
try {
wait(futuretime - System.currentTimeMillis());
System.out.println(getSharedPreferences(Userstate.SHARED_PREF_NAME,Context.MODE_PRIVATE).getString(Userstate.EMAIL_SHARED_PREF,"No User"));
System.out.println(longitude);
System.out.println(latitude);
enter(getSharedPreferences(Userstate.SHARED_PREF_NAME,Context.MODE_PRIVATE).getString(Userstate.EMAIL_SHARED_PREF,"No User"), String.valueOf(longitude), String.valueOf(latitude));
if (a == 9) {
a = 0;
}
} catch (Exception e) {
}
}
}
}
else
{
getSharedPreferences(Userstate.STATESAVE, Context.MODE_PRIVATE).edit().putBoolean(Userstate.status,true);
stopSelf();
break;
}
}
}
};
Thread thread = new Thread(r);
thread.start();
return Service.START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
getSharedPreferences(Userstate.STATESAVE,Context.MODE_PRIVATE).edit().putBoolean(Userstate.status,true);
}
private void enter( String email, String longitude, String latitude) {
class Enter extends AsyncTask<String, Void, String> {
Locationhander ruc11 = new Locationhander();
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
System.out.println("Location Entered Boss!");
}
#Override
protected String doInBackground(String... params) {
HashMap<String, String> data2 = new HashMap<String,String>();
data2.put("email",params[0]);
data2.put("longitude",params[1]);
data2.put("latitude",params[2]);
String result2 = ruc11.sendPostRequest(DATA_URL,data2);
return result2;
}
}
Enter ru2 = new Enter();
ru2.execute(email, longitude, latitude);
}
}
Try to make latitude,longitude volatile:
static volatile double latitude,longitude;
And also your code:
longitude = gpsTracker.getLongitude();
latitude = gpsTracker.getLatitude();
Must be called every time, you call it only in onCreate().

Calling HttpGet in Background Service but seems doesn't work

I am tryin to send values with HttpGet. The function is in a Service. What i'm trying is when i'm click the button from Activity sending this values,and when my app is ended.It's working fine when app is open i can sending values and see this values with Toast message.When i end app just i can see values in Toast,but when check i see they didn't go to Web Page and then my database.My code follows,
public class LocService extends Service {
Timer timer;
Handler handler;
Location location1;
String logId = "";
final static long TIME= 10000;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
LocationManager locManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
LocationListener locListener = new LocationListener() {
#Override
public void onStatusChanged(String provider, int status,
Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
}
#Override
public void onLocationChanged(Location loc) {
location1 = new Location(loc);
tempVeriler.loc = new Location(loc);//tempVeriler is a class keeps temp values
}
};
boolean gps_enabled = locManager
.isProviderEnabled(LocationManager.GPS_PROVIDER);
boolean network_enabled = locManager
.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if (tempVeriler.id != null)
logId = tempVeriler.id;
if (gps_enabled) {
locManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER, 0, 0, locListener);
} else if (network_enabled) {
locManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER, 0, 0, locListener);
}
timer= new Timer();
handler = new Handler(Looper.getMainLooper());
timer.schedule(new TimerTask() {
#Override
public void run() {
giveInfo();
}
}, 0, TIME);
}
private void giveInfo() {
handler.post(new Runnable() {
#Override
public void run() {
if (location1 != null) {
getInternetData();
Toast.makeText(
LocService.this,
location1.getLatitude() + " "
+ location1.getLongitude(),
Toast.LENGTH_SHORT).show();
}
}
});
}
#Override
public void onDestroy() {
timer.cancel();
super.onDestroy();
}
public void getInternetData() {
HttpClient client = new DefaultHttpClient();
URI website;
try {
website = new URI(
"http://www.someadress.com/Default.aspx?logID="
+ logID+ "&latitude="
+ new Double(location1.getLatitude()).toString()
+ "&longitude="
+ new Double(location1.getLongitude()).toString());
HttpGet request = new HttpGet();
request.setURI(website);
HttpResponse response = client.execute(request);
} catch (Exception e) {
}
}
You can not perform any networking task in UI or Main thread, you have to use handler for that purpose. Change your getInternetData() method in this way,
new Handler().postDelayed(new Runnable()
{
#Override
public void run() {
HttpClient client = new DefaultHttpClient();
URI website;
try {
website = new URI(
"http://www.someadress.com/Default.aspx?logID="
+ logID+ "&latitude="
+ new Double(location1.getLatitude()).toString()
+ "&longitude="
+ new Double(location1.getLongitude()).toString());
HttpGet request = new HttpGet();
request.setURI(website);
HttpResponse response = client.execute(request);
} catch (Exception e) {
}
}
}, 500);
And please read this NetworkOnMainThreadException | Android Developers

get location data from service?

I try to make a locationing service but somehow i cant make it work.
Lat and Lng are always NULL.
I had some exceptions on locManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locListener); so i put it inside a run() method, now exception is gone. What could be the problem?
So what is the solution to make a locationing service work?
Code:
public class LocationService extends Service {
private Timer timer = new Timer();
private LocationManager locManager;
private LocationListener locListener = new MyLocationListener();
private String latitude;
private String longitude;
private String providerToSend;
Messenger messenger;
Timer t = new Timer();
#Override
public IBinder onBind(Intent arg0) {
return null;
}
public void onCreate() {
super.onCreate();
locListener = new MyLocationListener();
locationProviderInit();
startService();
}
#Override
public void onDestroy() {
super.onDestroy();
shutdownService();
}
private void startService() {
locManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
String token = new SharedPreffer(this).loadPreferences("token");
Log.d("Debug - token: ", "Van Token: " + token);
t.schedule(new TimerTask() {
#Override
public void run() {
locationProviderInit();
if (latitude != null && longitude != null) {
Log.d("Debug - lat: ", latitude);
Log.d("Debug - lng: ", longitude);
} else {
Log.d("Debug - lat and lng are: ", "NULL");
}
}
}, 0, 5000);
}
private void locationProviderInit() {
new Runnable() {
#Override
public void run() {
try {
boolean gps_enabled = locManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
boolean network_enabled = locManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if (gps_enabled) {
locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locListener);
providerToSend = LocationManager.GPS_PROVIDER;
}
if (network_enabled) {
locManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locListener);
providerToSend = LocationManager.NETWORK_PROVIDER;
}
} catch (Exception e) {
Log.d("Debug", e.toString());
}
}
};
}
class MyLocationListener implements LocationListener {
public void onLocationChanged(Location location) {
if (location != null) {
longitude = Double.toString(location.getLongitude());
latitude = Double.toString(location.getLatitude());
}
}
public void onProviderDisabled(String arg) {
}
public void onProviderEnabled(String arg) {
}
public void onStatusChanged(String provider, int status, Bundle extras) {
}
}
private void shutdownService() {
if (timer != null)
timer.cancel();
Log.i(getClass().getSimpleName(), "Timer stopped!!!");
}
}
you don't execute the Runnable in locationProviderInit...
Have you tried to put a debug message inside the method run() within the Runnable object, and see if it has been ever executed?
Defining a Runnable instance without using it ,e.g. within a thread, won't work.
Here are few examples of open source GPS logging services that you can use as guide.
GPSLoggerService
GPSLoggingService

How to get location after every 5 minutes?

I am using this link for location service and it works
Now I want to create BackgroundService that make calls to a function that gets location after every 5 minutes.
I think I need to use Timer for this, please tell me how to manage this 5 minutes gap in between this location class gets called.
public class LocationService extends Service {
private Timer timer;
private long UPDATE_INTERVAL ;
public static final String Stub = null;
LocationManager mlocmag;
LocationListener mlocList ;
private double lat,longn;
#Override
public void onCreate() {
super.onCreate();
webService = new WebService();
mlocmag = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
mlocList = new MyLocationList();
Location loc = mlocmag.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (loc == null) {
loc = mlocmag.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
}
timer = new Timer(); // location.
UpdateWithNewLocation(loc); // This method is used to get updated
mlocmag.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0,mlocList);
}
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public void onDestroy() {
super.onDestroy();
if (timer != null) {
timer.cancel();
}
mlocmag.removeUpdates(mlocList);
}
#Override
public boolean stopService(Intent name) {
return super.stopService(name);
}
private void UpdateWithNewLocation(final Location loc) {
final SharedPreferences prefs = getSharedPreferences(Const.COMMON_SHARED, Context.MODE_PRIVATE);
userId = prefs.getString(Const.COMMON_USERID, null);
gps = prefs.getInt(Const.COMMON_GPS, 0);
UPDATE_INTERVAL = 500000;
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
if (loc != null) {
final double latitude = loc.getLatitude(); // Updated lat
final double longitude = loc.getLongitude(); // Updated long
String response = null ;
if (lat != latitude || longn != longitude ) {
response = webService.updateLatandLong(userId, latitude, longitude);
lat = latitude;
longn = longitude;
}
}
else {
String latLongStr = "No lat and longitude found";
}
}
}, 0, UPDATE_INTERVAL);
}
public class MyLocationList implements LocationListener {
public void onLocationChanged(Location arg0) {
UpdateWithNewLocation(arg0);
}
public void onProviderDisabled(String provider) {
Toast.makeText(getApplicationContext(), "GPS Disable ",
Toast.LENGTH_LONG).show();
}
public void onProviderEnabled(String provider) {
Toast.makeText(getApplicationContext(), "GPS enabled",
Toast.LENGTH_LONG).show();
}
public void onStatusChanged(String provider, int status, Bundle extras) {
}
}
}
use This:
Timer timer = new Timer();
timer.schedule(new TimerTask() {
public void run() {
//your code to get lat long
}
}, 0, 500000);

Categories

Resources