No GPS Update retrieved? Problem in Code? - java

I've got a serious problem with my GPS on my Nexus One: I wrote a kind of hello world with GPS, but the Toast that should be displayed isn't :(
I don't know what I'm doing wrong...maybe you could help me getting this work. Here's my code:
package gps.test;
import android.app.Activity;
import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.widget.Toast;
public class GPS extends Activity {
private LocationManager lm;
private LocationListener locationListener;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// ---use the LocationManager class to obtain GPS locations---
lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
locationListener = new MyLocationListener();
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 100, 1,
locationListener);
}
private class MyLocationListener implements LocationListener {
#Override
public void onLocationChanged(Location loc) {
if (loc != null) {
Toast.makeText(
getBaseContext(),
"Location changed : Lat: " + loc.getLatitude()
+ " Lng: " + loc.getLongitude(),
Toast.LENGTH_SHORT).show();
}
}
#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
}
}
}
Theoretically there should be a new toast every 100 milliseconds, shouldn't it? Or at least, when I change my position by one meter!?
I've no idea why it doesn't. I must admit I'm new to the topic, maybe I've missed something?
It would be great if you could give me a hint :)
nice greetings,
poeschlorn

The code looks correct to me. Do note that:
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 100, 1,
locationListener);
This means that you will have to move the phone by more than a meter to get location updates and the check is done approximately every 0.1 second.
I would suggest you add logging statements in these functions:
#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
}
This is so that you know what flow your code is taking. GPS could be disabled for e.g. and you'll not know within your app.
And finally, do remember to remove listening to locations in onPause (or when required). Having an app in the background that is continuously getting location updates when not required is a huge drain to the battery.

Here are few steps I would follow:
Check if you have enabled GPS location services.
Check if you have GPS signal available (you can get some GPS monitor from market)
You can change the code to use best possible provider: D:/java-workspace/android-sdk-windows/docs/reference/android/location/LocationManager.html#getBestProvider(android.location.Criteria, boolean)
Try it in the emulator (you have to send location update from DDMS (Emulator Control)

Related

Toast is shown even after finish();

I am new to android and I have found similar question here but none of it could solve my problem. The code below is basically to get two double values(latitude and longitude) from Firebase and plot them on the map. There is a toast that is shown when the user has logged out i.e when the double values have been removed from the database. The problem here is that this toast is shown even after I go back to other activities. How can I stop this. I just want to end the Activity where I have put the finishes at.
Any help would be appreciated. Thanks in advance!
Edit: If I open many instances of this activity (View locations of many people) I would get the toast of every instance as each person logs out. I am concerned this would waste a lot of resources.
Could it be because of the getMapAsync? Have read that Async tasks run on a different thread and does not stop even after finish().
java code:
package com.example.android.managers;
import android.app.Activity;
import android.os.Bundle;
import android.widget.Toast;
import com.google.android.gms.maps.CameraUpdate;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.MapView;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.firebase.database.ChildEventListener;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
public class LocateS extends Activity implements OnMapReadyCallback {
MapView mapView;
GoogleMap googleMap;
String username;
int firstTime=0;
LocationDetails loc;
ChildEventListener listen = null;
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference myRef = database.getReference("Staff");
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_locate);
Bundle extras = getIntent().getExtras();
username= extras.getString("user");
mapView = (MapView) findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
mapView.getMapAsync(this);
listen = myRef.child(username).addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String prevChildKey) {
loc = dataSnapshot.getValue(LocationDetails.class);
if(loc!=null)
setMap();
else
Toast.makeText(getApplicationContext(),"Location not received yet",Toast.LENGTH_LONG).show();
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String prevChildKey) {
loc = dataSnapshot.getValue(LocationDetails.class);
if(loc!=null)
setMap();
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
Toast.makeText(getApplicationContext(), username+" logged out", Toast.LENGTH_SHORT).show();
myRef.removeEventListener(listen);
// android.os.Process.killProcess(android.os.Process.myPid());
finish();
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String prevChildKey) {}
#Override
public void onCancelled(DatabaseError databaseError) {}
});
}
public void setMap(){
if(googleMap!=null){
googleMap.clear();
LatLng coordinate = new LatLng(loc.getLatitude(),loc.getLongitude());
googleMap.addMarker(new MarkerOptions().position(coordinate));
if(firstTime == 0) {
CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(coordinate, 17.0f);
googleMap.moveCamera(cameraUpdate);
firstTime++;
}
}
}
#Override
public void onMapReady(GoogleMap map) {
googleMap=map;
map.getUiSettings().setZoomControlsEnabled(true);
}
#Override
public void onResume() {
mapView.onResume();
super.onResume();
}
#Override
public void onPause() {
super.onPause();
}
#Override
public void onStop(){
finish();
super.onStop();
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Override
public void onLowMemory() {
mapView.onLowMemory();
super.onLowMemory();
}
#Override
public void onBackPressed() {
myRef.removeEventListener(listen);
finish();
// android.os.Process.killProcess(android.os.Process.myPid());
super.onBackPressed();
}
}
xml code:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activity_main2"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.android.managers.Locate">
<com.google.android.gms.maps.MapView
android:id="#+id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
/>
</RelativeLayout>
add finish after in your onDestroy() method
finish();
Your issue is the listener was not removed when you moved to another activity except when you back pressed.
You should put the
myRef.removeEventListener(listen);
Into the onPause/onStop method.
As your toast is still alive and any change to the child, it will trigger the toast.
You can use ActivityName.this.finish();
cancel your toast before calling finish
final Toast testing = Toast.makeText(context, "start.", Toast.LENGTH_SHORT);
testing.show();
and use this when you r calling finish.
testing.cancel();
finish();
toast will display until is will not complete execution no matter activity is closed or not. toast will tack 3 second(sort duration) . make sure you r calling after 3 second or cancel toast and call finish any time
The toast is shown for the duration corresponding to Toast.LENGTH_SHORT which is 3.5 sec according to this, no matter the calling activity is active or not. I think what you want is to show the toast that user had logged out. Wait till it is shown on screen. As soon as it is finished showing, destroy activity. This may be achieved by calling show toast, waiting for 3.5 sec and then destroying the activity.
So, as described here,
Toast.makeText(getApplicationContext(), username+" logged out", Toast.LENGTH_SHORT).show();
Thread thread = new Thread(){
#Override
public void run() {
try {
Thread.sleep(3500);
LocateS.this.finish();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
thread.start();
might work.
Alternatively, if you want to wait for duration other than 3.5 sec or that corresponding to Toast.LENGTH_LONG, follow this.
Edit:
Sorry I misinterpreted your problem!
I think the problem might be that we cannot detach a listener from its own method. I think putting myRef.removeEventListener(listen); in onDestroy() instead might be helpful.

Android - getting current location through Google Map

I am developing an app related to Google map. I have done following steps successfully.
Created API key to access Google Map
Added Google Play Services Library in my app
Added required permissions
Added map in my activity with SupportMapFragment
Added a separate class MyMap.java to manipulate the map
Passed tow parameters to this class - Context of main activity and object of GoogleMap
Turned Wi-Fi and GPS on and ran the app
After this I am getting map with nice look and controls.
MyMap.java
public class MyMap implements ConnectionCallbacks, OnConnectionFailedListener {
private Context context;
private GoogleMap map;
private GoogleApiClient client = null;
public MyMap(Context context, GoogleMap map) {
this.context = context;
this.map = map;
client = new GoogleApiClient.Builder(context)
.addApi(LocationServices.API).addConnectionCallbacks(this)
.addOnConnectionFailedListener(this).build();
}
#Override
public void onConnectionFailed(ConnectionResult arg0) {
// TODO Auto-generated method stub
}
#Override
public void onConnected(Bundle arg0) {
Toast.makeText(context, "Connected", 1).show();
Location mLastLocation = LocationServices.FusedLocationApi
.getLastLocation(client);
if (mLastLocation != null) {
Toast.makeText(
context,
String.valueOf(mLastLocation.getLatitude()) + ","
+ String.valueOf(mLastLocation.getLongitude()), 1)
.show();
}
}
#Override
public void onConnectionSuspended(int arg0) {
// TODO Auto-generated method stub
}
}
Problem
In the above class I want to toast the current location. But it is not toasting anything. At least I need to see a toast saying "connected" on onConnected
event. Is there something wrong in my implementation?
Thanks in advance.
You seemingly never connect your client so it would be a real suprise if onConnected was called :)
You create your client with
client = new GoogleApiClient.Builder(context)
.addApi(LocationServices.API).addConnectionCallbacks(this)
.addOnConnectionFailedListener(this).build();
but for the client to do something you have to add:
client.connect();
getLastLocation() is going to give location only once. To get periodic location updates, you need to override onLocationChanged() method. You can get this Link
Best way that I found is simple implement you activity like so:
public class MapActivity extends Activity implements GoogleMap.OnMyLocationChangeListener
and override method
#Override
public void onMyLocationChange(Location location) {
mMap.addMarker(new MarkerOptions().position(location).icon(
BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN)));
}
And don't forget about mMap.setMyLocationEnabled(true); and mMap.setOnMyLocationChangeListener(this); in map init method
That's all!
Also, you can check is map available like here:
public boolean checkMapsAvailable() {
int isAvailable = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if (isAvailable == ConnectionResult.SUCCESS) {
return true;
} else if (GooglePlayServicesUtil.isUserRecoverableError(isAvailable)) {
Dialog dialog = GooglePlayServicesUtil.getErrorDialog(isAvailable, this, 9001);
dialog.show();
} else {
Constants.showToast(Constants.ALERT_GOOGLEPLAY_CONNECTION);
}
return false;
}
Hope this helps.

I can't receive locations

I'm building a location based app, everything was fine until one day I stopped receiving locations.. I have no idea why. I will attach the important code:
private LocationManager mLocationManager;
public void onCreate()
{
super.onCreate();
...
// Get a reference to the LocationManager object.
mLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
...
setup();
}
private void setup()
{
mLocationManager.removeUpdates(listener);
// Request updates from just the providers.
if (mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER))
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, ONE_MINUTE, 0, listener);
if (mLocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER))
mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, ONE_MINUTE, 0, listener);
}
#Override
public void onLocationChanged(Location location)
{
handleLocation(location);
}
I put a break point on the onLocationChanged and nothing happened.. I tested it on other lines of my app to make sure that the debugging configuration is working and it is working. Looks like I just don't receive any locations.
Maybe I'm not seeing something.
I've good code to receive location :
public class Locato extends Activity implements LocationListener {
LocationManager locman;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.idlayout);
locman = (LocatonManager) getSystemService(Context.LOCATION_SERVICE);
}
public void onStatusChanged(String pr, int s, Bundle a) {
}
#Override public void onProviderDisabled(String provider)
{
Log.d("MyApp", "Provider disabled : " + provider);
}
#Override public void onProviderEnabled(String provider) {
Log.d("MyApp", "Provider enabled : " + provider);
}
#Override public void onLocationChanged(Location location) {
// do something
}
}
Try to use this.
Don't forget add ACCESS_FINE_LOCATION permission in manifest.
The same code now generates locations, it was kind of a joke when I said that it could be since it's cloudy but now when the clouds are gone it's working. I can't think about anything else and just to clarify it was very cloudy maybe even a small storm.

Is the function onLocationChanged called every movement of Android device?

I use the function onLocationChanged to identify the user's location, I want it to happen every movement of Android phone
exactly when the function is called?
My code looks like this:
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
locationListener = new GPSLocationListener();
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
GPSLocationListener:
public class GPSLocationListener extends DroidGap implements LocationListener
{
#Override
public void onLocationChanged(Location location) {
AlertDialog.Builder alt_bld = new AlertDialog.Builder(this);
alt_bld.setMessage("onLocationChanged");
AlertDialog alert = alt_bld.create();
alert.show();
}
#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
}
}
The alert onLocationChanged never appears.
According to this link:
http://developer.android.com/reference/android/location/LocationListener.html#onLocationChanged(android.location.Location) the method is called every time the location has changed.
From my observation there is some logic behind it and it does not change evvery time (e.g. when new location is nearby the old and has worse accuracy).
EDIT:
"every little movement" can be ACCURACY_HIGH at the most...I think you cant get more precise than this. Reference: http://developer.android.com/reference/android/location/Criteria.html#ACCURACY_HIGH
EDIT 2:
To use ACCURACY_HIGH create new Criteria object and use the setters (setHorizontalAccuracy, ...) and then use it like this
locationManager.requestLocationUpdates(locationManager.getBestProvider(locationCriteria, true), 1L, 2F, this);
It depends of arguments sent to:
requestLocationUpdates (String provider, long minTime, float minDistance, LocationListener listener)
minTime - minimum time interval between location updates, in milliseconds
minDistance - minimum distance between location updates,
in meters
Location updates are received by LocationListener callbacks
See here for more info.
From the documentation of
requestLocationUpdates(String provider, long minTime, float
minDistance, LocationListener listener)
concering the minTime parameter:
"the minimum time interval for notifications, in milliseconds. This
field is only used as a hint to conserve power, and actual time
between location updates may be greater or lesser than this value."
Also
public abstract void onLocationChanged (Location location)
Added in API level 1
Called when the location has changed.
There are no restrictions on the use of the supplied Location object.
Parameters
location The new location, as a Location object.
If this is a problem for you, you could ignore calls to the callback method if a certain amount of time hasn't passed.
Hope it will help you
When a location is changed .When a new location details is captured by gps receiver then the method
onLocationChanged(Location location)
is called automatically.

Custom Android LocationListener Questions

Currently i have the coding as below for use on my activity on android. Right now i use this as an object and start scanning location and get back it's location using returnBestLocation method 3seconds later using a handler.
However i would like to ask is there any possibility that MyLocationListener object will automatically return call the activity on location change instead of calling the object to retrtive location 3s later?
public class MyLocationListener implements LocationListener {
LocationManager locationManager;
Date currentBestLocationDate;
Intent notificationIntent;
Context mContext;
Location currentBestLocation = null, lastKnownLocation=null;
public MyLocationListener(Context mContext)
{this.mContext = mContext;
}
public void startLocationScan()
{
Log.d(Config.log_id, "Custom Location Listener started");
if (locationManager == null) {
locationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
Location locationNETWORK = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if (locationNETWORK != null) {
lastKnownLocation=locationNETWORK;
}
Location locationGPS = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (locationGPS != null) {
lastKnownLocation=locationGPS;
}
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, MyLocationListener.this);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0,MyLocationListener.this);
}
}
public void stopLocationScan()
{
if(locationManager!=null)
{
locationManager.removeUpdates(MyLocationListener.this);
Log.d(Config.log_id, "Custom Location Listener Stopped");
}
}
public Location returnBestLocation()
{
return currentBestLocation;
}
#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 onLocationChanged(Location location) {
// TODO Auto-generated method stub
if (currentBestLocation == null) {
currentBestLocation = location;
}
long timeDelta = location.getTime() - currentBestLocation.getTime();
Log.d(Config.log_id, "locationpostingservice's changed with accuracy " + location.getAccuracy() + " s different " + (float) timeDelta / 1000);
if (timeDelta >= 120000) {
currentBestLocation = location;
Log.d(Config.log_id,"posting service Location changed due to over 2min "+ location.getAccuracy() + " s different "+ (float) timeDelta / 1000);
}
if (currentBestLocation.getAccuracy() >= location.getAccuracy()) {
currentBestLocation = location;
}
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
// TODO Auto-generated method stub
}
You could pass the Activity you want to be notified to MyLocationListener as a Listener. Create your own Listener interface, let the Activity implement it and add a method to MyLocationListener like addListener(). Every time you want to notify those activities iterate through the list of Listeners and call their locationChanged method (or whatever you called it in your interface definition). Just be sure to add error handling for null listener Activities, etc.
So basically you have your own custom Listeners listening to a LocationListener.
Another way would be to use Broadcast Receivers and broadcast the location change.
The proper way to do this is, as Fraggle says, to create your own listener interface, implement it in your class, then call your listener from your Activity.
But a quick-n-dirty alternative could be to just implement the LocationListener interface in your Activity, rather than spinning it off into a new class (MyLocationListener). Then just put all the code you want to run into onLocationChanged, and don't worry about communicating with other objects.

Categories

Resources