如何在 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);
}
我使用以下代码创建了一个前台服务,该代码位于名为 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);
}