Android LocationServices.FusedLocationApi deprecated
Solution 1
Original Answer
This is happening because FusedLocationProviderApi
deprecated in a recent version of google play services. You can check it here. The official guide now suggests using FusedLocationProviderClient. You can find the detailed guide here.
for e.g inside onCreate()
or onViewCreated()
create a FusedLocationProviderClient
instance
Kotlin
val fusedLocationClient = LocationServices.getFusedLocationProviderClient(requireContext())
and for requesting the last known location all you have to do is call
fusedLocationClient.lastLocation.addOnSuccessListener { location: Location? ->
location?.let { it: Location ->
// Logic to handle location object
} ?: kotlin.run {
// Handle Null case or Request periodic location update https://developer.android.com/training/location/receive-location-updates
}
}
Java
FusedLocationProviderClient fusedLocationClient = LocationServices.getFusedLocationProviderClient(requireContext());
and
fusedLocationClient.getLastLocation().addOnSuccessListener(requireActivity(), location -> {
if (location != null) {
// Logic to handle location object
} else {
// Handle null case or Request periodic location update https://developer.android.com/training/location/receive-location-updates
}
});
Simple, Isn't it?
Important Update (October 24, 2017):
Yesterday Google updated its official developer page with a warning that says
Please continue using the FusedLocationProviderApi class and don't migrate to the FusedLocationProviderClient class until Google Play services version 12.0.0 is available, which is expected to ship in early 2018. Using the FusedLocationProviderClient before version 12.0.0 causes the client app to crash when Google Play services is updated on the device. We apologize for any inconvenience this may have caused.
So I think we should continue using the deprecated LocationServices.FusedLocationApi
until Google resolves the issue.
Latest Update (November 21, 2017):
The warning is gone now. Google Play services 11.6 November 6, 2017, release note says : I think Play Services won't crash when it updates itself in the background. So we can use new FusedLocationProviderClient
now.
Solution 2
// 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<Location>() {
@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.
* <p>
* Note: this method should be called after location permission has been granted.
*/
@SuppressWarnings("MissingPermission")
private void getLastLocation() {
mFusedLocationClient.getLastLocation()
.addOnCompleteListener(getActivity(), new OnCompleteListener<Location>() {
@Override
public void onComplete(@NonNull Task<Location> 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();
}
}
And our fragment_location.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/locationLayout"
android:layout_below="@+id/txtAddress"
android:layout_width="match_parent"
android:layout_height="@dimen/activity_margin_30dp"
android:orientation="horizontal">
<TextView
android:id="@+id/txtLatitude"
android:layout_width="@dimen/activity_margin_0dp"
android:layout_height="@dimen/activity_margin_30dp"
android:layout_weight="0.5"
android:gravity="center"
android:hint="@string/latitude"
android:textAllCaps="false"
android:textColorHint="@color/colorPrimaryDark"
android:textColor="@color/colorPrimaryDark" />
<TextView
android:id="@+id/txtLongitude"
android:layout_width="@dimen/activity_margin_0dp"
android:layout_height="@dimen/activity_margin_30dp"
android:layout_weight="0.5"
android:gravity="center"
android:hint="@string/longitude"
android:textAllCaps="false"
android:textColorHint="@color/colorPrimary"
android:textColor="@color/colorPrimary" />
</LinearLayout>
Solution 3
Use this method
mFusedLocationClient.requestLocationUpdates(mLocationRequest, mLocationCallback, Looper.myLooper());
In Detail Refer My This Answer
Solution 4
Yes, it has been deprecated. FusedLocationProviderClient
is easier than FusedLocationProviderApi
, because FusedLocationProviderApi
usually requires GoogleApiClient
too, which we need to connect to Google Play Service
manually. If you previously used GoogleApiClient
, now GoogleApiClient
is no longer needed (more here).
To get last location, can use this function:
import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.tasks.OnCompleteListener;
public class MainActivity extends AppCompatActivity{
//before public class MainActivity extends AppCompatActivity implements LocationListener,...,...
private static final String TAG = "MainActivity";
public static final int MY_PERMISSIONS_REQUEST_FINE_LOCATION = 101;
private FusedLocationProviderClient mFusedLocationClient;
private Location mGetedLocation;
private double currentLat, currentLng;
private void getLastLocation() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(new String[] {Manifest.permission.ACCESS_FINE_LOCATION}, MY_PERMISSIONS_REQUEST_FINE_LOCATION);
}
return;
}
mFusedLocationClient.getLastLocation()
.addOnCompleteListener(this, new OnCompleteListener<Location>() {
@Override
public void onComplete(@NonNull Task<Location> task) {
if (task.isSuccessful() && task.getResult() != null) {
mGetedLocation = task.getResult();
currentLat = mGetedLocation.getLatitude();
currentLng = mGetedLocation.getLongitude();
//updateUI();
}else{
Log.e(TAG, "no location detected");
Log.w(TAG, "getLastLocation:exception", task.getException());
}
}
});
}
Solution 5
Yes, it's deprecated!
Here are some points you'll need while using new FusedLocationProviderClient.
- import it as import
com.google.android.gms.location.FusedLocationProviderClient;
😅 - I notice that you are implementing LocationListener interface. In the mFusedLocationClient.requestLocationUpdates() method, now it doesn't take a LocationListener as a parameter. You can provide LocationCallback. As this is an abstract class you can't implement it like LocationListener. Make a callback method and pass it instead of 'this' as mentioned in Google's guide. import it as
import com.google.android.gms.location.LocationCallback;
- With LocationCallback, you'll have onLocationResult() instead of onLocationChanged(). It returns LocationResult object instead of Location object. Use LocationResult.getLastLocation() to get the most recent location available in this result object. Import it as
import com.google.android.gms.location.LocationResult;
vvvv
Updated on July 08, 2022Comments
-
vvvv almost 2 years
I couldn't figure out why
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient,mLocationRequest, this);
"FusedLocationApi" is cross out and point at it saying is deprecated. Click here to view Imageimport 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) { } }
-
mxcl over 6 yearsI love how Google docs still tell you to use the old API: developer.android.com/training/location/…
-
Juan Mendez over 6 yearsis getLastLocation() doing what LocationServices.FusedLocationApi.requestLocationUpdates() did? What's so strange, up to now, is the documentation pointing still to that old way. It's confusing. developer.android.com/training/location/…
-
Somesh Kumar over 6 years@JuanMendez I agree. They need to work on maintaining proper up-to-date examples. btw
getLastLocation()
only return the most recent known location of device.. you can request location update with newrequestLocationUpdates(LocationRequest request, PendingIntent callbackIntent)
method. -
Juan Mendez over 6 years@SomeshKumar, thanks. yes, that's the method I've been using. I am sticking to 11.2.0 in the meantime.
-
Fraid over 6 yearsLook like the warning is gone now (nov 13, 2017), I guess that mean we good to go with FusedLocationProviderClient ?
-
Fraid over 6 yearsMy bad! this has been reported hear for 11.6.0: developers.google.com/android/guides/releases
-
Somesh Kumar over 6 years@Fraid Yeah,warning is gone.. and the link you provided also states that new version of google play services won't crash if user updates the app. I think I should update my answer now.
-
Ramapati Maurya almost 6 yearsremove this line. And rest of the code will work for you
-
Vishal Yadav almost 6 yearsunable to get location in next interval
-
Ramapati Maurya almost 6 years@Vishal i am getting realtime location at every instance you need to check location permission in manifest as well as inside code
-
Somesh Kumar almost 6 years@copsonroad... Really ? Where is warning showing ? I tried searching for a warning on every webpage & fused client method and found no warning.
-
CopsOnRoad almost 6 years@SomeshKumar I am talking about
FusedLocationApi
, it is showing you warning. The OP asked this API is now deprecated and your edited answer showed the warning is gone. So are you sure you were also talking aboutFusedLocationApi
? -
Somesh Kumar almost 6 years@CopsOnRoad Yeah, It was showing warning initially when OP asked the question and after some days Google removed that warning and put a note telling that everyone should use the deprecated FusedLocationApi. Now everything is properly deprecated. FusedLocationApi is also showing warning. It think you're getting confused.
-
CopsOnRoad almost 6 years@SomeshKumar You said -- The warning is gone now (Latest Update (November 21, 2017). From where has it gone - Docs or Android Studio? Can't say about Docs but in Android Studio it is still showing you the warning.
-
Somesh Kumar almost 6 years@CopsOnRoad There was a warning on official docs.. see Oct, 24 update.
-
CopsOnRoad almost 6 years@SomeshKumar That means you were talking about the Docs warning. Not the warning shown by Android Studio. Even today AS shows you the warning not to use
FusedLocationApi
. -
Somesh Kumar almost 6 years@CopsOnRoad yeah. You're getting confused with the answer updates.
-
Pravinsingh Waghela over 5 yearsThanks for your code. But I have an issue, If I need location after every 100 meters and send it to server what should I do? Please help.
-
Ramapati Maurya over 5 yearsUse like this : locationRequest =LocationRequest.create() .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY) .setInterval(90000) .setSmallestDisplacement(10) .setFastestInterval(10000);
-
user924 over 5 yearsAnd what simple? Your example doesn't have
requestLocationUpdates
, what is difficult withmFusedLocationClient.getLastLocation()
? you better give example withrequestLocationUpdates
-
Somesh Kumar over 5 years@user924 Question was about depreciation. He never asked about a full API demo here.
-
Nikhil Singh about 5 years@SomeshKumar Sir will you please elaborate the difference between both why this new Fused location provider client differ with previous one and what problem get solved by new one.
-
Somesh Kumar about 5 years@NikhilSingh For that you can study the source code of both classes' and find out what are the changes between both implantation.