Getting location android? - java

I want to receive location updates every second for a small period of time, so I wrote this code:
public void registerListener() {
if (ActivityCompat.checkSelfPermission(c, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(c, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
} else {
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 10, locationListener);
}
}
private final LocationListener locationListener = new LocationListener() {
public void onLocationChanged(Location location) {
longitude = location.getLongitude();
latitude = location.getLatitude();
Log.v(TAG, ""+longitude + " " +latitude);
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {}
#Override
public void onProviderEnabled(String provider) {}
#Override
public void onProviderDisabled(String provider) {}
};
I call registerListener() from somewhere else. The problem is, my location update is only called once, and I only get that log once. Also, the log only comes about 5-10 seconds after calling registerListener.
What is the reason of the slowness, and why isn't the location being updated?
Thanks,
Ruchir

You're requesting GPS location. It will take a few seconds to get a satellite lock for the first time. It may never happen if you can't receive a signal lock (indoors in some buildings, too far underground, physical damage to the phone like a loose antenna (common in early gen Samsungs)).
As for not receiving it again- you won't receive it again unless you move at least 10 meters. Change that to 0 and see it come every second.

Related

How to precisely calculate speed and distance using GPS? Tracking user location. App for running

I want to make an application for running which tracks user location, speed and beaten distance. Currently I am using Google Location Services API to get GPS data, because Google recommends it on the official site.
But the problem is that I can recive location updates only every 10 seconds, which is OK if it comes only to drawning location on the map, but I want to calculte user current speed(km/h), current pace (min/m) and calculate exact time when he makes one lap (1km or 1 mile). And here is the problem if I am getting updates every 10sec I am not able to calculate precisely those parameters. For example, the update comes when user is on 996m and in 4m he will make one lap. But the next update will not be available for 10 sec, so it will come on e.g. 1010m. And that is not what user would like to have...
How to solve this problem? What do you think?
I am using the exact code form here.
Where location request looks like:
LocationRequest mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(10000);
mLocationRequest.setFastestInterval(5000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
From docs:
The priority of PRIORITY_HIGH_ACCURACY, combined with the ACCESS_FINE_LOCATION permission setting that you've defined in the app manifest, and a fast update interval of 5000 milliseconds (5 seconds), causes the fused location provider to return location updates that are accurate to within a few feet. This approach is appropriate for mapping apps that display the location in real time.
But it isn't enough. Even though I change interval for smaller it always is 10sec.
Use this code it can send Location updates every 3 seconds.
LocationListener listener = new LocationListener() {
#Override
public void onLocationChanged(final Location location) {
//This will be called when location is changed
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
Intent i = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
}
};
locationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
}
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 3000, 0, listener);
More details of this code on Github.

LocationListner no longer listen for gps status change after upgrade to Android 7

After updated my app to support Android 7 the GPS listner no longer is invoked when the GPS on/off is triggerd. If I refresh my activity it works as expected on Android 6, but not in Android 7. Does anyone have any idea. I have added both my listner, and code releated to gps change in my activity.
I have if its difficult a theory to override the backpressed or activity resumed to recreate view, but havn't suceeded with that either .
GPSListner.java
public abstract class GPSListener implements LocationListener {
private Context context;
public GPSListener(Context context) {
this.context = context;
}
#Override
public void onProviderEnabled(String provider) {
onGPSOn();
}
#Override
public void onProviderDisabled(String provider) {
onGPSOff();
}
public abstract void onGPSOff();
public abstract void onGPSOn();
#Override
public void onLocationChanged(Location location) {
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
}
My class
gpsListener = new GPSListener(this) {
#Override
public void onGPSOff() {
gpsImg.setImageResource(R.drawable.notok);
}
#Override
public void onGPSOn() {
gpsImg.setImageResource(R.drawable.ok);
}
};
final LocationManager manager;
manager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
final ImageView gpsImg = (ImageView) findViewById(R.id.gpsstatus);
if (manager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
gpsImg.setImageResource(R.drawable.ok);
} else {
gpsImg.setImageResource(R.drawable.notok); //not ok
}
This last method opens the gps settings.
public View.OnClickListener onButtongpsClick = new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent gpsOptionsIntent = new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(gpsOptionsIntent);
}
};
Obtaining location is a bit tricky itself. Only GPS can have line-of-sight issues and would vary depending on device too, not just Android version. Over the years Android location services have matured and using up-to-date standard practices does result in higher consistency with respect to results.
By the way, LocationClient is deprecated. FusedLocationProviderApi does not use it anymore.
It works through a GoogleApiClient and this part makes the GooglePlayServices mandatory. You have options if this does not suit your app.
Making your app location aware suggests:
The Google Play services location APIs are preferred over the Android
framework location APIs (android.location) as a way of adding location
awareness to your app. If you are currently using the Android
framework location APIs, you are strongly encouraged to switch to the
Google Play services location APIs as soon as possible.
You can break it into parts to understand it better, like;
Building the GoogleApiClient
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this) //this = activity
.addApi(LocationServices.API)
.addConnectionCallbacks(this) //interfaces implemented
.addOnConnectionFailedListener(this)
.build();
}
Requesting location,
// Create the location request
mLocationRequest = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setInterval(UPDATE_INTERVAL)
.setFastestInterval(FASTEST_INTERVAL);
// Request location updates
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient,
mLocationRequest, this);
Try the last known location, if that requirement works for you,
#Override
public void onConnected(Bundle bundle) {
Location mCurrentLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
...}
onConnected() is the callback from GoogleApiClient...
So there is more to location than initialising a client and implementing the listener. I recommend you go through a few questions or android docs to ensure you implement what suits your requirement.
Also,
instead of
Intent gpsOptionsIntent = new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS); ,
use SettingsApi
can refer to Enabling location mode...
Some useful Q&As:
Comprehensive answer for obtaining location
Good to go through LocationRequest part here if you want to avoid reading in detail
final LocationManager manager;
manager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
Do i even have to comment on this one? Read it again and you will understand what is wrong with it.
Hint. Try:
final LocationManager manager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
You can used fused location api to get the location
Fused Location Api :
Fused Location Provider automatically decides best location from the available options for that it uses GPS and Network Provider, So if the device GPS is off we can still get the location from Network provider vice versa.
Why Fused Location Api ?
Consumption of power while fetching location.
It will give accurate
location based on user priority.
Piggyback which means you can get
location every time when other application hits for location for you
advantage is user not blame you for that you just getting those
location which other application request.
We don’t have to pick the
provider(GPS or network provider)
please refer code for following for getting location.
LocationService : We required these for getting continues location and these register as pending intent so whenever device got new location these service invoke.
public class LocationService extends IntentService {
private String TAG = this.getClass().getSimpleName();
public LocationService() {
super("Fused Location");
}
public LocationService(String name) {
super("Fused Location");
}
#Override
protected void onHandleIntent(Intent intent) {
Location location = intent.getParcelableExtra(LocationClient.KEY_LOCATION_CHANGED);
if(location !=null){
Log.i(TAG, "onHandleIntent " + location.getLatitude() + "," + location.getLongitude());
// write your code here.
}
}
}
MainActivity : which register callbacks for it which tell us whether we are connected or disconnected with api.
public class MainActivity extends Activity implements GooglePlayServicesClient.ConnectionCallbacks,GooglePlayServicesClient.OnConnectionFailedListener,LocationListener {
private String TAG = this.getClass().getSimpleName();
private LocationClient locationclient;
private LocationRequest locationrequest;
private Intent mIntentService;
private PendingIntent mPendingIntent;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mIntentService = new Intent(this,LocationService.class);
mPendingIntent = PendingIntent.getService(this, 1, mIntentService, 0);
int resp =GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if(resp == ConnectionResult.SUCCESS){
locationclient = new LocationClient(this,this,this);
locationclient.connect();
}
else{
Toast.makeText(this, "Google Play Service Error " + resp, Toast.LENGTH_LONG).show();
}
}
public void buttonClicked(View v){
if(v.getId() == R.id.btnLastLoc){
if(locationclient!=null && locationclient.isConnected()){
Location loc =locationclient.getLastLocation();
Log.i(TAG, "Last Known Location :" + loc.getLatitude() + "," + loc.getLongitude());
txtLastKnownLoc.setText(loc.getLatitude() + "," + loc.getLongitude());
}
}
if(v.getId() == R.id.btnStartRequest){
if(locationclient!=null && locationclient.isConnected()){
if(((Button)v).getText().equals("Start")){
locationrequest = LocationRequest.create();
locationrequest.setInterval(Long.parseLong(etLocationInterval.getText().toString()));
locationclient.requestLocationUpdates(locationrequest, this);
((Button) v).setText("Stop");
}
else{
locationclient.removeLocationUpdates(this);
((Button) v).setText("Start");
}
}
}
if(v.getId() == R.id.btnRequestLocationIntent){
if(((Button)v).getText().equals("Start")){
locationrequest = LocationRequest.create();
locationrequest.setInterval(100);
locationclient.requestLocationUpdates(locationrequest, mPendingIntent);
((Button) v).setText("Stop");
}
else{
locationclient.removeLocationUpdates(mPendingIntent);
((Button) v).setText("Start");
}
}
}
#Override
protected void onDestroy() {
super.onDestroy();
if(locationclient!=null)
locationclient.disconnect();
}
#Override
public void onConnected(Bundle connectionHint) {
Log.i(TAG, "onConnected");
txtConnectionStatus.setText("Connection Status : Connected");
}
#Override
public void onDisconnected() {
Log.i(TAG, "onDisconnected");
txtConnectionStatus.setText("Connection Status : Disconnected");
}
#Override
public void onConnectionFailed(ConnectionResult result) {
Log.i(TAG, "onConnectionFailed");
txtConnectionStatus.setText("Connection Status : Fail");
}
#Override
public void onLocationChanged(Location location) {
if(location!=null){
Log.i(TAG, "Location Request :" + location.getLatitude() + "," + location.getLongitude());
}
}
}
For more reference refer below link
https://github.com/riteshreddyr/fused-location-provider
https://github.com/kpbird/fused-location-provider-example
Hope these help you.

Google play service is slow finding my location

I added google play api to my android application to get my current location because i need in my project.
After adding the necessary code to get my current location, it work fine but it is slow, so after clicking the button to get my location it respond after 20-25 seconds .
Is there is a way to make it faster ?
Here is my code :
....
LocationManager myManager;
MyLocListener loc;
loc = new MyLocListener();
myManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return;
}
myManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, loc);
}
public class MyLocListener implements LocationListener {
#Override
public void onLocationChanged(Location location)
{
if(location != null)
{
// it logs after 20-25 s
Log.d("Latitude :", "" + location.getLatitude());
Log.d("Latitude :", "" + location.getLongitude());
}
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
}
Using the GPS_PROVIDER requires a strict GPS fix, which generally does take 10-30 seconds depending on the hardware.
You should consider using the FusedLocationProviderApi as explained on the Receiving location updates training page, which combines the location information from many sources such as Wifi, Bluetooth, and GPS and provides a much faster location fix in general, even for high accuracy requests.

Getting current location (coordinates) in android?

I am trying to get the current location coordinates in longitude and latitude. Here is my code so far:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
MyLocationListener myLocationListener = new MyLocationListener();
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return;
}
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, myLocationListener);
}
}
and this class too:
public class MyLocationListener implements LocationListener {
private static final String TAG = "COORDINATES: ";
#Override
public void onLocationChanged(Location location) {
if(location != null){
Log.e(TAG, "Latitude: " + location.getLatitude());
Log.e(TAG, "Longitude: " + location.getLongitude());
}
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
}
}
When I run the app in emulator, I don't get any log message with coordinates. Any suggestions?
The best approach is to use the latest FusedLocationApi provided by Google Play Services library.
If you want to use the old approach, that is fine but you might not get very accurate results.
Either way, make sure you have enabled internet permission, either COARSE_LOCATION or FINE_LOCATION or both in your android manifest.
Also, if you have android 6.0, remember you must request runtime permissions or it won't work for you!
I answered a similar question yesterday and you can find here -which works;
There is also a link to a sample code for FusedLocationApi here.
I hope this helps you and good luck!
UPDATE
You can add Google Play Services to your build.gradle like this:
compile 'com.google.android.gms:play-services:9.2.'
But if you are only interested in one service like location, you can be specific:
compile 'com.google.android.gms:play-services-location:9.2.1'
NOTE
I would highly discourage you from getting user location on your UI thread because it will destroy user experience in the long run! Use a separate thread!!
You have to mimic the location in Emulator. You can do that by accessing the Android Device Manager and Select Emulator Control tab and send the locations to Emulator.

Cannot seem to get user location

I've been trying to get the longitude and latitude of a users location with Android. I've been trying to use the LocationManger however it does not seem to activate and give me an update. Here is the code, any ideas what I'm doing wrong?
LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);// Define a listener that responds to location updates
LocationListener locationListener = new LocationListener() {
public void onLocationChanged(Location location) { // Called when a new location is found by the network location provider.
System.out.println(location.getLatitude());
System.out.println(location.getLongitude());
locationplace = location.getProvider();
}
public void onStatusChanged(String provider, int status, Bundle extras) {}
public void onProviderEnabled(String provider) {}
public void onProviderDisabled(String provider) {} };// Register the listener with the Location Manager to receive location updates
//locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
System.out.println(locationplace);

Categories