我是移动应用程序开发新手,正在学习 .NET Maui。我正在创建的应用程序需要侦听加速计事件,并在事件满足特定条件时向 Web 服务发送通知。我正在努力解决的问题是如何让应用程序在后台运行,即没有可见的 UI,而不进入睡眠状态,因为我希望用户完全关闭 UI。所以我认为应用程序需要作为某种服务运行,并可以选择在需要时显示 UI - 如何才能做到这一点?
Lea*_*oza 31
我知道已经有一段时间了,但会为未来的用户发布答案。
首先我们需要了解后台服务取决于我们使用的平台。(感谢 Jason)我将专注于 ANDROID,基于Xamarin 文档(感谢 Eli),适应毛伊岛。
由于我们正在与ANDROID合作,因此在MauiProgram上我们将添加以下内容:
/// Add dependecy injection to main page
builder.Services.AddSingleton<MainPage>();
#if ANDROID
builder.Services.AddTransient<IServiceTest, DemoServices>();
#endif
Run Code Online (Sandbox Code Playgroud)
我们创建了 DI 接口,它为我们提供了启动和停止前台服务的方法
public interface IServiceTest
{
void Start();
void Stop();
}
Run Code Online (Sandbox Code Playgroud)
然后,在平台代码之前,我们需要在AndroidManifest.xml上添加 Android 权限:
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
Run Code Online (Sandbox Code Playgroud)
Android 主要活动
public class MainActivity : MauiAppCompatActivity
{
//set an activity on main application to get the reference on the service
public static MainActivity ActivityCurrent { get; set; }
public MainActivity()
{
ActivityCurrent = this;
}
}
Run Code Online (Sandbox Code Playgroud)
最后我们创建 Android 前台服务。检查下面的评论。另外,在 xamarin 文档上,它们显示了通知生成器的不同属性。
[Service]
public class DemoServices : Service, IServiceTest //we implement our service (IServiceTest) and use Android Native Service Class
{
public override IBinder OnBind(Intent intent)
{
throw new NotImplementedException();
}
[return: GeneratedEnum]//we catch the actions intents to know the state of the foreground service
public override StartCommandResult OnStartCommand(Intent intent, [GeneratedEnum] StartCommandFlags flags, int startId)
{
if (intent.Action == "START_SERVICE")
{
RegisterNotification();//Proceed to notify
}
else if (intent.Action == "STOP_SERVICE")
{
StopForeground(true);//Stop the service
StopSelfResult(startId);
}
return StartCommandResult.NotSticky;
}
//Start and Stop Intents, set the actions for the MainActivity to get the state of the foreground service
//Setting one action to start and one action to stop the foreground service
public void Start()
{
Intent startService = new Intent(MainActivity.ActivityCurrent, typeof(DemoServices));
startService.SetAction("START_SERVICE");
MainActivity.ActivityCurrent.StartService(startService);
}
public void Stop()
{
Intent stopIntent = new Intent(MainActivity.ActivityCurrent, this.Class);
stopIntent.SetAction("STOP_SERVICE");
MainActivity.ActivityCurrent.StartService(stopIntent);
}
private void RegisterNotification()
{
NotificationChannel channel = new NotificationChannel("ServiceChannel", "ServiceDemo", NotificationImportance.Max);
NotificationManager manager = (NotificationManager)MainActivity.ActivityCurrent.GetSystemService(Context.NotificationService);
manager.CreateNotificationChannel(channel);
Notification notification = new Notification.Builder(this, "ServiceChannel")
.SetContentTitle("Service Working")
.SetSmallIcon(Resource.Drawable.abc_ab_share_pack_mtrl_alpha)
.SetOngoing(true)
.Build();
StartForeground(100, notification);
}
}
Run Code Online (Sandbox Code Playgroud)
现在我们的前台服务在 Android 上运行,显示一条通知(“服务正在运行”)。每次开始。我制作了一个显示消息前台服务,以便在测试时更好地查看它,在您的情况下,如果您想要的话,它应该关闭应用程序,但功能是相同的。
因此,让我们的后台服务工作只留下一种调用它的方法,因此在我们的主页(作为示例)上我将执行以下操作:
主页.xaml
<VerticalStackLayout>
<Label
Text="Welcome to .NET Multi-platform App UI"
FontSize="18"
HorizontalOptions="Center" />
<Button
x:Name="CounterBtn"
Text="start Services"
Clicked="OnServiceStartClicked"
HorizontalOptions="Center" />
<Button Text="Stop Service" Clicked="Button_Clicked"></Button>
</VerticalStackLayout>
Run Code Online (Sandbox Code Playgroud)
MainPage.xaml.cs
public partial class MainPage : ContentPage
{
IServiceTest Services;
public MainPage(IServiceTest Services_)
{
InitializeComponent();
ToggleAccelerometer();
Services = Services_;
}
//method to start manually foreground service
private void OnServiceStartClicked(object sender, EventArgs e)
{
Services.Start();
}
//method to stop manually foreground service
private void Button_Clicked(object sender, EventArgs e)
{
Services.Stop();
}
//method to work with accelerometer
public void ToggleAccelerometer()
{
if (Accelerometer.Default.IsSupported)
{
if (!Accelerometer.Default.IsMonitoring)
{
Accelerometer.Default.ReadingChanged += Accelerometer_ReadingChanged;
Accelerometer.Default.Start(SensorSpeed.UI);
}
else
{
Accelerometer.Default.Stop();
Accelerometer.Default.ReadingChanged -= Accelerometer_ReadingChanged;
}
}
}
//on accelerometer property change we call our service and it would send a message
private void Accelerometer_ReadingChanged(object sender, AccelerometerChangedEventArgs e)
{
Services.Start(); //this will never stop until we made some logic here
}
}
Run Code Online (Sandbox Code Playgroud)
这是一个很长的答案,如果有更多关于此的官方文档就太好了!希望能帮助到你!如果有人可以提供有关 IOS、Windows、MacCatalyst 的更多信息,那就太棒了!
小智 8
我的代表太低,无法添加评论
要添加 Leandro 的答案,您必须在正确的平台操作系统中指定使用情况。否则,您将无法使用智能感知来添加用途。
从此图中所示的下拉列表中单击 Android 操作系统: Android 操作系统下拉选择
现在您可以使用智能感知来添加用途。
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
18445 次 |
| 最近记录: |