I have made an Android app that gets location by longitude and latitude on a button click.
At first I get the last known location reading, which is, for argument sake, inaccurate when I first load up the app/turn on gps.
What I would like to know is how to wait for it to be accurate, like in Google maps when you get the toast message 'waiting for location'.
If you see any way the code can be improved it would also be helpful.
Code for reference:
public class Clue extends Activity {
public static double latitude;
public static double longitude;
Criteria criteria;
LocationManager lm;
LocationListener ll;
Location location;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.questions);
criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
ll = new MyLocationListener();
lm.requestLocationUpdates(lm.getBestProvider(criteria, true), 0, 0, ll);
}
private boolean weAreThere() {
location = getLocation();
longitude = location.getLongitude();
latitude = location.getLatitude();
return inCorrectPlace(param);
}
private Location getLocation() {
lm.requestLocationUpdates(lm.getBestProvider(criteria, true), 0, 0, ll);
return lm.getLastKnownLocation(lm.getBestProvider(criteria, true));
}
}
public class MyLocationListener implements LocationListener
{
public void onLocationChanged(Location loc)
{
Clue.longitude = loc.getLongitude();
Clue.latitude = loc.getLatitude();
}
}
Thanks for reading, all replies will be appreciated.
Ben
If Location.hasAccuracy() returns true, you could call Location.getAccuracy() to retrieve the accuracy in meters, then filter the ones you don't consider enough accurate.
Notice you are not using LocationManager.GPS_PROVIDER so your fixes could also be obtained by other means (like WiFi).
Usually expect about a minute for the GPS chip to get "hot"* before getting GPS fixes (outdoors).
*By hot I mean having satellites coverage. Some chipsets get disconnected ("cold") after some time to preserve battery. The Time To First Fix (TTFF) is greater when the chip is cold.
Here is an excellent explanation,
http://android-developers.blogspot.com/2011/06/deep-dive-into-location.html
helps you understand exactly how to implement it.
Initially , u should get fix using getlastknownLocation ()
In addition, U can use a background service that updates location using NETWORK.PROVIDER... which shall not drain ur battery if used judiciously...and also works if GPS is turned off
If there is no network provider, then u should try and ask user to turn on GPS.
If u r using 2.2 try PASSIVE PROVIDER
Related
I know that I can get distance with google api and it is very good
But is it slow sometimes and not possible for my app
Is there any way to get distance between two location?
You should use Location.distanceBetween() or Location.distanceTo()
You could easily get the lastKnownLocation, add the co-ordinates to an ArrayList and then measure the distance between the points in that list as shown below:
Prerequisites:
Add permissions to manifest:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
Import Gradle Dependencies:
compile 'com.google.android.gms:play-services-location:10.2.1'
Add this class to your project:
Github: android-maps-utils : SphericalUtil.java
Implement LocationListener in your Activity:
public class myClass extends Activity implements LocationListener {
Define your global Variables:
private LocationManager locationManager;
private String provider;
private ArrayList<LatLng> coordList = new ArrayList<String>();
Get Initial Location (in onCreate() or onClick()):
locationManager = (LocationManager) getActivity().getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
// Define the criteria how to select the locatioin provider -> use
// default
Criteria criteria = new Criteria();
provider = locationManager.getBestProvider(criteria, false);
Location location = locationManager.getLastKnownLocation(provider);
if (coordList != null && !coordList.isEmpty()) {
coordList.get(0);
} else {
coordList.add(0, new LatLng(location.getLatitude(), location.getLongitude()));
}
if (location != null) {
onLocationChanged(location);
}
getLocationUpdates();
create a getLocationUpdates() method:
private void getLocationUpdates() {
if (locationManager != null) {
checkPermission();
locationManager.requestLocationUpdates(provider, ONE_SECOND, ONE_METER, this);
}
}
Request location updates from your locationManager (make sure you requestPermission for Android 6.0 and up)
#Override
public void onResume() {
super.onResume();
getLocationUpdates();
}
Use the SphericalUtil class to compute the distance within the ArrayList inside the onLocationChange function.
#Override
public void onLocationChanged(Location location) {
double distance = SphericalUtil.computeLength(coordList);
distance = round(distance, 2) / 1000;
distanceOutput.setText(distance + "km");
}
Add the round functionality:
public static double round(double value, int places) {
if (places < 0) throw new IllegalArgumentException();
BigDecimal bd = new BigDecimal(value);
bd = bd.setScale(places, RoundingMode.FLOOR);
return bd.doubleValue();
}
This will get the distance between start and end points in km and round it down to two decimal places, feel free to convert them into any other unit of distance depending on your use-case.
Google Distance matrix API need to use for the correct distance between places.
After many search and faq,Finally I understood that google's api is best and first way to get distance two location
I am new to android development but am taking a shot at making myself a golf rangefinder.. I have this activity -
public class hole_1 extends Activity implements View.OnClickListener {
Button nextBtn;
GPSTracker gps;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_hole_1);
gps = new GPSTracker(hole_1.this);
// Get Variable From Home Activity
Bundle extras = getIntent().getExtras();
String course = null;
if (extras != null) {
course = extras.getString("Course");
}
//Set Next Hole Button
nextBtn = (Button) findViewById(R.id.nextButton);
nextBtn.setOnClickListener(this);
gps = new GPSTracker(hole_1.this);
if (gps.canGetLocation()) {
double latitude = gps.getLatitude();
double longitude = gps.getLongitude();
double lat2 = 39.765718;
double lon2 = -121.860080;
Location loc1 = new Location("");
loc1.setLatitude(latitude);
loc1.setLongitude(longitude);
Location loc2 = new Location("");
loc2.setLatitude(lat2);
loc2.setLongitude(lon2);
float distanceInMeters = loc1.distanceTo(loc2);
int myDist = (int) (distanceInMeters * 1.0936);
TextView latView = (TextView) findViewById(R.id.yardage);
latView.setText(String.valueOf(myDist));
}else{
gps.showSettingsAlert();
}
}
#Override
public void onClick(View v) {
Intent myIntent = new Intent(this, end.class);
myIntent.putExtra("Hole",1);
startActivity(myIntent);
}
}
What I would like to do is update the myDist variable which is the distance between my current coordinates and the fixed coordinates (lat2, lon2). I have done some research and found asyncTask, threading and setting a timer but cannot figure out the best method for this application.. The app works great as is but I have to refresh the page to get updated distances and would like it to just update itself every few seconds.. What should I do?
Thanks!
1)You can't update every couple of seconds. GPS only updates every 30s to a minute.
2)You wouldn't use an async task here or any oter form of threading, GPS works on a callback system. You request updates and it will call you back whenever an update is available.
3)DO NOT USE the GpsTracker LIBRARY EVER. It's broken. Badly. See the full writeup I have on why its broken at http://gabesechansoftware.com/location-tracking/
I am having trouble figuring how to get the distance between 2 non fixed locations. The first location is my current location and the second is the latest current location after walking say 100 meters. Below is a snippet of code.
/**
* Callback that fires when the location changes.
*/
#Override
public void onLocationChanged(Location location) {
mCurrentLocation = location;
updateUI();
}
/**
* Updates the latitude, the longitude, and the last location time in the UI.
*/
private void updateUI() {
latitude = mCurrentLocation.getLatitude();
longitude = mCurrentLocation.getLongitude();
mLatitudeTextView.setText(String.format("%s: %f", mLatitudeLabel,latitude));
mLongitudeTextView.setText(String.format("%s: %f", mLongitudeLabel, longitude));
}
So below I have my mCurrentLocation but how do I get the newCurrentLocation so I use the distanceTo method.
double distance = mCurrentLocation.distanceTo(newCurrentLocation);
Any suggestions would be much appreciated.
You'll have to save the current location in a temporary variable, something like this:
public void onLocationChanged(Location location) {
Location temp = mCurrentLocation; //save the old location
mCurrentLocation = location; //get the new location
distance = mCurrentLocation.distanceTo(temp); //find the distance
updateUI();
}
When I run the app, I get the world map, where you can see all the countries. But this is not what I want, I want it to show the map of my country or city as an example. Is there a way to do this? This is my code so far. I don't think the xml code should be necassary for this?
public class MainActivity extends Activity {
private GoogleMap gMap;
private LocationManager locationManager;
private Location location, g;
private double lati, longi;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
gMap = ((MapFragment) getFragmentManager().findFragmentById(R.id.map)).getMap();
// gMap.setMyLocationEnabled(true);
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
System.out.println("Last known location: " + location);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
public void showUsersPosition(View v) {
gMap.setMyLocationEnabled(true);
if(location != null) {
lati = location.getLatitude();
longi = location.getLongitude();
}
gMap.addMarker(new MarkerOptions().position(new LatLng(lati, longi)).title("You are here"));
}
}
I also have added a button, where I want to show the users location when this button is clicked. This happens in the method "showUsersPosition". But at this point, Location is null, even though I try to set it when the app is beeing started. Can anyone see why it is null? When the gMap.setMyLocation(true) is called, a symbole appears at the right corner, and if I click on this, it will show me my position. But I want it so that it does this when I click the button.
So the questions again are:
1. How to show the map of my country or city, and not the world map?
2. Why is Location null?
3. How do I make it show my exact location when the button is clicked
1)
You can use this on your fragment declaration to set the default latitude and longitude.
map:cameraTargetLat="Your Latitude"
map:cameraTargetLng="Your Longitude"
Do not forget to put xmlns:map="http://schemas.android.com/apk/res-auto" on your fragment if it is not there.
2) From the docs:
If the provider is currently disabled, null is returned.
Is the GPS turned on?. Also, you should use the new Location API.
3) The exactness of your Location will be based on the Provider used to get the Location. One of the advantages of using the new Fused Provider is that the system will try to get the best Location possible for you.
My MapActivity records a polyline just fine however when I tip the screen on it's side and the orientation changes the polyline disappears? What could be causing this? Here is my code that is recording the polyline:
Location lastLocationloc;
private GoogleMap myMap;
#Override
public void onLocationChanged(Location location) {
if (lastLocationloc == null) {
lastLocationloc = location;
}
LatLng lastLatLng = locationToLatLng(lastLocationloc);
LatLng thisLatLng = locationToLatLng(location);
//Log.e(TAG, "Last LatLng is :"+lastLatLng);
//Log.e(TAG, "Last LatLng is :"+thisLatLng);
myMap.addPolyline(new PolylineOptions().add(lastLatLng).add(thisLatLng).width(10).color(Color.RED));
lastLocationloc = location;
}
How can I prevent this from happening?
You have to save your points and restore them later. One simple way is to use onSaveInstanceState which will keep your data across configuration changes and process being killed. Other options are files and DB. More info here: http://developer.android.com/guide/topics/data/data-storage.html