问题描述
我有从剪贴板读取并写入它的xamarin android应用程序。如果用户单击按钮,它将使用前台服务。问题是当用户再次按下按钮时,服务从正在运行的服务中消失,但仍在执行其工作(编辑复制的文本)。我怎么能完全阻止它工作?
foreground.cs:
public override IBinder OnBind(Intent intent)
{
return null;
}
public override StartCommandResult OnStartCommand(Intent intent,StartCommandFlags flags,int startId)
{
Clipboard.ClipboardContentChanged += async (o,e) =>
{
var text = await Clipboard.GetTextAsync();
Toast.MakeText(this,text,ToastLength.Long).Show();
if (text.Contains("@"))
{
await Clipboard.SetTextAsync(text.Replace("@",""));
}
};
Notification notif = ReturnNotif();
StartForeground(1,notif);
return StartCommandResult.NotSticky;
}
public override void OnDestroy()
{
base.OnDestroy();
}
public override void OnCreate()
{
base.OnCreate();
}
public override bool StopService(Intent name)
{
StopForeground(true);
StopSelf();
return base.StopService(name);
}
MainActivity.cs:
if (id == Resource.Id.myService)
{
if (count != 1)
{
count = 1;
var intent = new Intent(this,typeof(foreground));
intent.SetAction("No");
if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
{
StartForegroundService(intent);
}
else
{
StartService(intent);
}
}
else
{
var intent = new Intent(this,typeof(foreground));
StopService(intent);
Toast.MakeText(this,"Service Stopped",ToastLength.Long).Show();
count = 0;
}
}
我做错了什么?
编辑: 如果从最近使用的应用程序中删除了该应用程序,服务将完全停止。
解决方法
在您的MyForegroundService.cs
中。只需像下面的代码那样在StopForeground(true)
方法中添加OnDestroy()
。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
namespace ForegroundServiceDemo
{
[Service]
class MyForegroundService : Service
{
public const int SERVICE_RUNNING_NOTIFICATION_ID = 10000;
[return: GeneratedEnum]
public override StartCommandResult OnStartCommand(Intent intent,[GeneratedEnum] StartCommandFlags flags,int startId)
{
CreateNotificationChannel();
string messageBody = "service starting";
// / Create an Intent for the activity you want to start
Intent resultIntent = new Intent(this,typeof(Activity1));
// Create the TaskStackBuilder and add the intent,which inflates the back stack
TaskStackBuilder stackBuilder = TaskStackBuilder.Create(this);
stackBuilder.AddNextIntentWithParentStack(resultIntent);
// Get the PendingIntent containing the entire back stack
PendingIntent resultPendingIntent = stackBuilder.GetPendingIntent(0,PendingIntentFlags.UpdateCurrent);
var notification = new Notification.Builder(this,"10111")
.SetContentIntent(resultPendingIntent)
.SetContentTitle("Foreground")
.SetContentText(messageBody)
.SetSmallIcon(Resource.Drawable.main)
.SetOngoing(true)
.Build();
StartForeground(SERVICE_RUNNING_NOTIFICATION_ID,notification);
//do you work
return StartCommandResult.Sticky;
}
public override void OnDestroy()
{
base.OnDestroy();
StopForeground(true);
}
public override IBinder OnBind(Intent intent)
{
return null;
}
void CreateNotificationChannel()
{
if (Build.VERSION.SdkInt < BuildVersionCodes.O)
{
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);
}
}
}
要停止它时。只需调用以下代码即可。
Android.App.Application.Context.StopService(intent);
这是我在“活动”中的代码。
public class MainActivity : AppCompatActivity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this,savedInstanceState);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.activity_main);
Button button1 = FindViewById<Button>(Resource.Id.button1);
Button button2 = FindViewById<Button>(Resource.Id.button2);
button2.Click += Button2_Click;
button1.Click += Button1_Click;
}
Intent intent;
private void Button2_Click(object sender,System.EventArgs e)
{
// stop foreground service.
Android.App.Application.Context.StopService(intent);
}
private void Button1_Click(object sender,System.EventArgs e)
{
intent = new Intent(Android.App.Application.Context,typeof(MyForegroundService));
// start foreground service.
if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.O)
{
StartForegroundService(intent);
}
}
此处正在运行GIF。
==== 更新 ====
预期的行为是:服务停止时,用户可以正常复制和粘贴而不会受到服务的干扰
您可以使用以下方法来实现。使用Clipboard.ClipboardContentChanged += Clipboard_ClipboardContentChanged;
执行行为,使用Clipboard.ClipboardContentChanged -= Clipboard_ClipboardContentChanged;
禁用OnDistory
方法中的行为。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Xamarin.Essentials;
namespace ForegroundServiceDemo
{
[Service]
class MyForegroundService : Service
{
public const int SERVICE_RUNNING_NOTIFICATION_ID = 10000;
[return: GeneratedEnum]
public override StartCommandResult OnStartCommand(Intent intent,int startId)
{
CreateNotificationChannel();
string messageBody = "service starting";
Clipboard.ClipboardContentChanged += Clipboard_ClipboardContentChanged;
// / Create an Intent for the activity you want to start
Intent resultIntent = new Intent(this,notification);
//do you work
return StartCommandResult.Sticky;
}
private async void Clipboard_ClipboardContentChanged(object sender,EventArgs e)
{
//throw new NotImplementedException();
var text = await Clipboard.GetTextAsync();
Toast.MakeText(this,text,ToastLength.Long).Show();
if (text.Contains("@"))
{
await Clipboard.SetTextAsync(text.Replace("@",""));
}
}
public override void OnDestroy()
{
base.OnDestroy();
Clipboard.ClipboardContentChanged -= Clipboard_ClipboardContentChanged;
StopForeground(true);
}
public override IBinder OnBind(Intent intent)
{
return null;
}
void CreateNotificationChannel()
{
if (Build.VERSION.SdkInt < BuildVersionCodes.O)
{
return;
}
var channelName = Resources.GetString(Resource.String.channel_name);
var channelDescription = GetString(Resource.String.channel_description);
var channel = new NotificationChannel("10111",NotificationImportance.Default)
{
Description = channelDescription
};
var notificationManager = (NotificationManager)GetSystemService(NotificationService);
notificationManager.CreateNotificationChannel(channel);
}
}
}
此处运行GIF。
,为防止出现此问题,请按如下所示在启动前台方法时在“属性”字典中添加“ myServiceIsRunning” bool值:
Application.Current.Properties["myServiceIsRunning"] = true
使用get函数或所需的任何方法,在启动前台方法之前,请验证键“ myServiceIsRunning”是否存在,以及是否存在,其状态如何:
public bool getRunningStateMyService(){
bool myServiceIsRunningValue;
if (Application.Current.Properties.ContainsKey("myServiceIsRunning"))
{
myServiceIsRunningValue = Convert.ToBoolean(Application.Current.Properties["myServiceIsRunning"]);
}
else
{
myServiceIsRunningValue = false;
}
return locationServiceIsRunning;
}
使用简单的if {} / else {}获取值后,如果服务是否正在运行,则可以选择是否启动新实例。或者,在这种情况下,只需阻止前台方法继续运行即可。
在销毁前台方法时,请不要忘记将值设置为false。
“属性”字典可以存储关闭应用后发送的数据。您可以在此处获得更多信息: https://docs.microsoft.com/fr-fr/xamarin/xamarin-forms/app-fundamentals/application-class#Properties_Dictionary