问题
I am working on xamarin.forms app and I am setting local notification using alarm manager. It is triggering fine on android version 8 and 9 but somehow it's not triggering in Android 10.
In android device logs for Android 10, I got
07-22 15:00:06.612 Samsung SM-M205F Verbose 4185 SamsungAlarmManager Sending to uid : 10244 action=null alarm=Alarm{a757a70 type 0 when 1595410200000 com.MyApp.andr.connect}
07-22 15:00:06.613 Samsung SM-M205F Warning 4185 BroadcastQueue Unable to launch app com.MyApp.andr.connect/10244 for broadcast Intent { flg=0x14 cmp=com.MyApp.andr.connect/crc640e87e93c5dbd1629.AlarmReceiver (has extras) }: process is bad
Update (Issue is still with Android 10)
I have managed to get notification when app is running, but now notifications are not firing when app is closed.
Note : I have made a sample which is working just fine with Android 10, Notifications are triggering when app is running or closed in the sample. I don't have to use foreground service. (I have used same approach in my work project). So There is something wrong in my work project which I am not able to figure out.
Here is the Android device logs when app is closed and notifications are about to trigger,
If someone can help !
回答1:
All of the code will be frozen when your application is closed including the alarm manager. If you want it still alive, we could use foreground service: https://docs.microsoft.com/en-us/xamarin/android/app-fundamentals/services/foreground-services This may be a little out of date, here is my approach to create the notification:
[Service]
public class SampleService : Service
{
public static string CHANNEL_ID = "com.channelid";
public static string CHANNEL_NAME = "com.channelname";
public override void OnCreate()
{
base.OnCreate();
}
public override StartCommandResult OnStartCommand(Intent intent, [GeneratedEnum] StartCommandFlags flags, int startId)
{
registerNotificationChannel();
int notifyId = (int)JavaSystem.CurrentTimeMillis();
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this, CHANNEL_ID);
mBuilder.SetSmallIcon(Resource.Mipmap.ic_launcher);
if (Build.VERSION.SdkInt < BuildVersionCodes.N)
{
mBuilder.SetContentTitle("app name");
}
StartForeground(notifyId, mBuilder.Build());
return StartCommandResult.Sticky;
}
private void registerNotificationChannel()
{
if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
{
NotificationManager mNotificationManager = (NotificationManager)GetSystemService(Context.NotificationService);
NotificationChannel notificationChannel = mNotificationManager.GetNotificationChannel(CHANNEL_ID);
if (notificationChannel == null)
{
NotificationChannel channel = new NotificationChannel(CHANNEL_ID,
CHANNEL_NAME, NotificationImportance.High);
channel.EnableLights(true);
channel.LightColor = Color.Red;
channel.LockscreenVisibility = NotificationVisibility.Public;
mNotificationManager.CreateNotificationChannel(channel);
}
}
}
public override IBinder OnBind(Intent intent)
{
throw new NotImplementedException();
}
}
Update
Now you don't need to use alarmmanager any more .
In MainActivity
public static MainActivity Instance { get; set; }
protected override void OnCreate(Bundle savedInstanceState)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(savedInstanceState);
Instance = this;
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
LoadApplication(new App());
}
In AlarmAndNotificationService
void IAlarmAndNotificationService.ScheduleLocalNotification(string notificationTitle, string notificationMessage, DateTime specificDateTime, TimeSpan timeSpan, int notificationId, NotificationInterval interval)
{
// start service here
Intent s = new Intent(MainActivity.Instance, typeof(SampleService));
MainActivity.Instance.StartService(s);
}
in SampleService
public class SampleService : Service
{
private Handler handler;
private Action runnable;
private bool isStarted;
private int DELAY_BETWEEN_LOG_MESSAGES = 5000; // set time span
private int NOTIFICATION_SERVICE_ID = 1001;
private int NOTIFICATION_AlARM_ID = 1002;
private string NOTIFICATION_CHANNEL_ID = "1003";
private string NOTIFICATION_CHANNEL_NAME = "MyChannel";
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
{
CreateNotificationChannel();
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();
}
private void CreateNotificationChannel()
{
//Notification Channel
NotificationChannel notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, NOTIFICATION_CHANNEL_NAME, NotificationImportance.Max);
notificationChannel.EnableLights(true);
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);
}
//start a foreground notification to keep alive
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);
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, NOTIFICATION_CHANNEL_ID)
.SetSmallIcon(Resource.Drawable.icon)
.SetContentTitle("Alarm")
.SetContentText(message)
.SetAutoCancel(true)
.SetContentIntent(pendingIntent);
var notificationManager = (NotificationManager)GetSystemService(NotificationService);
notificationManager.Notify(NOTIFICATION_AlARM_ID, notificationBuilder.Build());
}
}
来源:https://stackoverflow.com/questions/62909338/local-notification-not-triggering-in-android-10