安卓前台定位服务会在一段时间后停止

3

我正在使用这段代码获取我的Xamarin Android应用程序的位置更新。 我有两个问题。

  1. 如何使这个前台服务永久运行? 我试过将 return StartCommandResult.NotSticky; 改为 return StartCommandResult.Sticky; 并从 OnDestroy() 方法中删除所有内容,但操作系统似乎无法在服务被终止或崩溃后重新创建服务。 因此,它只能运行大约半天,即使我已将应用添加到我的电池优化排除列表中。 如何使其永久运行?

  2. 如何正确地从引导时启动服务? 这是我尝试的方式。 添加以下内容到MainActivity.cs

            [IntentFilter(new[] { Android.Content.Intent.ActionBootCompleted })]
            public class BootReceiver : BroadcastReceiver
            {
                public Context Context { get; set; }
                public override void OnReceive(Context context, Intent intent)
                {
                    var stepServiceIntent = new Intent(context, typeof(LocationUpdatesService));
                    stepServiceIntent.PutExtra("StartedFromBoot", true);
                    if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.O)
                    {
                        context.StartForegroundService(stepServiceIntent);
                    }
                    else
                    {
                        context.StartService(stepServiceIntent);
                    }
                }
            }

编辑了LocationUpdatesService.cs

public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
        {
            Log.Info(Tag, "Service started");
            var startedFromNotification = intent.GetBooleanExtra(ExtraStartedFromNotification, false);

            var startedFromBoot = intent.GetBooleanExtra("StartedFromBoot", false);

            if (startedFromBoot)
            {
                
                //Preferences.Set("LocationUpdates", true);
                
                StartForeground(NotificationId, StartNotification("",""));
                Preferences.Set("foreground", true);

                try
                {
                    FusedLocationClient.RequestLocationUpdates(LocationRequest, LocationCallback, Looper.MyLooper());
                }
                catch (SecurityException unlikely)
                {
                    Preferences.Set("LocationUpdates", false);
                    Log.Error(Tag, "Lost location permission. Could not request updates. " + unlikely);
                }
            }
            if (startedFromNotification)
            {
                RemoveLocationUpdates();
                StopSelf();
            }
            return StartCommandResult.Sticky;
        }

我只从启动时得到了一次位置更新。这之后,我就会得到"未知位置",因此服务无法持续运行。那么,如何正确地从启动开始运行该服务,使其持续运行?

也许有一个单一的解决方案可以同时回答这两个问题。如果有一种方式可以从启动时开始完全功能的服务,那么系统可以使用Sticky标志重新创建它并永远运行。

1个回答

1
实际上,当手机开启时,前台服务将保持运行。但您也可以使用PowerManager.WakeLock确保您的应用程序即使设备处于睡眠状态也始终保持活动状态。
您可以检查此案例:Xamarin wakelock 此外,似乎您想循环获取用户位置。因此,您可以在前台服务中运行定时任务。有许多方法可以做到这一点。例如:
  • JobScheduler
  • AlarmManager
  • WorkManager
  • ScheduledThreadPoolExecutor
您可以检查此案例:Xamarin Android - Periodic task execution

谢谢!但这不是我的情况下的解决方案。该服务应该连续运行并进行位置更新。原始源链接在第一条消息中。问题是我无法单独运行服务(例如,从引导程序)并使其像应该工作一样连续工作(它只能使用我编辑的代码获取单个更新)。当然,我可以使用定时任务运行服务一次并获取单个更新,但这不是我寻找的方式,因为该服务应始终工作并自行获取周期性更新。WakeLock也是部分解决方案,因为在崩溃的情况下,操作系统无法重新创建服务。 - ibit
但是你只需要在服务中调用FusedLocationClient.RequestLocationUpdates一次,所以你只会得到一次位置。此外,操作系统崩溃是什么意思?即使没有调用ondestory方法,你是否希望前台服务重新启动?@ibit - Liyun Zhang - MSFT
感谢您的再次回答!请检查原始源代码:https://docs.microsoft.com/zh-cn/samples/xamarin/monodroid-samples/android-o-androidplaylocation-locupdfgservice/ 。我无法理解FusedLocationClient.RequestLocationUpdates如何获取周期性更新并在主应用程序运行或从主应用程序启动前台服务(暂停时)时仍然持续工作。那么我应该如何重写我的代码,使它可以像应用程序中一样从引导中运行?我还有一个ondestroy方法覆盖(与源代码相同),但我已删除了内部代码,这也可能是问题吗? - ibit
我已经阅读了代码,发现它通过主活动中的按钮点击事件更新位置。此外,并不涉及ondestroy方法。@ibit - Liyun Zhang - MSFT

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接