Xamarin Forms:即使应用程序在后台,如何每 x 秒 运行 一个服务?
Xamarin Forms: How to run a service every x seconds even the app is in background?
我使用以下代码每 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()
功能。这是我的sample,你能看看吗?我需要在后台或前台模式下每 x 秒 运行 MyFunction()
。
更新 10-07-2020
@Leon Lu - MSFT 我找到了一个新的解决方案 here。 :)
var second = TimeSpan.FromSeconds(10);
Device.StartTimer(second, () => {
Debug.WriteLine("Hiiiii");
return true;
});
我用这段代码创建了一个示例应用程序,它在前台和后台模式下都运行良好。每隔 10 秒,Hiii 消息就会打印在输出框中,即使应用程序在后台 运行ning。
这包含在 Xamarin Forms 中,因此不需要任何特定于平台的逻辑。
这种做法有什么问题吗?
2020 年 7 月 15 日更新
今天在真机上进行了测试。 :)
案例 1:运行 Visual Studio 上的应用程序,服务正在前台模式下调用。将应用程序移至后台(仍然,应用程序在 VS 中 运行ning),当应用程序每 10 秒在后台时,后台服务正在调用。
情况二:正常打开app安装的app,(不是运行在VS中打开),服务在前台调用,把app移到后台,后台服务也不调用10 分钟。
我现在完全糊涂了,当应用程序在 VS 上 运行ning 时后台服务正在调用,而当正常打开已安装的应用程序时不调用。第二种情况,等了10多分钟,添加的服务没有调用。两种情况都是在调试模式下完成的。
这是 xamarin 表单平台的唯一行为吗?如果我们在原生ios平台做,是不是可以每隔x秒触发一次后台服务? Skype 后台服务如何?
测试设备型号:iPhone7
软件版本:13.5.1
在 Android 中,您可以使用 foreground service 让您的 MyFunction()
始终 运行 处于后台。如果您以 xamarin 形式使用它。你可以使用依赖服务来调用前台服务,然后在前台服务中用MyFunction
执行你的Timer
。
下面是使用 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);
}
}
这是我关于如何以 xamarin 形式使用前台服务的演示。
https://github.com/851265601/ForeGroundService
在iOS中,无法实现始终运行您的应用程序在后台运行,因为iOS,只允许正常应用程序(:音频、VoIP、外部配件和蓝牙Newsstand、Location、Fetch(iOS 7+)、远程通知(iOS 7+)应用程序可以一直在后台运行运行,你可以看到this thread)运行 在 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()
功能。这是我的sample,你能看看吗?我需要在后台或前台模式下每 x 秒 运行 MyFunction()
。
更新 10-07-2020
@Leon Lu - MSFT 我找到了一个新的解决方案 here。 :)
var second = TimeSpan.FromSeconds(10);
Device.StartTimer(second, () => {
Debug.WriteLine("Hiiiii");
return true;
});
我用这段代码创建了一个示例应用程序,它在前台和后台模式下都运行良好。每隔 10 秒,Hiii 消息就会打印在输出框中,即使应用程序在后台 运行ning。
这包含在 Xamarin Forms 中,因此不需要任何特定于平台的逻辑。
这种做法有什么问题吗?
2020 年 7 月 15 日更新
今天在真机上进行了测试。 :)
案例 1:运行 Visual Studio 上的应用程序,服务正在前台模式下调用。将应用程序移至后台(仍然,应用程序在 VS 中 运行ning),当应用程序每 10 秒在后台时,后台服务正在调用。
情况二:正常打开app安装的app,(不是运行在VS中打开),服务在前台调用,把app移到后台,后台服务也不调用10 分钟。
我现在完全糊涂了,当应用程序在 VS 上 运行ning 时后台服务正在调用,而当正常打开已安装的应用程序时不调用。第二种情况,等了10多分钟,添加的服务没有调用。两种情况都是在调试模式下完成的。
这是 xamarin 表单平台的唯一行为吗?如果我们在原生ios平台做,是不是可以每隔x秒触发一次后台服务? Skype 后台服务如何?
测试设备型号:iPhone7 软件版本:13.5.1
在 Android 中,您可以使用 foreground service 让您的 MyFunction()
始终 运行 处于后台。如果您以 xamarin 形式使用它。你可以使用依赖服务来调用前台服务,然后在前台服务中用MyFunction
执行你的Timer
。
下面是使用 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);
}
}
这是我关于如何以 xamarin 形式使用前台服务的演示。
https://github.com/851265601/ForeGroundService
在iOS中,无法实现始终运行您的应用程序在后台运行,因为iOS,只允许正常应用程序(:音频、VoIP、外部配件和蓝牙Newsstand、Location、Fetch(iOS 7+)、远程通知(iOS 7+)应用程序可以一直在后台运行运行,你可以看到this thread)运行 在 10 分钟内在后台运行。可以参考这篇文章