Android onLocationChanged stopped being called - android

I have a fragment:
public class myMap extends Fragment implements LocationListener
{
// do all the usual stuff
#Override
public void onResume()
{
super.onResume();
if(mIsGPSEnabled)
{
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 60000, 10, this);
}
// and of course a bit more of code I am skipping
}
#Override
public void onLocationChanged(Location location) {
Toast.makeText(getActivity(), "location changed " + location.getLatitude() + " " + location.getLongitude(), Toast.LENGTH_LONG).show();
}
I noticed the following behavior:
onResume gets always the last known location that works fine.
Upon start of the app on my notification bar I see this little icon that GPS is on
after a while I get the onLocationChanged called the first time (so far all is fine)
now the little GPS icon vanishes from the notification bar and onLocationChanged is never called again. The app is at all times in the forground
I never unregister (for now) my location change listener
I bring my app in the backround and start for example osmand (a navigation software) while this software is running I see my toast in onLocationChanged on every update, working as it should.
Anyone an idea?

Check if
mLocationManager != null
if is null you can requesteLocationUpdates otherwise avoids to call requests

Use Log and watch it using free logcat app or this to be sure that your location not updated:
Toast.makeText(getApplicationContext(), "location changed " + location.getLatitude() + " " + location.getLongitude(), Toast.LENGTH_LONG).show();
because i don't think that your default home screen is an activity! that's why toasts appear in osmand and your app and don't in home screen.
so i think you are in a famous android location api issue that i spent more than 30 days before knowing that there lot of peoples have the same problem!, than you can feel better if you take a look here https://code.google.com/p/android/issues/detail?id=57707
the problem have no limit no algorithm no special cases : >> get first location, stop for a while, work perfectly for two days and switch work n stop for a week... !!
I think you must buy new test phone!

Related

Android Periodic GPS location updates with AlarmManager inside a Service

I read a lot of questions on here but couldn't figure out what the problem is.
I'm writing a field service application for Android. In one of the Activities (MyActivity.java) I have two buttons: Start and Stop.
When the field worker presses start I need to get his current location with GPS and send it to server in timely intervals (say it be 5 minutes default, here I set it to 20 secs. for testing). The customer wants this to see how long the workers spend time in traffic, the traffic in my city (Istanbul) is a mess.
I have an AlarmManager in my activity, when the start button is pressed the alarm is set by AlarmManager.setRepeating() to start the service (ServiceClass.java).
Intent intent = new Intent (MyActivity.this, ServiceClass.class);
mPendingIntent = PendingIntent.getService(MyActivity.this, 0, intent,
PendingIntent.FLAG_CANCEL_CURRENT);
mAlarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
mAlarmManager.setRepeating(AlarmManager.RTC, calendar.getTimeInMillis(), 20*1000,
mPendingIntent);
I cancel the Alarm with the Stop button.
It works perfectly till here, the Service starts. Its onCreate(), onStart() and onDestroy() methods are executed. But I can't get the location. I'm not working on a real device so I'm using DDMS to send locations. But the application skips that step and prints Longitude and Latitude of my location as Lon:0 Lat:0.
Here's the code inside the service:
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
Log.d("Testing", "Service got started, calling location updates:");
mLocationManager.requestSingleUpdate(mCriteria, mLocationListener,
getMainLooper());
Log.i("TESTING LOCATION UPDATE: LOCATION:", "\nLat:" + mLatitude +
" Lon:" + mLongitude);
stopSelf(startId);
Log.d("Testing", "Service Stopped!");
And finally, here's my LocationListener:
mLocationListener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
if(location != null){
mLatitude = location.getLatitude();
mLongitude = location.getLongitude();
Log.i("onLocationChanged(Location location)", "Lat:"+mLatitude + "
Lon:" + mLongitude);
}
Also something caught my eye, when I run the code:
mLocationProvider = mLocationManager.getBestProvider(mCriteria, true);
Log.i("BEST PROVIDER IS:", mLocationProvider);
It says BEST PROVIDER IS: gps. But this log inside onProviderEnabled() is never shown in logcat.
#Override
public void onProviderEnabled(String s) {
Log.v("onProviderEnabled", "ENABLED");
}
Two things to add, if I use:
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0,
mLocationListener);
it doesn't work either.
This however works and I can get the LastKnownLocation:
Location lastKnown = mLocationManager.getLastKnownLocation(
LocationManager.GPS_PROVIDER);
First of all, is this a good approach for doing this? If it is please check to see what I am missing. If it is not, can you please tell me how can I implement this any better?
Thank you. :)
First, you cannot register for location updates, then shut down the service. At best, you will leak threads. At worst, Android will terminate your process (thinking there is nothing running in it) and you will not get the update. Also, GPS takes a while to warm up, so you might not get a fix within 20 seconds, particularly in an urban setting. Also, you have to make sure the device stays awake while you are trying to collect a fix.
As a result, getting periodic location fixes in the background is a rather complicated problem.
I wrote a now-discontinued LocationPoller to try to address this, and another developer has forked and extended it. You could try the fork or simply use it as a source of ideas.
try this:
AlarmManager.setRepeating(AlarmManager.RTC_WAKEUP,,,);
I am doing for get one's current location with GPS, but my project works every 10 seconds. I have no idea now. And my code :
AlarmManager.setRepeating(AlarmManager.RTC_WAKEUP,System.currentTimeMillis(),6000000,pi);

Send GPS coordinates to Android emulator using DDMS, telnet or any other means

DDMS is not able to send location to the emulator. I have tried sending just the location from DDMS but still the emulator is not able to receive location. Nothing appears on the DDMS log when I click the Send button.
I tried sending geo fix from telnet which returns OK but doesn't actually update the location, or if it does I can't read it via my application.
The application works properly in the device, is able to capture test location details but not able to capture location data sent to the emulator either via DDMS or telnet.
I am testing on Android 2.2 emulator. Can anyone let me know what is wrong?
My app (below) is written in C# using Mono for Android and may need fixing (I'm a newbie to all things Android so I could have missed something). OnLocationChanged(Location location) just doesn't seem to fire at all, as if the listener isn't properly defined. Any help appreciated.
Note: The first time I run this Activity the LocationManager.GetLastKnownLocation is null but the test provider stuff isn't accessed. When I run it again GetLastKnowLocation is still null but the test provider stuff is accessed and set. Weird.
[Activity(Label = "Location Demo")]
public class LocationActivity : Activity, ILocationListener
{
private TextView _locationText;
private LocationManager _locationManager;
private StringBuilder _builder;
private Geocoder _geocoder;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.LocationActivity);
_geocoder = new Geocoder(this);
_locationText = FindViewById<TextView>(Resource.Id.TextView1);
_locationManager = (LocationManager)GetSystemService(LocationService);
if (_locationManager.GetLastKnownLocation("gps") == null)
{
_locationManager.AddTestProvider("gps", false, false, false, false, false, false, false, 0, 5);
_locationManager.SetTestProviderEnabled("gps", true);
Location loc = new Location("gps");
loc.Latitude = 50;
loc.Longitude = 50;
_locationManager.SetTestProviderLocation("gps", loc);
}
Location lastKnownLocation = _locationManager.GetLastKnownLocation("gps");
if (lastKnownLocation != null)
{
_locationText.Text += string.Format("Last known location, lat: {0}, long: {1}", lastKnownLocation.Latitude, lastKnownLocation.Longitude);
}
else
{
_locationText.Text += string.Format("Last location unknown");
}
_locationManager.RequestLocationUpdates("gps", 5000, 2, this);
}
public void OnLocationChanged(Location location)
{
_locationText.Text += string.Format("Location updated, lat: {0}, long: {1}", location.Latitude, location.Longitude);
}
public void OnProviderDisabled(string provider){}
public void OnProviderEnabled(string provider){}
public void OnStatusChanged(string provider, Android.Locations.Availability availability, Bundle extras){}
}
Kudos to https://stackoverflow.com/users/170333/greg-shackles for getting me this far.
I think the problem may be with how you're calling RequestLocationUpdates(). That third parameter is the minimum distance the device needs to move before you get updates, so you're telling the system to only send updates after the device has moved 2 meters. If it works on a real device, it's probably because you moved more than 6 feet. :)
Try starting with RequestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this). That will start a stream of updates on a real device, but only one when you press 'Send' in DDMS. Once that works, I would work back from there on how often you get updates.
Also, GetLastKnownLocation() is always null when you start the emulator. It's better for devices since it can send you the network location as a starting estimate, or the GPS location if another program was using it recently.
EDIT
It could also be a permissions issue. Normally you need to alter AndroidManifest.xml to get GPS access. The line is
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
See the docs here.
Call
_locationManager.RequestLocationUpdates("gps", 5000, 2, this);
function before doing any location operations, like below:
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.LocationActivity);
_geocoder = new Geocoder(this);
_locationText = FindViewById<TextView>(Resource.Id.TextView1);
_locationManager = (LocationManager)GetSystemService(LocationService);
_locationManager.RequestLocationUpdates("gps", 5000, 2, this); //this will cause updated location to be retrieved from telnet
Note: Its normal that program works after the first run, so that after the first run your application could get the initial updated location from telnet and that will be enough to not throws an exception
Finally resolved this. When the emulator is launched by VS2010 (i.e. F5, start debugging) it does not behave as expected. Launch the emulator externally using AVD.exe, start a virtual device and deploy the app. to it (using F5, start debugging) and everything works fine.
Why starting the emulator from within or outside VS2010 should make any difference is a mystery I am able to live with. Thanks to everyone for their helpful suggestions.
Does your emulated android image have GPS hardware? The description in the emulator should have "hw.gps=yes".
I had the same symptoms before recreating a new image with the right (emulated) hardware. I found a simple web page that displays the current location was handy when debugging the emulation environment.

Android GPS Always Returns Same Location

I'm trying to get the user's location within Android, the code below works however it always returns the same location no matter what I do. I've tested out in the middle of an empty parking lot to ensure the GPS is locked on, and it is. Google maps also shows my location correctly. Is there something wrong with the code below?
public class LocationTestActivity extends Activity implements LocationListener
{
private Location myLoc;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
output = (TextView) findViewById(R.id.output);
myLong = (TextView) findViewById(R.id.longi);
myLat = (TextView) findViewById(R.id.lat);
myRefreshed = (TextView) findViewById(R.id.counter);
mgr = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
mgr.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
}
#Override
public void onLocationChanged(Location location)
{
timesChanged++;
myRefreshed.setText("Refreshed: " + timesChanged);
myLong.setText("Longitude: " + location.getLongitude());
myLat.setText("Latitude: " + location.getLatitude());
}
}
I'd like to add that I can pass in a location using the emulator with no problem. I also removed the other needed methods required by LocationListener for clarity. Thanks for the help!
First make sure that onLocationChanged() is actually getting called. If your GPS has locked before then there is a chance that onLocationChanged won't get fired at all because the phone thinks that you haven't really moved. Therefore it is not a good practice to rely only on requestLocationUpdates() to get your current location.
In general here is what you should do to get your position:
You should use getLastKnownLocation() first to try locating your current location based on last known position.
Check if the location retrieved from step #1 is within reasonable time (not too old) by calling getTime() in the location and comparing with the current time
If this last known position is considered old (I normally use 5-10 minutes depending on the context of the app) then you start requestLocationUpdates() with specific distance (the app should make assumption that the user has moved within the specified limit of last known position)
Implement the onLocationChanged() as desired
Another note, I notice you are only using GPS, there is a lot of situation where GPS cannot lock and therefore never call onLocationChange(), your code should take account of that and checking Network based triangulation in the case onLocationChange() is not called within specified time
Try getting last location fix
Location loc = mgr.getLastKnownLocation(LocationManager.GPS_PROVIDER);
and give some time/distance between each location service request
mgr.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 0, this);
And I hope you have enough patience to wait until your device retrieves the location and onLocationChanged() is triggered ;) Joking.
please check your manifest file whether have you added those permission or not.
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"></uses-permission>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission>
One more thing.Where did you call "removeUpdates()"?

Opening a sub-activity several times causes an InstanceCountViolation despite being destroyed

I'm working on a project that has a lower level activity called RecordView to display record details such as an image, the date and time it was taken, and the latitude/longitude information. Rather than trying to manipulate the camera to geotag and access exif data I'm trying to implement a location listener to get the location where the image is first taken (on the button press). This approach works - I get my location to display and update the record in the database correctly (returning to the view later displays the location from the beginning). However, if I back out of the current RecordView and then enter two more (any combination) the program will crash with the error InstanceCountViolation (full error reprinted below). When I override the lifetime methods of RecordView to display when each is called we find that it is destroyed before being called again. That is to say, it doesn't appear that more than a single RecordView exists at any given time.
So my question boils down to this: where is that error coming from and how can I fix it?
Is something lying about being destroyed? Is the LocationListener sitting around somewhere and causing problems? Is it something unrelated that might be providing a bogus error?
Also, should I do the horrible hard coded fix and just up the limit of RecordView instances allowed? Or continue hunting for another approach (as an example I'm attempting to request a single update using a PendingIntent.getBroadcast(...) call)?
For reference this error has appeared on the emulator for 3.1 and on an actual tablet (a Xoom, 3.1). Commenting out the listener update code seems to avoid the crash (EDIT 2: I appear to have been wrong about that). The code as it relates to the listener is below (it can be found inside a public method updateLocation inside the RecordView class).
// Listener for the update request
LocationListener locListener = new LocationListener() {
// Store the currentRecord so the listener can update it after return
Record currentRecord = record;
GeoDatabase database = data;
#Override
public void onLocationChanged(Location location) {
if (location != null) {
myLocation = location;
Log.d(TAG, "Location pulled as " + myLocation);
String lat = Location.convert(myLocation.getLatitude(),
Location.FORMAT_SECONDS);
String lon = Location.convert(myLocation.getLongitude(),
Location.FORMAT_SECONDS);
// Update the record values
currentRecord.setRecordLatitude(lat);
currentRecord.setRecordLongitude(lon);
database.updateRecord(currentRecord);
Log.d(TAG, "Record values now listed as "+ record.getValues());
// Update the text boxes
latitude.setText(lat);
longitude.setText(lon);
Toast.makeText(getBaseContext(),"GPS location updated",
Toast.LENGTH_LONG).show();
} else {
Log.w(TAG, "Passed location is null!");
Toast.makeText(getBaseContext(),
"GPS error - unusable location",
Toast.LENGTH_LONG).show();
}
}
#Override
public void onProviderDisabled(String provider) {
Toast.makeText(getBaseContext(),
"GPS disabled", Toast.LENGTH_SHORT).show();
}
#Override
public void onProviderEnabled(String provider) {
Toast.makeText(getBaseContext(),
"GPS enabled", Toast.LENGTH_SHORT).show();
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
};
lm.requestSingleUpdate(LocationManager.GPS_PROVIDER, locListener, null);
The full error:
android.os.StrictMode$InstanceCountViolation:class [program path].RecordView; instances=3; limit=2
at android.os.StrictMode.setClassInstanceLimit(StrictMode.java:1)
EDIT:
Two things I've determined.
The first is that when Logcat shows the destruction of the RecordView activity the LocationListener is correctly disconnected (destroyed? It's null anyway). However the listener seems to update from beyond the grave as it were - that is, I sometimes see my Toast message about a GPS update on the higher level activities screen and the GPS information appears to have been updated.
The second is that it isn't exactly crashing per say - it appears to be Force Closing the RecordView rather than the entire app. The main chunk of the app seems to just basically be minimized.
EDIT 2:
We recently added a preference screen using a new activity and this has the same InstanceCountViolation error as the RecordView. We've verified that nothing has to be changed in the activity for the error to occur: it only needs to be opened a few times. An example of how we open our sub-activities from the main activities is below:
Intent intent = new Intent(this.getActivity()
.getApplicationContext(), RecordView.class);
Bundle extras = new Bundle();
extras.putString("tableName", "table1");
extras.putInt("id", mId);
extras.putBoolean("newRecord", false);
extras.putLong("folder_id", mFolderId);
extras.putString("type", recordList.get(mId).getTableName());
intent.putExtras(extras);
startActivity(intent);
So now I'm wondering if there's a problem in how the Intent is handling activity creation and deletion.
It seems like it shouldn't be needed, but have you tried calling
lm.removeUpdates(locListener);
to un-register the listener?
I know that this is old post. Just for guys who is looking for solution and explanation to this problem.
In case there is InstanceCountViolation exception it means that there can be real with Activity leak or problem which is related to how detectActivityLeaks check is implemented in Android SDK.
To identify if this is a problem I can recommend the following post: Detecting leaked Activities in Android. If you will see that there are objects holding a reference to this activity which don't related to Android Framework then you have a problem which should be fixed by you.
In case there are no objects holding a reference to this activity which don't related to Android Framework than it means that you encountered with the problem related to how detectActivityLeaks check is implemented. In this case to fix the problem with failed activity without turning off detectActivityLeaks you can simply run System.gc() before starting activity in debug configuration like in the following example:
if (BuildConfig.DEBUG)
{
System.gc();
}
Intent intent = new Intent(context, SomeActivity.class);
this.startActivity(intent);
More information are available in this answer.

LocationListener works on emulator, not on phone

I'm having trouble getting a LocationListener to call the onLocationChanged() callback on my phone. When I run my code in the emulator, it works fine, the callback is called each time I do a geo fix.
When I run the application on my phone, nothing at all happens. The callback is never called. I have location enabled by both GPS and by Wireless in my settings. The application has all of the uses-permissions for location permissions.
Also, when I call getLastKnownLocation() on a LocationManager object, my application crashes. (Still, only on my stupid phone). Even if I try to catch an exception that's causing it to crash, it still just crashes, so I can't even get any information on what is causing it to crash. This is extremely frustrating.
LocationManager.getBestProvider() is returning GPS, and when I open google maps it finds my location in no time at all. What the heck is going on here? Is there some way I can figure out why it's crashing on my phone?
private void setupLocListener(){
Criteria c = new Criteria();
c.setAccuracy(Criteria.ACCURACY_FINE);
c.setAltitudeRequired(false);
c.setBearingRequired(false);
c.setSpeedRequired(false);
c.setCostAllowed(false);
lm.requestLocationUpdates(lm.getBestProvider(c,true), 0, 0, new LocationListener() {
#Override
public void onLocationChanged(Location arg0) {
map.setLocation(arg0);
}
public void onProviderDisabled(String arg0) {
}
public void onProviderEnabled(String arg0) {
}
public void onStatusChanged(String arg0, int arg1, Bundle arg2) { }
});
}
onLocationChanged() wont fire until you actually start receiving GPS coordinates.
By that I mean the chip has to warm up for about a minute or so from my experience before you start receiving data from it.
I usually start some other application and wait for it to prove that the GPS chip has warmed up before I go testing any of my GPS apps.
I know that you mentioned that it works properly in Google Maps but have you tried clearing your memory and restarting your application straight away afterwards?
Also getLastKnownLocation() is always null until you start receiving coords.
The Location framework pushes coordinates to your callback, when they become available. Depending on weather, etc. you may not get a "fix" initially. You should see the "GPS" indicator on the status bar when your listener is successfully registered.
getLastKnownPosition() works just fine (it may return null); and Google Maps uses that, while it is waiting for an initial fix from the location provider.
You may also want to see what other providers are available, e.g. cell-tower data, and attempt to obtain data from those (i.e. LKP), either instead of, or until, your "preferred" provider starts pushing data.
Also, don't assume any particular service exists, e.g. LocationManager (Context.getSystemService() can return null), or any suitable provider exists, (getBestProvider() can return null). Your code will fail as-is on the right device with the right settings. If the documentation says null you must check for it, or users will be uninstalling it because it FC's all over the place.

Categories

Resources