Xamarin.forms Xamarin表单:即使应用程序在后台,如何每x秒运行一次服务?

Xamarin.forms Xamarin表单:即使应用程序在后台,如何每x秒运行一次服务?,xamarin.forms,background-process,Xamarin.forms,Background Process,我使用以下代码每10秒调用一个函数 var startTimeSpan = TimeSpan.Zero; var periodTimeSpan = TimeSpan.FromSeconds(10); var timer = new System.Threading.Timer((e) => { MyFunction(); }, null, startTimeSpan, periodTimeSpan); 当应用程序处于打开状态时,MyFunction()将每10秒执行一次。当应用

我使用以下代码每10秒调用一个函数

var startTimeSpan = TimeSpan.Zero;
var periodTimeSpan = TimeSpan.FromSeconds(10);

var timer = new System.Threading.Timer((e) =>
{
    MyFunction();
}, null, startTimeSpan, periodTimeSpan);
当应用程序处于打开状态时,
MyFunction()
将每10秒执行一次。当应用程序在后台时,该函数不会调用

那么,当应用程序在后台时,如何调用函数呢?是否有任何NuGet包用于此,或者我们需要使用依赖项服务来完成此操作

更新

当我运行您的演示时,我得到以下异常:

我已将代码集成到我的样本中。代码执行将在
StartServiceDroid
中启动
Start()
。但不点击
OnStartCommand()
函数。这是我的名片,你能看一下吗?我需要在后台或前台模式下每隔x秒运行一次
MyFunction()

更新10-07-2020

@Leon Lu-MSFT我找到了一个新的解决方案。:)

我用这段代码创建了一个示例应用程序,它在前台和后台模式下运行良好。每隔10秒,即使应用程序在后台运行,Hiii消息也会打印在输出框上

这包含在Xamarin表单中,因此不需要任何特定于平台的逻辑

这种方法有什么问题吗

更新日期:2020年7月15日

今天我在一台真正的设备上测试了它。:)

案例1:在Visual Studio上运行应用程序,服务正在前台模式下调用。将应用程序移动到后台(仍然,应用程序在VS中运行),当应用程序位于后台时,后台服务每10秒调用一次

var startTimeSpan = TimeSpan.Zero;
var periodTimeSpan = TimeSpan.FromSeconds(10);

var timer = new System.Threading.Timer((e) =>
{
    MyFunction();
}, null, startTimeSpan, periodTimeSpan);
案例2:正常打开应用程序安装的应用程序(不在VS中运行),服务在前台模式下调用,将应用程序移动到后台,即使10分钟后后台服务也不调用

我现在完全搞糊涂了,后台服务在应用程序在VS上运行时调用,而在正常打开已安装的应用程序时不调用。对于第二种情况,我已经等待了10多分钟,但是我添加的服务没有调用。这两种情况都是在调试模式下完成的

这是xamarin forms平台的唯一行为吗?如果我们在本机ios平台上执行此操作,是否有可能每x秒触发一次后台服务?skype如何提供后台服务

测试设备型号:iPhone 7 软件版本:13.5.1

在Android中,您可以使用来保持您的
MyFunction()
始终在后台运行。如果你在xamarin中使用它。您可以使用依赖性服务调用前台服务,然后在前台服务中使用
MyFunction
执行
Timer

  [Service]
    public class DependentService : Service, IService
    {
        public void Start()
        {
            var intent = new Intent(Android.App.Application.Context,
     typeof(DependentService));


            if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.O)
            {
                Android.App.Application.Context.StartForegroundService(intent);
            }
            else
            {
                Android.App.Application.Context.StartService(intent);
            }
        }

        public override IBinder OnBind(Intent intent)
        {
            return null;
        }
        public const int SERVICE_RUNNING_NOTIFICATION_ID = 10000;
        public override StartCommandResult OnStartCommand(Intent intent,StartCommandFlags flags, int startId)
        {
            // From shared code or in your PCL

            CreateNotificationChannel();
            string messageBody = "service starting";

            var notification = new Notification.Builder(this, "10111")
            .SetContentTitle("Foreground")
            .SetContentText(messageBody)
            .SetSmallIcon(Resource.Drawable.main)
            .SetOngoing(true)
            .Build();
            StartForeground(SERVICE_RUNNING_NOTIFICATION_ID, notification);

     //=======you can do you always running work here.=====
           var startTimeSpan = TimeSpan.Zero;
           var periodTimeSpan = TimeSpan.FromSeconds(10);

           var timer = new System.Threading.Timer((e) =>
          {
              MyFunction();
          }, null, startTimeSpan, periodTimeSpan);
          



           
            return StartCommandResult.Sticky;
        }


        void CreateNotificationChannel()
        {
            if (Build.VERSION.SdkInt < BuildVersionCodes.O)
            {
                // Notification channels are new in API 26 (and not a part of the
                // support library). There is no need to create a notification
                // channel on older versions of Android.
                return;
            }

            var channelName = Resources.GetString(Resource.String.channel_name);
            var channelDescription = GetString(Resource.String.channel_description);
            var channel = new NotificationChannel("10111", channelName, NotificationImportance.Default)
            {
                Description = channelDescription
            };

            var notificationManager = (NotificationManager)GetSystemService(NotificationService);
            notificationManager.CreateNotificationChannel(channel);
        }
    }
下面是关于使用DependentService打开前台服务的简单代码

  [Service]
    public class DependentService : Service, IService
    {
        public void Start()
        {
            var intent = new Intent(Android.App.Application.Context,
     typeof(DependentService));


            if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.O)
            {
                Android.App.Application.Context.StartForegroundService(intent);
            }
            else
            {
                Android.App.Application.Context.StartService(intent);
            }
        }

        public override IBinder OnBind(Intent intent)
        {
            return null;
        }
        public const int SERVICE_RUNNING_NOTIFICATION_ID = 10000;
        public override StartCommandResult OnStartCommand(Intent intent,StartCommandFlags flags, int startId)
        {
            // From shared code or in your PCL

            CreateNotificationChannel();
            string messageBody = "service starting";

            var notification = new Notification.Builder(this, "10111")
            .SetContentTitle("Foreground")
            .SetContentText(messageBody)
            .SetSmallIcon(Resource.Drawable.main)
            .SetOngoing(true)
            .Build();
            StartForeground(SERVICE_RUNNING_NOTIFICATION_ID, notification);

     //=======you can do you always running work here.=====
           var startTimeSpan = TimeSpan.Zero;
           var periodTimeSpan = TimeSpan.FromSeconds(10);

           var timer = new System.Threading.Timer((e) =>
          {
              MyFunction();
          }, null, startTimeSpan, periodTimeSpan);
          



           
            return StartCommandResult.Sticky;
        }


        void CreateNotificationChannel()
        {
            if (Build.VERSION.SdkInt < BuildVersionCodes.O)
            {
                // Notification channels are new in API 26 (and not a part of the
                // support library). There is no need to create a notification
                // channel on older versions of Android.
                return;
            }

            var channelName = Resources.GetString(Resource.String.channel_name);
            var channelDescription = GetString(Resource.String.channel_description);
            var channel = new NotificationChannel("10111", channelName, NotificationImportance.Default)
            {
                Description = channelDescription
            };

            var notificationManager = (NotificationManager)GetSystemService(NotificationService);
            notificationManager.CreateNotificationChannel(channel);
        }
    }
[服务]
公共类DependentService:服务,iSeries服务
{
公开作废开始()
{
var intent=新的intent(Android.App.Application.Context,
类型(从属服务);
if(Android.OS.Build.VERSION.SdkInt>=Android.OS.BuildVersionCodes.O)
{
Android.App.Application.Context.StartForegroundService(intent);
}
其他的
{
Android.App.Application.Context.StartService(intent);
}
}
公共覆盖iBind OnBind(意图)
{
返回null;
}
public const int SERVICE_RUNNING_NOTIFICATION_ID=10000;
公共覆盖StartCommandResult OnStartCommand(意图、StartCommandFlags标志、int-startId)
{
//从共享代码或您的PCL中
CreateNotificationChannel();
字符串messageBody=“服务启动”;
var notification=new notification.Builder(这是“10111”)
.SetContentTitle(“前景”)
.SetContentText(messageBody)
.SetSmallIcon(Resource.Drawable.main)
.正在进行(正确)
.Build();
StartForeground(服务运行通知ID,通知);
//======你可以在这里一直工作=====
var startTimeSpan=时间跨度0;
var periodTimeSpan=从秒开始的时间跨度(10);
var timer=新系统.线程.计时器((e)=>
{
MyFunction();
},null,startTimeSpan,periodTimeSpan);
返回StartCommandResult.Sticky;
}
void CreateNotificationChannel()
{
if(Build.VERSION.SdkInt
下面是我的演示,介绍如何使用xamarin表单中的前台服务

在iOS中,无法实现始终在后台运行应用程序,因为iOS只允许正常应用程序(:音频、VoIP、外部配件和蓝牙报摊、位置、获取(iOS 7+)、远程通知(iOS 7+)应用程序可以始终在后台运行,您可以看到)10分钟内在后台运行。你可以参考这篇文章


您可以设置任何您想要的,我