web-dev-qa-db-de.com

Android LocationServices.FusedLocationApi veraltet

Ich konnte nicht herausfinden, warum LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient,mLocationRequest, this); "FusedLocationApi" durchgestrichen ist und darauf hinweist, dass veraltet ist . Klicken Sie hier, um das Bild anzuzeigen

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) {

}

}

51
vvvv

Ursprüngliche Antwort

Dies geschieht, weil FusedLocationProviderApi in einer aktuellen Version von Google Play-Diensten veraltet ist. Sie können es hier überprüfen. Der offizielle Leitfaden schlägt nun die Verwendung von FusedLocationProviderClient vor. Den ausführlichen Leitfaden finden Sie hier .

zum Beispiel in onCreate() eine FusedLocationProviderClient-Instanz erstellen 

 mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);

und um den letzten bekannten Standort anzufordern, brauchen Sie nur anzurufen

mFusedLocationClient.getLastLocation()
    .addOnSuccessListener(this, 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
            }
        }
    });

Einfach ist es nicht?


Wichtiges Update (24. Oktober 2017):

Gestern hat Google seine offizielle Entwicklerseite mit Warnung aktualisiert, die besagt, dass

Verwenden Sie weiterhin die Klasse FusedLocationProviderApi und migrieren Sie nicht zur Klasse FusedLocationProviderClient, bis die Version 12.0.0 von Google Play verfügbar ist, die voraussichtlich Anfang 2018 ausgeliefert wird. Wenn Sie den FusedLocationProviderClient vor Version 12.0.0 verwenden, stürzt die Client-App ab, wenn die Anwendung herunterfällt Google Play-Dienste werden auf dem Gerät aktualisiert. Wir entschuldigen uns für etwaige Unannehmlichkeiten.

warning Ich denke, wir sollten den veralteten LocationServices.FusedLocationApi weiter verwenden, bis Google das Problem gelöst hat. 


Letzte Aktualisierung (21. November 2017):

Die Warnung ist jetzt weg.Google Play-Dienste 11.6. 6. November 2017, Versionshinweis sagt: Fixed FusedLocationProviderClient issue that occasionally caused crashes when Google Play services updated. Ich denke, dass Play Services nicht abstürzt, wenn es sich im Hintergrund aktualisiert. Also können wir jetzt neue FusedLocationProviderClient verwenden. 

104
Somesh Kumar
   // 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();
        }
    }

Und unsere 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>
7
JoboFive

Verwenden Sie diese Methode

mFusedLocationClient.requestLocationUpdates(mLocationRequest, mLocationCallback, Looper.myLooper());

Im Detail meine Antwort finden

1
Ketan Ramani

Ja, es ist veraltet!
Hier sind einige Punkte, die Sie benötigen, wenn Sie den neuen FusedLocationProviderClient verwenden. 

  1. importiere es als Import com.google.Android.gms.location.FusedLocationProviderClient; ????
  2. Ich stelle fest, dass Sie die LocationListener - Schnittstelle implementieren. In der Methode mFusedLocationClient.requestLocationUpdates () wird jetzt kein LocationListener als Parameter verwendet. Sie können LocationCallback bereitstellen. Da dies eine abstrakte Klasse ist, können Sie sie nicht wie LocationListener implementieren. Erstellen Sie eine Rückrufmethode, und übergeben Sie diese anstelle von "this", wie in " guide " von Google erwähnt. Importiere es als import com.google.Android.gms.location.LocationCallback; 
  3. Mit LocationCallback haben Sie onLocationResult () anstelle von onLocationChanged () . Es gibt LocationResult - Objekt anstelle des Location-Objekts zurück. Verwenden Sie LocationResult.getLastLocation (), um den aktuellsten in diesem Ergebnisobjekt verfügbaren Speicherort abzurufen. Importiere es als import com.google.Android.gms.location.LocationResult; 
1
Malith

Ja, es ist veraltet. FusedLocationProviderClient ist einfacher als FusedLocationProviderApi, da FusedLocationProviderApi normalerweise auch GoogleApiClient erfordert, das wir manuell mit Google Play Service verbinden müssen. Wenn Sie zuvor GoogleApiClient verwendet haben, wird jetzt GoogleApiClient nicht mehr benötigt ( hier mehr ).

Verwenden Sie diese Funktion, um den letzten Standort abzurufen:

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());
                    }
                }
            });

}
0
Latief Anwar

Aus Gründen der Vernunft halte ich mich an 11.2.0. Ich verstehe die Verachtung nicht. Seit dem 03.11.2017 bezieht sich die Google-Dokumentation bisher noch auf Folgendes: LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, mListener);

0
Juan Mendez