Blog coding and discussion of coding about JavaScript, PHP, CGI, general web building etc.

Tuesday, March 8, 2016

Fused location provider doesn't seem to use GPS receiver

Fused location provider doesn't seem to use GPS receiver


Android 4.3 on Moto G, Android 4.4.2 on Nexus 7 2012, Android 4.4.2 on Nexus 5. Android Studio 0.4.

I don't want to receive regular location updates, I just want an accurate location when the user presses a button.

I have followed this example: https://developer.android.com/training/location/retrieve-current.html

In manifest file:

    

I check that Play Services are available using GooglePlayServicesUtil.isGooglePlayServicesAvailable

In main activity:

//in activity onCreate method  mLocationClient = new LocationClient(this, this, this);    @Override  protected void onStart() {      mLocationClient.connect();      super.onStart();  }    @Override  protected void onStop() {      mLocationClient.disconnect();      super.onStop();  }    //in button onclick method      mCurrentLocation = mLocationClient.getLastLocation();  

I have no SIM card. If I enable Wifi then sometimes I get an accurate location. Other times mCurrentLocation is null.

If I disable Wifi then mCurrentLocation is always null.

I am testing outside in several locations always with a clear view of the sky. I waited three minutes in each location.

I never see the GPS icon appear on the Android notification bar at the top of the screen.

I have these location settings: enter image description here

A GPS Test app manages to use GPS successfully indoors on the same device with Wi-Fi disabled so GPS is working: enter image description here

Registering for location updates, as at https://developer.android.com/training/location/receive-location-updates.html, doesn't work either. Registered method never called.

What am I doing wrong?

Answer by vinay Maneti for Fused location provider doesn't seem to use GPS receiver


I think your are testing your application in Indoor , it doesn't works..

and code flow..

public void setUpLocationClientIfNeeded() {          createLocReq();          if (mLocationClient == null) {              mLocationClient = new LocationClient(getApplicationContext(), this, // ConnectionCallbacks                      this); // OnConnectionFailedListener          }      }        private void createLocReq() {          if (mLocationRequest == null) {              // Create a new global location parameters object              mLocationRequest = LocationRequest.create();              // Set the update interval              mLocationRequest.setInterval(LocationServices.UPDATE_INTERVAL_IN_MILLISECONDS);              // Use high accuracy              mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);              // Set the interval ceiling to one minute              mLocationRequest.setFastestInterval(LocationServices.FAST_INTERVAL_CEILING_IN_MILLISECONDS);                mLocationClient = new LocationClient(getApplicationContext(), this, this);              mLocationClient.connect();          }      }        public void updateLocation(Location location) {          if (lastTrackedLat == 0.0) {              lastTrackedLat = location.getLatitude();          }          if (lastTrackedLng == 0.0) {              lastTrackedLng = location.getLongitude();          }            currentLat = location.getLatitude();          currentLng = location.getLongitude();      }        @Override      public void onLocationChanged(Location location) {          if (location != null) {              this.location = location;              updateLocation(location);          }      }        public Location getLocation() {          // mLocationClient.getLastLocation();          return location;      }  

Answer by tyczj for Fused location provider doesn't seem to use GPS receiver


According to the docs

This method provides a simplified way to get location. It is particularly well suited for applications that do not require an accurate location and that do not want to maintain extra logic for location updates.

so it may or may not return a highly accurate location.

GPS can take a while to lock on so calling getLastLocation may or may not return a location

you are better off requesting location updates then after you get a location just stop requesting location updates.

Also looking at you code you provided are you waiting for the LocationClient to connect before trying to get a location? That will certainly give you a null location since it is not connected to get the location yet.

what you should be doing is in your onConnected get the last location there, example

public void onConnected(Bundle connectionHint) {      Location location = mLocationClient.getLastLocation();  }  

as it says in that example onConnected is Called by Location Services when the request to connect the client finishes successfully. At this point, you can request the current location or start periodic updates

Answer by user1993392 for Fused location provider doesn't seem to use GPS receiver


Without a sim card the coarse location provider has no way to know the coarse position, unless it is able to find a WiFi network that has been mapped by Google.

Requesting the last known location may result in a outdated location, and as such is rather useless. I guess this is the position that was recorded the last time some app requested a location update.

I use the following code to get a recent location:

    Criteria criteria = new Criteria();      criteria.setAccuracy(Criteria.ACCURACY_COARSE);      criteria.setAltitudeRequired(false);      criteria.setSpeedRequired(false);      criteria.setBearingRequired(false);      criteria.setCostAllowed(false);        final LocationManager manager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);        ....      LocationListener listener = new LocationListener() {          @Override          public void onLocationChanged(Location lastKnownLocation) {                       ....          }          // rest of interface       }           manager.requestSingleUpdate(criteria, listener, null);  

The last call ensures that we request the current location, not the location it was able to find an unknown amount of time before.

You might try to change it to Criteria.ACCURACY_FINE in order to get the GPS fired up. Be aware that if the GPS didn't have a fix for quite some while it may take more than several minutes before it is actually capable of getting a fix. I'd expect in the mean time that you'd see the GPS icon indicating it is waiting for a fix.

Answer by Andrew for Fused location provider doesn't seem to use GPS receiver


Location provider won't wake up GPS until some of clients ask (subscribe) for high precision location (as described in examples given by other users). GPS test app doesn't use location provider but uses old "direct" way of obtaining location.

Also there is expiry mechanism, which removes information about last location after some time if it is believed to be stale.

Summing up all above it is really possible that LP(Location Provider) has nothing to give you.

Answer by c0m3tx for Fused location provider doesn't seem to use GPS receiver


Try this:

public final static int MINACCURACY = 50;    private LocationManager lm;  private LocationListener listener;    private void foundLoc(double x, double y) {      // do something with x,y      Log.v("DEBUG", x + "," + y);  }      public void findMe(View v) {      lm = (LocationManager) getSystemService(LOCATION_SERVICE);      listener = new LocationListener() {          @Override          public void onLocationChanged(Location location) {              if(location.getAccuracy() < MINACCURACY) {                  foundLoc(location.getLatitude(), location.getLongitude());                  lm.removeUpdates(listener);              }          }            @Override          public void onStatusChanged(String provider, int status, Bundle extras) {          }            @Override          public void onProviderEnabled(String provider) {          }            @Override          public void onProviderDisabled(String provider) {          }      };      lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 100, 0, listener);  }  

MINACCURACY is in meters. This way, on button press (which calls the findMe method), the GPS is enabled, your location is found with a minimum accuracy, the method foundLoc gets the data and the listener terminates (which, in turn, disables GPS).

Answer by Saran for Fused location provider doesn't seem to use GPS receiver


The problem is with getLastLocation() because it uses a cached location. I had the same problem as I also tried to use this simple approach. Since, I have switched to listening to updates (and stopping after 1st successfull update automatically).

This is my code that works.

First, the check for availability in Application (not essential, can be in Activity and without keeping of result):

public class MainApp extends Application {    public static enum PlayServices {      NOT_CHECKED, AVAILABLE, UNAVAILABLE    };    public static PlayServices mPlayServices = PlayServices.NOT_CHECKED;      @Override    public void onCreate() {      super.onCreate();        if (GooglePlayServicesUtil.isGooglePlayServicesAvailable(this) == ConnectionResult.SUCCESS) {        MainApp.mPlayServices = MainApp.PlayServices.AVAILABLE;      }    }  }  

Then, on to the Activity:

public class MainActivity extends SherlockFragmentActivity implements    GooglePlayServicesClient.ConnectionCallbacks,    GooglePlayServicesClient.OnConnectionFailedListener, LocationListener {  

In its onCreate():

if (MainApp.mPlayServices != MainApp.PlayServices.UNAVAILABLE) {    mLocationClient = new LocationClient(this, this, this);      mLocationRequest = LocationRequest.create();    mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);    mLocationRequest.setInterval(5000);    mLocationRequest.setNumUpdates(1);    mLocationRequest.setFastestInterval(1000);      mUpdatesRequested = false;    MainApp.prefs.edit().putBoolean(MainApp.KEY_LOCATION_UPDATES_REQUESTED, mUpdatesRequested)        .commit();  }  

The rest of the MainActivity class:

@Override  protected void onActivityResult(int requestCode, int resultCode, Intent data) {    Log.d(this.getClass().getSimpleName(), "onActivityResult(" + requestCode + ", " + resultCode        + ")");    // Decide what to do based on the original request code    switch (requestCode) {      case MainApp.PLAY_CONNECTION_FAILURE_RESOLUTION_REQUEST:        /*         * If the result code is Activity.RESULT_OK, try         * to connect again         */        switch (resultCode) {          case Activity.RESULT_OK:            // here we want to initiate location requests!            mLocationClient = new LocationClient(this, this, this);              break;        }        break;    }  }    @Override  public void onConnected(Bundle dataBundle) {    Log.d(this.getClass().getSimpleName(), "onConnected()");      Log.d(this.getClass().getSimpleName(), "Google Play Services are available.");    MainApp.mPlayServices = MainApp.PlayServices.AVAILABLE;      if (!mUpdatesRequested) {        LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);        boolean gps_enabled = false;      try {        gps_enabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);      } catch (Exception ex) {      }        boolean network_enabled = false;      try {        network_enabled = lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER);      } catch (Exception ex) {      }        // don't start listeners if no provider is enabled      MainApp.locEnabled = gps_enabled || network_enabled;        if (!MainApp.locEnabled) {        // we have access to PlayServices, but user has disabled location visibility --> alert him        alertLocationOff();      } else {        mLocationClient.requestLocationUpdates(mLocationRequest, this);        mUpdatesRequested = true;      }    }  }    @Override  public void onDisconnected() {    Log.d(this.getClass().getSimpleName(), "onDisconnected()");  }    @Override  public void onConnectionFailed(ConnectionResult connectionResult) {    Log.d(this.getClass().getSimpleName(), "onConnectionFailed()");      Log.d(this.getClass().getSimpleName(), "Google Play Services not available.");    MainApp.mPlayServices = MainApp.PlayServices.UNAVAILABLE;      /*     * Google Play services can resolve some errors it detects.     * If the error has a resolution, try sending an Intent to     * start a Google Play services activity that can resolve     * error.     */    if (connectionResult.hasResolution()) {      try {        // Start an Activity that tries to resolve the error        connectionResult.startResolutionForResult(this,            MainApp.PLAY_CONNECTION_FAILURE_RESOLUTION_REQUEST);        /*         * Thrown if Google Play services canceled the original         * PendingIntent         */      } catch (IntentSender.SendIntentException e) {        // Log the error        e.printStackTrace();      }    } else {      /*       * If no resolution is available, display a dialog to the       * user with the error.       */      GooglePlayServicesUtil.getErrorDialog(connectionResult.getErrorCode(), this, 0).show();    }  }    @SuppressLint("NewApi")  @Override  public void onLocationChanged(Location location) {    Log.d(this.getClass().getSimpleName(), "onLocationChanged(), location=" + location);      if (location != null) {      boolean present = true;      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {        present = Geocoder.isPresent();      }        if (present) {        (new ExtractLocationTask(this)).execute(location);      } else {        Log.e(this.getClass().getSimpleName(), "Geocoder not present");        MainApp.mPlayServices = MainApp.PlayServices.UNAVAILABLE;      }    }  }      private class ExtractLocationTask extends AsyncTask {    Context mContext;      public ExtractLocationTask(Context context) {      super();      mContext = context;    }      @Override    protected Boolean doInBackground(Location... params) {      Log.d(getClass().getSimpleName(), "ExtractLocationTask.onPreExecute()");        boolean found = false;      try {        Geocoder geoCoder_local = new Geocoder(mContext, Locale.getDefault());        Geocoder geoCoder_en = new Geocoder(mContext, Locale.ENGLISH);          List
addresses_local = geoCoder_local.getFromLocation(params[0].getLatitude(), params[0].getLongitude(), 10); List
addresses_en = geoCoder_en.getFromLocation(params[0].getLatitude(), params[0].getLongitude(), 10); if (addresses_local != null && addresses_local.size() > 0) { // do what you want with location info here // based on mLocationRequest.setNumUpdates(1), no need to call // removeLocationUpdates() MainApp.locEnabled = true; mUpdatesRequested = false; MainApp.prefs.edit() .putBoolean(MainApp.KEY_LOCATION_UPDATES_REQUESTED, mUpdatesRequested).commit(); found = true; } } catch (IOException e) { Log.e(this.getClass().getSimpleName(), "Exception: ", e); } return found; } @Override protected void onPostExecute(Boolean found) { Log.d(getClass().getSimpleName(), "ExtractLocationTask.onPostExecute()"); if (found) { // update UI etc. } else if (!mUpdatesReRequested) { mLocationClient.requestLocationUpdates(mLocationRequest, (LocationListener) mContext); mUpdatesRequested = true; mUpdatesReRequested = true; } } }

I hope this will help you get it to work!

Answer by Tamal for Fused location provider doesn't seem to use GPS receiver


I prefer to use Service that implements LocationListener to get current near-accurate location. I normally take following steps:

  1. Initialize LocationManager and call requestLocationUpdates for both GPS_PROVIDER and NETWORK_PROVIDER in onCreate()
  2. Call getLastKnownLocation for both GPS_PROVIDER and NETWORK_PROVIDER and use getTime() to know last newer location.
  3. Broadcast last location (if it's <30 sec old) (optional)
  4. In the meantime, when onLocationChanged is called I compare newly updated location with last best location (if any) and check accuracy level.
  5. If accuracy delta < MIN_ACCURACY (user variable), use it as best location
  6. Broadcast current best location
  7. Must remove LocationManager locationManager.removeUpdates(this);
  8. Call stopSelf(); (you can also stop service from activity's onDestroy)

EDIT:

OK...Above method was using Location API, below I have coded using Fused Provider (GooglePlayServices). I have tested on my Nexus 5 (Android 4.4.2), NO SIM, NO WIFI...and I'm getting results.

Edit 2: I have also tested on Android 2.3.3 LG Optimus (No SIM & Wifi) and it took about 5 min to get lock (using Fused Provided), but I was getting location icon instantly.

public class HomeActivity extends FragmentActivity implements          ActionBar.OnNavigationListener,          GooglePlayServicesClient.ConnectionCallbacks,          GooglePlayServicesClient.OnConnectionFailedListener, LocationListener {        private LocationClient locationClient;      private LocationRequest locationRequest;        @Override      protected void onCreate(Bundle savedInstanceState) {          super.onCreate(savedInstanceState);              setContentView(R.layout.activity_home);              // ...              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();            }      }        @Override      public void onConnected(Bundle connectionHint) {          if (locationClient != null && locationClient.isConnected()) {                locationRequest = LocationRequest.create();              locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);              locationRequest.setInterval(100);              locationClient.requestLocationUpdates(locationRequest, this);            }      }        @Override      public void onLocationChanged(Location location) {            try {              if (location != null) {                  LatLng gps = new LatLng(location.getLatitude(), location.getLongitude());                  Log.v("JD", "My Location: " + gps.toString());              }          } catch (Exception e) {              Log.d("JD",                      "onLocationChanged", e);            }             }  }  

Answer by user1639673 for Fused location provider doesn't seem to use GPS receiver


What's on the "OnConnected" method?

In this method you should create the "LocationRequest" object with "PRIORITY_HIGH_ACCURACY" priority.

@Override  public void onConnected(Bundle dataBundle) {      mLocationRequest = LocationRequest.create();      mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);      mLocationClient.requestLocationUpdates(mLocationRequest, fusedListener);  }  

Answer by Sean Barbeau for Fused location provider doesn't seem to use GPS receiver


There are two things going on here that are causing you to sometimes get null, and sometimes get a location.

First, you're creating a new instance of the LocationClient in the onClick method, which is not the same instance you're calling connect() on in onStart(). This will create unpredictable behavior where sometimes the client will have enough time to connect before returning a result from LocationClient.getLastLocation(), and sometimes it won't.

Second, you should guard the call to LocationClient.getLastLocation() with a call to LocationClient.isConnected(). It says the following in the LocationClient.isConnected() docs: https://developer.android.com/reference/com/google/android/gms/location/LocationClient.html#isConnected()

Checks if the client is currently connected to the service, so that requests to other methods will succeed. Applications should guard client actions caused by the user with a call to this method.

Since the user is triggering the onClick() code by tapping on the button, you should call this method before trying to get the last location.

So, your code should look like this:

LocationClient mLocationClient;  Location mCurrentLocation;    @Override  protected void onCreate() {      ...      mLocationClient = new LocationClient(this, this, this);      ...  }    @Override  protected void onStart() {      mLocationClient.connect();      super.onStart();  }    @Override  protected void onStop() {      mLocationClient.disconnect();      super.onStop();  }    public void onClick(View v) {      ...      if (mLocationClient.isConnected()) {          // You should get a valid location here          mCurrentLocation = mLocationClient.getLastLocation();      }  }  

This should give the LocationClient a long enough time to connect and give you a valid location, which should hopefully include GPS data.

Answer by Eric Woodruff for Fused location provider doesn't seem to use GPS receiver


Since no one has shared this link, I found this to be the most helpful documentation http://developer.android.com/guide/topics/location/strategies.html

"You might expect that the most recent location fix is the most accurate. However, because the accuracy of a location fix varies, the most recent fix is not always the best. You should include logic for choosing location fixes based on several criteria. The criteria also varies depending on the use-cases of the application and field testing."

Your best bet is to keep a location listener going as long as the activity is in the foreground and select the most accurate cached location when the button is pressed. You may need to show a spinner or something and disable the button while it waits for an accurate measurement to show up.

Answer by cja for Fused location provider doesn't seem to use GPS receiver


I solved it. The problem was that "Let Google apps access your location" was turned off: enter image description here

When I turn it on I get GPS readings and when it's off I don't.

I had left it off for two reasons:

  1. I'm developing an app to be used to lots of devices at a company and I want minimum manual configuration to be necessary

  2. The screen says clearly "This setting affects Google apps only." I know that Play Services is Google software but I didn't think Google would expect an end user to understand that.

Then I got the Android 4.4.2 update and the location settings page has changed. It appears that I can have Google Location Reporting turned off and still get GPS readings from the fused location provider: enter image description here

So maybe Google realised that the setting was confusing and improved it. Either way, I'd have saved a lot of time if I'd got 4.4.2 a few days ago.

Answer by Sujal Mandal for Fused location provider doesn't seem to use GPS receiver


All you need to do is to add a priority property to the request object like this.

public void onConnected(Bundle arg0)  {      locationrequest = LocationRequest.create();      locationrequest.setInterval(1000);      locationrequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);      locationclient.requestLocationUpdates(locationrequest, this);  }  

Maybe use a boolean variable to let the user have options to force GPS like

boolean forceGPS=false;  .  .  .//make the user choose to change the value of the boolean  .  .  public void onConnected(Bundle arg0)      {          locationrequest = LocationRequest.create();          locationrequest.setInterval(1000);          if(forceGPS==true)          {          locationrequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);          }          locationclient.requestLocationUpdates(locationrequest, this);      }  

Answer by Imran Khan Saifi for Fused location provider doesn't seem to use GPS receiver


STEPS TO GET LAST KNOWN LOCATION :--  -------------------------------------  -------------------------------------      1. First check for availability of Google Play Services :--              int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);           if (resultCode == ConnectionResult.SUCCESS)               return true          2. Creating google api client object:-             GoogleApiClient mGoogleApiClient = new GoogleApiClient.Builder(this)              .addConnectionCallbacks(this)              .addOnConnectionFailedListener(this)              .addApi(LocationServices.API).build();        3.  After creating connect, OnConnected Method of ConnectionCallbacks Interface called where we get location As :--            Location mLastLocation = LocationServices.FusedLocationApi.getLastLocation( mGoogleApiClient );  


Fatal error: Call to a member function getElementsByTagName() on a non-object in D:\XAMPP INSTALLASTION\xampp\htdocs\endunpratama9i\www-stackoverflow-info-proses.php on line 72

0 comments:

Post a Comment

Popular Posts

Powered by Blogger.