Xamarin - onLocationChanged不会使用fusedLocationAPI.requestLocationUpdates调用

时间:2016-08-06 17:26:23

标签: android xamarin location

我一直在尝试使用fusedLocationApi来获取当前位置。我使用Xamarin和模拟的Nexus 5(Genymotion)也在设备上进行测试。根据在线文档https://developer.android.com/training/location/receive-location-updates.html?hl=es,我们可以使用以下方式请求位置更新:

FusedLocationApi.requestLocationUpdates

并且回调转到:

onLocationChanged(位置位置)

它的作品低于api 23 ..

using Android.App;
using Android.OS;
using Android.Views;
using System.Threading.Tasks;
using Android.Gms.Maps;
using Android.Gms.Common;
using Android.Locations;
using Android.Gms.Common.Apis;
using Android.Gms.Location;
using Android.Gms.Maps.Model;
using Android;
using Android.Support.Design.Widget;
using Android.Content.PM;

namespace stops
{
    public class MapFragment : FocuableFragment, IOnMapReadyCallback, Android.Gms.Common.Apis.GoogleApiClient.IOnConnectionFailedListener, Android.Gms.Common.Apis.GoogleApiClient.IConnectionCallbacks, ILocationSource, Android.Gms.Location.ILocationListener
    {

        private View _view;

        readonly string[] PermissionsLocation =
        {
            Manifest.Permission.AccessCoarseLocation,
            Manifest.Permission.AccessFineLocation,
            Manifest.Permission.AccessNetworkState
        };

        const int RequestLocationId = 0;

        private GoogleApiClient mGoogleApiClient;
        private static LocationRequest REQUEST;
        private ILocationSourceOnLocationChangedListener mMapLocationListener;

        public void OnConnectionFailed(ConnectionResult result)
        {
            // Do nothing
        }

        public void OnConnected(Bundle connectionHint)
        {
            LocationServices.FusedLocationApi.RequestLocationUpdates(
                mGoogleApiClient,
                REQUEST,
                this);  // LocationListener

        }

        public void OnConnectionSuspended(int cause)
        {
            // Do nothing
        }

        public void OnLocationChanged(Location location)
        {
            var newLocation = location;


            if (mMapLocationListener != null)
            {
                mMapLocationListener.OnLocationChanged(location);
            }
        }

        public void Activate(ILocationSourceOnLocationChangedListener listener)
        {
            mMapLocationListener = listener;
        }

        public void Deactivate()
        {
            mMapLocationListener = null;
        }



        private SupportMapFragment _supportMapFragment;
        private GoogleMap _googleMap;

        private ViewGroup _mapcardLayout;

        public override void onFocus()
        {

        }

        public override void offFocus()
        {

        }


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

            // Create your fragment here
        }

        public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
        {
            // Use this to return your custom view for this Fragment
            _view = inflater.Inflate(Resource.Layout.MapCard, container, false);

            _mapcardLayout = (ViewGroup)_view.FindViewById(Resource.Id.mapcardLayout);

            /*
             * Create the map
             */
            _supportMapFragment = new SupportMapFragment();
            Android.Support.V4.App.FragmentTransaction transaction = FragmentManager.BeginTransaction();

            transaction.Add(Resource.Id.mainMapFragmentMapWrapper, _supportMapFragment);
            transaction.SetTransition(Android.Support.V4.App.FragmentTransaction.TransitFragmentFade);
            transaction.Commit();

            _supportMapFragment.GetMapAsync(this);

            return _view;
        }

        public void EnableAPI()
        {

            if (mGoogleApiClient != null && !mGoogleApiClient.IsConnected)
            {
                mGoogleApiClient.Connect();
            }
        }


        public void DisableAPI()
        {
            if (mGoogleApiClient != null && mGoogleApiClient.IsConnected)
            {
                mGoogleApiClient.Disconnect();
            }
        }

        public void OnMapReady(GoogleMap googleMap)
        {
            _googleMap = googleMap;
            _googleMap.UiSettings.MapToolbarEnabled = false;
            _googleMap.UiSettings.CompassEnabled = false;
            _googleMap.UiSettings.MyLocationButtonEnabled = false;
            _googleMap.UiSettings.TiltGesturesEnabled = false;

            _googleMap.MapType = GoogleMap.MapTypeHybrid;

            TryGetLocationAsync();
        }


        async void TryGetLocationAsync()
        {
            if ((int)Build.VERSION.SdkInt < 23)
            {
                Snackbar.Make(_mapcardLayout, "Aktiverar gps (lågenergi-läge används)", Snackbar.LengthShort).Show();

                EnableLocation();
                return;
            }

            await GetLocationPermissionAsync();
        }

        async Task<int> GetLocationPermissionAsync()
        {
            //Check to see if any permission in our group is available, if one, then all are
            const string permission = Manifest.Permission.AccessFineLocation;
            if (Application.Context.CheckSelfPermission(permission) == (int)Permission.Granted)
            {
                Snackbar.Make(_mapcardLayout, "Aktiverar gps (lågenergi-läge används)", Snackbar.LengthShort).Show();
                EnableLocation();
                return 1;
            }

            //need to request permission
            if (ShouldShowRequestPermissionRationale(permission))
            {
                //Explain to the user why we need to read the contacts
                Snackbar.Make(_mapcardLayout, "GPS (lågenergi-läge) behövs för att visa vart du är.", Snackbar.LengthIndefinite)
                        .SetAction("OK", v => RequestPermissions(PermissionsLocation, RequestLocationId))
                        .Show();
                return 1;
            }

            Snackbar.Make(_mapcardLayout, "GPS (lågenergi-läge) behövs för att visa vart du är.", Snackbar.LengthLong)
                        .Show();

            await Task.Delay(1250);

            //Finally request permissions with the list of permissions and Id
            RequestPermissions(PermissionsLocation, RequestLocationId);

            return 1;
        }

        public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Permission[] grantResults)
        {

            switch (requestCode)
            {
                case RequestLocationId:
                    {
                        if (grantResults[0] == Permission.Granted)
                        {
                            //Permission granted
                            var snack = Snackbar.Make(_mapcardLayout, "Aktiverar GPS.", Snackbar.LengthShort);
                            snack.Show();

                            EnableLocation();
                        }
                        else
                        {
                            //Permission Denied :(
                            //Disabling location functionality
                            var snack = Snackbar.Make(_mapcardLayout, "Användning av GPS nekad.", Snackbar.LengthShort);
                            snack.Show();
                        }
                    }
                    break;
            }
        }

        public void EnableLocation()
        {

            REQUEST = LocationRequest.Create().SetPriority(LocationRequest.PriorityBalancedPowerAccuracy);


            _googleMap.MyLocationEnabled = true;
            _googleMap.UiSettings.MapToolbarEnabled = false;
            _googleMap.UiSettings.CompassEnabled = false;
            _googleMap.UiSettings.MyLocationButtonEnabled = false;
            _googleMap.UiSettings.TiltGesturesEnabled = false;

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

            mGoogleApiClient.Connect();

            _googleMap.SetLocationSource(this);


            /*
             *  Init GPS posistioning
             */
            PositionCamera(Util.Util.GetLastKnownLocation());




        }

        Location PositionCamera(Location location)
        {
            if (location != null)
            {
                _googleMap.AnimateCamera(CameraUpdateFactory.NewLatLngZoom(new LatLng(57.695443, 11.992507), 15.0f));
            }
            else {
                _googleMap.AnimateCamera(CameraUpdateFactory.NewLatLngZoom(new LatLng(57.695443, 11.992507), 15.0f));
            }
            return location;
        }
    }
}

解决方案

using Android.App;
using Android.OS;
using Android.Views;
using System.Threading.Tasks;
using Android.Gms.Maps;
using Android.Gms.Common;
using Android.Locations;
using Android.Gms.Common.Apis;
using Android.Gms.Location;
using Android.Gms.Maps.Model;
using Android;
using Android.Support.Design.Widget;
using Android.Content.PM;
using Java.Lang;
using Android.Util;
using System;
using Android.Content;

namespace stops
{
    public class MapFragment : FocuableFragment, Android.Gms.Maps.IOnMapReadyCallback, GoogleApiClient.IConnectionCallbacks,
        GoogleApiClient.IOnConnectionFailedListener, Android.Gms.Location.ILocationListener, Android.Gms.Maps.ILocationSource
    {

        readonly string[] PermissionsLocation =
        {
            Manifest.Permission.AccessCoarseLocation,
            Manifest.Permission.AccessFineLocation,
            Manifest.Permission.AccessNetworkState
        };

        const int RequestLocationId = 0;



        private View _view;
        private SupportMapFragment _supportMapFragment;
        private GoogleMap _googleMap;

        protected const string TAG = "location-settings";
        protected const int REQUEST_CHECK_SETTINGS = 0x1;
        public const long UPDATE_INTERVAL_IN_MILLISECONDS = 5000;
        public const long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS = UPDATE_INTERVAL_IN_MILLISECONDS / 2;
        protected const string KEY_REQUESTING_LOCATION_UPDATES = "requesting-location-updates";
        protected const string KEY_LOCATION = "location";
        protected const string KEY_LAST_UPDATED_TIME_STRING = "last-updated-time-string";

        protected GoogleApiClient mGoogleApiClient;
        protected LocationRequest mLocationRequest;
        protected LocationSettingsRequest mLocationSettingsRequest;
        protected Location mCurrentLocation;

        private ViewGroup _mapcardLayout;

        protected bool mRequestingLocationUpdates;
        protected string mLastUpdateTime;
        private ILocationSourceOnLocationChangedListener mMapLocationListener;

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

            // Create your fragment here
        }

        public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
        {
            // Use this to return your custom view for this Fragment
            _view = inflater.Inflate(Resource.Layout.MapCard, container, false);
            _mapcardLayout = (ViewGroup)_view.FindViewById(Resource.Id.mapcardLayout);


            /*
             * Create the map
             */
            _supportMapFragment = new SupportMapFragment();
            Android.Support.V4.App.FragmentTransaction transaction = FragmentManager.BeginTransaction();

            transaction.Add(Resource.Id.mainMapFragmentMapWrapper, _supportMapFragment);
            transaction.SetTransition(Android.Support.V4.App.FragmentTransaction.TransitFragmentFade);
            transaction.Commit();

            _supportMapFragment.GetMapAsync(this);

            return _view;
        }


        async void TryGetLocationAsync()
        {

            if (Build.VERSION.SdkInt > Android.OS.BuildVersionCodes.Lollipop)
            {
                await GetLocationPermissionAsync();
                return;
            }

            await CheckLocationSettings();
        }

        async Task<int> GetLocationPermissionAsync()
        {
            //Check to see if any permission in our group is available, if one, then all are
            const string permission = Manifest.Permission.AccessFineLocation;
            if (Application.Context.CheckSelfPermission(permission) == (int)Permission.Granted)
            {
                Snackbar.Make(_mapcardLayout, "Aktiverar gps (lågenergi-läge används)", Snackbar.LengthShort).Show();
                await CheckLocationSettings();
                return 1;
            }

            //need to request permission
            if (ShouldShowRequestPermissionRationale(permission))
            {
                //Explain to the user why we need to read the contacts
                Snackbar.Make(_mapcardLayout, "GPS (lågenergi-läge) behövs för att visa vart du är.", Snackbar.LengthIndefinite)
                        .SetAction("OK", v => RequestPermissions(PermissionsLocation, RequestLocationId))
                        .Show();
                return 1;
            }

            Snackbar.Make(_mapcardLayout, "GPS (lågenergi-läge) behövs för att visa vart du är.", Snackbar.LengthLong)
                        .Show();

            await Task.Delay(1250);

            //Finally request permissions with the list of permissions and Id
            RequestPermissions(PermissionsLocation, RequestLocationId);

            return 1;
        }

        public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Permission[] grantResults)
        {

            switch (requestCode)
            {
                case RequestLocationId:
                    {
                        if (grantResults[0] == Permission.Granted)
                        {
                            //Permission granted
                            var snack = Snackbar.Make(_mapcardLayout, "Aktiverar GPS.", Snackbar.LengthShort);
                            snack.Show();

                            CheckLocationSettings();
                        }
                        else
                        {
                            //Permission Denied :(
                            //Disabling location functionality
                            var snack = Snackbar.Make(_mapcardLayout, "Användning av GPS nekad.", Snackbar.LengthShort);
                            snack.Show();
                        }
                    }
                    break;
            }
        }


        public void OnMapReady(GoogleMap googleMap)
        {
            _googleMap = googleMap;
            _googleMap.UiSettings.MapToolbarEnabled = false;
            _googleMap.UiSettings.CompassEnabled = false;
            _googleMap.UiSettings.MyLocationButtonEnabled = false;
            _googleMap.UiSettings.TiltGesturesEnabled = false;

            _googleMap.MapType = GoogleMap.MapTypeHybrid;

            PositionCamera();

            BuildGoogleApiClient();

            EnableAPI();
            CreateLocationRequest();
            BuildLocationSettingsRequest();


            TryGetLocationAsync();

        }


        void PositionCamera()
        {
            _googleMap.AnimateCamera(CameraUpdateFactory.NewLatLngZoom(new LatLng(57.695443, 11.992507), 15.0f));
        }


        protected void BuildGoogleApiClient()
        {
            Log.Info(TAG, "Building GoogleApiClient");
            mGoogleApiClient = new GoogleApiClient.Builder(Activity)
                .AddConnectionCallbacks(this)
                .AddOnConnectionFailedListener(this)
                .AddApi(LocationServices.API)
                .Build();
        }

        public void EnableAPI()
        {

            if (mGoogleApiClient != null && !mGoogleApiClient.IsConnected)
            {
                mGoogleApiClient.Connect();
            }
        }


        public void DisableAPI()
        {
            if (mGoogleApiClient != null && mGoogleApiClient.IsConnected)
            {
                mGoogleApiClient.Disconnect();
            }
        }

        protected void CreateLocationRequest()
        {
            mLocationRequest = new LocationRequest();
            mLocationRequest.SetInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
            mLocationRequest.SetFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
            mLocationRequest.SetPriority(LocationRequest.PriorityHighAccuracy);
        }

        protected void BuildLocationSettingsRequest()
        {
            LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
            builder.AddLocationRequest(mLocationRequest);
            mLocationSettingsRequest = builder.Build();
        }


        protected async Task CheckLocationSettings()
        {
            var result = await LocationServices.SettingsApi.CheckLocationSettingsAsync(
                mGoogleApiClient, mLocationSettingsRequest);
            await HandleResult(result);
        }

        public async Task HandleResult(LocationSettingsResult locationSettingsResult)
        {
            var status = locationSettingsResult.Status;
            switch (status.StatusCode)
            {
                case CommonStatusCodes.Success:
                    Log.Info(TAG, "All location settings are satisfied.");
                    await StartLocationUpdates();
                    break;
                case CommonStatusCodes.ResolutionRequired:
                    Log.Info(TAG, "Location settings are not satisfied. Show the user a dialog to" +
                    "upgrade location settings ");

                    try
                    {
                        status.StartResolutionForResult(Activity, REQUEST_CHECK_SETTINGS);
                    }
                    catch (IntentSender.SendIntentException)
                    {
                        Log.Info(TAG, "PendingIntent unable to execute request.");
                    }
                    break;
                case LocationSettingsStatusCodes.SettingsChangeUnavailable:
                    Log.Info(TAG, "Location settings are inadequate, and cannot be fixed here. Dialog " +
                    "not created.");
                    break;
            }
        }



        protected async Task StartLocationUpdates()
        {
            await LocationServices.FusedLocationApi.RequestLocationUpdates(
                mGoogleApiClient,
                mLocationRequest,
                this
            );

            _googleMap.MyLocationEnabled = true;
            _googleMap.SetLocationSource(this);


            mRequestingLocationUpdates = true;

        }

        protected async Task StopLocationUpdates()
        {
            await LocationServices.FusedLocationApi.RemoveLocationUpdates(
                    mGoogleApiClient,
                    this
                );

            mRequestingLocationUpdates = false;
        }

        public void OnConnectionFailed(ConnectionResult result)
        {
            Log.Info(TAG, "Connection failed: ConnectionResult.getErrorCode() = " + result.ErrorCode);
        }

        public void OnLocationChanged(Location location)
        {
            mCurrentLocation = location;


            mLastUpdateTime = DateTime.Now.TimeOfDay.ToString();

            if (mMapLocationListener != null)
            {
                mMapLocationListener.OnLocationChanged(location);
            }
        }

        public void OnConnected(Bundle connectionHint)
        {
            if (mCurrentLocation == null)
            {
                mCurrentLocation = LocationServices.FusedLocationApi.GetLastLocation(mGoogleApiClient);
                mLastUpdateTime = DateTime.Now.TimeOfDay.ToString();
            }
        }

        public void OnConnectionSuspended(int cause)
        {
            Log.Info(TAG, "Connection suspended");
        }

        public void Activate(ILocationSourceOnLocationChangedListener listener)
        {
            mMapLocationListener = listener;
        }

        public void Deactivate()
        {
            mMapLocationListener = null;
        }
    }   
}

0 个答案:

没有答案