Android LocationServices FusedLocationApi เลิกใช้แล้ว


89

ฉันคิดไม่ออกว่าทำไมLocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient,mLocationRequest, this);"FusedLocationApi" ถึงขีดฆ่าและชี้ไปที่มันบอกว่าเลิกใช้งานแล้ว คลิกที่นี่เพื่อดูภาพ

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

}
}

หากเลิกใช้แล้วจะมีบรรทัดบนนี้ได้อย่างไรโปรดตรวจสอบว่าฉันกำลังใช้ LocationServices นี้ FusedLocationApi.requestLocationUpdates (mGoogleApiClient, mLocationRequest นี้);
Omar Hayat

@OmarHayat FusedLocationApi ถูกตัดออก
vvvv

ตรวจสอบการอ้างอิงของคุณที่ฉันรวบรวมโดยใช้คอมไพล์นี้ 'com.google.android.gms: play-services-location: 9.4.0'
Omar Hayat

คุณกำลังใช้สิ่งนี้ใน oncreate metod mGoogleApiClient = new GoogleApiClient.Builder (this) .addApi (LocationServices.API) .addConnectionCallbacks (this) .addOnConnectionFailedListener (this) .build ();
Omar Hayat

@OmarHayat ฉันใช้คอมไพล์ 'com.google.android.gms: play-services-location: 11.4.0' และหลังจากที่ฉันเปลี่ยนเป็น 9.4.0 ก็แก้ไขปัญหาได้ทำไมจึงแก้ไขได้หลังจากเปลี่ยนหมายเลข
vvvv

คำตอบ:


156

คำตอบเดิม

สิ่งนี้เกิดขึ้นเนื่องจากFusedLocationProviderApiเลิกใช้บริการ Google Play เวอร์ชันล่าสุด คุณสามารถตรวจสอบได้ที่นี่ คู่มืออย่างเป็นทางการในขณะนี้แนะนำให้ใช้FusedLocationProviderClient คุณสามารถหาคู่มือรายละเอียด ที่นี่

เช่นภายในonCreate()หรือonViewCreated()สร้างFusedLocationProviderClientอินสแตนซ์

Kotlin

val fusedLocationClient = LocationServices.getFusedLocationProviderClient(requireContext())

และสำหรับการขอตำแหน่งสุดท้ายที่ทราบสิ่งที่คุณต้องทำคือโทร

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

เรียบง่ายใช่มั้ย?


การอัปเดตที่สำคัญ (24 ตุลาคม 2017):

เมื่อวานนี้ Google ได้อัปเดตหน้านักพัฒนาซอฟต์แวร์อย่างเป็นทางการพร้อมคำเตือนว่า

โปรดใช้คลาส FusedLocationProviderApi ต่อไปและอย่าย้ายไปยังคลาส FusedLocationProviderClient จนกว่าบริการ Google Play เวอร์ชัน 12.0.0 จะพร้อมใช้งานซึ่งคาดว่าจะจัดส่งในต้นปี 2018 การใช้ FusedLocationProviderClient ก่อนเวอร์ชัน 12.0.0 ทำให้แอปไคลเอนต์หยุดทำงานเมื่อ บริการ Google Play ได้รับการอัปเดตบนอุปกรณ์ ขออภัยในความไม่สะดวกที่อาจเกิดขึ้น

คำเตือน ดังนั้นฉันคิดว่าเราควรใช้การเลิกใช้งานLocationServices.FusedLocationApiต่อไปจนกว่า Google จะแก้ไขปัญหาได้


อัปเดตล่าสุด (21 พฤศจิกายน 2560):

คำเตือนหายไปแล้ว บริการ Google Play 11.6 6 พฤศจิกายน 2017 บันทึกประจำรุ่นระบุว่า: แก้ไขปัญหา FusedLocationProviderClient ที่บางครั้งทำให้เกิดปัญหาเมื่อบริการ Google Play อัปเดตฉันคิดว่า Play Services จะไม่ขัดข้องเมื่ออัปเดตตัวเองในพื้นหลัง เราสามารถใช้ใหม่ได้FusedLocationProviderClientแล้ว


3
ฉันชอบที่ Google เอกสารยังบอกให้คุณใช้ API เก่า: developer.android.com/training/location/…
mxcl

getLastLocation () ทำสิ่งที่ LocationServices.FusedLocationApi.requestLocationUpdates () ทำหรือไม่ สิ่งที่แปลกมากจนถึงตอนนี้คือเอกสารที่ชี้ไปยังวิธีการเดิม ๆ มันสับสน developer.android.com/training/location/…
Juan Mendez

@JuanMendez ฉันเห็นด้วย พวกเขาจำเป็นต้องทำงานเพื่อรักษาตัวอย่างที่ทันสมัยอยู่เสมอ btw getLastLocation()ส่งคืนตำแหน่งที่รู้จักล่าสุดของอุปกรณ์เท่านั้น .. คุณสามารถขอการอัปเดตตำแหน่งด้วยrequestLocationUpdates(LocationRequest request, PendingIntent callbackIntent)วิธีการใหม่
Somesh Kumar

@SomeshKumar ขอบคุณ ใช่นั่นเป็นวิธีที่ฉันใช้ ในระหว่างนี้ฉันติด 11.2.0
Juan Mendez

2
@Fraid Yeah คำเตือนหายไป .. และลิงค์ที่คุณให้ยังระบุด้วยว่าบริการ Google Play เวอร์ชันใหม่จะไม่ขัดข้องหากผู้ใช้อัปเดตแอป ฉันคิดว่าฉันควรอัปเดตคำตอบของฉันตอนนี้
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();
        }
    }

และ 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>

ลบบรรทัดนี้ และรหัสที่เหลือจะใช้ได้กับคุณ
JoboFive

ไม่สามารถรับตำแหน่งในช่วงเวลาถัดไปได้
VY

@Vishal ฉันได้รับตำแหน่งแบบเรียลไทม์ทุกครั้งที่คุณต้องตรวจสอบการอนุญาตตำแหน่งในรายการและรหัสภายใน
JoboFive

ขอบคุณสำหรับรหัสของคุณ แต่ฉันมีปัญหาถ้าฉันต้องการตำแหน่งหลังจากทุกๆ 100 เมตรและส่งไปที่เซิร์ฟเวอร์ฉันควรทำอย่างไร กรุณาช่วย.
Pravinsingh Waghela

ใช้ดังนี้ locationRequest = LocationRequest.create () .setPriority (LocationRequest.PRIORITY_HIGH_ACCURACY) .setInterval (90000) .setSm maximumDisplacement (10) .setFastestInterval (10000);
JoboFive


2

ใช่เลิกใช้แล้ว!
นี่คือบางประเด็นที่คุณต้องการในขณะที่ใช้FusedLocationProviderClientใหม่ FusedLocationProviderClient

  1. นำเข้าเป็นการนำเข้า com.google.android.gms.location.FusedLocationProviderClient; 😅
  2. ฉันสังเกตเห็นว่าคุณกำลังใช้งานอินเตอร์เฟสLocationListener ในเมธอด mFusedLocationClient.requestLocationUpdates () ตอนนี้ไม่ได้ใช้ LocationListener เป็นพารามิเตอร์ คุณสามารถให้LocationCallback เนื่องจากเป็นคลาสนามธรรมคุณจึงไม่สามารถใช้งานได้เช่น LocationListener ใช้วิธีการโทรกลับและส่งแทน 'this' ตามที่กล่าวไว้ในคู่มือของ Googleคู่มือนำเข้าเป็นimport com.google.android.gms.location.LocationCallback;
  3. ด้วย LocationCallback คุณจะมีonLocationResult ()แทนonLocationChanged () ส่งคืนวัตถุLocationResultแทนวัตถุตำแหน่ง ใช้ LocationResult.getLastLocation () เพื่อรับตำแหน่งล่าสุดที่มีอยู่ในวัตถุผลลัพธ์นี้ นำเข้าเป็นimport com.google.android.gms.location.LocationResult;

2

ใช่มันเลิกใช้งานแล้ว FusedLocationProviderClientง่ายกว่าFusedLocationProviderApiเพราะFusedLocationProviderApiมักจะต้องใช้GoogleApiClientเช่นกันซึ่งเราต้องเชื่อมต่อGoogle Play Serviceด้วยตนเอง หากคุณเคยใช้มาก่อนGoogleApiClientตอนนี้GoogleApiClientก็ไม่จำเป็นอีกต่อไป ( เพิ่มเติมที่นี่ )

หากต้องการรับตำแหน่งสุดท้ายสามารถใช้ฟังก์ชันนี้:

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

ปัญหาคือใบแจ้งยอดการนำเข้าของคุณ

ลบสิ่งนี้ออก

import android.location.LocationListener;

เพิ่ม

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

-1

โปรดทำให้กิจกรรมของคุณใช้ LocationListener จากบริการของ Google ไม่ใช่จากระบบปฏิบัติการ Android สิ่งนี้ใช้ได้กับฉัน


-1

ใช้ getFusedLocationProviderClient แทน 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) {
                // ...
            }
        });
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.