Android LocationServices.FusedLocationApi tidak digunakan lagi


89

Saya tidak tahu mengapa LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient,mLocationRequest, this);"FusedLocationApi" dicoret dan menunjukkannya dengan mengatakan tidak digunakan lagi. Klik di sini untuk melihat Gambar

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

}
}

Bagaimana jika tidak digunakan lagi, ada baris tentang ini, harap periksa Saya menggunakan LocationServices.FusedLocationApi.requestLocationUpdates (mGoogleApiClient, mLocationRequest, this);
Omar Hayat

@OmarHayat FusedLocationApi dicoret
vvvv

periksa dependensi Anda yang saya kompilasi menggunakan kompilasi ini 'com.google.android.gms: play-services-location: 9.4.0'
Omar Hayat

Anda menggunakan ini dalam metod oncreate mGoogleApiClient = new GoogleApiClient.Builder (this) .addApi (LocationServices.API) .addConnectionCallbacks (this) .addOnConnectionFailedListener (this) .build ();
Omar Hayat

@OmarHayat Saya menggunakan kompilasi 'com.google.android.gms: play-services-location: 11.4.0' dan setelah saya ubah ke 9.4.0 memperbaiki masalah, mengapa diperbaiki setelah mengganti nomor?
vvvv

Jawaban:


156

Jawaban Asli

Ini terjadi karena FusedLocationProviderApisudah tidak digunakan lagi dalam versi terbaru layanan google play. Anda bisa mengeceknya di sini . Panduan resmi sekarang menyarankan penggunaan FusedLocationProviderClient . Anda dapat menemukan panduan lengkapnya di sini .

misalnya di dalam onCreate()atau onViewCreated()membuat sebuah FusedLocationProviderClientinstance

Kotlin

val fusedLocationClient = LocationServices.getFusedLocationProviderClient(requireContext())

dan untuk meminta lokasi terakhir yang diketahui yang harus Anda lakukan adalah menelepon

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

Jawa

FusedLocationProviderClient fusedLocationClient = LocationServices.getFusedLocationProviderClient(requireContext());

dan

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

Sederhana, bukan?


Pembaruan Penting (24 Oktober 2017):

Kemarin Google memperbarui halaman pengembang resminya dengan peringatan yang mengatakan

Harap terus gunakan kelas FusedLocationProviderApi dan jangan bermigrasi ke kelas FusedLocationProviderClient hingga layanan Google Play versi 12.0.0 tersedia, yang diharapkan akan dikirimkan pada awal 2018. Menggunakan FusedLocationProviderClient sebelum versi 12.0.0 menyebabkan aplikasi klien mogok saat Layanan Google Play diperbarui di perangkat. Kami mohon maaf atas ketidaknyamanan yang mungkin ditimbulkan.

peringatan Jadi saya pikir kita harus terus menggunakan yang tidak berlaku lagi LocationServices.FusedLocationApisampai Google menyelesaikan masalah.


Pembaruan Terbaru (21 November 2017):

Peringatan itu hilang sekarang. Layanan Google Play 11.6 6 November 2017, catatan rilis mengatakan: Memperbaiki masalah FusedLocationProviderClient yang terkadang menyebabkan error saat layanan Google Play diperbarui.Saya pikir Layanan Play tidak akan mogok saat memperbarui dirinya sendiri di latar belakang. Jadi kita bisa menggunakan yang baru FusedLocationProviderClientsekarang.


3
Saya suka bagaimana dokumen Google masih memberi tahu Anda untuk menggunakan API lama: developer.android.com/training/location/…
mxcl

adalah getLastLocation () melakukan apa yang dilakukan LocationServices.FusedLocationApi.requestLocationUpdates ()? Anehnya, hingga saat ini, dokumentasinya masih mengacu pada cara lama itu. Ini membingungkan. developer.android.com/training/location/…
Juan Mendez

@Juanendez Saya setuju. Mereka perlu bekerja untuk memelihara contoh-contoh terbaru yang benar. btw getLastLocation()hanya mengembalikan lokasi perangkat yang diketahui terbaru .. Anda dapat meminta pembaruan lokasi dengan requestLocationUpdates(LocationRequest request, PendingIntent callbackIntent)metode baru .
Somesh Kumar

@SomeshKumar, terima kasih. ya, itulah metode yang saya gunakan. Sementara itu, saya berpegang pada 11.2.0.
Juan Mendez

2
@ Takut Ya, peringatan hilang .. dan tautan yang Anda berikan juga menyatakan bahwa versi baru layanan google play tidak akan mogok jika pengguna memperbarui aplikasi. Saya pikir saya harus memperbarui jawaban saya sekarang.
Somesh Kumar

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

Dan fragment_location.xml kami

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

hapus baris ini. Dan kode lainnya akan bekerja untuk Anda
JoboFive

tidak bisa mendapatkan lokasi pada interval berikutnya
VY

@Vishal saya mendapatkan lokasi waktu nyata di setiap contoh Anda perlu memeriksa izin lokasi dalam kode manifes serta di dalam
JoboFive

Terima kasih untuk kode Anda. Tapi saya punya masalah, Jika saya membutuhkan lokasi setelah setiap 100 meter dan mengirimkannya ke server apa yang harus saya lakukan? Tolong bantu.
Pravinsingh Waghela

Gunakan seperti ini: locationRequest = LocationRequest.create () .setPriority (LocationRequest.PRIORITY_HIGH_ACCURACY) .setInterval (90000) .setSmallestDisplacement (10) .setFastestInterval (10000);
JoboFive


2

Ya, itu sudah usang!
Berikut ini beberapa poin yang Anda perlukan saat menggunakan FusedLocationProviderClient baru .

  1. impor sebagai impor com.google.android.gms.location.FusedLocationProviderClient;😅
  2. Saya melihat bahwa Anda sedang mengimplementasikan antarmuka LocationListener . Dalam metode mFusedLocationClient.requestLocationUpdates (), sekarang tidak menggunakan LocationListener sebagai parameter. Anda dapat memberikan LocationCallback . Karena ini adalah kelas abstrak, Anda tidak dapat mengimplementasikannya seperti LocationListener. Buat metode panggilan balik dan teruskan alih-alih 'ini' seperti yang disebutkan dalam panduan Google . impor sebagaiimport com.google.android.gms.location.LocationCallback;
  3. Dengan LocationCallback, Anda akan memiliki onLocationResult (), bukan onLocationChanged () . Ini mengembalikan objek LocationResult alih-alih objek Lokasi. Gunakan LocationResult.getLastLocation () untuk mendapatkan lokasi terbaru yang tersedia di objek hasil ini. Impor sebagaiimport com.google.android.gms.location.LocationResult;

2

Ya, itu sudah tidak digunakan lagi. FusedLocationProviderClientlebih mudah daripada FusedLocationProviderApi, karena FusedLocationProviderApibiasanya membutuhkan GoogleApiClientjuga, yang kita perlu menghubungkan Google Play Servicesecara manual. Jika sebelumnya Anda menggunakan GoogleApiClient, sekarang GoogleApiClienttidak lagi diperlukan ( selengkapnya di sini ).

Untuk mendapatkan lokasi terakhir, bisa menggunakan fungsi ini:

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

masalah dengan pernyataan impor Anda

pindahkan ini

import android.location.LocationListener;

Menambahkan

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

-1

Harap buat Aktivitas Anda mengimplementasikan LocationListener dari Layanan Google, bukan dari OS Android, ini berfungsi untuk saya.


-1

gunakan getFusedLocationProviderClient sebagai ganti LocationServices.FusedLocationApi.

Kotlin

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

Jawa

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) {
                // ...
            }
        });
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.