Xamarin.Android后台任务在应用程序关闭后被处置 [英] Xamarin.Android Background task disposed after application closed
问题描述
任务:创建一个后台任务,以在应用程序停止/暂停时运行,该任务定期(3-7秒)执行HTTP请求并将响应信息存储在mysqlite中,并在需要时显示本地通知.
Task: Create a background task to run when application is stopped/paused that periodically (3-7 seconds) performs HTTP requests and stores response information in mysqlite and displays local notifications when required.
我已经创建了如下的后台服务,
I have create a background service like the following,
[Service(Enabled = true)]
public class MyRequestService : Service
这就像MainActivity的意图一样开始
That is started like an intent from MainActivity,
public void StartMyRequestService()
{
var serviceToStart = new Intent(this, typeof(MyRequestService));
StartService(serviceToStart);
}
public void StopMyRequestService()
{
var serviceToStart = new Intent(this, typeof(MyRequestService));
StopService(serviceToStart);
}
protected override void OnPause()
{
base.OnPause();
StartMyRequestService();
}
protected override void OnDestroy()
{
base.OnDestroy();
StartMyRequestService();
}
protected override void OnResume()
{
base.OnResume();
StopMyRequestService();
}
在我的服务中,我具有以下功能,
In my service I have the following features in use,
- 在OnStartCommand中返回STICKY
- 创建一个永久"本地人
- 频道通知
- 电源管理器锁
代码如下所示,
private Handler handler;
private Action runnable;
private bool isStarted
private WakeLock wakeLock;
public override void OnCreate()
{
base.OnCreate();
handler = new Handler();
runnable = new Action(() =>
{
DispatchNotificationThatAlarmIsGenerated("I'm running");
handler.PostDelayed(runnable, DELAY_BETWEEN_LOG_MESSAGES);
});
}
public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
{
if (isStarted)
{
// service is already started
}
else
{
CreateNotificationChannel();
DispatchNotificationThatServiceIsRunning();
handler.PostDelayed(runnable, DELAY_BETWEEN_LOG_MESSAGES);
isStarted = true;
PowerManager powerManager = (PowerManager)this.GetSystemService(Context.PowerService);
WakeLock wakeLock = powerManager.NewWakeLock(WakeLockFlags.Full, "Client Lock");
wakeLock.Acquire();
}
return StartCommandResult.Sticky;
}
public override void OnTaskRemoved(Intent rootIntent)
{
//base.OnTaskRemoved(rootIntent);
}
public override IBinder OnBind(Intent intent)
{
// Return null because this is a pure started service. A hybrid service would return a binder that would
// allow access to the GetFormattedStamp() method.
return null;
}
public override void OnDestroy()
{
// Stop the handler.
handler.RemoveCallbacks(runnable);
// Remove the notification from the status bar.
var notificationManager = (NotificationManager)GetSystemService(NotificationService);
notificationManager.Cancel(NOTIFICATION_SERVICE_ID);
isStarted = false;
wakeLock.Release();
base.OnDestroy();
}
private void CreateNotificationChannel()
{
//Notification Channel
NotificationChannel notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, NOTIFICATION_CHANNEL_NAME, NotificationImportance.Max);
notificationChannel.EnableLights(true);
notificationChannel.LightColor = Color.Red;
notificationChannel.EnableVibration(true);
notificationChannel.SetVibrationPattern(new long[] { 100, 200, 300, 400, 500, 400, 300, 200, 400 });
NotificationManager notificationManager = (NotificationManager)this.GetSystemService(Context.NotificationService);
notificationManager.CreateNotificationChannel(notificationChannel);
}
private void DispatchNotificationThatServiceIsRunning()
{
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
.SetDefaults((int)NotificationDefaults.All)
.SetSmallIcon(Resource.Drawable.icon)
.SetVibrate(new long[] { 100, 200, 300, 400, 500, 400, 300, 200, 400 })
.SetSound(null)
.SetChannelId(NOTIFICATION_CHANNEL_ID)
.SetPriority(NotificationCompat.PriorityDefault)
.SetAutoCancel(false)
.SetContentTitle("Mobile")
.SetContentText("My service started")
.SetOngoing(true);
NotificationManagerCompat notificationManager = NotificationManagerCompat.From(this);
notificationManager.Notify(NOTIFICATION_SERVICE_ID, builder.Build());
}
private void DispatchNotificationThatAlarmIsGenerated(string message)
{
var intent = new Intent(this, typeof(MainActivity));
intent.AddFlags(ActivityFlags.ClearTop);
var pendingIntent = PendingIntent.GetActivity(this, 0, intent, PendingIntentFlags.OneShot);
Notification.Builder notificationBuilder = new Notification.Builder(this, NOTIFICATION_CHANNEL_ID)
.SetSmallIcon(Resource.Drawable.icon_round)
.SetContentTitle("Alarm")
.SetContentText(message)
.SetAutoCancel(true)
.SetContentIntent(pendingIntent);
var notificationManager = (NotificationManager)GetSystemService(NotificationService);
notificationManager.Notify(App.NOTIFICATION_ALARM, notificationBuilder.Build());
}
这只是一个示例,代码不发出任何HTTP请求,也不与实体,数据库连接等一起使用,它只是每X秒发送一次新的通知.我应该看到的是,当应用程序关闭时,服务会启动并创建本机通知,这就是我所看到的.然后一段时间,我看到正在生成警报"通知,然后我的服务通知被杀死,服务被处置,仅此而已.如果单击手机上的电源按钮以点亮屏幕,则会看到警报"通知再次生效.我已经检查了几种具有不同Android操作系统(6、7和8)并且禁用了省电模式的移动设备,没有区别,服务通知被终止.是什么问题,我在做什么错了?
This is just a sample, the code is not making any HTTP requests, nor works with entities, db connection etc, it just simply dispatches a new notification every X seconds. What I should see is, when application is closed, the service starts and native notification is created, which is what I see. Then for some time I see 'Alarm' notification is being generated and then my service notification is killed, service disposed and that is all. If I click the power button on my phone, to light up the screen, I see 'Alarm' notifications come to live again. I've checked on several mobile devices with different Android OS (6, 7 and 8) and with disabled power saving modes, no difference, the service notification is killed. What is the issue, what am I doing wrong?
在此先感谢您的帮助或指导!
Thanks in advance for any help or guidance!
推荐答案
我认为您正在使用您应该通过StartForeground方法调度服务通知(前景通知).
you should dispatch the service notification(foreground notification) by StartForeground method.
所以尝试更改
private void DispatchNotificationThatServiceIsRunning()
{
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
.SetDefaults((int)NotificationDefaults.All)
.SetSmallIcon(Resource.Drawable.icon)
.SetVibrate(new long[] { 100, 200, 300, 400, 500, 400, 300, 200, 400 })
.SetSound(null)
.SetChannelId(NOTIFICATION_CHANNEL_ID)
.SetPriority(NotificationCompat.PriorityDefault)
.SetAutoCancel(false)
.SetContentTitle("Mobile")
.SetContentText("My service started")
.SetOngoing(true);
NotificationManagerCompat notificationManager = NotificationManagerCompat.From(this);
notificationManager.Notify(NOTIFICATION_SERVICE_ID, builder.Build());
}
到
private void DispatchNotificationThatServiceIsRunning()
{
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
.SetDefaults((int)NotificationDefaults.All)
.SetSmallIcon(Resource.Drawable.icon)
.SetVibrate(new long[] { 100, 200, 300, 400, 500, 400, 300, 200, 400 })
.SetSound(null)
.SetChannelId(NOTIFICATION_CHANNEL_ID)
.SetPriority(NotificationCompat.PriorityDefault)
.SetAutoCancel(false)
.SetContentTitle("Mobile")
.SetContentText("My service started")
.SetOngoing(true);
NotificationManagerCompat notificationManager = NotificationManagerCompat.From(this);
//dispatch foreground notification
StartForeground(NOTIFICATION_SERVICE_ID, builder.Build());
}
这篇关于Xamarin.Android后台任务在应用程序关闭后被处置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!