Android LocationServices.FusedLocationApi không được dùng nữa


87

Tôi không thể tìm ra lý do tại sao LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient,mLocationRequest, this);"FusedLocationApi" bị gạch bỏ và chỉ vào nó nói rằng không được dùng nữa. Ấn vào đây để xem ảnh

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

}
}

Làm thế nào nếu nó không được dùng nữa. Có dòng trên này, vui lòng kiểm tra Tôi đang sử dụng LocationServices.FusedLocationApi.requestLocationUpdates (mGoogleApiClient, mLocationRequest này);
Omar Hayat

@OmarHayat FusedLocationApi là cross ra
vvvv

kiểm tra sự phụ thuộc của bạn tôi biên dịch sử dụng biên dịch này 'com.google.android.gms: play-dịch vụ-vị trí: 9.4.0'
Omar Hayat

Bạn đang sử dụng điều này trong oncreate metod mGoogleApiClient = new GoogleApiClient.Builder (this) .addApi (LocationServices.API) .addConnectionCallbacks (this) .addOnConnectionFailedListener (this) .build ();
Omar Hayat

@OmarHayat Tôi đang sử dụng biên dịch 'com.google.android.gms: play-services-location: 11.4.0' và sau khi tôi thay đổi thành 9.4.0, nó đã khắc phục được sự cố, tại sao nó lại khắc phục được sau khi thay đổi số?
vvvv

Câu trả lời:


155

Câu trả lời gốc

Điều này đang xảy ra vì FusedLocationProviderApiphiên bản gần đây của dịch vụ google play không được dùng nữa. Bạn có thể kiểm tra nó ở đây . Hướng dẫn chính thức hiện đề xuất sử dụng FusedLocationProviderClient . Bạn có thể tìm thấy hướng dẫn chi tiết tại đây .

ví dụ: bên trong onCreate()hoặc onViewCreated()tạo một FusedLocationProviderClientphiên bản

Kotlin

val fusedLocationClient = LocationServices.getFusedLocationProviderClient(requireContext())

và để yêu cầu vị trí đã biết cuối cùng, tất cả những gì bạn phải làm là gọi

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

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

Đơn giản phải không?


Cập nhật quan trọng (ngày 24 tháng 10 năm 2017):

Hôm qua, Google đã cập nhật trang nhà phát triển chính thức của mình với một cảnh báo cho biết

Vui lòng tiếp tục sử dụng lớp FusedLocationProviderApi và không di chuyển sang lớp FusedLocationProviderClient cho đến khi các dịch vụ của Google Play phiên bản 12.0.0 khả dụng, dự kiến ​​sẽ xuất xưởng vào đầu năm 2018. Việc sử dụng FusedLocationProviderClient trước phiên bản 12.0.0 khiến ứng dụng khách gặp sự cố khi Các dịch vụ của Google Play được cập nhật trên thiết bị. Chúng tôi xin lỗi vì bất kỳ sự bất tiện này có thể đã gây ra.

cảnh báo Vì vậy, tôi nghĩ chúng ta nên tiếp tục sử dụng phiên bản không dùng nữa LocationServices.FusedLocationApicho đến khi Google giải quyết được vấn đề.


Cập nhật mới nhất (ngày 21 tháng 11 năm 2017):

Cảnh báo đã biến mất ngay bây giờ. Các dịch vụ của Google Play 11.6 Ngày 6 tháng 11 năm 2017, ghi chú phát hành cho biết: Đã khắc phục sự cố FusedLocationProviderClient đôi khi gây ra sự cố khi các dịch vụ của Google Play được cập nhật.Tôi nghĩ Dịch vụ Play sẽ không gặp sự cố khi nó tự cập nhật trong nền. Vì vậy, chúng tôi có thể sử dụng mới FusedLocationProviderClientngay bây giờ.


3
Tôi yêu cách Google docs vẫn nói với bạn để sử dụng API cũ: developer.android.com/training/location/...
mxcl

getLastLocation () đang làm những gì LocationServices.FusedLocationApi.requestLocationUpdates () đã làm? Điều kỳ lạ là cho đến nay, tài liệu hướng dẫn vẫn theo cách cũ. Thật khó hiểu. developer.android.com/training/location/…
Juan Mendez,

@JuanMendez Tôi đồng ý. Họ cần cố gắng duy trì các ví dụ cập nhật phù hợp. btw getLastLocation()chỉ trả về vị trí đã biết gần đây nhất của thiết bị .. bạn có thể yêu cầu cập nhật vị trí bằng requestLocationUpdates(LocationRequest request, PendingIntent callbackIntent)phương pháp mới .
Somesh Kumar,

@SomeshKumar, cảm ơn. vâng, đó là phương pháp tôi đang sử dụng. Tôi đang gắn bó với 11.2.0 trong thời gian chờ đợi.
Juan Mendez

2
@Fraid Vâng, cảnh báo đã biến mất .. và liên kết bạn cung cấp cũng cho biết rằng phiên bản mới của dịch vụ google play sẽ không bị lỗi nếu người dùng cập nhật ứng dụng. Tôi nghĩ tôi nên cập nhật câu trả lời của mình ngay bây giờ.
Somesh Kumar

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

Và pixel_location.xml của chúng tôi

       <?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>

loại bỏ dòng này. Và phần còn lại của mã sẽ làm việc cho bạn
JoboFive

không thể nhận được vị trí trong khoảng thời gian tiếp theo
VY

@Vishal Tôi đang nhận được vị trí thời gian thực tại mọi trường hợp bạn cần kiểm tra quyền vị trí trong tệp kê khai cũng như mã bên trong
JoboFive

Cảm ơn vì mã của bạn. Nhưng tôi có một vấn đề, Nếu tôi cần vị trí sau mỗi 100 mét và gửi nó đến máy chủ, tôi phải làm gì? Xin vui lòng giúp đỡ.
Pravinsingh Waghela.

Sử dụng như sau: locationRequest = LocationRequest.create () .setPosystem (LocationRequest.PRIORITY_HIGH_ACCURACY) .setInterval (90000) .setSmallestDisplacement (10) .setFastestInterval (10000);
JoboFive


2

Có, nó không được dùng nữa!
Dưới đây là một số điểm bạn sẽ cần khi sử dụng FusedLocationProviderClient mới .

  1. nhập nó dưới dạng nhập khẩu com.google.android.gms.location.FusedLocationProviderClient;😅
  2. Tôi nhận thấy rằng bạn đang triển khai giao diện LocationListener . Trong phương thức mFusedLocationClient.requestLocationUpdates (), bây giờ nó không sử dụng LocationListener làm tham số. Bạn có thể cung cấp LocationCallback . Vì đây là một lớp trừu tượng nên bạn không thể triển khai nó như LocationListener. Thực hiện một phương thức gọi lại và chuyển nó thay vì 'this' như được đề cập trong hướng dẫn của Google . nhập nó dưới dạngimport com.google.android.gms.location.LocationCallback;
  3. Với LocationCallback, bạn sẽ có onLocationResult () thay vì onLocationChanged () . Nó trả về đối tượng LocationResult thay vì đối tượng Location. Sử dụng LocationResult.getLastLocation () để lấy vị trí gần đây nhất có sẵn trong đối tượng kết quả này. Nhập nó dưới dạngimport com.google.android.gms.location.LocationResult;

2

Có, nó đã không được dùng nữa. FusedLocationProviderClientdễ dàng hơn FusedLocationProviderApi, bởi vì FusedLocationProviderApithông thường GoogleApiClientcũng yêu cầu mà chúng ta cần kết nối Google Play Servicetheo cách thủ công. Nếu trước đây bạn đã sử dụng GoogleApiClientthì bây giờ GoogleApiClientkhông cần nữa ( xem thêm tại đây ).

Để có được vị trí cuối cùng, có thể sử dụng chức năng này:

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

}

-1

vấn đề là với câu lệnh nhập của bạn

tháo cái này

import android.location.LocationListener;

thêm vào

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

-1

Vui lòng thực hiện Hoạt động của bạn triển khai LocationListener từ Dịch vụ của Google, không phải từ Hệ điều hành Android, điều này phù hợp với tôi.


-1

sử dụng getFusedLocationProviderClient thay cho LocationServices.FusedLocationApi.

Kotlin

activity?.let { activity ->
      val client = LocationServices.getFusedLocationProviderClient(activity)
           client.lastLocation.addOnCompleteListener(activity, OnCompleteListener<Location> {
              // it.result.latitude
              // it.result.longitude
      })
}

java

FusedLocationProviderClient client =
        LocationServices.getFusedLocationProviderClient(this);

// Get the last known location
client.getLastLocation()
        .addOnCompleteListener(this, new OnCompleteListener<Location>() {
            @Override
            public void onComplete(@NonNull Task<Location> task) {
                // ...
            }
        });
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.