如何在 Oreo 8.0 以下为 Android 创建带有通知的前台服务?

How to create a foreground service with notification for Android below Oreo 8.0?

我使用以下代码创建了一个前台服务,该代码位于名为 DemoIntentService.cs 的服务 class 中的覆盖方法 OnStartCommand 中。

base.OnStartCommand(intent,flags,startId);
if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
{
 Intent notificationIntent = new Intent(this, Java.Lang.Class.FromType(typeof(DemoIntentService)));
            PendingIntent pendingIntent = PendingIntent.GetActivity(this, 0, notificationIntent, 0);

            Notification.Builder notificationBuilder = new Notification.Builder(this, "Example_Service_Channel")
            .SetSmallIcon(Resource.Drawable.AlertLightFrame)
            .SetContentTitle(Resources.GetString(Resource.String.DialogAlertTitle))
            .SetContentText(Resources.GetString(Resource.String.SelectTextMode))
            .SetContentIntent(pendingIntent);

            Notification notificationAfterBuild = notificationBuilder.Build();

            StartForeground(123, notificationAfterBuild);

            InitializeAlarmManager();
            setAlarm();
}
return StartCommandResult.RedeliverIntent;

显然,上面的代码仅适用于AndroidOreo 8.0及以上版本,服务运行正常,即使我手动关闭应用程序也不会清除通知。 (这很好,这就是我想要的!)。但是,当我使用上面的代码在 Android Nougat 7.1.1 上进行测试时,它不起作用。

首先,我在网上查了一下他们说8.0以下的Android不需要创建通知通道,所以我去掉了“Example_Service_Channel”,也就是channelID。该应用程序已成功部署,但当我终止该应用程序时通知消失了。第二件事,当我删除 channelID 时,Xamarin 向我发出警告说“Notification.Builder.Builder(Context) is obsolete : deprecated”并且该行已变为黄色。我忽略错误并部署应用程序。该服务确实 运行 因为它在开发人员选项中的 运行ning 服务中可见。但是当我终止应用程序时,服务和通知一起消失了。有没有其他方法可以创建一个永远不会在 8.0 以下 Android 结束的前台通知服务?感谢您的任何评论和想法。

尝试使用

启动服务
ContextCompat.startForegroundService(context,intent)

构建通知然后调用

startForeground(1, notification)

在 onCreate() 或 onStartCommand() 中,无论什么对你有用,但在服务启动后 运行 不要忘记请求许可

<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

我写了一个简单的示例,它适用于 Android 7.1。我刚刚从 Android 8.0

中删除了通知通道

1.Create 一项服务 MyService.cs :

[Service(Enabled = true)]
public class MyService : Service
{
    private Handler handler;
    private Action runnable;
    private bool isStarted;
    private int DELAY_BETWEEN_LOG_MESSAGES = 5000;
    private int NOTIFICATION_SERVICE_ID = 1001;
    private int NOTIFICATION_AlARM_ID = 1002;
    public override void OnCreate()
    {
        base.OnCreate();

        handler = new Handler();

        //here is what you want to do always, i just want to push a notification every 5 seconds here
        runnable = new Action(() =>
        {
           if (isStarted)
            {
                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
        {
            DispatchNotificationThatServiceIsRunning();

            handler.PostDelayed(runnable, DELAY_BETWEEN_LOG_MESSAGES);
            isStarted = true;
        }
        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;
        base.OnDestroy();
    }



    //start a foreground notification to keep alive 
    private void DispatchNotificationThatServiceIsRunning()
    {
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
               .SetDefaults((int)NotificationDefaults.All)
               .SetSmallIcon(Resource.Drawable.Icon)
               .SetVibrate(new long[] { 100, 200, 300, 400, 500, 400, 300, 200, 400 })
               .SetSound(null)
               .SetPriority(NotificationCompat.PriorityDefault)
               .SetAutoCancel(false)
               .SetContentTitle("Mobile")
               .SetContentText("My service started")
               .SetOngoing(true);

        NotificationManagerCompat notificationManager = NotificationManagerCompat.From(this);
        StartForeground(NOTIFICATION_SERVICE_ID, builder.Build());
    }

    //every 5 seconds push a notificaition
    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)
            .SetSmallIcon(Resource.Drawable.Icon)
            .SetContentTitle("Alarm")
            .SetContentText(message)
            .SetAutoCancel(true)
            .SetContentIntent(pendingIntent);

        var notificationManager = (NotificationManager)GetSystemService(NotificationService);
        notificationManager.Notify(NOTIFICATION_AlARM_ID, notificationBuilder.Build());
    }
}

2.in 你的 activity :

protected override void OnResume()
  {
      base.OnResume();
      StartMyRequestService();
  }
public void StartMyRequestService()
  {
      var serviceToStart = new Intent(this, typeof(MyService));
      StartService(serviceToStart);
  }