Xamarin Forms - 每 10 秒获取一次设备位置(当应用程序在前台/后台运行时)

Posted

技术标签:

【中文标题】Xamarin Forms - 每 10 秒获取一次设备位置(当应用程序在前台/后台运行时)【英文标题】:Xamarin Forms - Get device location every 10 seconds (when app runs in foreground/background) 【发布时间】:2020-06-23 12:08:33 【问题描述】:

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

当 Xamarin 表单应用程序在后台运行时(在 IOS 和 Android 上),也应该可以获取设备的本地。

【问题讨论】:

“但我无法决定该位置应该被拍摄多少次。” - 你已经说过你需要每 10 秒更新一次。因此,请使用每 10 秒触发一次的 Timer。 说实话,我不认为你可以在 Android 操作系统发生变化之后做到这一点,这是不可能的,因为一旦设备进入待机状态并且打瞌睡几乎所有应用程序,即您将无法在此处不断分享位置更多信息developer.android.com/training/monitoring-device-state/… @M Yil 我搜索了一些并找到了一个可以获取设备位置的样本:github.com/CherryBu/LocationSample 【参考方案1】:

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

Check my Github repo here

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

【讨论】:

如果可行,我会寄给你一大瓶 Guaro【参考方案2】:

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

This section 帮助我弄清楚了如何使用它。对我来说,即使应用程序暂停(运行 Android 6.1 的物理设备),它也会发送位置更新。

为了获得位置,我将我的服务设为“LocationListener”并像这样实现了 ILocationListener-Interface:

[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)  

有关后台和如何设置服务的更多信息,请阅读this。

需要注意的重要一点是 locationUpdates 的时间不一致(有时需要超过 10 秒),因为您只需给出 minimumTime 并且操作系统会根据其容量处理请求。不过还不错。

更新:这似乎不适用于 Android 8.0 及更高版本。见here

【讨论】:

【参考方案3】:

您可以使用设备计时器来做到这一点。计时器将定期运行并检查位置更新并通知位置是否更新。我使用 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
        
    

【讨论】:

以上是关于Xamarin Forms - 每 10 秒获取一次设备位置(当应用程序在前台/后台运行时)的主要内容,如果未能解决你的问题,请参考以下文章

使用 Xamarin.Forms 作为背景

Xamarin Forms Android 10 及更高版本在公共外部存储中按文件名查找视频并获取路径

在 Xamarin Forms 中获取设备音量

Xamarin Forms 使用 CrossGeolocator 获取前台服务位置更新

Xamarin.Forms - 使用 Xamarin.Essentials 在两个坐标之间获取里程

在 Xamarin.Forms 中录制语音后如何保存音频文件