Android LocationServices.FusedLocationApi obsoleto

No pude entender por qué LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient,mLocationRequest, this); “FusedLocationApi” está tachado e indica que está en desuso. Haga clic aquí para ver la imagen

 import android.location.Location; import android.location.LocationListener; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.app.FragmentActivity; import android.os.Bundle; import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.api.GoogleApiClient; import com.google.android.gms.location.LocationRequest; import com.google.android.gms.location.LocationServices; import com.google.android.gms.maps.CameraUpdateFactory; import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.OnMapReadyCallback; import com.google.android.gms.maps.SupportMapFragment; import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.MarkerOptions; public class MaintainerMapActivity extends FragmentActivity implements OnMapReadyCallback, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener{ private GoogleMap mMap; GoogleApiClient mGoogleApiClient; Location mLastLocaton; LocationRequest mLocationRequest; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_maintainer_map2); // Obtain the SupportMapFragment and get notified when the map is ready to be used. SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager() .findFragmentById(R.id.map); mapFragment.getMapAsync(this); } @Override public void onMapReady(GoogleMap googleMap) { mMap = googleMap; // Add a marker in Sydney and move the camera LatLng sydney = new LatLng(-34, 151); mMap.addMarker(new MarkerOptions().position(sydney).title("Marker in Sydney")); mMap.moveCamera(CameraUpdateFactory.newLatLng(sydney)); } @Override public void onLocationChanged(Location location) { } @Override public void onStatusChanged(String provider, int status, Bundle extras) { } @Override public void onProviderEnabled(String provider) { } @Override public void onProviderDisabled(String provider) { } @Override public void onConnected(@Nullable Bundle bundle) { mLocationRequest = new LocationRequest(); mLocationRequest.setInterval(1000); mLocationRequest.setFastestInterval(1000); mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient,mLocationRequest, this); } @Override public void onConnectionSuspended(int i) { } @Override public void onConnectionFailed(@NonNull ConnectionResult connectionResult) { } 

}

Última actualización (21 de noviembre de 2017):

La advertencia ya no está. Servicios de Google Play 11.6 6 de noviembre de 2017, nota de la versión que dice: Se solucionó el problema de FusedLocationProviderClient que ocasionalmente causaba bloqueos cuando se actualizaban los servicios de Google Play. Creo que Play Services no se bloqueará cuando se actualice en segundo plano. Entonces podemos usar el nuevo FusedLocationProviderClient ahora.


Actualización importante (24 de octubre de 2017):

Ayer Google actualizó su página oficial de desarrollador con una advertencia que dice

Continúe utilizando la clase FusedLocationProviderApi y no migre a la clase FusedLocationProviderClient hasta que esté disponible la versión 12.0.0 de los servicios de Google Play, que se espera que se envíe a principios de 2018. El uso de FusedLocationProviderClient antes de la versión 12.0.0 hace que la aplicación cliente se cuelgue cuando Los servicios de Google Play se actualizan en el dispositivo. Nos disculpamos por cualquier inconveniente que esto pueda haber causado.

enter image description here Por lo tanto, creo que deberíamos continuar usando los LocationServices.FusedLocationApi obsoletos hasta que Google resuelva el problema.


Respuesta original

Esto sucede porque FusedLocationProviderApi desaprobó en una versión reciente de los servicios de google play. Puedes consultarlo aquí . La guía oficial ahora sugiere usar FusedLocationProviderClient . Puede encontrar la guía detallada aquí .

por ejemplo, dentro de onCreate() crea una instancia de FusedLocationProviderClient

  mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this); 

y para solicitar la última ubicación conocida todo lo que tiene que hacer es llamar

 mFusedLocationClient.getLastLocation() .addOnSuccessListener(this, new OnSuccessListener() { @Override public void onSuccess(Location location) { // Got last known location. In some rare situations, this can be null. if (location != null) { // Logic to handle location object } } }); 

Simple, ¿no?

  // Better to use GoogleApiClient to show device location. I am using this way in my aap. public class SuccessFragment extends Fragment{ private TextView txtLatitude, txtLongitude, txtAddress; // private AddressResultReceiver mResultReceiver; // removed here because cause wrong code when implemented and // its not necessary like the author says //Define fields for Google API Client private FusedLocationProviderClient mFusedLocationClient; private Location lastLocation; private LocationRequest locationRequest; private LocationCallback mLocationCallback; private static final int REQUEST_PERMISSIONS_REQUEST_CODE = 14; @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_location, container, false); txtLatitude = (TextView) view.findViewById(R.id.txtLatitude); txtLongitude = (TextView) view.findViewById(R.id.txtLongitude); txtAddress = (TextView) view.findViewById(R.id.txtAddress); // mResultReceiver = new AddressResultReceiver(null); // cemented as above explained try { mFusedLocationClient = LocationServices.getFusedLocationProviderClient(getActivity()); mFusedLocationClient.getLastLocation() .addOnSuccessListener(getActivity(), new OnSuccessListener() { @Override public void onSuccess(Location location) { // Got last known location. In some rare situations this can be null. if (location != null) { // Logic to handle location object txtLatitude.setText(String.valueOf(location.getLatitude())); txtLongitude.setText(String.valueOf(location.getLongitude())); if (mResultReceiver != null) txtAddress.setText(mResultReceiver.getAddress()); } } }); locationRequest = LocationRequest.create(); locationRequest.setInterval(5000); locationRequest.setFastestInterval(1000); if (txtAddress.getText().toString().equals("")) locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); else locationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY); mLocationCallback = new LocationCallback() { @Override public void onLocationResult(LocationResult locationResult) { for (Location location : locationResult.getLocations()) { // Update UI with location data txtLatitude.setText(String.valueOf(location.getLatitude())); txtLongitude.setText(String.valueOf(location.getLongitude())); } } ; }; } catch (SecurityException ex) { ex.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } return view; } @Override public void onStart() { super.onStart(); if (!checkPermissions()) { startLocationUpdates(); requestPermissions(); } else { getLastLocation(); startLocationUpdates(); } } @Override public void onPause() { stopLocationUpdates(); super.onPause(); } /** * Return the current state of the permissions needed. */ private boolean checkPermissions() { int permissionState = ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_COARSE_LOCATION); return permissionState == PackageManager.PERMISSION_GRANTED; } private void startLocationPermissionRequest() { ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, REQUEST_PERMISSIONS_REQUEST_CODE); } private void requestPermissions() { boolean shouldProvideRationale = ActivityCompat.shouldShowRequestPermissionRationale(getActivity(), Manifest.permission.ACCESS_COARSE_LOCATION); // Provide an additional rationale to the user. This would happen if the user denied the // request previously, but didn't check the "Don't ask again" checkbox. if (shouldProvideRationale) { Log.i(TAG, "Displaying permission rationale to provide additional context."); showSnackbar(R.string.permission_rationale, android.R.string.ok, new View.OnClickListener() { @Override public void onClick(View view) { // Request permission startLocationPermissionRequest(); } }); } else { Log.i(TAG, "Requesting permission"); // Request permission. It's possible this can be auto answered if device policy // sets the permission in a given state or the user denied the permission // previously and checked "Never ask again". startLocationPermissionRequest(); } } /** * Callback received when a permissions request has been completed. */ @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { Log.i(TAG, "onRequestPermissionResult"); if (requestCode == REQUEST_PERMISSIONS_REQUEST_CODE) { if (grantResults.length <= 0) { // If user interaction was interrupted, the permission request is cancelled and you // receive empty arrays. Log.i(TAG, "User interaction was cancelled."); } else if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { // Permission granted. getLastLocation(); } else { // Permission denied. // Notify the user via a SnackBar that they have rejected a core permission for the // app, which makes the Activity useless. In a real app, core permissions would // typically be best requested during a welcome-screen flow. // Additionally, it is important to remember that a permission might have been // rejected without asking the user for permission (device policy or "Never ask // again" prompts). Therefore, a user interface affordance is typically implemented // when permissions are denied. Otherwise, your app could appear unresponsive to // touches or interactions which have required permissions. showSnackbar(R.string.permission_denied_explanation, R.string.settings, new View.OnClickListener() { @Override public void onClick(View view) { // Build intent that displays the App settings screen. Intent intent = new Intent(); intent.setAction( Settings.ACTION_APPLICATION_DETAILS_SETTINGS); Uri uri = Uri.fromParts("package", BuildConfig.APPLICATION_ID, null); intent.setData(uri); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); } }); } } } /** * Provides a simple way of getting a device's location and is well suited for * applications that do not require a fine-grained location and that do not need location * updates. Gets the best and most recent location currently available, which may be null * in rare cases when a location is not available. * 

* Note: this method should be called after location permission has been granted. */ @SuppressWarnings("MissingPermission") private void getLastLocation() { mFusedLocationClient.getLastLocation() .addOnCompleteListener(getActivity(), new OnCompleteListener() { @Override public void onComplete(@NonNull Task task) { if (task.isSuccessful() && task.getResult() != null) { lastLocation = task.getResult(); txtLatitude.setText(String.valueOf(lastLocation.getLatitude())); txtLongitude.setText(String.valueOf(lastLocation.getLongitude())); } else { Log.w(TAG, "getLastLocation:exception", task.getException()); showSnackbar(getString(R.string.no_location_detected)); } } }); } private void stopLocationUpdates() { mFusedLocationClient.removeLocationUpdates(mLocationCallback); } private void startLocationUpdates() { if (ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { // TODO: Consider calling // ActivityCompat#requestPermissions // here to request the missing permissions, and then overriding // public void onRequestPermissionsResult(int requestCode, String[] permissions, // int[] grantResults) // to handle the case where the user grants the permission. See the documentation // for ActivityCompat#requestPermissions for more details. return; } mFusedLocationClient.requestLocationUpdates(locationRequest, mLocationCallback, null); } // private void showSnackbar(final String text) { // if (canvasLayout != null) { // Snackbar.make(canvasLayout, text, Snackbar.LENGTH_LONG).show(); // } //} // this also cause wrong code and as I see it dont is necessary // because the same method which is really used private void showSnackbar(final int mainTextStringId, final int actionStringId, View.OnClickListener listener) { Snackbar.make(getActivity().findViewById(android.R.id.content), getString(mainTextStringId), Snackbar.LENGTH_INDEFINITE) .setAction(getString(actionStringId), listener).show(); } }

Y nuestro fragment_location.xml

       

Sí, está obsoleto!
Aquí hay algunos puntos que necesitará al usar el nuevo FusedLocationProviderClient .

  1. importarlo como importación com.google.android.gms.location.FusedLocationProviderClient; 😅
  2. Veo que está implementando la interfaz LocationListener . En el método mFusedLocationClient.requestLocationUpdates (), ahora no toma un LocationListener como parámetro. Puede proporcionar LocationCallback . Como esta es una clase abstracta, no puedes implementarla como LocationListener. Realice un método de callback y páselo en lugar de ‘esto’ como se menciona en la guía de Google. importarlo como import com.google.android.gms.location.LocationCallback;
  3. Con LocationCallback, tendrá onLocationResult () en lugar de onLocationChanged () . Devuelve el objeto LocationResult en lugar del objeto Location. Use LocationResult.getLastLocation () para obtener la ubicación más reciente disponible en este objeto de resultado. Importación como import com.google.android.gms.location.LocationResult;

Para la cordura me estoy apegando a 11.2.0. No entiendo la desaprobación. A partir del 3 de noviembre de 2017, la documentación de Google todavía hace referencia a: LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, mListener);

problema es con su statement de importación

elimina esto

 import android.location.LocationListener; 

añadir

 import com.google.android.gms.location.LocationListener; 

Haga que su actividad implemente LocationListener desde Google Services, no desde el sistema operativo Android; esto funcionó para mí.