【问题标题】:Xamarin Location Service OnLocationChanged dont triggerXamarin 位置服务 OnLocationChanged 不触发
【发布时间】:2018-04-27 05:52:41
【问题描述】:

我们有一个问题,它在某些设备上随机发生,即无法触发 OnLocationChanged 事件。

LocationManager.RequestLocationUpdates(LocationManager.GpsProvider, 30000, 100, this);
LocationManager.RequestLocationUpdates(LocationManager.NetworkProvider, 30000, 100, this);

我们也尝试设置一个计时器,如果一分钟后事件没有触发,我们将尝试获取最后一个已知位置,但它仍然返回 null。

 CurrentLocation = LocationManager.GetLastKnownLocation(LocationManager.GpsProvider);
            LocationManager.RequestLocationUpdates(LocationManager.GpsProvider, 0, 0, this);

            if (CurrentLocation == null)//network provider
            {
                CurrentLocation = LocationManager.GetLastKnownLocation(LocationManager.NetworkProvider);
                LocationManager.RequestLocationUpdates(LocationManager.NetworkProvider, 0, 0, this);
            }

            if (CurrentLocation == null)//passive provider
            {
                CurrentLocation = LocationManager.GetLastKnownLocation(LocationManager.PassiveProvider);
                LocationManager.RequestLocationUpdates(LocationManager.PassiveProvider, 0, 0, this);
            }

我可以知道我的代码有什么问题吗?

已编辑(完整代码):

public class LocationService : Service, ILocationListener
{
    public IBinder Binder { get; private set; }
    public MainActivity MainAC { get { return m_ac; } set { m_ac = value; } }
    public Android.Locations.Location CurrentLocation { get; set; }
    public Android.Locations.LocationManager LocationManager { get; set; }
    public DateTime LastUpdateTime { get; set; }
    public bool IsMockLocation { get; set; }
    public string CurrentAddress { get; set; }
    public string CurrentCity { get; set; }

    private int iUpdateLocationInterval = 30000;// 30sec
    private int iUpdateLocationDistance = 100;// 100meter

    private int iUpdateLocationInterval_LastKnown = 0;// 0sec
    private int iUpdateLocationDistance_LastKnown = 0;// 0meter

    private System.Timers.Timer timerBackground = null;
    private MainActivity m_ac;
    private Lib.GoogleMaps google = new Lib.GoogleMaps();
    private bool bUpdateLocationIntervalUnknown = false;

    public LocationService()
    {
    }

    #region Override Function
    public override void OnCreate()
    {
        base.OnCreate();
    }

    [return: GeneratedEnum]
    public override StartCommandResult OnStartCommand(Intent intent, [GeneratedEnum] StartCommandFlags flags, int startId)
    {
        StartCommandResult result = base.OnStartCommand(intent, flags, startId);

        return result;
    }

    public override void OnDestroy()
    {
        Binder = null;

        if (LocationManager != null)
        {
            LocationManager.RemoveUpdates(this);
        }

        base.OnDestroy();
    }

    public override IBinder OnBind(Intent intent)
    {
        // Return the communication channel to the service.

        this.Binder = new LocalLocationBinder(this);
        return this.Binder;
    }
    #endregion

    private void StartBackgroundTimer()
    {
        timerBackground = new System.Timers.Timer();
        timerBackground.Elapsed -= TimerBackground_Elapsed;
        timerBackground.Elapsed += TimerBackground_Elapsed;
        timerBackground.Interval = 10000;
        timerBackground.AutoReset = false;
        timerBackground.Enabled = true;
    }

    private void TimerBackground_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    {
        timerBackground.Enabled = false;

        try
        { 
            if (CurrentLocation == null)// OnLocationChanged didnt trigger, so get from last known location
            {
                GetLastKnownLocation();
            }
        }
        catch { }
    }

    public void GetLastKnownLocation()
    {
        m_ac.RunOnUiThread(() =>
        {
            bUpdateLocationIntervalUnknown = true;
            CurrentLocation = LocationManager.GetLastKnownLocation(LocationManager.GpsProvider);
            LocationManager.RequestLocationUpdates(LocationManager.GpsProvider, iUpdateLocationInterval_LastKnown, iUpdateLocationDistance_LastKnown, this);

            if (CurrentLocation == null)//network provider
            {
                CurrentLocation = LocationManager.GetLastKnownLocation(LocationManager.NetworkProvider);
                LocationManager.RequestLocationUpdates(LocationManager.NetworkProvider, iUpdateLocationInterval_LastKnown, iUpdateLocationDistance_LastKnown, this);
            }

            if (CurrentLocation == null)//passive provider
            {
                CurrentLocation = LocationManager.GetLastKnownLocation(LocationManager.PassiveProvider);
                LocationManager.RequestLocationUpdates(LocationManager.PassiveProvider, iUpdateLocationInterval_LastKnown, iUpdateLocationDistance_LastKnown, this);
            }

            if (CurrentLocation != null)
            {
                UpdateCurrentLocationInterval();
                ResolveGPSCoordinates(CurrentLocation);
            }
            else
            {
                m_ac.UpdateLocationName(Function.GetLanguage(m_ac, Resource.String.lblLocationServiceGetFailure));
            }
        }); 
    }

    // Location GPS
    public  void InitializeLocationManager()
    {
        try
        {
            m_ac.RunOnUiThread(() =>
            {
                try
                {
                    if (LocationManager != null) return;

                    LocationManager = (LocationManager)GetSystemService(LocationService);
                    Criteria criteriaForLocationService = new Criteria
                    {
                        Accuracy = Accuracy.Fine
                    };
                    IList<string> acceptableLocationProviders = LocationManager.GetProviders(criteriaForLocationService, true);

                    if (!LocationManager.IsProviderEnabled(LocationManager.GpsProvider))
                    {
                        m_ac.ShowMessageToast(Function.GetLanguage(this, Resource.String.lblGPSLocationIsNotEnabled));
                        return;
                    }

                    if (acceptableLocationProviders.Any())
                    {
                        StartBackgroundTimer();
                        LocationManager.RequestLocationUpdates(LocationManager.GpsProvider, iUpdateLocationInterval, iUpdateLocationDistance, this);
                        LocationManager.RequestLocationUpdates(LocationManager.NetworkProvider, iUpdateLocationInterval, iUpdateLocationDistance, this);
                    }
                    else
                    {
                        m_ac.ShowMessageToast(Function.GetLanguage(this, Resource.String.lblGPSLocationIsNotEnabled));
                    }
                }
                catch(Exception ex) { m_ac.ShowMessageToast("ERROR:" + ex.Message); }
            });  

        }
        catch (Exception ex) { m_ac.ShowMessageToast("ERROR:" + ex.Message); }
    }

    private void UpdateCurrentLocationInterval()
    {
        try
        {
            if (LocationManager != null)
            {
                bUpdateLocationIntervalUnknown = false ;
                LocationManager.RequestLocationUpdates(LocationManager.GpsProvider, iUpdateLocationInterval, iUpdateLocationDistance, this);
                LocationManager.RequestLocationUpdates(LocationManager.NetworkProvider, iUpdateLocationInterval, iUpdateLocationDistance, this);
            }
        }
        catch { }
    }

    public void OnLocationChanged(Location location)
    {
        LastUpdateTime = DateTime.Now;
        IsMockLocation = true;
        CurrentLocation = location;
        CurrentAddress = string.Empty;
        CurrentCity = string.Empty;

        if (bUpdateLocationIntervalUnknown)
        {
            UpdateCurrentLocationInterval();
        }

        if (location.IsFromMockProvider)
        {
            CurrentLocation = null;
            m_ac.UpdateLocationName(CurrentCity);
        }
        else
        {
            IsMockLocation = false;

            ResolveGPSCoordinates(location);
        }
    }

    private void ResolveGPSCoordinates(Location location)
    {
        ResolveGPSCoordinatesAwait(location);
    }

    private async void ResolveGPSCoordinatesAwait(Location location)
    {
        int iResult = await google.ResolveLatLng(location.Latitude, location.Longitude);

        if (iResult == 0)
        {
            CurrentAddress = google.AddressName;
            CurrentCity = google.CityName;

            if(CurrentCity == string.Empty)
                m_ac.UpdateLocationName(Function.GetLanguage(m_ac, Resource.String.lblLocationServiceGetFailure));
            else
                m_ac.UpdateLocationName(CurrentCity);
        }
        else if (iResult == -2)
        {
            m_ac.UpdateLocationName(Function.GetLanguage(m_ac, Resource.String.lblLocationServiceExceedAPIQuota));
        }
        else
        {
            if (string.IsNullOrEmpty(google.APIErrorMessage))
            {
                m_ac.UpdateLocationName("ERROR:" + location.Latitude + "," + location.Longitude );
            }
            else
            {
                m_ac.UpdateLocationName(google.APIErrorMessage);
            }
        } 
    }

    public void OnProviderDisabled(string provider)
    {
        if (provider.Equals(LocationManager.GpsProvider, StringComparison.InvariantCultureIgnoreCase))
        {
            LastUpdateTime = DateTime.Now;
            IsMockLocation = false;
            CurrentLocation = null;
            CurrentAddress = string.Empty;
            CurrentCity = Function.GetLanguage(m_ac, Resource.String.lblLocationServiceDisable);

            m_ac.UpdateLocationName(CurrentCity);
        }
    }

    public void OnProviderEnabled(string provider)
    {
        UpdateCurrentLocationInterval();
    }

    public void OnStatusChanged(string provider, [GeneratedEnum] Availability status, Bundle extras)
    {

    }

}

public class LocationServiceConnection : Java.Lang.Object, IServiceConnection
{
    MainActivity m_ac = null;

    public LocationServiceConnection(MainActivity activity)
    {
        m_ac = activity;
        IsConnected = false;
        Binder = null;
    }

    public bool IsConnected { get; private set; }
    public LocalLocationBinder Binder { get; private set; }

    public void OnServiceConnected(ComponentName name, IBinder service)
    {
        Binder = service as LocalLocationBinder;
        IsConnected = this.Binder != null;
        Binder.Service.MainAC = m_ac;
        Binder?.Service.InitializeLocationManager();
    }

    public void OnServiceDisconnected(ComponentName name)
    {
        IsConnected = false;
        Binder.Service.MainAC = null;
        Binder = null; 
    } 

    public void GetLastKnownLocation()
    {
        Binder?.Service.GetLastKnownLocation();
    }

}


#region LocalBinder
public class LocalLocationBinder : Binder
{
    public LocalLocationBinder(LocationService service)
    {
        this.Service = service;
    }

    public LocationService Service { get; private set; }
} 
#endregion

【问题讨论】:

    标签: c# xamarin.android android-gps currentlocation


    【解决方案1】:

    好吧,我建议您检查是否提供了位置服务,我的意思是,如果不这样做,它们是否已打开,这样可以解决问题,您可以做的是,如果这些服务不可用,或者您可以说目前是拒绝,您可以简单地使用它来检查它是否可用,然后将您自己的代码应用于它,这可以确定您是否继续前进到地图页面。

     public class LocationEnabled : Fragment
    {
        public GoogleApiClient googleApiClient;
      //  static int REQUEST_LOCATION = 199;
        public const int MIN_TIME_BW_UPDATES = 1000 * 3;
        public const int REQUEST_CHECK_SETTINGS = 9000;
        AppCompatActivity _activity;
        public LocationEnabled(AppCompatActivity activity)
        {
            _activity = activity;
        }
        private bool hasGPSDevice(Context context)
        {
            LocationManager mgr = (LocationManager)context.GetSystemService(Context.LocationService);
            if (mgr == null)
                return false;
            IList<string> providers = mgr.AllProviders;
            if (providers == null)
                return false;
            return providers.Contains(LocationManager.GpsProvider);
        }
        private async void enableLoc()
        {
            if (googleApiClient == null)
            {
                googleApiClient = new GoogleApiClient.Builder(_activity)
                 .AddApi(LocationServices.API)
                 .AddConnectionCallbacks(new CallBackHelper(googleApiClient))
                 .AddOnConnectionFailedListener(new ConnectionFailedCallBack(_activity)).Build();
    
                googleApiClient.Connect();
    
                LocationRequest locationRequest = LocationRequest.Create();
                locationRequest.SetPriority(LocationRequest.PriorityHighAccuracy);
                locationRequest.SetInterval(MIN_TIME_BW_UPDATES);
                locationRequest.SetFastestInterval(MIN_TIME_BW_UPDATES/2);
    
                LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
                  .AddLocationRequest(locationRequest);
                builder.SetAlwaysShow(true);
    
                LocationSettingsResult locationSettingsResult =
                 await LocationServices.SettingsApi.CheckLocationSettingsAsync(googleApiClient, builder.Build());
    
                switch (locationSettingsResult.Status.StatusCode)
                {
                    case LocationSettingsStatusCodes.Success:
                        Toast.MakeText(_activity, "SUCCESS", ToastLength.Short).Show();
                        break;
    
                    case LocationSettingsStatusCodes.ResolutionRequired:
                        try
                        {
                            locationSettingsResult.Status.StartResolutionForResult(_activity, REQUEST_CHECK_SETTINGS);
                        }
                        catch (Exception e)
                        {
                            Toast.MakeText(_activity, "CANCEL: " + e.Message, ToastLength.Short).Show();
                        }
                        break;
    
                    default:
                        googleApiClient.Disconnect();
                        break;
                }
            }
        }
    
        public override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);
            LocationManager manager = (LocationManager)_activity.GetSystemService(Context.LocationService);
            if (manager.IsProviderEnabled(LocationManager.GpsProvider) && hasGPSDevice(_activity))
            {
                Intent intent = new Intent(_activity, typeof(GoogleMapsActivity));
                StartActivity(intent);
            }
            if (!hasGPSDevice(_activity))
            {
                  Toast.MakeText(_activity, "Gps not Supported", ToastLength.Long).Show();
            }
    
            if (!manager.IsProviderEnabled(LocationManager.GpsProvider) && hasGPSDevice(_activity))
            {
                enableLoc();              
            }
            else
            {
    
            }
        }
    
        public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
        {
            return base.OnCreateView(inflater, container, savedInstanceState);
        }
    }
    public class ConnectionFailedCallBack : Java.Lang.Object, GoogleApiClient.IOnConnectionFailedListener
    {
        Context _context;
        public ConnectionFailedCallBack(Context context)
        {
            _context = context;
        }
        public void OnConnectionFailed(ConnectionResult result)
        {
            Toast.MakeText(_context, "Location connection failed.", ToastLength.Short).Show();
        }
    }
    public class CallBackHelper : Java.Lang.Object, GoogleApiClient.IConnectionCallbacks
    {
        GoogleApiClient googleApiClient;
        public CallBackHelper(GoogleApiClient googleApiClient)
        {
            this.googleApiClient = googleApiClient;
        }
        public void OnConnected(Bundle connectionHint)
        {
    
        }
    
        public void OnConnectionSuspended(int cause)
        {
            googleApiClient.Connect();
        }
    }
    

    并使用以下方法获取片段主机活动的结果:

      protected override void OnActivityResult(int requestCode, [GeneratedEnum] Result resultCode, Intent data)
        {
            base.OnActivityResult(requestCode, resultCode, data);
            if (requestCode == LocationEnabled.REQUEST_CHECK_SETTINGS)
            {
                switch (resultCode)
                {
                    case Result.Canceled:
                     //negative result 
                        break;
    
                    case Result.Ok:
                   //positive result 
                        break;
    
                    case Result.FirstUser:
                    default:
                        break;
                }
            }
        }
    

    祝你好运!

    【讨论】:

    • 设备已连接wifi并开启GPS定位,精度很高,但设备仍然无法获取位置。
    • 你能更新你实现ILocationListener的代码吗@user2021195
    • 那么你需要在一个活动或一个片段中拥有你的位置监听器才能被调用,否则它不会被调用@user2021195
    • 也就是说,位置监听器不能放入服务?
    • 是的,这就是我的理解
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多