Xamarin.Android后台任务在应用程序关闭后被处置 [英] Xamarin.Android Background task disposed after application closed

查看:106
本文介绍了Xamarin.Android后台任务在应用程序关闭后被处置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

任务:创建一个后台任务,以在应用程序停止/暂停时运行,该任务定期(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,

  1. 在OnStartCommand中返回STICKY
  2. 创建一个永久"本地人
  3. 频道通知
  4. 电源管理器锁

代码如下所示,

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆