[Xamarin.Android后台任务在应用程序关闭后被处置

问题描述 投票:0回答:1

[任务:创建一个后台任务以在应用程序停止/暂停时运行,该任务定期(3-7秒)执行HTTP请求并将响应信息存储在mysqlite中,并在需要时显示本地通知。

我已经创建了如下所示的后台服务,

[Service(Enabled = true)]
public class MyRequestService : Service

从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();
}

在我的服务中,我使用了以下功能,

  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)并且禁用了省电模式的移动设备,没有区别,服务通知被终止。问题是什么,我在做什么错?

提前感谢您的帮助或指导!

xamarin android-intent service xamarin.android background
1个回答
0
投票

我认为您正在使用Foreground Services

您应该通过StartForeground方法调度服务通知(前景通知)。

因此请尝试更改

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());

}
© www.soinside.com 2019 - 2024. All rights reserved.