【问题标题】:Android - Xamarin - Fused LocationAndroid - Xamarin - 融合位置
【发布时间】:2016-08-15 10:22:16
【问题描述】:

我正在尝试实现一个自定义活动,该活动在 Xamarin c# 中初始化 Fused Location 服务,因此我可以在需要 Fused Location 时重用此活动。我遇到的问题是地图是在定位服务之前加载的。这样一来,由于该位置仍为空,我无法为相机设置动画以放大用户的位置。

这是自定义活动:

using System;
using Android.App;
using Android.Gms.Common;
using Android.Gms.Common.Apis;
using Android.Gms.Maps.Model;
using Android.Locations;
using Android.OS;
using Android.Gms.Location;
using Android.Widget;

namespace Maps.Droid.LocationService {
    public class LocationTrackerActivity : Activity, GoogleApiClient.IConnectionCallbacks, GoogleApiClient.IOnConnectionFailedListener, Android.Gms.Location.ILocationListener {
        // Static Fields
        public static long MIN_DISTANCE_CHANGE_FOR_UPDATES = 5; // 5 meters
        public static long MIN_TIME_BW_UPDATES = 1000 * 10; // 10 seconds

        private Location currentLocation;
        private Activity activity;
        private bool hasGooglePlayServices;
        private GoogleApiClient mGoogleApiClient;
        private LocationRequest mLocationRequest;
        private bool locationAvailable = false;

        protected override void OnCreate(Bundle savedInstanceState) {
            base.OnCreate(savedInstanceState);

            this.activity = this;

            hasGooglePlayServices = checkPlayServices();

            if (hasGooglePlayServices) {
                initFusedLocation();
            } else {
                initAndroidLocation();
            }
        }

        private void initFusedLocation() {
            mLocationRequest = new LocationRequest();
            mLocationRequest.SetInterval(LocationTrackerActivity.MIN_TIME_BW_UPDATES);
            mLocationRequest.SetFastestInterval(LocationTrackerActivity.MIN_TIME_BW_UPDATES / 2);
            mLocationRequest.SetSmallestDisplacement(LocationTrackerActivity.MIN_DISTANCE_CHANGE_FOR_UPDATES);
            mLocationRequest.SetPriority(LocationRequest.PriorityHighAccuracy);

            mGoogleApiClient = new GoogleApiClient.Builder(Application.Context)
                .AddConnectionCallbacks(this)
                .AddOnConnectionFailedListener(this)
                .AddApi(LocationServices.API)
                .Build();
        }

        protected override void OnResume() {
            base.OnResume();
            if (mGoogleApiClient.IsConnected) {
                LocationServices.FusedLocationApi.RequestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
            }
        }

        protected override void OnPause() {
            base.OnPause();
            // Stop location updates to save battery, but don't disconnect the GoogleApiClient object.
            if (mGoogleApiClient.IsConnected) {
                LocationServices.FusedLocationApi.RemoveLocationUpdates(mGoogleApiClient, this);
            }
        }

        protected override void OnStart() {
            base.OnStart();
            mGoogleApiClient.Connect();
        }

        protected override void OnStop() {
            base.OnStop();
            // only stop if it's connected, otherwise we crash
            if (mGoogleApiClient != null) {
                mGoogleApiClient.Disconnect();
            }
        }

        private void initAndroidLocation() {

        }

        private bool checkPlayServices() {
            GoogleApiAvailability apiAvailability = GoogleApiAvailability.Instance;
            int resultCode = apiAvailability.IsGooglePlayServicesAvailable(activity);
            if (resultCode != ConnectionResult.Success) {
                // In case we want to tell the user to install or update Google Play Services
                //if (apiAvailability.IsUserResolvableError(resultCode)) {
                //    apiAvailability.GetErrorDialog(activity, resultCode, PLAY_SERVICES_RESOLUTION_REQUEST).Show();
                //} else {
                //    Toast.MakeText(activity, "This device is not supported", ToastLength.Long).Show();
                //}
                return false;
            }
            return true; // has google play services installed
        }

        public double getLatitude() {
            return currentLocation == null ? 0.0 : currentLocation.Latitude;
        }

        public double getLongitude() {
            return currentLocation == null ? 0.0 : currentLocation.Longitude;
        }

        public bool canGetLocation() {
            return locationAvailable;
        }

        public LatLng getLatLng() {
            return new LatLng(currentLocation.Latitude, currentLocation.Longitude);
        }

        public void OnConnected(Bundle connectionHint) {
            // Get last known recent location. If the user launches the activity,
            // moves to a new location, and then changes the device orientation, the original location
            // is displayed as the activity is re-created.
            if (currentLocation == null && mGoogleApiClient.IsConnected) {
                currentLocation = LocationServices.FusedLocationApi.GetLastLocation(mGoogleApiClient);
            }
            Console.WriteLine("location is about to be set to true");

            locationAvailable = true;

            LocationServices.FusedLocationApi.RequestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
        }

        public void OnConnectionSuspended(int cause) {
            // GoogleApiClient will automatically attempt to restore the connection.
            // Applications should disable UI components that require the service, and wait for a call to onConnected(Bundle) to re-enable them

            if (cause == GoogleApiClient.ConnectionCallbacks.CauseServiceDisconnected) {
                Toast.MakeText(activity, "Location Services disconnected. Please re-connect.", ToastLength.Long).Show();
            } else if (cause == GoogleApiClient.ConnectionCallbacks.CauseNetworkLost) {
                Toast.MakeText(activity, "Network lost. Please re-connect.", ToastLength.Long).Show();
            }
        }

        public void OnConnectionFailed(ConnectionResult result) {
            Console.WriteLine("Connection failed: " + result.ToString());
        }

        public void OnLocationChanged(Location location) {
            currentLocation = location;
        }
    }
}

这里是继承自定义类的类:

using Android.App;
using Android.OS;
using Maps.Droid.LocationService;

namespace Maps.Droid {
    [Activity(Label = "Map Activity")]
    public class MapActivity : LocationTrackerActivity {
        // Properties

        protected override void OnCreate(Bundle savedInstanceState) {
            base.OnCreate(savedInstanceState);
            SetContentView(Resource.Layout.map_activity);

            var mapFrag = new MapViewFragment();
            var ft = FragmentManager.BeginTransaction();
            ft.Add(Resource.Id.map_container, mapFrag);
            ft.Commit();
        }
    }
}

这是继承活动中的片段:

using System;
using Android.App;
using Android.OS;
using Android.Views;
using Android.Gms.Maps;

namespace Maps.Droid {
    public class MapViewFragment : Fragment, IOnMapReadyCallback {
        // private Activity activity;
        private GoogleMap map;
        private MapActivity parent;

        public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            View view = inflater.Inflate(Resource.Layout.map_fragment, null);

            parent = ((MapActivity)Activity);

            MapFragment frag = this.FragmentManager.FindFragmentById<MapFragment>(Resource.Id.map);
            frag.GetMapAsync(this);

            return view;
        }

        public void OnMapReady(GoogleMap googleMap) {
            if (googleMap != null) {
                map = googleMap;
                var zoomVariance = 0.2;
                var defaultZoom = 16f;
                var currentZoomLevel = map.CameraPosition.Zoom;

                map.MapType = GoogleMap.MapTypeNormal;
                map.MyLocationEnabled = true;

                map.CameraChange += delegate (object sender, GoogleMap.CameraChangeEventArgs e) {
                    if (Math.Abs(e.Position.Zoom - currentZoomLevel) < zoomVariance) {
                        return;
                    }

                    currentZoomLevel = e.Position.Zoom;
                    Console.WriteLine("Zooming " + currentZoomLevel);
                };

                map.UiSettings.ZoomControlsEnabled = true;
                map.UiSettings.CompassEnabled = true;
                map.UiSettings.SetAllGesturesEnabled(true); // Zoom, Tilt, Scroll, Rotate

                if (parent.canGetLocation()) {
                    // ***** PROBLEM HERE ******* canGetLocation is set to true just afterwards.
                    map.AnimateCamera(CameraUpdateFactory.NewLatLngZoom(parent.getLatLng(), defaultZoom)); // Mosaic coordinates
                }
            }
        }
    }
}

我正在考虑实现对 LocationTrackerActivity 的回调。因此,当位置服务可用时,类 MapActivity 将能够在该自定义回调中加载 MapViewFragment。这样定位服务将在地图之前加载。因此,这部分代码会一直执行:

if (parent.canGetLocation()) {
    // ***** PROBLEM HERE ******* canGetLocation is set to true just afterwards.
    map.AnimateCamera(CameraUpdateFactory.NewLatLngZoom(parent.getLatLng(), defaultZoom)); // Mosaic coordinates
}

但是我不知道如何自定义回调。也许这个问题有更好的解决方案?

【问题讨论】:

    标签: xamarin callback android-fusedlocation


    【解决方案1】:

    问题可能是由于 OnConnected 方法。这是我在 Xamarin 中的 FusedLocationProvider 的 OnConnected 方法。你可以看看它。

    public async void OnConnected(Bundle bundle)
        {
            Location location = LocationServices.FusedLocationApi.GetLastLocation(apiClient);
    
            if (location != null)
            {
                latitude = location.Latitude;
                longitude = location.Longitude;
    
                locRequest.SetPriority(100);
                locRequest.SetFastestInterval(500);
                locRequest.SetInterval(1000);
    
                await LocationServices.FusedLocationApi.RequestLocationUpdates(apiClient, locRequest, this);
            } 
        }
    

    连接后,我设置纬度和经度值。然后在我的 onMapReady 方法中,使用这些纬度和经度变量创建一个新的 LatLng 变量。

    void IOnMapReadyCallback.OnMapReady(GoogleMap myMap)
        {
            this.myMap = myMap;
            myMarker = new MarkerOptions();
            locCoordinates = new LatLng(latitude, longitude);
    
            myMap.MapType = GoogleMap.MapTypeNormal;
            myMap.UiSettings.ZoomControlsEnabled = true;
            myMap.AnimateCamera(CameraUpdateFactory.NewLatLngZoom(locCoordinates, 10));
        }
    

    更新:

    我设法找到了解决方案。如果用户有 google play 服务,则使用 FusedLocation 服务,如果用户没有,则我们使用 Android 定位服务。然后我们只需要与一个LocationTracker类型的对象进行交互,一切都由这个接口完成:

    namespace Maps.Droid.LocationService {
        public interface LocationInterface {
            void startLocationServices();
            void stopLocationServices();
            void pauseLocationServices();
            void resumeLocationServices();
            double getLatitude();
            double getLongitude();
            bool canGetLocation();
        }
    }
    
    using System;
    using Android.App;
    using Android.Gms.Location;
    using Android.Gms.Common.Apis;
    using Android.OS;
    using Android.Gms.Maps.Model;
    using Android.Widget;
    using Android.Locations;
    using Android.Gms.Common;
    using Android.Gms.Maps;
    
    namespace Maps.Droid.LocationService {
        public class FusedLocation : Java.Lang.Object, GoogleApiClient.IConnectionCallbacks, GoogleApiClient.IOnConnectionFailedListener, Android.Gms.Location.ILocationListener {
            private Activity activity;
            private GoogleApiClient mGoogleApiClient;
            private LocationRequest mLocationRequest;
            private Location currentLocation;
            private bool locationAvailable = false;
            private GoogleMap map;
    
            public FusedLocation(Activity activity) {
                this.activity = activity;
    
                mLocationRequest = new LocationRequest();
                mLocationRequest.SetInterval(LocationTracker.MIN_TIME_BW_UPDATES);
                mLocationRequest.SetFastestInterval(LocationTracker.MIN_TIME_BW_UPDATES / 2);
                mLocationRequest.SetSmallestDisplacement(LocationTracker.MIN_DISTANCE_CHANGE_FOR_UPDATES);
                mLocationRequest.SetPriority(LocationRequest.PriorityHighAccuracy);
    
                mGoogleApiClient = new GoogleApiClient.Builder(Application.Context)
                    .AddConnectionCallbacks(this)
                    .AddOnConnectionFailedListener(this)
                    .AddApi(LocationServices.API)
                    .Build();
            }
    
            public Location getCurrentLocation() {
                return currentLocation;
            }
    
            public void setMap(GoogleMap map) {
                this.map = map;
            }
    
            public double getLatitude() {
                return currentLocation.Latitude;
            }
    
            public double getLongitude() {
                return currentLocation.Longitude;
            }
    
            public void OnResume() {
                if (mGoogleApiClient.IsConnected) {
                    LocationServices.FusedLocationApi.RequestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
                }
            }
            public void OnPause() {
                // Stop location updates to save battery, but don't disconnect the GoogleApiClient object.
                if (mGoogleApiClient.IsConnected) {
                    LocationServices.FusedLocationApi.RemoveLocationUpdates(mGoogleApiClient, this);
                }
            }
    
            public void OnStart() {
                mGoogleApiClient?.Connect();
            }
    
            public void OnStop() {
                // only stop if it's connected, otherwise we crash
                if (mGoogleApiClient.IsConnected) {
                    mGoogleApiClient?.Disconnect();
                }
            }
    
            public LatLng getLatLng() {
                return new LatLng(currentLocation.Latitude, currentLocation.Longitude);
    
            }
            public bool canGetLocation() {
                return locationAvailable && currentLocation != null;
            }
    
            public void OnConnected(Bundle connectionHint) {
                // Get last known recent location. If the user launches the activity,
                // moves to a new location, and then changes the device orientation, the original location
                // is displayed as the activity is re-created.
                currentLocation = LocationServices.FusedLocationApi.GetLastLocation(mGoogleApiClient);
    
                if (currentLocation != null) {
                    locationAvailable = true;
                    LocationServices.FusedLocationApi.RequestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
    
                    if (map != null) {
                        map.AnimateCamera(CameraUpdateFactory.NewLatLngZoom(getLatLng(), LocationTracker.DEFAULT_ZOOM));
                    }
                }
            }
    
            public void OnConnectionSuspended(int cause) {
                // GoogleApiClient will automatically attempt to restore the connection.
                // Applications should disable UI components that require the service, and wait for a call to onConnected(Bundle) to re-enable them
                if (cause == GoogleApiClient.ConnectionCallbacks.CauseServiceDisconnected) {
                    Toast.MakeText(activity, "Location Services disconnected. Please re-connect.", ToastLength.Long).Show();
                } else if (cause == GoogleApiClient.ConnectionCallbacks.CauseNetworkLost) {
                    Toast.MakeText(activity, "Network lost. Please re-connect.", ToastLength.Long).Show();
                }
            }
    
            public void OnLocationChanged(Location location) {
                currentLocation = location;
            }
    
            public void OnConnectionFailed(ConnectionResult result) {
                Console.WriteLine("Connection failed: " + result.ToString());
            }
        }
    }
    
    using System;
    using Android.OS;
    using Android.Locations;
    using Android.Runtime;
    using Android.App;
    using Android.Content;
    using Android.Widget;
    using Android.Gms.Maps.Model;
    using Java.Util.Concurrent;
    
    namespace Maps.Droid.LocationService {
        public class AndroidLocation : Java.Lang.Object, ILocationListener {
            // Properties
            private LocationManager locMgr;
            private Activity activity;
            private Location locationGPS, locationNetwork/*, locationPassive*/, currentLocation;
            private bool locationAvailable = false;
            private Android.Gms.Maps.GoogleMap map;
    
            // UNCOMMNET
            // private bool isPassiveEnabled = false; // Gets location from other apps that uses Location Services
    
            // Initializer method (Constructor). Call this method onCreate
            public AndroidLocation(Activity activity) {
                this.activity = activity;
                getLocation();
            }
    
            public Location getCurrentLocation() {
                return currentLocation;
            }
    
            public void setMap(Android.Gms.Maps.GoogleMap map) {
                this.map = map;
            }
    
            private Location getLocation() {
                // Use Standard Android Location Service Provider
                try {
                    locMgr = activity.GetSystemService(Context.LocationService) as LocationManager;
    
                    bool isGPSEnabled = locMgr.IsProviderEnabled(LocationManager.GpsProvider);
    
                    // Varying precision, Less power consuming. Combination of WiFi and Cellular data
                    bool isNetworkEnabled = locMgr.IsProviderEnabled(LocationManager.NetworkProvider);
    
                    // UNCOMMENT
                    // bool isPassiveEnabled = locMgr.IsProviderEnabled(LocationManager.GpsProvider);
    
                    // UNCOMMNET
                    //if (isPassiveEnabled) {
                    //    locMgr.RequestLocationUpdates(LocationManager.PassiveProvider, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
                    //    locationPassive = locMgr.GetLastKnownLocation(LocationManager.PassiveProvider);
                    //}
    
                    if (isGPSEnabled) {
                        locMgr.RequestLocationUpdates(LocationManager.GpsProvider, LocationTracker.MIN_TIME_BW_UPDATES, LocationTracker.MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
                        locationGPS = locMgr?.GetLastKnownLocation(LocationManager.GpsProvider);
                    }
    
                    if (isNetworkEnabled) {
                        locMgr.RequestLocationUpdates(LocationManager.NetworkProvider, LocationTracker.MIN_TIME_BW_UPDATES, LocationTracker.MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
                        locationNetwork = locMgr?.GetLastKnownLocation(LocationManager.NetworkProvider);
                    }
    
                    // UNCOMMENT - Method must be implement if PassiveLocation is to be used
                    // currentLocation = getBestLocation(locationGPS, locationNetwork, locationPassive);
    
                    currentLocation = getBestLocation(locationNetwork, locationGPS);
    
                    if (currentLocation != null) {
                        locationAvailable = true;
                        if (map != null) {
                            map.AnimateCamera(Android.Gms.Maps.CameraUpdateFactory.NewLatLngZoom(getLatLng(), LocationTracker.DEFAULT_ZOOM));
                        }
                    }
                } catch (Exception e) {
                    Console.WriteLine("ERROR: getLocation() " + e.ToString());
                }
    
                return currentLocation;
            }
    
            // Determines the most recent and/or most accurate location
            private Location getBestLocation(Location loc1, Location loc2) {
                if (loc1 == null || loc2 == null) {
                    return loc1 ?? loc2; // If either location is null then return the not null location
                }
    
                long time1 = TimeUnit.Milliseconds.ToSeconds(loc1.Time);
                long time2 = TimeUnit.Milliseconds.ToSeconds(loc2.Time);
    
                long twiceUpdate = (LocationTracker.MIN_TIME_BW_UPDATES / 1000) * 2;
                if (Math.Abs(time1 - time2) > twiceUpdate) { // If location times are more than twiceUpdate apart
                    if (time1 > time2) { // More time value, most current time
                        return loc1;
                    } else {
                        return loc2;
                    }
                } else {
                    float accuracy1 = loc1.Accuracy;
                    float accuracy2 = loc2.Accuracy;
    
                    // Smaller the value (meters), the greater the accuracy
                    if (accuracy1 < accuracy2) {
                        return loc1;
                    } else {
                        return loc2;
                    }
                }
            }
    
            public void OnStop() {
                locMgr = null;
            }
    
            public void OnPause() {
                locMgr?.RemoveUpdates(this);
            }
    
            public void OnStart() {
            }
    
            public void OnResume() {
                if (locMgr == null || currentLocation == null) {
                    getLocation();
                }
            }
    
            public bool canGetLocation() {
                return locationAvailable;
            }
    
            public LatLng getLatLng() {
                return new LatLng(currentLocation.Latitude, currentLocation.Longitude);
            }
    
            public double getLatitude() {
                return currentLocation.Latitude;
            }
    
            public double getLongitude() {
                return currentLocation.Longitude;
            }
    
            public void OnLocationChanged(Location location) {
                currentLocation = getBestLocation(currentLocation, location);
            }
    
            // User disabled a provider
            public void OnProviderDisabled(string provider) {
                getLocation(); // Check if all providers are disabled and pop up alertDialog if they are so
            }
    
            // User enabled a provider
            public void OnProviderEnabled(string provider) {
                getLocation(); // Update all available providers for getting the best provider available
            }
    
            public void OnStatusChanged(string provider, [GeneratedEnum] Availability status, Bundle extras) {
            }
        }
    }
    
    using Android.App;
    using Android.Gms.Common;
    using Android.Gms.Common.Apis;
    using Android.Gms.Maps.Model;
    using Android.Gms.Maps;
    using Android.Locations;
    using Android.Content;
    using Android.Widget;
    
    namespace Maps.Droid.LocationService {
        public class LocationTracker {
            public static long MIN_DISTANCE_CHANGE_FOR_UPDATES = 5; // 5 meters
            public static long MIN_TIME_BW_UPDATES = 1000 * 15; // 15 seconds ok, 5 seconds really fast, 30s slow
            public static float DEFAULT_ZOOM = 16f;
    
            private bool hasGooglePlayServices;
            public GoogleApiClient mGoogleApiClient;
            private FusedLocation fusedLocation;
            private AndroidLocation androidLocation;
            private bool locationIsDisabled;
    
            public LocationTracker(Activity activity) {
                if (locationIsDisabled = isLocationDisabled(activity)) {
                    showSettingsAlert(activity);
                } else {
                    hasGooglePlayServices = checkPlayServices(activity);
    
                    if (hasGooglePlayServices) {
                        fusedLocation = new FusedLocation(activity);
                    } else {
                        androidLocation = new AndroidLocation(activity);
                    }
                }
            }
    
            private void showSettingsAlert(Activity activity) {
                AlertDialog.Builder builder = new AlertDialog.Builder(activity);
                builder.SetTitle("Location Services Not Active");
                builder.SetMessage("Please enable Location Services and GPS");
                builder.SetPositiveButton("OK", delegate {
                    // Show location settings when the user acknowledges the alert dialog
                    var intent = new Intent(Android.Provider.Settings.ActionLocationSourceSettings);
                    activity.StartActivity(intent);
                });
                builder.SetNegativeButton("Cancel", delegate {
                    Toast.MakeText(activity, "Location disabled by user", ToastLength.Short).Show();
                });
                AlertDialog alertDialog = builder.Create();
                alertDialog.SetCanceledOnTouchOutside(false);
                alertDialog.Show();
            }
    
            private bool isLocationDisabled(Activity activity) {
                LocationManager locMgr = activity.GetSystemService(Context.LocationService) as LocationManager;
    
                // More precise, More power consuming
                bool isGPSEnabled = locMgr.IsProviderEnabled(LocationManager.GpsProvider);
    
                // Varying precision, Less power consuming. Combination of WiFi and Cellular data
                bool isNetworkEnabled = locMgr.IsProviderEnabled(LocationManager.NetworkProvider);
    
                // UNCOMMENT
                // bool isPassiveEnabled = locMgr.IsProviderEnabled(LocationManager.PassiveProvider);
    
                // UNCOMMENT
                // return !isGPSEnabled && !isNetworkEnabled && !isPassiveEnabled; // True only when the 3 location services are disabled
    
                return !isGPSEnabled && !isNetworkEnabled; // True only when both location services are disabled
            }
    
            // Call this method at OnMapReady callback if initial zooming/animation on user's location is desired
            public void setMap(GoogleMap map) {
                if (locationIsDisabled) {
                    return;
                }
    
                if (hasGooglePlayServices) {
                    fusedLocation.setMap(map);
                } else {
                    androidLocation.setMap(map);
                }
            }
    
            public void OnResume() {
                if (locationIsDisabled) {
                    return;
                }
    
                if (hasGooglePlayServices) {
                    fusedLocation.OnResume();
                } else {
                    androidLocation.OnResume();
                }
            }
    
            public void OnPause() {
                if (locationIsDisabled) {
                    return;
                }
    
                if (hasGooglePlayServices) {
                    fusedLocation.OnPause();
                } else {
                    androidLocation.OnPause();
                }
            }
    
            public void OnStart() {
                if (locationIsDisabled) {
                    return;
                }
    
                if (hasGooglePlayServices) {
                    fusedLocation.OnStart();
                } else {
                    androidLocation.OnStart();
                }
            }
    
            public void OnStop() {
                if (locationIsDisabled) {
                    return;
                }
    
                if (hasGooglePlayServices) {
                    fusedLocation.OnStop();
                } else {
                    androidLocation.OnStop();
                }
            }
    
            private bool checkPlayServices(Activity activity) {
                GoogleApiAvailability apiAvailability = GoogleApiAvailability.Instance;
                int resultCode = apiAvailability.IsGooglePlayServicesAvailable(activity);
                if (resultCode == ConnectionResult.Success) {
                    return true;
                }
                return false;
            }
    
            public double getLatitude() {
                if (locationIsDisabled) {
                    return 0;
                }
    
                if (hasGooglePlayServices) {
                    return fusedLocation.getCurrentLocation() == null ? 0.0 : fusedLocation.getLatitude();
                } else {
                    return androidLocation.getCurrentLocation() == null ? 0.0 : androidLocation.getLatitude();
                }
            }
    
            public double getLongitude() {
                if (locationIsDisabled) {
                    return 0;
                }
    
                if (hasGooglePlayServices) {
                    return fusedLocation.getCurrentLocation() == null ? 0.0 : fusedLocation.getLongitude();
                } else {
                    return androidLocation.getCurrentLocation() == null ? 0.0 : androidLocation.getLongitude();
                }
            }
    
            public bool canGetLocation() {
                if (locationIsDisabled) {
                    return false;
                }
    
                if (hasGooglePlayServices) {
                    return fusedLocation.canGetLocation();
                } else {
                    return androidLocation.canGetLocation();
                }
            }
    
            public LatLng getLatLng() {
                if (locationIsDisabled) {
                    return null;
                }
    
                LatLng latlng;
                if (hasGooglePlayServices) {
                    latlng = fusedLocation.getLatLng();
                } else {
                    latlng = androidLocation.getLatLng();
                }
    
                return latlng;
            }
    
            public Location getCurrentLocation() {
                if (hasGooglePlayServices) {
                    return fusedLocation.getCurrentLocation();
                } else {
                    return androidLocation.getCurrentLocation();
                }
            }
        }
    }
    

    然后在您的片段或活动上使用它:

    在 OnCreate 初始化它:

    Location tracker = new LocationTracker(this.Activity);
    

    为生命周期做一个参照:

    public override void OnResume() {
                base.OnResume();
                tracker.OnResume();
            }
    
            public override void OnPause() {
                base.OnPause();
                tracker.OnPause();
            }
    
            public override void OnStart() {
                base.OnStart();
                tracker.OnStart();
            }
    
            public override void OnStop() {
                base.OnStop();
                tracker.OnStop();
            }
    

    如果您希望动画在开始时缩放到用户位置,那么您必须在拥有 googlemap 时添加这行代码:

    tracker.setMap(googleMap); // Invoke this method if zooming/animating to the user's location is desired
    

    在这个解决方案上花了很多天。希望它可以帮助别人!

    【讨论】:

    • 我遇到的问题是 OnMapReady 方法是在 OnConnected 方法之前调用的。所以当我在 OnMapReady 上得到纬度和经度时,仍然是 null
    • 在 OnLocationChanged 方法中,您可以重新设置地图的动画。也许这个链接可以帮助你:stackoverflow.com/questions/33739971/…
    猜你喜欢
    • 1970-01-01
    • 2019-10-26
    • 2017-07-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-02
    • 2016-12-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多