I'm trying to get the current location using this code and it works when launching the app and when bringing it to the foreground. The toasts show up in both cases, but otherwise they don't. Can anybody tell me where I messed up?
public class LocationFragment extends Fragment implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener, LocationListener {
double oldLon,oldLat;
private static final String TAG = MainActivity.class.getSimpleName(); // LogCat tag
private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 1000;
private static final int MY_PERMISSIONS_REQUEST_FINE_LOCATION = 100;
private Location mLastLocation;
private GoogleApiClient mGoogleApiClient;
private FusedLocationProviderClient mFusedLocationClient;
private LocationRequest mLocationRequest;
// Location updates intervals in sec
private static int UPDATE_INTERVAL = 10000; // 10 sec
private static int FATEST_INTERVAL = 5000; // 5 sec
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
// First we need to check availability of play services
if (checkPlayServices()) {
buildGoogleApiClient();
createLocationRequest();
}
}
#Override
public void onDetach() {
mCallback = null; // => avoid leaking
super.onDetach();
}
public interface InterfaceTextClicked {
public void sendText(String text);
}
private boolean checkPermission(){
if(ActivityCompat.checkSelfPermission(getContext(),
ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED){
System.out.println("We have been granted.");
return true;}
else return false;
}
private void requestPermission(){
ActivityCompat.requestPermissions(getActivity(),new String[]
{ACCESS_FINE_LOCATION},MY_PERMISSIONS_REQUEST_FINE_LOCATION);
}
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_FINE_LOCATION: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted, yay!
System.out.println("Permission Granted!");
} else {
// permission denied, boo!
System.out.println("Permission Denied!");
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
if(shouldShowRequestPermissionRationale(ACCESS_FINE_LOCATION)){
new AlertDialog.Builder(getActivity())
.setMessage("Permission needed to access your location.")
.setPositiveButton("OK", new DialogInterface.OnClickListener(){
#Override
public void onClick(DialogInterface dialog,int which){
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
requestPermissions(new String[]{ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_FINE_LOCATION);
}
}
})
.setNegativeButton("Cancel", null)
.create()
.show();
return;
}
}
}
// return;
}
}
}
private void displayLocation(){
System.out.println("Inside displayLocation");
requestPermission();
if(checkPermission()){
mLastLocation = LocationServices.FusedLocationApi
.getLastLocation(mGoogleApiClient);
}
if (mLastLocation != null) {
double latitude = mLastLocation.getLatitude();
double longitude = mLastLocation.getLongitude();
System.out.println("Location1: "+latitude+" "+longitude);
if(Double.compare(oldLat,latitude)==0 || Double.compare(oldLon,longitude)==0){
Toast.makeText(getContext(), "Location didn't change! "+latitude+ " "+ longitude,
Toast.LENGTH_LONG).show();
}else{
Toast.makeText(getContext(), "Location changed! NEW: "+latitude+ " "+ longitude+" OLD: "+oldLat+ " "+oldLon,
Toast.LENGTH_LONG).show();
}
// mCallback.sendText(latitude+" "+longitude);
oldLon = longitude;
oldLat = latitude;
} else {
System.out.println("Couldn't get coordinates");
if(mGoogleApiClient.isConnected()){
System.out.println("Client connected");
}else{
System.out.println("Client NOT connected");
}
}
}
/**
* Creating google api client object
* */
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(getContext())
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API).build();
}
/**
* Method to verify google play services on the device
* */
private boolean checkPlayServices() {
GoogleApiAvailability googleAPI = GoogleApiAvailability.getInstance();
int resultCode = googleAPI.isGooglePlayServicesAvailable(getContext());
if (resultCode != ConnectionResult.SUCCESS) {
if(googleAPI.isUserResolvableError(resultCode)){
googleAPI.getErrorDialog(getActivity(),resultCode,
PLAY_SERVICES_RESOLUTION_REQUEST).show();
} else {
Toast.makeText(getContext(),
"This device is not supported.", Toast.LENGTH_LONG)
.show();
getActivity().finish();
}
return false;
}
return true;
}
#Override
public void onStart() {
super.onStart();
if (mGoogleApiClient != null) {
mGoogleApiClient.connect();
}
}
#Override
public void onResume() {
super.onResume();
if (mGoogleApiClient != null && !mGoogleApiClient.isConnected()) {
mGoogleApiClient.connect();
}
checkPlayServices();
}
#Override
public void onStop() {
super.onStop();
if (mGoogleApiClient.isConnected()) {
mGoogleApiClient.disconnect();
}
}
/**
* Creating location request object
* */
protected void createLocationRequest() {
mLocationRequest = LocationRequest.create();
mLocationRequest.setInterval(UPDATE_INTERVAL);
mLocationRequest.setFastestInterval(FATEST_INTERVAL);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); }
/**
* Starting the location updates
* */
protected void startLocationUpdates() {
System.out.println("Inside startLocationUpdates");
requestPermission();
if(checkPermission()){
if ((mGoogleApiClient != null) && (mGoogleApiClient.isConnected())){
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
}
}
}
/**
* Google api callback methods
*/
#Override
public void onConnectionFailed(ConnectionResult result) {
Log.i(TAG, "Connection failed: ConnectionResult.getErrorCode() = "
+ result.getErrorCode());
}
#Override
public void onConnected(Bundle arg0){
startLocationUpdates();
// Once connected with google api, get the location
displayLocation();
}
#Override
public void onConnectionSuspended(int arg0) {
mGoogleApiClient.connect();
}
#Override
public void onPause() {
super.onPause();
stopLocationUpdates();
}
/**
* Stopping location updates
*/
protected void stopLocationUpdates() {
if ((mGoogleApiClient != null) && (mGoogleApiClient.isConnected())) {
LocationServices.FusedLocationApi.removeLocationUpdates(
mGoogleApiClient, this);
}
}
#Override
public void onLocationChanged(Location location) {
// Assign the new location
mLastLocation = location;
Toast.makeText(getContext(), "******Location changed!",
Toast.LENGTH_SHORT).show();
// Displaying the new location on UI
displayLocation();
}
}
Sorry to put so much code up there, I thought my mistake could be anywhere so didn't want to cut out anything.
The Log shows the following:
10-14 01:10:27.408 14485-14485/com.android.wy.parkingauthoritytickingsystem I/System.out: Inside startLocationUpdates
10-14 01:10:27.536 14485-14485/com.android.wy.parkingauthoritytickingsystem I/System.out: We have been granted.
10-14 01:10:27.610 14485-14485/com.android.wy.parkingauthoritytickingsystem I/System.out: Inside displayLocation
10-14 01:10:27.617 14485-14485/com.android.wy.parkingauthoritytickingsystem I/System.out: We have been granted.
10-14 01:10:27.641 14485-14485/com.android.wy.parkingauthoritytickingsystem I/System.out: Location1: 40.4868602 -74.4388156
I don't see anything obviously wrong with your code, though it is making its API calls through the deprecated versions of the location APIs rather than the new FusedLocationProviderClient interface.
While you declare a new-style FusedLocationProviderClient:
private FusedLocationProviderClient mFusedLocationClient;
you never initialize it or use it at runtime; rather you call through FusedLocationApi (the old method):
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
You might try using the new API, which has a slightly more robust interface, to shed some light on your problem. You can get the new API interface with:
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
Then you'll just need to tweak your class to add an onLocationAvailability callback as per the documentation before attaching your listener:
mFusedLocationClient.requestLocationUpdates(mLocationRequest,
mLocationCallback,
null /* Looper */);
Related
I write a simple code to show and update the latitude and longitude through GPS. The problem is they remain unchanged when I change the location of AVD.
public class PocketSphinxActivity extends Activity implements
RecognitionListener {
boolean updateOn = false;
private static final int PERMISSIONS_FINE_LOCATION = 99;
TextView tv_lat, tv_lon, tv_add, tv_sen, tv_ud;
#SuppressLint("UseSwitchCompatOrMaterialCode")
Switch sw_locationupdates, sw_GPS;
LocationRequest locationRequest;
LocationCallback locationCallback;
FusedLocationProviderClient fusedLocationProviderClient;
/* Named searches allow to quickly reconfigure the decoder */
private static final String KWS_SEARCH = "wakeup";
private static final String STORE_SEARCH = "store";
private static final String LIBRARY_SEARCH = "library";
private static final String MUSEUM_SEARCH = "museum";
private static final String MENU_SEARCH = "menu";
/* Keyword we are looking for to activate menu */
private static final String KEYPHRASE = "guide me";
/* Used to handle permission request */
private static final int PERMISSIONS_REQUEST_RECORD_AUDIO = 1;
private SpeechRecognizer recognizer;
private TextToSpeech tts;
private HashMap<String, Integer> captions;
#SuppressLint("SetTextI18n")
#Override
public void onCreate(Bundle state) {
super.onCreate(state);
setContentView(R.layout.main);
// Prepare the data for UI
tv_lat = findViewById(R.id.tv_lat);
tv_lon = findViewById(R.id.tv_lon);
tv_add = findViewById(R.id.tv_add);
sw_locationupdates = findViewById(R.id.sw_locationupdates);
tv_sen = findViewById(R.id.tv_sen);
sw_GPS = findViewById(R.id.sw_GPS);
tv_ud = findViewById(R.id.tv_ud);
captions = new HashMap<>();
captions.put(KWS_SEARCH, R.string.kws_caption);
captions.put(MENU_SEARCH, R.string.menu_caption);
captions.put(LIBRARY_SEARCH, R.string.digits_caption);
captions.put(MUSEUM_SEARCH, R.string.phone_caption);
captions.put(STORE_SEARCH, R.string.forecast_caption);
((TextView) findViewById(R.id.caption_text))
.setText("Preparing the recognizer");
// set properties of LocationRequest
locationRequest = LocationRequest.create();
locationRequest.setInterval(1000 * 5);
locationRequest.setFastestInterval(1000 * 1);
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
// triggered whenever update interval is met
locationCallback = new LocationCallback() {
#Override
public void onLocationResult(#NonNull LocationResult locationResult) {
super.onLocationResult(locationResult);
Location location = locationResult.getLastLocation();
updateUI(location);
}
};
sw_GPS.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (sw_GPS.isChecked()) {
locationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
tv_sen.setText("Using Tower + Wifi");
} else {
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
tv_sen.setText("Using GPS");
}
}
});
//StartLocUpdates();
sw_locationupdates.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (sw_locationupdates.isChecked()) {
//start tracking
StartLocUpdates();
} else {
//stop tracking
StopLocUpdates();
}
}
});
// Check if user has given permission to record audio
int permissionCheck = ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.RECORD_AUDIO);
if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.RECORD_AUDIO}, PERMISSIONS_REQUEST_RECORD_AUDIO);
return;
}
// Recognizer initialization is a time-consuming and it involves IO,
// so we execute it in async task
new SetupTask(this).execute();
updateGPS();
}
private void StopLocUpdates() {
tv_lat.setText("Not tracking location");
tv_lon.setText("Not tracking location");
tv_add.setText("Not tracking location");
tv_ud.setText("Location stop tracking");
fusedLocationProviderClient.removeLocationUpdates(locationCallback);
}
private void StartLocUpdates() {
//tv_ud.setText("stop ");
tv_ud.setText("Location is being tracked");
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
fusedLocationProviderClient.requestLocationUpdates(locationRequest,locationCallback,null);
updateGPS();
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
//PERMISSIONS_REQUEST_RECORD_AUDIO
if (requestCode == PERMISSIONS_FINE_LOCATION || requestCode == PERMISSIONS_REQUEST_RECORD_AUDIO) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// Recognizer initialization is a time-consuming and it involves IO,
// so we execute it in async task
updateGPS();
new SetupTask(this).execute();
} else {
Toast.makeText(this, "This app permission to be granted in order to work properly", Toast.LENGTH_SHORT).show();
finish();
}
}
}
private void updateGPS() {
//get permission
//get current location
//update UI
fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(PocketSphinxActivity.this);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
fusedLocationProviderClient.getLastLocation().addOnSuccessListener(this, new OnSuccessListener<Location>() {
#Override
public void onSuccess(Location location) {
//put values into UI
updateUI(location);
}
});
} else {
//
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, PERMISSIONS_FINE_LOCATION);
}
}
}
private void updateUI(Location location) {
tv_lat.setText(String.valueOf(location.getLatitude()));
tv_lon.setText(String.valueOf(location.getLongitude()));
Geocoder geocoder = new Geocoder(PocketSphinxActivity.this);
try{
List<Address>addresses=geocoder.getFromLocation(location.getLatitude(),location.getLongitude(),1);
tv_add.setText(addresses.get(0).getAddressLine(0));
}
catch(Exception e){
tv_add.setText("Unable to get address");
}
}
}
It seems that the location generated by fusedLocationProviderClient.getLastLocation() in method updateGPS() never changed. I wonder why.
private void updateGPS() {
//get permission
//get current location
//update UI
fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(PocketSphinxActivity.this);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
fusedLocationProviderClient.getLastLocation().addOnSuccessListener(this, new OnSuccessListener<Location>() {
#Override
public void onSuccess(Location location) {
//put values into UI
updateUI(location);
}
});
} else {
//
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, PERMISSIONS_FINE_LOCATION);
}
}
I think my app enters loop because once it starts in device, it doesn't respond to any commands including lisener the button. I believe that the problem is the methods for permits in RunTime. I'm sorry for my English.
My code is:
public class MainActivity extends AppCompatActivity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
private static final int REQUEST_RESOLVE_ERROR = 3;
private GoogleApiClient mGoogleApiClient;
private volatile Location mCurrentLocation;
private static final int REQUEST_PERMISSION_LOCATE = 2;
private static final int LOCATION_DURATE_TIME = 5000;
private boolean mResolvingError = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
Toast.makeText(MainActivity.this, "ciao", Toast.LENGTH_LONG).show();
}
});
}
#Override
protected void onStart() {
super.onStart();
mGoogleApiClient.connect();
Toast.makeText(MainActivity.this, "connesso", Toast.LENGTH_LONG).show();
}
#Override
protected void onStop() {
super.onStop();
mGoogleApiClient.disconnect();
}
#Override
public void onConnected(#Nullable Bundle bundle) {
manageLocationPermission();
}
#Override
public void onConnectionSuspended(int i) {
}
//gestione dell'errore
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult)
{
if (mResolvingError) {
// If we're already managing an error we skip the invocation of this method
return;
} else if (connectionResult.hasResolution()) {
// Here we check if the ConnectionResult has already the solution. If it has
// we start the resolution process
try {
// Starting resolution
mResolvingError = true;
// We launch the Intent using a request id
connectionResult.startResolutionForResult(MainActivity.this, REQUEST_RESOLVE_ERROR);
} catch (IntentSender.SendIntentException e) {
// If we have an error during resolution we can start again.
mGoogleApiClient.connect();
}
} else {
// The ConnectionResult in the worse case has the error code we have to manage
// into a Dialog
// Starting resolution
mResolvingError = true;
}
}
//location update
private void updateLocation()
{
LocationRequest locationRequest = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setNumUpdates(1)
.setExpirationDuration(LOCATION_DURATE_TIME);
LocationServices.FusedLocationApi
.requestLocationUpdates(mGoogleApiClient, locationRequest, new LocationListener() {
#Override
public void onLocationChanged(Location location)
{
mCurrentLocation = location;
}
});
}
private void startLocationListener()
{
updateLocation();
}
//permessi in RunTime
private void manageLocationPermission()
{
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED)
{
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION))
{
new AlertDialog.Builder(this)
.setTitle("Permesso di geolocalizzazione")
.setMessage("Devi dare il permesso alla geolocalizzazione")
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_PERMISSION_LOCATE);
}
})
.create()
.show();
}
else {
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_PERMISSION_LOCATE);
}
}else
{
mCurrentLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
manageLocationPermission();
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults)
{
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(requestCode == REQUEST_PERMISSION_LOCATE)
{
if (grantResults[0] == PackageManager.PERMISSION_GRANTED)
{
//se mi hanno accettato i permessi
startLocationListener();
}
else{
new AlertDialog.Builder(this)
.setTitle("Permesso di geolocalizzazione")
.setMessage("Devi dare il permesso alla geolocalizzazione")
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
})
.create()
.show();
}
}
}
}
If manageLocationPermission() is called with the permissions already granted, your code enters the following else clause
} else {
mCurrentLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
manageLocationPermission();
}
Here you're calling the same function again, and since the permissions are granted, you will enter the same else clause, and again the same thing... You see where this is going? Just remove manageLocationPermission() from this else clause
I've implemented the fused location api in my code. I can clearly see the changes of latitude and longitude for every required (Priority High accuracy,Interval- 1sec,fastest interval -1s) seconds in my logs. But the getSpeed() is always returning 0.0 in motoG (marshmallow). But the similar code works fine in Lenovo(marhsmallow).
While exploring this issue, articles stated difficulties in locking agps in motoG.But in my case lat and long update is fine which means locking is considerably good. :(
Tried different settings, nothing works. I need solution regarding this issue from someone who had overcome this. Thanks in advance.
public class MainActivity extends AppCompatActivity implements
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,
ActivityCompat.OnRequestPermissionsResultCallback,
LocationListener {
private static final String TAG = "MainActivity";
private static final int REQUEST_LOCATION_PERMISSION = 1;
private boolean mPermissionApproved;
private GoogleApiClient mGoogleApiClient;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mPermissionApproved = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED;
if (!mPermissionApproved) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_LOCATION_PERMISSION);
}
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
}
#Override
protected void onPause() {
super.onPause();
if ((mGoogleApiClient != null) && (mGoogleApiClient.isConnected()) &&
(mGoogleApiClient.isConnecting())) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
mGoogleApiClient.disconnect();
}
}
#Override
protected void onResume() {
super.onResume();
if (mGoogleApiClient != null) {
mGoogleApiClient.connect();
}
}
#Override
public void onConnected(Bundle bundle) {
requestLocation();
}
private void requestLocation() {
if (mPermissionApproved) {
LocationRequest locationRequest = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setInterval(0)
.setFastestInterval(0);
LocationServices.FusedLocationApi
.requestLocationUpdates(mGoogleApiClient, locationRequest, this)
.setResultCallback(new ResultCallback<Status>() {
#Override
public void onResult(Status status) {
if (status.getStatus().isSuccess()) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "Successfully requested location updates");
}
} else {
Log.e(TAG,
"Failed in requesting location updates, "
+ "status code: "
+ status.getStatusCode() + ", message: " + status
.getStatusMessage());
}
}
});
}
}
#Override
public void onConnectionSuspended(int i) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
}
#Override
public void onLocationChanged(Location location) {
Toast.makeText(this,"latitude::" + location.getLatitude()+" longitude::"+ location.getLongitude()+ " Speed::" + location.getSpeed(), Toast.LENGTH_SHORT).show();
}
#Override
public void onRequestPermissionsResult( int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
if (requestCode == REQUEST_LOCATION_PERMISSION) {
if ((grantResults.length == 1)
&& (grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
mPermissionApproved = true;
if(mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
requestLocation();
}
} else {
mPermissionApproved = false;
}
}
}
}
I am working on a new open source library, called Galileo, that helps developers using location api from Google in a single line.
However, when I resume my app, in OnConnected I get the exception that the client is not yet connected. The problem is, that using their methods, everything works fine, but I can't get to work my implementation. Here is what I got so far:
Galileo.java:
public class Galileo {
static volatile Galileo singleton;
private GoogleApiClient mGoogleApiClient;
private LocationManager locationManager;
private LocationListener locationListener;
Galileo (GoogleApiClient mGoogleApiClient, LocationListener locationListener){
this.mGoogleApiClient = mGoogleApiClient;
this.locationListener = locationListener;
}
public static Galileo with(#NonNull GoogleApiClient mGoogleApiClient, #NonNull LocationListener locationListener ) {
if (mGoogleApiClient == null || locationListener==null) {
throw new IllegalArgumentException("context == null");
}
if (singleton == null) {
synchronized (Galileo.class) {
if (singleton == null) {
singleton = new Builder(mGoogleApiClient, locationListener).build();
}
}
}
return singleton;
}
public LocationRequest load(){
return new LocationRequest(this);
}
LocationListener getLocationListener(){
return this.locationListener;
}
GoogleApiClient getmGoogleApiClient(){
return this.mGoogleApiClient;
}
public static class Builder {
private final GoogleApiClient mGoogleApiClient;
private final LocationListener locationListener;
public Builder(#NonNull GoogleApiClient mGoogleApiClient, #NonNull LocationListener locationListener) {
if (mGoogleApiClient == null || locationListener == null) {
throw new IllegalArgumentException("Context must not be null.");
}
this.mGoogleApiClient = mGoogleApiClient;
this.locationListener = locationListener;
}
/**
* Toggle whether debug logging is enabled.
* <p>
* <b>WARNING:</b> Enabling this will result in excessive object allocation. This should be only
* be used for debugging purposes. Do NOT pass {#code BuildConfig.DEBUG}.
*/
public Galileo build() {
GoogleApiClient mGoogleApiClient = this.mGoogleApiClient;
LocationListener locationListener = this.locationListener;
return new Galileo(mGoogleApiClient, locationListener);
}
}
}
LocationRequest.java:
public class LocationRequest {
private LocationListener locationListener;
private GoogleApiClient mGoogleApiClient;
private float mDistance;
private int mTime;
private int priority;
private boolean askForGPS;
private com.google.android.gms.location.LocationRequest mLocationRequest;
LocationRequest(Galileo galileo) {
this.mGoogleApiClient = galileo.getmGoogleApiClient();
this.locationListener = galileo.getLocationListener();
this.mTime = 10000;
this.priority = com.google.android.gms.location.LocationRequest.PRIORITY_HIGH_ACCURACY;
this.askForGPS = false;
}
public LocationRequest time(int mTime){
this.mTime = mTime;
return this;
}
public LocationRequest distance(float mDistance){
this.mDistance = mDistance;
return this;
}
public void go(){
createLocationRequest();
startLocationUpdates();
}
public void stop(){
stopLocationUpdates();
}
protected void stopLocationUpdates() {
// It is a good practice to remove location requests when the activity is in a paused or
// stopped state. Doing so helps battery performance and is especially
// recommended in applications that request frequent location updates.
// The final argument to {#code requestLocationUpdates()} is a LocationListener
// (http://developer.android.com/reference/com/google/android/gms/location/LocationListener.html).
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, locationListener);
}
protected void startLocationUpdates() {
// The final argument to {#code requestLocationUpdates()} is a LocationListener
// (http://developer.android.com/reference/com/google/android/gms/location/LocationListener.html).
System.out.print(mGoogleApiClient.isConnected());
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest , locationListener);
}
protected void createLocationRequest() {
mLocationRequest = new com.google.android.gms.location.LocationRequest();
// Sets the desired interval for active location updates. This interval is
// inexact. You may not receive updates at all if no location sources are available, or
// you may receive them slower than requested. You may also receive updates faster than
// requested if other applications are requesting location at a faster interval.
mLocationRequest.setInterval(mTime);
// Sets the fastest rate for active location updates. This interval is exact, and your
// application will never receive updates faster than this value.
mLocationRequest.setFastestInterval(mTime/2);
mLocationRequest.setPriority(priority);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
builder.addLocationRequest(mLocationRequest);
builder.setAlwaysShow(true);
PendingResult<LocationSettingsResult> result =
LocationServices.SettingsApi.checkLocationSettings(mGoogleApiClient, builder.build());
result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
#Override
public void onResult(#NonNull LocationSettingsResult result) {
final Status status = result.getStatus();
final LocationSettingsStates state = result.getLocationSettingsStates();
switch (status.getStatusCode()) {
case LocationSettingsStatusCodes.SUCCESS:
// All location settings are satisfied. The client can initialize location
// requests here.
break;
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
// Location settings are not satisfied. But could be fixed by showing the user
// a dialog.
/*try {
// Show the dialog by calling startResolutionForResult(),
// and check the result in onActivityResult().
//status.startResolutionForResult(MapsActivity.this, 1000);
} catch (IntentSender.SendIntentException e) {
// Ignore the error.
}*/
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
// Location settings are not satisfied. However, we have no way to fix the
// settings so we won't show the dialog.
break;
}
}
});
}
}
and MapsActivity.java:
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 stopLocationUpdates() {
// It is a good practice to remove location requests when the activity is in a paused or
// stopped state. Doing so helps battery performance and is especially
// recommended in applications that request frequent location updates.
// The final argument to {#code requestLocationUpdates()} is a LocationListener
// (http://developer.android.com/reference/com/google/android/gms/location/LocationListener.html).
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}
protected void startLocationUpdates() {
// The final argument to {#code requestLocationUpdates()} is a LocationListener
// (http://developer.android.com/reference/com/google/android/gms/location/LocationListener.html).
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
}
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
// Sets the desired interval for active location updates. This interval is
// inexact. You may not receive updates at all if no location sources are available, or
// you may receive them slower than requested. You may also receive updates faster than
// requested if other applications are requesting location at a faster interval.
mLocationRequest.setInterval(10000);
// Sets the fastest rate for active location updates. This interval is exact, and your
// application will never receive updates faster than this value.
mLocationRequest.setFastestInterval(5000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
builder.addLocationRequest(mLocationRequest);
builder.setAlwaysShow(true);
PendingResult<LocationSettingsResult> result =
LocationServices.SettingsApi.checkLocationSettings(mGoogleApiClient, builder.build());
result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
#Override
public void onResult(#NonNull LocationSettingsResult result) {
final Status status = result.getStatus();
final LocationSettingsStates state = result.getLocationSettingsStates();
switch (status.getStatusCode()) {
case LocationSettingsStatusCodes.SUCCESS:
// All location settings are satisfied. The client can initialize location
// requests here.
break;
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
// Location settings are not satisfied. But could be fixed by showing the user
// a dialog.
try {
// Show the dialog by calling startResolutionForResult(),
// and check the result in onActivityResult().
status.startResolutionForResult(
MapsActivity.this, 1000);
} catch (IntentSender.SendIntentException e) {
// Ignore the error.
}
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
// Location settings are not satisfied. However, we have no way to fix the
// settings so we won't show the dialog.
break;
}
}
});
}
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(48.162253, 17.0463122), 15));
MarkerOptions marker = new MarkerOptions().position(new LatLng(48.162253, 17.0463122)).title("Hello Maps ");
mMap.addMarker(marker);
mMap.setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() {
#Override
public boolean onMarkerClick(Marker marker) {
behavior.setState(BottomSheetBehaviorGoogleMapsLike.STATE_COLLAPSED);
String imageURL = "https://maps.googleapis.com/maps/api/streetview?size=400x400&location="+String.valueOf(marker.getPosition().latitude)+","+String.valueOf(marker.getPosition().longitude);
Picasso.with(MapsActivity.this).load(imageURL).into(imageView);
bottomSheetTextView.setText(marker.getTitle());
currentMarker = marker;
Geocoder geocoder;
List<Address> addresses;
String address;
geocoder = new Geocoder(MapsActivity.this, Locale.getDefault());
try {
addresses = geocoder.getFromLocation(marker.getPosition().latitude, marker.getPosition().longitude, 1); // Here 1 represent max location result to returned, by documents it recommended 1 to 5
address = addresses.get(0).getAddressLine(0);
} catch (IOException e) {
address = "";
e.printStackTrace();
}
addressView.setText(address);
return false;
}
});
mMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
#Override
public void onMapClick(LatLng latLng) {
if (behavior.getState() == BottomSheetBehaviorGoogleMapsLike.STATE_COLLAPSED) {
behavior.setState(BottomSheetBehaviorGoogleMapsLike.STATE_HIDDEN);
}
currentMarker = null;
}
});
mMap.setOnMapLongClickListener(new GoogleMap.OnMapLongClickListener() {
#Override
public void onMapLongClick(LatLng latLng) {
MarkerOptions marker = new MarkerOptions().position(latLng).title("Hello Maps ");
mMap.addMarker(marker);
}
});
}
#Override
protected void onStart() {
super.onStart();
String[] LOCATION_PERMISSIONS = {Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION};
Permission.PermissionBuilder permissionBuilder =
new Permission.PermissionBuilder(LOCATION_PERMISSIONS, 1000, new Permission.PermissionCallback() {
#Override
public void onPermissionGranted(int i) {
buildGoogleApiClient();
mGoogleApiClient.connect();
}
#Override
public void onPermissionDenied(int i) {
}
#Override
public void onPermissionAccessRemoved(int i) {
}
});
requestAppPermissions(permissionBuilder.build());
}
#Override
public void onResume() {
super.onResume();
// Within {#code onPause()}, we pause location updates, but leave the
// connection to GoogleApiClient intact. Here, we resume receiving
// location updates if the user has requested them.
if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
Galileo.with(mGoogleApiClient,this).load().go();
}
}
#Override
protected void onPause() {
super.onPause();
// Stop location updates to save battery, but don't disconnect the GoogleApiClient object.
if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
Galileo.with(mGoogleApiClient,this).load().stop();
}
}
#Override
protected void onStop() {
if (mGoogleApiClient != null) {
mGoogleApiClient.disconnect();
}
super.onStop();
}
#Override
public void onConnected(#Nullable Bundle bundle) {
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if(mLastLocation!=null){
Log.d("Lat, lon", String.valueOf(mLastLocation.getLatitude()) + " ," + String.valueOf(mLastLocation.getLongitude()));
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(mLastLocation.getLatitude(), mLastLocation.getLongitude()), 15));
}
//Log.d(TAG, String.valueOf(mGoogleApiClient.isConnected()));
if(mGoogleApiClient.isConnected()){
Galileo.with(mGoogleApiClient,this).load().go();}
}
#Override
public void onConnectionSuspended(int i) {
Log.i(TAG, "Connection suspended");
mGoogleApiClient.connect();
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
Log.i(TAG, "Connection failed: ConnectionResult.getErrorCode() = " + connectionResult.getErrorCode());
}
#Override
public void onLocationChanged(Location location) {
if(mLastLocation==null){
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(location.getLatitude(), location.getLongitude()), 15));
}
mLastLocation = location;
Log.d("Lat, lon", String.valueOf(mLastLocation.getLatitude()) + " ," + String.valueOf(mLastLocation.getLongitude()));
//mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(mLastLocation.getLatitude(), mLastLocation.getLongitude()), 15));
}
For countless hours, I have been trying to get the user's current location upon launching my app, but then every approach I have tried has returned null.
My instantiation of the GoogleApiClient takes place in "onCreate"
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EventBus.getDefault().register(this);
FirebaseMessagingHelper.registerDevice(this, FirebaseInstanceId.getInstance().getToken());
activity = this;
//xaxaxa
driverMapView = (MapView) findViewById(R.id.googleMapObject);
driverMapView.onCreate(savedInstanceState);
driverMapView.getMapAsync(this);
getUserToEnableCameraUsage();
if (googleApiClient == null)
{
googleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
googleApiClient.connect();
Here is the code in my project (extremely similar to the code provided in the api's tutorial:
#Override
public void onConnected(#Nullable Bundle bundle)
{
int LOCATION_ALLOWED = ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.ACCESS_COARSE_LOCATION);
if (LOCATION_ALLOWED != PackageManager.PERMISSION_GRANTED)
{
lastLocation = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
if (lastLocation != null)
{
driverGoogleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(lastLocation.getLatitude(), lastLocation.getLongitude()), 16));
testHelper.setDriverLatLngLocation(new LatLng(lastLocation.getLatitude(), lastLocation.getLongitude()));
}
}
}
protected void createLocationRequest()
{
locationRequest = new LocationRequest();
locationRequest.setInterval(1000);
locationRequest.setFastestInterval(500);
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
LocationSettingsRequest.Builder locationSettingsRequestBuilder = new LocationSettingsRequest.Builder()
.addLocationRequest(locationRequest);
PendingResult<LocationSettingsResult> pendingResult = LocationServices
.SettingsApi
.checkLocationSettings(googleApiClient, locationSettingsRequestBuilder.build());
pendingResult.setResultCallback(new ResultCallback<LocationSettingsResult>() {
#Override
public void onResult(#NonNull LocationSettingsResult locationSettingsResult)
{
Status result = locationSettingsResult.getStatus();
if (result.getStatusCode() == LocationSettingsStatusCodes.SUCCESS)
{
requestingLocationUpdates = true;
startLocationUpdates();
Toast.makeText(MainActivity.this, "Gucci", Toast.LENGTH_SHORT).show();
}
if (result.getStatusCode() == LocationSettingsStatusCodes.RESOLUTION_REQUIRED)
{
requestingLocationUpdates = false;
Toast.makeText(MainActivity.this, "Please enable location services", Toast.LENGTH_SHORT).show();
}
if (result.getStatusCode() == LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE)
{
requestingLocationUpdates = false;
Toast.makeText(MainActivity.this, "App cannot access settings", Toast.LENGTH_SHORT).show();
}
}
});
}
protected void startLocationUpdates()
{
int LOCATION_ALLOWED = ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.ACCESS_COARSE_LOCATION);
if (LOCATION_ALLOWED != PackageManager.PERMISSION_GRANTED)
{
LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, locationRequest, this);
}
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult)
{
}
#Override
public void onLocationChanged(Location location)
{
driverGoogleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(location.getLatitude(), location.getLongitude()), 16));
testHelper.setDriverLatLngLocation(new LatLng(location.getLatitude(), location.getLongitude()));
Toast.makeText(MainActivity.this, "It's working", Toast.LENGTH_SHORT).show();
}
protected void stopLocationUpdates()
{
LocationServices.FusedLocationApi.removeLocationUpdates(
googleApiClient, this);
requestingLocationUpdates = false;
}
I instantiate "createLocationRequest here:
public void onMapReady(GoogleMap googleMap)
{
//Setting map starts here
int LOCATION_ALLOWED = ContextCompat.checkSelfPermission(this.getApplicationContext(), Manifest.permission.ACCESS_COARSE_LOCATION);
if (LOCATION_ALLOWED == PackageManager.PERMISSION_GRANTED)
{
googleMap.setMyLocationEnabled(true);
}
createLocationRequest();
The instantiation of "createLocationRequest()" takes place before the block of code that needs it and it is null?
I have looked over multiple solutions, but they've all not helped me. I was hoping that maybe someone could help me out as this has been really bothering me and has halted the development of my app.