I am trying to implement fused location for getting the current location. I am doing it with the help of this link
My googleAPiCLient is connected. But location is always null
In my Manifest file I have put this
<meta-data android:name="com.google.android.gms.version"
android:value="5089000" />
I created a seperate Fusionclass.
MY fusion class--
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import android.app.Activity;
import android.location.Location;
import android.os.Bundle;
import android.util.Log;
import com.XXX.constants.LogConstants;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.FusedLocationProviderApi;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
public class FusedLocation implements
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener {
private static final long INTERVAL = 1000 * 30;
private static final long FASTEST_INTERVAL = 1000 * 5;
private static final long ONE_MIN = 1000 * 60;
private static final long REFRESH_TIME = ONE_MIN * 5;
// private static final float MINIMUM_ACCURACY = 50.0f;
Activity LauncherActivity;
private LocationRequest locationRequest;
private GoogleApiClient googleApiClient;
private Location location;
private FusedLocationProviderApi fusedLocationProviderApi = LocationServices.FusedLocationApi;
public FusedLocation(Activity LauncherActivity) {
locationRequest = LocationRequest.create();
// locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setInterval(INTERVAL);
locationRequest.setFastestInterval(FASTEST_INTERVAL);
this.LauncherActivity = LauncherActivity;
googleApiClient = new GoogleApiClient.Builder(LauncherActivity)
.addApi(LocationServices.API).addConnectionCallbacks(this)
.addOnConnectionFailedListener(this).build();
if (googleApiClient != null) {
Log.i(LogConstants.INFO_LOG, "googleApiClient is not null");
//the console prints this
googleApiClient.connect();
}
}
@Override
public void onConnected(Bundle connectionHint) {
Log.i(LogConstants.INFO_LOG, "GoogleApiClient connected");
Location currentLocation = fusedLocationProviderApi.getLastLocation(googleApiClient);
if (currentLocation != null && currentLocation.getTime() > REFRESH_TIME) {
location = currentLocation;
} else {
fusedLocationProviderApi.requestLocationUpdates(googleApiClient,locationRequest, locListen);
// Schedule a Thread to unregister location listeners
Executors.newScheduledThreadPool(1).schedule(new Runnable() {
@Override
public void run() {
fusedLocationProviderApi.removeLocationUpdates(googleApiClient, locListen);
}
}, ONE_MIN, TimeUnit.MILLISECONDS);
}
}
com.google.android.gms.location.LocationListener locListen=new com.google.android.gms.location.LocationListener() {
@Override
public void onLocationChanged(Location location) {
Log.i(LogConstants.INFO_LOG, "75location::"+location);
}
};
public Location getLocation() {
return this.location;
}
@Override
public void onConnectionSuspended(int i) {
}
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
}
}
My activity class I am calling the FusedLOcation class from the oncreate
//show error dialog if GoolglePlayServices not available
if (!isGooglePlayServicesAvailable()) {
finish();
}
fusedLocation = new FusedLocation(this);
Location location = fusedLocation.getLocation();
String locationResult = "";
if (null != location) {
Log.i(LogConstants.INFO_LOG, location.toString());
double latitude = location.getLatitude();
double longitude = location.getLongitude();
Log.i(LogConstants.INFO_LOG, "longitude::!"+longitude);
float accuracy = location.getAccuracy();
/*double elapsedTimeSecs = (double) location.getElapsedRealtimeNanos()
/ 1000000000.0;*/
String provider = location.getProvider();
double altitude = location.getAltitude();
locationResult = "Latitude: " + latitude + "\n" +
"Longitude: " + longitude + "\n" +
"Altitude: " + altitude + "\n" +
"Accuracy: " + accuracy + "\n" +
"Elapsed Time: " + " secs" + "\n" +
"Provider: " + provider + "\n";
} else {
locationResult = "Location Not Available!";
Log.i(LogConstants.INFO_LOG, "Location Not Available!");
}
private boolean isGooglePlayServicesAvailable() {
int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
Log.i(LogConstants.INFO_LOG, "status:"+status);
if (ConnectionResult.SUCCESS == status) {
return true;
} else {
GooglePlayServicesUtil.getErrorDialog(status, this, 0).show();
return false;
}
}
Location is always null. The listeners do not seem to be working.
First of all, if you're using the emulator you have to set the position manually doing:
telnet localhost 5554
when connected run the command
geo fix <longitude> <latitude>
as decribed here Using the emulator #geo or here how-to-emulate-gps-location-in-the-android-emulator. I suggest you to do so at soon as the emulator is booting and obviously before you're app start.
Second thing, your FusedLocation isn't implementing LocationListener as it is in the example you have posted. You have to implement that interface and then implement the method onLocationChanged inside your FusedLocation. Anyway, I think that you are trying to load the location as soon as the app is started, right? Well the example you posted doesn't work in this way but it's the user that ask for location through a visible botton. If you want to load the location at the beginning you can modify the example code like this:
the FusedLocationService is your FusedLocation class
import android.app.Activity;
import android.location.Location;
import android.os.Bundle;
import android.util.Log;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.FusedLocationProviderApi;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class FusedLocationService implements
LocationListener,
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener {
private static final String TAG = "FusedLocationService";
private static final long INTERVAL = 1000 * 30;
private static final long FASTEST_INTERVAL = 1000 * 5;
private static final long ONE_MIN = 1000 * 60;
private static final long REFRESH_TIME = ONE_MIN * 5;
private static final float MINIMUM_ACCURACY = 50.0f;
Activity locationActivity;
private LocationRequest locationRequest;
private GoogleApiClient googleApiClient;
private Location location;
private FusedLocationProviderApi fusedLocationProviderApi = LocationServices.FusedLocationApi;
FusedLocationReceiver locationReceiver = null;
public FusedLocationService(Activity locationActivity, FusedLocationReceiver locationReceiver) {
this.locationReceiver = locationReceiver;
locationRequest = LocationRequest.create();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setInterval(INTERVAL);
locationRequest.setFastestInterval(FASTEST_INTERVAL);
this.locationActivity = locationActivity;
googleApiClient = new GoogleApiClient.Builder(locationActivity)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
if (googleApiClient != null) {
googleApiClient.connect();
}
}
@Override
public void onConnected(Bundle connectionHint) {
Log.i(TAG, "I'm connected now");
Location currentLocation = fusedLocationProviderApi.getLastLocation(googleApiClient);
if (currentLocation != null && currentLocation.getTime() > REFRESH_TIME) {
location = currentLocation;
} else {
fusedLocationProviderApi.requestLocationUpdates(googleApiClient, locationRequest, this);
// Schedule a Thread to unregister location listeners
Executors.newScheduledThreadPool(1).schedule(new Runnable() {
@Override
public void run() {
fusedLocationProviderApi.removeLocationUpdates(googleApiClient,
FusedLocationService.this);
}
}, ONE_MIN, TimeUnit.MILLISECONDS);
}
}
@Override
public void onLocationChanged(Location location) {
Log.i(TAG, "Location is changed!");
//if the existing location is empty or
//the current location accuracy is greater than existing accuracy
//then store the current location
if (null == this.location || location.getAccuracy() < this.location.getAccuracy()) {
this.location = location;
// let's inform my client class through the receiver
locationReceiver.onLocationChanged();
//if the accuracy is not better, remove all location updates for this listener
if (this.location.getAccuracy() < MINIMUM_ACCURACY) {
fusedLocationProviderApi.removeLocationUpdates(googleApiClient, this);
}
}
}
public Location getLocation() {
return this.location;
}
@Override
public void onConnectionSuspended(int i) {
}
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
}
}
This is the receiver
public abstract class FusedLocationReceiver {
public abstract void onLocationChanged();
}
and this is the activity
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.app.Activity;
import android.location.Location;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
public class MainActivity extends Activity {
private static final String TAG = "MyActivity";
Button btnFusedLocation;
TextView tvLocation;
FusedLocationService fusedLocationService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//show error dialog if GoolglePlayServices not available
if (!isGooglePlayServicesAvailable()) {
finish();
}
setContentView(R.layout.activity_main);
tvLocation = (TextView) findViewById(R.id.tvLocation);
fusedLocationService = new FusedLocationService(this, new FusedLocationReceiver(){
@Override
public void onLocationChanged() {
Log.i(TAG, "I'm the receiver, let's do my job!");
updateUI();
}
});
btnFusedLocation = (Button) findViewById(R.id.btnGPSShowLocation);
btnFusedLocation.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
updateUI();
}
});
}
private void updateUI() {
Location location = fusedLocationService.getLocation();
String locationResult = "";
if (null != location) {
Log.i(TAG, location.toString());
double latitude = location.getLatitude();
double longitude = location.getLongitude();
float accuracy = location.getAccuracy();
double elapsedTimeSecs = (double) location.getElapsedRealtimeNanos()
/ 1000000000.0;
String provider = location.getProvider();
double altitude = location.getAltitude();
locationResult = "Latitude: " + latitude + "\n" +
"Longitude: " + longitude + "\n" +
"Altitude: " + altitude + "\n" +
"Accuracy: " + accuracy + "\n" +
"Elapsed Time: " + elapsedTimeSecs + " secs" + "\n" +
"Provider: " + provider + "\n";
} else {
Log.i(TAG, "Location Not Available!");
locationResult = "Location Not Available!";
}
tvLocation.setText(locationResult);
}
private boolean isGooglePlayServicesAvailable() {
int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if (ConnectionResult.SUCCESS == status) {
return true;
} else {
GooglePlayServicesUtil.getErrorDialog(status, this, 0).show();
return false;
}
}
}
Essentially when you instantiate a FusedLocationService you give it an object (the receiver) that will be called by the FusedLocationService when the location is ready. Warning: this will give you the location only once.