Xamarin.forms Xamarin表单-每10秒获取设备位置(应用程序在前台/后台运行时)

Xamarin.forms Xamarin表单-每10秒获取设备位置(应用程序在前台/后台运行时),xamarin.forms,geolocation,background-process,geofencing,Xamarin.forms,Geolocation,Background Process,Geofencing,我已经创建了一个Xamarin表单应用程序。应用程序应定期(每10秒)获取设备的位置(iOS和Android)。我怎样才能做到这一点?我知道有一些库,例如:Xamarin.Essentials,但我无法决定该位置应该使用多少次 当Xamarin forms应用程序在后台(在IOS和Android上)运行时,还可以获取设备的本地信息。对于Android,您可以尝试启动一项服务,使用Android的LocationManager开始监听位置更改。可以指定要跟踪的时间间隔和最小距离 帮我弄明白如何使用

我已经创建了一个Xamarin表单应用程序。应用程序应定期(每10秒)获取设备的位置(iOS和Android)。我怎样才能做到这一点?我知道有一些库,例如:Xamarin.Essentials,但我无法决定该位置应该使用多少次


当Xamarin forms应用程序在后台(在IOS和Android上)运行时,还可以获取设备的本地信息。

对于Android,您可以尝试启动一项服务,使用Android的LocationManager开始监听位置更改。可以指定要跟踪的时间间隔和最小距离

帮我弄明白如何使用它。对我来说,即使应用程序被暂停(运行安卓6.1的物理设备),它也在发送位置更新

为了获得位置,我将我的服务设置为“LocationListener”,并实现了ILocationListener接口,如下所示:

[Service]
public class TestService : Service, ILocationListener
{
    public override IBinder OnBind(Intent intent)
    {
        return null;
    }


    public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
    {
        // start your location updates with the locationManager here

        return StartCommandResult.Sticky; // remember to return sticky for the service to run when app is suspended
    }


    public override void OnDestroy() { }

    ...

    public void OnLocationChanged(Location location)
    {
        // react to location changes here
    }

    public void OnProviderDisabled(string provider) { }

    public void OnProviderEnabled(string provider) { }

    public void OnStatusChanged(string provider, Availability status, Bundle extras) { }
}
有关背景和如何设置服务的更多信息,请阅读

重要的是要注意位置更新的时间不一致(有时需要10秒以上),因为您只需给出最短时间,操作系统会根据其容量处理请求。但也不算太糟


更新:这似乎不适用于Android 8.0及以上版本。请看

我过去因为头痛而通过的一个跨平台应用程序,它每x秒更新一次位置,应该在后台运行。 我用Xamarin表单开发了一个模板,支持后台位置更新、后台权限,这些功能需要根据操作系统(iOs/Android)进行调整

为此,我使用了Xamarin Essentials和消息中心。 请让我知道模板是否适合您的需要。
谢谢。

您可以使用设备计时器来完成。计时器将定期运行&检查位置更新,并在位置更新时通知。我使用Xam.Plugins.Notifier在位置更新时生成本地通知

下面是它的代码:

public partial class MainPage : ContentPage
{
    Location oldLocation = null;
    CancellationTokenSource cts;
    public MainPage()
    {
        InitializeComponent();
        Device.StartTimer(TimeSpan.FromSeconds(10), () =>
        {
            GetCurrentLocation();
            return true;
        });
    }

    protected async override void OnAppearing()
    {
        base.OnAppearing();
        await GetCurrentLocation();
    }

    async Task GetCurrentLocation()
    {
        try
        {
            var request = new GeolocationRequest(GeolocationAccuracy.Medium, TimeSpan.FromSeconds(10));
            cts = new CancellationTokenSource();
            var location = await Geolocation.GetLocationAsync(request, cts.Token);

            if (location != null)
            {
                Debug.WriteLine($"Latitude: {location.Latitude}, Longitude: {location.Longitude}, Altitude: {location.Altitude}");
                if (oldLocation == null)
                {
                    oldLocation = location;
                    map.MoveToRegion(MapSpan.FromCenterAndRadius(
                   new Position(location.Latitude, location.Longitude), Distance.FromMiles(0.3)));
                }
                if (location.Latitude != oldLocation.Latitude || location.Longitude != oldLocation.Longitude)
                {
                    map.MoveToRegion(MapSpan.FromCenterAndRadius(
                   new Position(location.Latitude, location.Longitude), Distance.FromMiles(0.3)));

                    oldLocation = location;
                    double zoomLevel = 0.5;
                    double latlongDegrees = 360 / (Math.Pow(2, zoomLevel));
                    if (map.VisibleRegion != null)
                    {
                        map.MoveToRegion(new MapSpan(map.VisibleRegion.Center, latlongDegrees, latlongDegrees));
                    }

                    var placemarks = await Geocoding.GetPlacemarksAsync(location.Latitude, location.Longitude);
                    var placemark = placemarks?.FirstOrDefault();
                    if (placemark != null)
                    {
                        var geocodeAddress =
                            $"AdminArea:       {placemark.AdminArea}\n" +
                            $"CountryCode:     {placemark.CountryCode}\n" +
                            $"CountryName:     {placemark.CountryName}\n" +
                            $"FeatureName:     {placemark.FeatureName}\n" +
                            $"Locality:        {placemark.Locality}\n" +
                            $"PostalCode:      {placemark.PostalCode}\n" +
                            $"SubAdminArea:    {placemark.SubAdminArea}\n" +
                            $"SubLocality:     {placemark.SubLocality}\n" +
                            $"SubThoroughfare: {placemark.SubThoroughfare}\n" +
                            $"Location :       {placemark.Location}\n" +
                            $"Thoroughfare:    {placemark.Thoroughfare}\n";

                        Debug.WriteLine(geocodeAddress);
                    }
                    
                    CrossLocalNotifications.Current.Show("Location Updated", "You checked in to " + placemark.FeatureName + " " + placemark.Locality + " " + placemark.SubLocality, 101, DateTime.Now.AddSeconds(5));
                }
            }
        }
        catch (FeatureNotSupportedException)
        {
            // Handle not supported on device exception
        }
        catch (FeatureNotEnabledException)
        {
            // Handle not enabled on device exception
        }
        catch (PermissionException)
        {
            // Handle permission exception
        }
        catch (Exception)
        {
            // Unable to get location
        }
    }
}

“但我无法决定该位置应该被拍摄多少次。”-您已经声明需要每10秒更新一次。所以,使用一个每10秒触发一次的计时器。老实说,我认为在安卓操作系统发生变化之后,你无法做到这一点,这是不可能的,因为一旦设备进入待机状态,打瞌睡就会停止几乎所有的应用程序,也就是说,你将无法在这里不断共享位置更多信息@M Yil我搜索了一些,并找到了一个可以获取时间间隔内设备位置的示例:如果这样做有效,我就给你邮寄一大瓶GuaroWell?来吧,分享爱!它起作用了吗?