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
Related
I need to check current user location every 10 minutes even if user turned off the screen or closed app (not Force stop). For start of LocationCheckService I'm using AlarmService, but it's start to checking location always (onLocationChanged, for example). How to make only one request for location update every 10 minutes (without onLocationChanged every time) via Network or GPS provider?
MainActivity
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, LocationCheckService.class);
PendingIntent pendingIntent = PendingIntent.getService(getApplicationContext(), 0, intent, 0);
manager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 100, 200, pendingIntent);
}
}
LocationCheckService.class
public class LocationCheckService extends Service {
LocationManager locationManager = null;
#SuppressLint("MissingPermission")
#Override
public void onCreate() {
locationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1000, 0, new LocationListener(LocationManager.NETWORK_PROVIDER));
new Timer().schedule(new MyTimer(), 0, 10000);
}
#SuppressLint("MissingPermission")
class MyTimer extends TimerTask {
#SuppressLint("MissingPermission")
#Override
public void run() {
try {
Location location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
Geocoder geocoder = new Geocoder(getApplicationContext(), Locale.getDefault());
List<Address> listAddress = geocoder.getFromLocation(location.getLatitude(), location.getLongitude(), 1);
if (listAddress != null && listAddress.size() > 0)
Log.d(TAG, listAddress.get(0).getCountryCode());
listAddress = geocoder.getFromLocation(1.3707295, 32.3032414, 1);
if (listAddress != null && listAddress.size() > 0)
Log.d(TAG, listAddress.get(0).getCountryCode());
} catch (IOException e) {
e.printStackTrace();
}
}
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
private class LocationListener implements android.location.LocationListener {
Location mLastLocation;
public LocationListener(String provider) {
Log.e(TAG, "LocationListener " + provider);
mLastLocation = new Location(provider);
}
#Override
public void onLocationChanged(Location location) {
Log.e(TAG, "onLocationChanged: " + location);
mLastLocation.set(location);
}
#Override
public void onProviderDisabled(String provider) {
Log.e(TAG, "onProviderDisabled: " + provider);
}
#Override
public void onProviderEnabled(String provider) {
Log.e(TAG, "onProviderEnabled: " + provider);
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
Log.e(TAG, "onStatusChanged: " + provider);
}
}
}
i'm trying to get user's current location via the code, the basic idea is like this:
public class LocationProducer extends Thread {
// Timer timer1;
LocationManager lm;
boolean gps_enabled = false;
UpdateInterface mUpdateInterface;
private Looper mThreadLooper;
private Handler mHandler;
public LocationProducer(Context context, UpdateInterface updateInterface,
String name) {
super(name);
mContext = context;
mUpdateInterface = updateInterface;
}
public void run() {
Looper.prepare();
if (lm == null)
lm = (LocationManager) mContext
.getSystemService(Context.LOCATION_SERVICE);
try {
gps_enabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
} catch (Exception ex) {
}
if (gps_enabled) {
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0,
locationListenerGps);
}
Log.d(TAG, "requestLocationUpdates int thread:"
+ Thread.currentThread().getName());
// timer1 = new Timer();
// timer1.schedule(new GetLastLocation(), MAXWAITTIME);
mThreadLooper = Looper.myLooper();
mHandler = new Handler();
mHandler.postDelayed(GetLastLocation, MAXWAITTIME);
Looper.loop();
}
public void quitLooper() {
lm.removeUpdates(locationListenerGPSLongTimeRun);
lm.removeUpdates(locationListenerNetworkLongTimeRun);
mThreadLooper.quit();
// mHandler.getLooper().quit();
}
LocationListener locationListenerGps = new LocationListener() {
public void onLocationChanged(Location location) {
Log.d(TAG,
"get location int short time run locationlistenerGPS, in thread"
+ Thread.currentThread().getName());
// timer1.cancel();
mHandler.removeCallbacks(GetLastLocation);
mUpdateInterface.update(location);
lm.removeUpdates(this);
lm.removeUpdates(locationListenerNetwork);
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER,
MINUPDATETIME, MINUPDATEDISTANCE,
locationListenerGPSLongTimeRun);
if (network_enabled)
lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
MINUPDATETIME, MINUPDATEDISTANCE,
locationListenerNetworkLongTimeRun);
}
public void onProviderDisabled(String provider) {
}
public void onProviderEnabled(String provider) {
}
public void onStatusChanged(String provider, int status, Bundle extras) {
}
};
the basic idea is to get user location. i have to use looper to regist a listener in a non UI thread, but when i get handler of this loop. i found that the thread just wait,in nativePollOnce as
so if new gps location update comes ,the listener just don't work anymore.
is there any way to make the listener work again ? thank you very much.
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);
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();
}
}
I can get longitude and latitude by network provider, but unable to get it by GPS. How can I do that?
public void onCreate(Bundle savedInstanceState) {
...
mLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
if (mLocation != null) {
gp1 = getGeoByLocation(mLocation);
gp2 = gp1;
refreshMapView();
if( !mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)){
mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 2000,
10, mLocationListener);
}else{
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 2000,
10, mLocationListener);
}
private GeoPoint getGeoByLocation(Location location) {
GeoPoint gp = null;
try {
if (location != null) {
double geoLatitude = location.getLatitude() * 1E6;
double geoLongitude = location.getLongitude() * 1E6;
gp = new GeoPoint((int) geoLatitude, (int) geoLongitude);
}
} catch (Exception e) {
e.printStackTrace();
}
return gp;
}
Get lat long using GPS in every 10 min.
// Des: Start Device's GPS and get current latitude and longitude
public void GPS() throws IOException {
// Des: This is a background service and called after every 10 minutes and fetch latitude-longitude values
background = new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i < j; i++) {
if (ProjectStaticVariable.GPSExit == true ) {
try {
Thread.sleep(600000); //10 minutes
mainhandler.sendMessage(mainhandler.obtainMessage());
j++;
}
catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
}
});
background.start();
mainhandler = new Handler() {
public void handleMessage(Message msg) {
// Check Internet status
isInternetPresent = cd.isConnectingToInternet();
if (isInternetPresent) {
lat_long_Service_flag = true;
mlocManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
mlocListener = new MyLocationListener(getApplicationContext());
mlocManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 60000, 0, mlocListener);
mlocManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
}
}
};
}
// Des: Location Listener through which we get current latitude and longitude
public class MyLocationListener implements LocationListener {
public MyLocationListener(Context mContext) {}
public MyLocationListener(Runnable runnable) {}
#Override
public void onLocationChanged(Location loc) {
longitude = loc.getLongitude();
latitude = loc.getLatitude();
final_latitude = Double.toString(latitude);
final_longitude = 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) {
}
}