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

Posted

技术标签:

【中文标题】Xamarin Forms 使用 CrossGeolocator 获取前台服务位置更新【英文标题】:Xamarin Forms Getting foreground service location updates with CrossGeolocator 【发布时间】:2021-10-10 22:52:01 【问题描述】:

我正在使用 CrossGeolocator 插件在 android 的 Xamarin Forms 应用程序中订阅位置更新(对于 ios,即使应用程序在后台,位置更新也会继续)。

我实现了一个前台服务,这样即使应用程序进入后台,我也可以继续获取位置。

据我了解,如果我在前台服务中收听位置更新,我应该能够获得位置更新。

但是,当应用程序进入后台时,我没有获得位置更新。

我的服务数据源的 StartCommand:

public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)

    Notification notif = DependencyService.Get<INotification>().ReturnNotif();
    StartForeground(ServiceRunningNotifID, notif);

    CrossGeolocator.Current.StartListeningAsync(TimeSpan.FromSeconds(10), 0, true, new Plugin.Geolocator.Abstractions.ListenerSettings
    
        ActivityType = ActivityType.Other,
        PauseLocationUpdatesAutomatically = false,
        AllowBackgroundUpdates = true,
        DeferLocationUpdates = false,
        ListenForSignificantChanges = false,
    );

    CrossGeolocator.Current.PositionChanged += PositionChanged;
    CrossGeolocator.Current.PositionError += PositionError;


    return StartCommandResult.Sticky;

还有事件:

private void PositionError(object sender, PositionErrorEventArgs e)

    Console.WriteLine($"e.Error");


private void PositionChanged(object sender, PositionEventArgs e)

    Console.WriteLine($"e.Position.Latitude, e.Position.Longitude");

这些事件仅在应用处于活动状态时触发。服务启动,设备显示服务正在运行的通知标志。

我已分配所需的权限:

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.LOCATION_HARDWARE" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

任何人都可以对实现有所了解吗? 如果需要,我可以提供额外的代码。

【问题讨论】:

【参考方案1】:

我通过添加以下内容找到了解决方案:

ForegroundServiceType = ForegroundService.TypeDataSync | ForegroundService.TypeLocation

作为前台服务中的服务属性

[Service(ForegroundServiceType = ForegroundService.TypeDataSync | ForegroundService.TypeLocation)]
public class LocationForegroundService : Service

    ...

【讨论】:

【参考方案2】:

每个平台的后台更新处理方式略有不同。对于 Android,您需要集成一个订阅位置更改和用户界面绑定的前台服务。

您可以为此使用 Xamarin.Essentials 和 MessagingCenter。

  [Service]
 public class AndroidLocationService : Service
 
    CancellationTokenSource _cts;
    public const int SERVICE_RUNNING_NOTIFICATION_ID = 10000;

    public override IBinder OnBind(Intent intent)
    
        return null;
    

    public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
    
        _cts = new CancellationTokenSource();

        Notification notif = DependencyService.Get<INotification>().ReturnNotif();
        StartForeground(SERVICE_RUNNING_NOTIFICATION_ID, notif);

        Task.Run(() => 
            try
            
                var locShared = new Location();
                locShared.Run(_cts.Token).Wait();
            
            catch (OperationCanceledException)
            
            
            finally
            
                if (_cts.IsCancellationRequested)
                
                    var message = new StopServiceMessage();
                    Device.BeginInvokeOnMainThread(
                        () => MessagingCenter.Send(message, "ServiceStopped")
                    );
                
            
        , _cts.Token);

        return StartCommandResult.Sticky;
    

    public override void OnDestroy()
    
        if (_cts != null)
        
            _cts.Token.ThrowIfCancellationRequested();
            _cts.Cancel();
        
        base.OnDestroy();
    


有关详细信息,请查看以下链接中的代码示例。 https://***.com/a/63665571/11850033

【讨论】:

以上是关于Xamarin Forms 使用 CrossGeolocator 获取前台服务位置更新的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Xamarin.Forms 创建抽屉/滑块菜单?

在 Xamarin.Forms 中使用 Android 绑定

Xamarin.Forms:Forms.Context 已过时

Xamarin.Forms 手势密码实现

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

Xamarin.Forms之Effects的使用