1

We have one problem where it happen randomly on certain devices which is the OnLocationChanged event cannot be triggered.

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

We also try set a timer, if after a minute, the event didn't trigger, we will try get the last known location, but it still returning 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);
            }

May I know what wrong with my code ?

Edited (Complete Code) :

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
user2021195
  • 105
  • 11

1 Answers1

0

Well I would suggest you check if the location services are provided and by that I mean are they turned on if not doing that would solve the issue also what you can do is if these services are not available or you can say are currently declined you can simply use this to check if it's available or not and in that way apply your own code to it which could determine if you continue forward to the maps page or not.

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

And get the result on your fragment host activity using this :

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

Goodluck!

FreakyAli
  • 13,349
  • 3
  • 23
  • 63