On this code i want to get the gps location every 3 seconds. but when i run this program on my device it tells me that latitude and longitude are both 0 every time. how should i handle this problem?
and what is the looper task ?? it gives me error when i donot use it
public class LocationService extends Service {
final static String TAG = "MyService";
double latitude ;
double Longitude ;
LocationManager lm;
LocationListener ll;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
Log.d(TAG, "onCreate");
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
new Thread() {
public void run() {
Looper.prepare();
while(true){
lm = (LocationManager) getSystemService(LOCATION_SERVICE);
ll = new MyLocationListener();
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER,
0, 0, ll);
//when i log here , it gives me wronganswer
Log.d(TAG,Double.toString(latitude));
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onDestroy() {
Log.d(TAG, "OnDestroy");
super.onDestroy();
}
class MyLocationListener implements LocationListener{
#Override
public void onLocationChanged(Location location) {
//when i log here , it gives me correct answer
double lat = location.getLatitude();
double lon = location.getLongitude();
latitude = lat;
Longitude = lon;
}
#Override
public void onProviderDisabled(String arg0) {
}
#Override
public void onProviderEnabled(String arg0) {
}
#Override
public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
}
};
}
When you get location from GPS, it can take some time, because GPS module needs to find satellites. So you need to wait couple or few minutes while GPS module find satellites. If WI-FI location provider available you can get location more quick.
Additional info about location providers you can find here: http://developer.android.com/guide/topics/location/strategies.html
Since Android has
GPS_PROVIDER and NETWORK_PROVIDER
you can register to both and start fetch events from onLocationChanged(Location location) from two at the same time. So far so good. Now the question do we need two results or we should take the best. As I know GPS_PROVIDER results have better accuracy than NETWORK_PROVIDER.
for example you have location listener:
LocationListener locationListener = new LocationListener() {
public void onLocationChanged(Location location) {
//here you get locations from both providers
}
public void onProviderDisabled(String provider) {
}
public void onProviderEnabled(String provider) {
}
public void onStatusChanged(String provider, int status, Bundle extras) {
}
};
YOu need to do something like that:
LocationManager lm = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0,locationListener);
lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0,locationListener);
but before registering you need to check is these providers available on this device, like that:
boolean network_enabled = lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
boolean gps_enabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
Related
I have implemented a LocationListener to receive regular updates in a service when app is minimized. However this does not work. Updates are only received when the app is visible. Location updates cease when screen is locked or app is minimized.
public class MapService1 extends Service {
private static final long MINIMUM_DISTANCE_CHANGE_FOR_UPDATES = 0;
private static final long MINIMUM_TIME_BETWEEN_UPDATES = 0;
protected LocationManager locationManager;
Location location;
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate() {
super.onCreate();
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER,
MINIMUM_TIME_BETWEEN_UPDATES,
MINIMUM_DISTANCE_CHANGE_FOR_UPDATES,
new MyLocationListener());
location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
}
#Override
public void onDestroy() {
super.onDestroy();
}
private class MyLocationListener implements LocationListener {
public void onLocationChanged(Location location) {
System.out.println("----------------------NEW ON LOCATION CHANGED (" + location.getLatitude() + "," + location.getLongitude() + ")----------------------");
}
public void onStatusChanged(String s, int i, Bundle b) {
}
public void onProviderDisabled(String s) {
}
public void onProviderEnabled(String s) {
}
}
}
Add this permission to your manifest file
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
Your problem is likely that your app only has permission to location while using the app. This will give you the option to accept location permissions all the time.
I need a service in my reminder program to check location repeatedly and I'm doing that with this code but I get force close when service started:
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
ll = new Mylocationlistener();
checkPermission("android.permission.ACCESS_FINE_LOCATION",1,0);
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, ll);
return START_STICKY;
}
private class Mylocationlistener implements LocationListener {
#Override
public void onLocationChanged(Location location) {
if (location != null) {
Toast.makeText(getBaseContext(), "Location changed" + location.getLatitude() + location.getLongitude(), Toast.LENGTH_SHORT).show();
}
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
}
}
You have to check if GPS is enabled, every time your Service is triggered. Try this:
In onStartCommand, add a GPS checker:
if (lm.isProviderEnabled(LocationManager.GPS_PROVIDER)){
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, ll);
}
I've written my custom location manager to check for an update in the user's location every 30 seconds. The code is working fine i.e. I'm receiving updates in user's location. But the problem is that the GPS icon is always visible on the status bar on top. I'm guessing that it should be visible only once in 30 seconds. Is this normal or I'm doing something wrong?
public volatile Double mLatitude = 0.0;
public volatile Double mLongitude = 0.0;
int minTime = 30000;
float minDistance = 0;
MyLocationListener myLocListener = new MyLocationListener();
LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
Criteria criteria = new Criteria();
criteria.setAltitudeRequired(false);
criteria.setBearingRequired(false);
criteria.setCostAllowed(true);
criteria.setSpeedRequired(false);
String bestProvider = locationManager.getBestProvider(criteria, false);
locationManager.requestSingleUpdate(criteria, myLocListener, null);
locationManager.requestLocationUpdates(bestProvider, minTime, minDistance, myLocListener);
private class MyLocationListener implements LocationListener {
#Override
public void onLocationChanged(Location loc)
{
if (loc != null) {
//Do something knowing the location changed by the distance you requested
mLatitude = loc.getLatitude();
mLongitude = loc.getLongitude();
Toast.makeText(mContext, "Location Changed! "+Double.toString(mLatitude)+" "+Double.toString(mLongitude), Toast.LENGTH_LONG).show();
}
}
#Override
public void onProviderDisabled(String arg0)
{
//Do something here if you would like to know when the provider is disabled by the user
Toast.makeText(mContext, "Provider Disabled! "+Double.toString(mLatitude)+" "+Double.toString(mLongitude), Toast.LENGTH_LONG).show();
}
#Override
public void onProviderEnabled(String arg0)
{
//Do something here if you would like to know when the provider is enabled by the user
Toast.makeText(mContext, "Provider Enabled! "+Double.toString(mLatitude)+" "+Double.toString(mLongitude), Toast.LENGTH_LONG).show();
}
#Override
public void onStatusChanged(String arg0, int arg1, Bundle arg2)
{
//Do something here if you would like to know when the provider status changes
Toast.makeText(mContext, "Provider Status Changed! "+Double.toString(mLatitude)+" "+Double.toString(mLongitude), Toast.LENGTH_LONG).show();
}
}
As long as 1 or more apps have called requestLocationUpdates for the GPS provider, GPS will stay on. It doesn't turn off between requests. It can't- doing so would cause it to lose satellite lock, which would cause it to have to re-establish. That takes a lot more than 30 seconds sometimes. So GPS will stay on until you unregister for GPS events.
The question is old but still, it would be great to give a better answer.
You need to use a Handler which runs continuously on 5 minutes interval so, you get the location update only once and you release the GPS device, this way your app won't listen to the GPS updates but your handler know when it should be called again to listen the updates.
public static void getLocation(Context context) {
Handler locationHandler = new Handler();
locationHandler.post(new Runnable() {
#Override
public void run() {
LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
locationManager.requestSingleUpdate(LocationManager.GPS_PROVIDER, new LocationListener() {
#Override
public void onLocationChanged(Location location) {
// Handle the location update
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
}
}, null);
locationHandler.postDelayed(this, 1000 * 60 * 5);
}
});
}
I'm kinda lost here: In my main activity, I register a LocationManager and connect it to a LocationListener to use myLocation.getLatitude() and such.
Now I need to use the Location- methods from another class.
I can't use those object from another class because I cant intantiate the main activity.
I can't use getters to pass the L.Manager or L.Listener around, because those are non- static again.
So, in general, how do i access objects that I created in the main activity?
Any hints on how to organize this better? Is the LocationListener class within the main activity class a stupid thing to do in general?
public class URNavActivity extends Activity
{
public LocationManager mlocManager;
public LocationListener mlocListener;
...
}
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
mResourceProxy = new DefaultResourceProxyImpl(getApplicationContext());
actVar=this;
initGraph();
setMap();
gpsEnable();
initMyLocation();
getItems();
initOverlay();
}
public void gpsEnable ()
{
mlocManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
mlocListener = new MyLocationListener();
mlocManager.requestLocationUpdates( LocationManager.GPS_PROVIDER, 0, 0, mlocListener);
}
public class MyLocationListener implements LocationListener
{
#Override
public void onLocationChanged(Location loc)
{
loc.getLatitude();
loc.getLongitude();
myMap.getController().setCenter(new GeoPoint(lati, longi));
}
First and foremost your LocationListener should not be part of an activity. Activities have a clearly defined lifecycle and can come into being, and be destroyed, by the Android framework on an as-needed basis. Therefore the instance variables of your Activity will need to be re-initialised in your activity's onResume() method, making them completely unsuitable for long-term storage.
So. Start by creating a sticky service to manage the starting and stopping of location updates. Being sticky means that the service instance hangs around between invocations and therefore you can reliably use instance variables and know that they will retain their values until the service is terminated. This service should also implement the LocationListener interface, and now it can store the Location notified to it when onLocationChanged is invoked:
public class LocationService extends Service implements LocationListener {
private LocationManager locationManager;
private Location location;
#Override
public int onStartCommand(final Intent intent, final int flags, final int startId) {
Logging.i(CLAZZ, "onHandleIntent", "invoked");
if (intent.getAction().equals("startListening")) {
locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
}
else {
if (intent.getAction().equals("stopListening")) {
locationManager.removeUpdates(this);
locationManager = null;
}
}
return START_STICKY;
}
#Override
public IBinder onBind(final Intent intent) {
return null;
}
public void onLocationChanged(final Location location) {
this.location = location;
// TODO this is where you'd do something like context.sendBroadcast()
}
public void onProviderDisabled(final String provider) {
}
public void onProviderEnabled(final String provider) {
}
public void onStatusChanged(final String arg0, final int arg1, final Bundle arg2) {
}
}
Now you have a service you can start and stop the location updates as you need them. This also allows you to continue to receive and process location changes even when your application is not in the foreground, if that is what you want.
You now have two choices on how to make that Location information available: Use context.sendBroadcast() to propagate the new Location to (for example) an activity, or use the bound service approach to allow other classes to invoke the exposed API and obtain the Location. See http://developer.android.com/guide/topics/fundamentals/bound-services.html for more details on creating a bound service.
Note that there are many other aspects to listening for location updates that I have not included here, for the sake of clarity.
I would offer two elegant ways to access your object from anywhere:
use a Singleton design pattern
use ProjectApp class. This class can be accessed from any activity simply by calling getApplication().
ProjectApp app = (ProjectApp)getApplication();
I used a combination of the two:
public class MyApp extends Application {
private MyLocation mMyLocation;
#Override
public void onCreate() {
super.onCreate();
mMyLocation = new MyLocation();
mMyLocation.getLocation(this, GlobalData.getInstance(), true);
}
}
You can see that GlobalData is a singleton class that implements LocationResult interface, meaning that it will send the updated location to this object.
When I need to get the updated location, I take it from GlobalData.
Here is MyLocation class implementation (I used some code from here and made some changes:
package com.pinhassi.android.utilslib;
import java.util.Timer;
import java.util.TimerTask;
import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
public class MyLocation {
private Timer timer1;
private LocationManager lm;
private LocationResult locationResult;
private boolean gps_enabled=false;
private boolean network_enabled=false;
private boolean mContinuesUpdates;
private int decimalAccuracy;
/**
* Class constructor
*/
public MyLocation(){
decimalAccuracy = 0;
}
public boolean getLocation(Context context, LocationResult result, boolean continuesUpdates)
{
mContinuesUpdates = continuesUpdates;
//I use LocationResult callback class to pass location value from MyLocation to user code.
locationResult=result;
if(lm==null)
lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
//exceptions will be thrown if provider is not permitted.
try{gps_enabled=lm.isProviderEnabled(LocationManager.GPS_PROVIDER);}catch(Exception ex){}
try{network_enabled=lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER);}catch(Exception ex){}
//don't start listeners if no provider is enabled
if(!gps_enabled && !network_enabled)
return false;
if(gps_enabled)
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListenerGps);
if(network_enabled)
lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListenerNetwork);
timer1=new Timer();
timer1.schedule(new GetLastLocation(), 20000);
return true;
}
LocationListener locationListenerGps = new LocationListener() {
public void onLocationChanged(Location location) {
timer1.cancel();
locationResult.gotLocation(getDecimalAccurated(location));
if (!mContinuesUpdates)
lm.removeUpdates(this);
lm.removeUpdates(locationListenerNetwork);
}
public void onProviderDisabled(String provider) {}
public void onProviderEnabled(String provider) {}
public void onStatusChanged(String provider, int status, Bundle extras) {}
};
LocationListener locationListenerNetwork = new LocationListener() {
public void onLocationChanged(Location location) {
timer1.cancel();
locationResult.gotLocation(getDecimalAccurated(location));
if (!mContinuesUpdates)
lm.removeUpdates(this);
lm.removeUpdates(locationListenerGps);
}
public void onProviderDisabled(String provider) {}
public void onProviderEnabled(String provider) {}
public void onStatusChanged(String provider, int status, Bundle extras) {}
};
class GetLastLocation extends TimerTask {
#Override
public void run() {
lm.removeUpdates(locationListenerGps);
lm.removeUpdates(locationListenerNetwork);
Location net_loc=null, gps_loc=null;
if(gps_enabled)
gps_loc=lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if(network_enabled)
net_loc=lm.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
//if there are both values use the latest one
if(gps_loc!=null && net_loc!=null){
if(gps_loc.getTime()>net_loc.getTime())
locationResult.gotLocation(getDecimalAccurated(gps_loc));
else
locationResult.gotLocation(getDecimalAccurated(net_loc));
return;
}
if(gps_loc!=null){
locationResult.gotLocation(getDecimalAccurated(gps_loc));
return;
}
if(net_loc!=null){
locationResult.gotLocation(getDecimalAccurated(net_loc));
return;
}
locationResult.gotLocation(null);
}
}
/**
* called when the GPS returns a location.
* can be called multiple times as the location is updated
*/
public interface LocationResult {
public void gotLocation(Location location);
}
/**
* sets location result accuracy
* #param n number of places after the point. negative value or 0 means not set.
*/
public void setDecimalAccuracy(int n)
{
this.decimalAccuracy = n;
}
private Location getDecimalAccurated(Location location) {
if (decimalAccuracy > 0){
double accuracy = Math.pow(10, this.decimalAccuracy);
int ix;
ix = (int)(location.getLatitude() * accuracy);
location.setLatitude(((double)ix)/accuracy);
ix = (int)(location.getLongitude() * accuracy);
location.setLongitude(((double)ix)/accuracy);
}
return location;
}
}
I'll talk in general since I had the same issue:
How to manage the LocationListener and lit this listener access the activity ..
This was my try :
The Listener :
public class MyLocationListener implements LocationListener{
ProgressDialog dialog;
LocationManager locManager;
Context context;
public MyLocationListener (Context context,ProgressDialog dialog){
this.context = context;
this.dialog = dialog;
}
public void startSearch() {
locManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
// If the network provider works run it , else try GPS provider
// TODO : what happens if GPS and Network providers are not suuported ??
if(!locManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER) )
locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0,
0, this);
else
locManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0,
0, this);
dialog = new ProgressDialog(context);
dialog.setTitle("");
dialog.setMessage(context.getString(R.string.pleaseWait));
dialog.setButton(context.getString(R.string.cancel), new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int which)
{
locManager.removeUpdates(MyLocationListener .this);
dialog.dismiss();
return;
}
});
dialog.show();
}
// Location Listener implementation
// read Android doc for more info
// this methods is triggered when new location ( latitiude and longitude ) is found by the system
private void updateWithNewLocation(Location location) {
if (location != null) {
double lat = location.getLatitude();
double lng = location.getLongitude();
//THIS IS MY ACTIVITY
MainActivity mainActivity = (MainActivity) context;
mainActivity.init();
} else {
//this.setSummary( "No location found" );
}
// remove the listener , we don't need it anymore
locManager.removeUpdates(this);
dialog.hide();
}
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) {
}
}
init the listener in the MainActivity like this :
ProgressDialog dialog;
.
.
.
new MyLocationListener (this, dialog).startSearch();
I don't know if that help ? but that was my solution ...
I've implemented code that should return present location.
First the code:
public static double[] getLocation(Context context) {
double[] result;
lm = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
MyLocationListener ll = new MyLocationListener();
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, ll);
while(!hasLocation) { }
result = ll.getResult();
return result;
}
private static class MyLocationListener implements LocationListener {
double[] result = new double[2];
public double[] getResult() {
return result;
}
#Override
public void onLocationChanged(Location location) {
if(location.getAccuracy() != 0.0 && location.getAccuracy() < 100) {
result[0] = location.getLatitude();
result[1] = location.getLongitude();
hasLocation = true;
lm.removeUpdates(this);
}
}
#Override
public void onProviderDisabled(String provider) {}
#Override
public void onProviderEnabled(String provider) {}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {}
}
The problem is that all stopps on 'while' statement. WHen I've tried to debug this setting breakpoint on the first line in onLocationChanged() nothing happens, but Logcat was showing some logs like:
loc_eng_report_position: vertical_accuracy = 64.000000
DEBUG/libloc(1292): date:2011-08-11, time:10:51:03.372, raw_sec=1313052663, raw_sec2=1313052663,raw_msec=1313052663372
Any ideas?
The while(!hasLocation) {} is blocking your application from doing anything. You'll either need to deal with the location in the callback onLocationChanged, or you'll need to start the location manager a lot earlier and hope that you have a result by the time you need it. You can't busy-wait for the answer.