No location is ever retrieved from FusedLocationProviderApi - android

I have the following simple class, which is my main activity. I essentially followed this verbatim from the Android docs. I am running this from my phone through Android Studio. The problem I am running into is I absolutely never get a legitimate location out of this setup. The location object is always null. In reality, I want the location immediately in a similar fashion to how a browser quickly grabs the location through navigator.geolocation.
Is there something weird with the way I have this set up? If not, how do I force a location out of the Fused Location Provider API?
public class MyActivity extends AppCompatActivity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
private Location location;
private GoogleApiClient mGoogleApiClient;
private static LocationRequest locationRequest;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
// Create an instance of GoogleAPIClient.
if (mGoogleApiClient == null) {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
}
#Override
protected void onStart() {
mGoogleApiClient.connect();
super.onStart();
}
#Override
protected void onStop() {
mGoogleApiClient.disconnect();
super.onStop();
}
private void requestLocationUpdates() {
locationRequest = new LocationRequest();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setInterval(1000);
locationRequest.setFastestInterval(500);
}
#Override
public void onConnected(#Nullable Bundle bundle) {
requestLocationUpdates();
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, locationRequest, this);
location = LocationServices.FusedLocationApi.getLastLocation(
mGoogleApiClient);
if (location != null) {
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
#Override
public void onLocationChanged(Location location) {
if (location != null) {
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
#Override
public void onConnectionSuspended(int i) {}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {}
}

High accuracy means its going to require GPS. If you can't actually contact the GPS satellies (for example, you're inside a building without a clear line to the sky) then it will never send a result. This is actually correct behavior- you wanted high accuracy, its waiting until you have it.
If you're ok with less accuracy, use a different priority type. Otherwise you'll have to accept that you may never get a response.
DO expect it to take a few seconds even under optimal conditions, BTW. It has to find a half dozen sattelites in space before it can give an answer, that takes time.

Related

using Location Services fusedlocationapi in Android service -- Receiving only one location update

I'm trying my hand at making a background service that I'd like to run when the app is closed and terminate when the app is open.
as you can see in the code below, I have a Toast message that is supposed that is supposed to display in onLocationChanged(). I am only seeing that message appear once.
Here is what the permission looks like in the manifest:
<application
...
<activity android:name=".activities.ChatUsersActivity" />
<activity android:name=".activities.RequestsActivity"></activity>
<service android:name=".pops.PopService"
android:exported="false"
android:icon="#drawable/usericonmdpi"/>
</application>
And also, here is my Service extended class:
public class PopService extends Service implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
ScheduledThreadPoolExecutor threadPoolExecutor = new ScheduledThreadPoolExecutor(2);
Runnable backgroundCollector = new BackgroundPopCollector();
private GoogleApiClient mGoogleApiClient;
LocationRequest mLocationRequest;
Location mLastLocation;
private PopCityCollection cities;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
// Code to execute when the service is first created
super.onCreate();
buildGoogleApiClient();
}
#Override
public void onDestroy() {
super.onDestroy();
threadPoolExecutor.shutdownNow();
}
#Override
public void onLocationChanged(Location location) {
if (mGoogleApiClient != null) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}
UserLocation.setLatitude(location.getLatitude());
UserLocation.setLongitude(location.getLongitude());
Toast.makeText(getBaseContext(), "Latitude is " + location.getLatitude(), Toast.LENGTH_SHORT).show();
System.out.println(UserLocation.getLatitude()+", "+UserLocation.getLongitude()+" --->BACKGROUND!!");
if(cities==null) {
cities = new PopCityCollection(new LatLng(location.getLatitude(), location.getLongitude()));
cities.findMyCity(this);
}
DatabaseReference db = FirebaseDatabase.getInstance().getReference().child("pops");
db.push().setValue("test");
}
#Override
public void onConnected(#Nullable Bundle bundle) {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(100);
mLocationRequest.setFastestInterval(100);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
if (ContextCompat.checkSelfPermission(this,
android.Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
}
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(getApplicationContext())
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
mGoogleApiClient.connect();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId){
threadPoolExecutor.scheduleAtFixedRate(backgroundCollector, 0, 10, TimeUnit.SECONDS);
return START_NOT_STICKY;
}
}
Thank you for any insights you can provide!
-T
if (mGoogleApiClient != null) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}
the above condition will remove the location updates , after first time so remove this code
removeLocationUpdates
Removes all location updates for the given location listener.

GoogleApiClient stops to work properly after GPS turned on/off

I'm trying to implement abstract Activity, whose inheritants would be able to get Location data. I'm strictly following this guide, that seems pretty straightforward.
But after all I have a few problems. Google API should pass location data even if GPS is off, getting this from network data or even passive data from other apps. But in my case it works only with GPS enabled.
Another question is what happens when I turn GPS off/on. In my case after that I can't het any data at all.
Here's the class that makes everything done.
public abstract class LocationProviderActivity extends BaseDrawerActivity
implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
private final String TAG = "LOCATION";
GoogleApiClient client;
protected Location location;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (client == null) {
client = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
}
#Override
protected void onStart() {
client.connect();
Log.i(TAG, "Connected");
super.onStart();
}
#Override
protected void onStop() {
client.disconnect();
Log.i(TAG, "Disconnected");
super.onStop();
}
#Override
public void onConnected(#Nullable Bundle bundle) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
//TODO
return;
}
location = LocationServices.FusedLocationApi.getLastLocation(client);
}
#Override
public void onConnectionSuspended(int i) {
Log.i(TAG, "Location services connected.");
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
Log.i(TAG, "Location services suspended. Please reconnect.");
}
#Override
public void onLocationChanged(Location location) {
}
}

Location Services taking a lot of time to get a coarse location from FusedLocationApi

I have this app where I need to get a single coarse location (I'm only requesting for android.permission.ACCESS_COARSE_LOCATION) as quickly as possible before starting showing anything (besides a splash screen) to the user.
For some reason(s) my code is not working in some use cases where it needs to request for a location update (if it can't find a last know location).
If Location Services were disabled recently and I enable them back and then launch my app, it might take a lot of time (or not) to get a location fix and it might never happen. In this situation, I usually have to disable the Location Services and enable them back with the quick switch button from the notifications dropdown with the app in the foreground. And it's not immediate either, it takes a few seconds.
Another similar case is where the Location Services are disabled, I open the app and can't get a fix. I open the device settings (placing the app in the background), re-enable Location Services and bring the app back to the foreground. It takes a lot of time to get a location fix sometimes.
Honestly, it's complicated for me to describe the use cases where it usually takes a lot of time to get a fix on location. I've tried many things, constantly disabling/enabling Location services, with the app opened/closed, on the foreground/background. Many things, it just doesn't work consistently.
And given the nature of my app, I really need to get a single location fix as quickly as possible. And since I don't need a precise location (a really rough estimate is fine), I don't understand why it takes so long...
Sorry for the long post, here's my current code:
// BaseActivityLifecycleCallbacks extends Application.ActivityLifecycleCallbacks with default blank methods
public class MyLocation extends BaseActivityLifecycleCallbacks implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener, LocationListener {
private static final int LOCATION_REQUEST_INTERVAL = 1000; // 1 second
private static final int LOCATION_REQUEST_FASTEST_INTERVAL = 250; // 250 milliseconds
private static final int LOCATION_REQUEST_UPDATE_TIMEOUT = 15000; // 15 seconds
private final Handler mMainHandler;
private final Runnable mExpiredRunnable;
private final GoogleApiClient mGoogleApiClient;
private final LocationRequest mLocationRequest;
private LocationCallback mLocationCallback;
#DebugLog
public MyLocation(Context context) {
mMainHandler = new Handler(Looper.getMainLooper());
mExpiredRunnable = new Runnable() {
#DebugLog
#Override
public void run() {
handleNewOrEmptyLocation(null);
}
};
MyApplication.getInstance().registerActivityLifecycleCallbacks(this);
mGoogleApiClient = new GoogleApiClient.Builder(context)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
mLocationRequest = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY)
.setInterval(LOCATION_REQUEST_INTERVAL)
.setFastestInterval(LOCATION_REQUEST_FASTEST_INTERVAL);
}
public void requestFusedLocation(#NonNull LocationCallback callback) {
mLocationCallback = callback;
mGoogleApiClient.connect();
}
#DebugLog
#Override
public void onActivityResumed(Activity activity) {
super.onActivityResumed(activity);
if (activity instanceof MainActivity) {
if (!mGoogleApiClient.isConnected() && !mGoogleApiClient.isConnecting() && mLocationCallback != null) {
mGoogleApiClient.connect();
}
}
}
#DebugLog
#Override
public void onActivityPaused(Activity activity) {
super.onActivityPaused(activity);
if (activity instanceof MainActivity) {
if (mGoogleApiClient.isConnected()) {
mMainHandler.removeCallbacks(mExpiredRunnable);
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
mGoogleApiClient.disconnect();
}
}
}
#DebugLog
#Override
// I'm handling permission request some place else...
#SuppressWarnings("MissingPermission")
public void onConnected(#Nullable Bundle bundle) {
Location lastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if (lastLocation != null) {
handleNewOrEmptyLocation(lastLocation);
return;
}
// I've disabled this for testing purposes. Sometimes the current 15s timeout is not enough to get a location fix...
//mMainHandler.postDelayed(mExpiredRunnable, LOCATION_REQUEST_UPDATE_TIMEOUT);
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
#DebugLog
#Override
public void onLocationChanged(Location location) {
mMainHandler.removeCallbacks(mExpiredRunnable);
handleNewOrEmptyLocation(location);
}
#DebugLog
#Override
public void onConnectionSuspended(int i) {
// TODO: Is there something that needs to be done here?
Timber.e("onConnectionSuspended");
}
#DebugLog
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
// TODO: Is there something that needs to be done here?
Timber.e("onConnectionFailed");
}
#DebugLog
private void handleNewOrEmptyLocation(Location location) {
MyApplication.getInstance().unregisterActivityLifecycleCallbacks(this);
mGoogleApiClient.disconnect();
if (location != null) {
mLocationCallback.onLocationReceived(location);
} else {
mLocationCallback.onEmptyLocation();
}
}
public interface LocationCallback {
void onLocationReceived(Location location);
void onEmptyLocation();
}
}
And this is how it's currently being used:
public class MAinActivity extends BaseActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyLocation myLocation = new MyLocation(this);
myLocation.requestFusedLocation(new MyLocation.LocationCallback() {
#DebugLog
#Override
public void onLocationReceived(Location location) {
Toast.makeText(MainActivity.this, String.valueOf(location), Toast.LENGTH_SHORT).show();
}
#DebugLog
#Override
public void onEmptyLocation() {
Toast.makeText(MainActivity.this, "HUSTON, WE HAVE A PROBLEM!", Toast.LENGTH_SHORT).show();
finish();
}
});
}
}
To finish and as bonus question... In what circumstances are onConnectionSuspended and onConnectionFailed called? Should I handle these callbacks somehow?

Fused Location Provider doesnot give Location Updates on Displacement

I have used Fused Location API to get location updates. I am getting updates while setting LocationRequest based on setTimeInterval. But I need only updates on 10m Movement. So i placed setSmallestDisplacement(10) .But when i put setSmallestDisplacement(10), i didnt get updates. Following is my LocationUpdate class
public class LocationManger implements
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener, com.google.android.gms.location.LocationListener {
GoogleApiClient mLocationClient;
Location mCurrentLocation;
LocationRequest mLocationRequest;
Context mContext;
public LocationManger(Context context) {
super();
mLocationClient = new GoogleApiClient.Builder(context)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
mContext = context;
}
#Override
public void onLocationChanged(Location location) {
mCurrentLocation = location;
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Helper.showToast("failed", mContext);
}
#Override
public void onConnected(Bundle arg0) {
if (mLocationRequest == null) {
mLocationRequest = LocationRequest.create();
mLocationRequest.setSmallestDisplacement(10);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
LocationServices.FusedLocationApi.requestLocationUpdates(mLocationClient, mLocationRequest, this);
}
#Override
public void onConnectionSuspended(int i) {
mLocationClient.connect();
}
/**
* Function to start the location updates
*/
public void startLocationUpdates() {
if (!mLocationClient.isConnected())
mLocationClient.connect();
}
/**
* function to stop the location updates
*/
public void stopUpdatingLocation() {
if (mLocationClient.isConnected()) {
LocationServices.FusedLocationApi.removeLocationUpdates(mLocationClient, this);
}
mLocationClient.disconnect();
}
/**
* function to get the current latitude
*/
public double getCurrentLatitude() {
if (mCurrentLocation != null) {
return mCurrentLocation.getLatitude();
}
return 0;
}
/**
* function to get the current longitude
*/
public double getCurrentLongitude() {
if (mCurrentLocation != null) {
return mCurrentLocation.getLongitude();
}
return 0;
}
/**
* function to get the current location
*/
public Location getCurrentLocation() {
return LocationServices.FusedLocationApi.getLastLocation(mLocationClient);
}
}
Please give me a solution if anyone know the issue. Thanks in advance
Use setFastestInterval(0) to allow updates more frequently than called for by setInterval. Otherwise you will miss some updates from displacement

on locaton changed never gets called in android google client api

I am developing app which require location services my code is as follow.
The main problem is on location changed never gets called
public class MainActivity extends ActionBarActivity implements
ConnectionCallbacks, OnConnectionFailedListener, LocationListener {
protected GoogleApiClient mGoogleApiClient;
public static final long UPDATE_INTERVAL_IN_MILLISECONDS = 100;
public static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS =
UPDATE_INTERVAL_IN_MILLISECONDS / 2;
protected LocationRequest mLocationRequest;
protected static final String TAG = "location-updates-sample";
protected Location mCurrentLocation;
Button btn;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn=(Button)findViewById(R.id.button);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.i(TAG,"btn is clicked");
buildGoogleApiClient();
Log.i(TAG,"build google api completed");
mGoogleApiClient.connect();
Log.i(TAG,"client conneted");
}
});
}
protected synchronized void buildGoogleApiClient() {
Log.i(TAG, "Building GoogleApiClient");
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
createLocationRequest();
}
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
protected void startLocationUpdates() {
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
}
#Override
public void onConnected(Bundle bundle) {
startLocationUpdates();
Log.i(TAG,"from onconnected method");
}
#Override
public void onConnectionSuspended(int i) {
mGoogleApiClient.connect();
}
#Override
public void onLocationChanged(Location location) {
mCurrentLocation = location;
Log.i(TAG,"on location changed");
Log.i(TAG,String.valueOf(mCurrentLocation.getLongitude()));
Log.i(TAG,String.valueOf(mCurrentLocation.getLatitude()));
Toast.makeText(this,"liocation changed", Toast.LENGTH_SHORT).show();
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
}
}
I have done "ACCESS_FINE_LOCATION" in manifest. also set the setting to be ''gps'' device only.
i am getting the result when i click on button
location-updates-sample﹕ btn is clicked
location-updates-sample﹕ Building GoogleApiClient
location-updates-sample﹕ build google api completed
location-updates-sample﹕ client conneted
location-updates-sample﹕ from onconnected method
whats wrong with my code
I use the same code to handle locations.
Don't know if it's the correct solution but try to replace
mLocationRequest = new LocationRequest();
with
mLocationRequest = LocationRequest.create();
Works for me.
I don't know english. Hope i can help:
I think your UPDATE_INTERVAL_IN_MILLISECONDS = 100( 0,1 s) and FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS ( 100/ 2 = 0.05s) is very fast with gps chip . you should set it > 1s . some thing like this
UPDATE_INTERVAL_IN_MILLISECONDS = 10 * 1000;// 10s
FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS = 5 *1000; // 5s
Make Sure you have added .addApi(LocationServices.API)
I was not getting onLocationChanged(Location location) call in my emulator.
current_location =LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
Using this can find current location.
Hope this will help you.

Categories

Resources