I have a xamarin.forms android application on playstore. In which I have implemented foreground service to fire AlarmManager notifications (for android version >= Q). I can see some crashes logged on platstore for my app which I think is related to these foreground service and AlarmManager notifications. Here I am posting crash logs from the playstore that is all I have.
java.lang.IllegalStateException
crc640e87e93c5dbd1629.AlarmReceiver.n_onReceive
java.lang.RuntimeException:
at android.app.ActivityThread.handleReceiver (ActivityThread.java:4125)
at android.app.ActivityThread.access$1400 (ActivityThread.java:270)
at android.app.ActivityThread$H.handleMessage (ActivityThread.java:2062)
at android.os.Handler.dispatchMessage (Handler.java:107)
at android.os.Looper.loop (Looper.java:237)
at android.app.ActivityThread.main (ActivityThread.java:7948)
at java.lang.reflect.Method.invoke (Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1075)
Caused by: java.lang.IllegalStateException:
at android.app.ContextImpl.startServiceCommon (ContextImpl.java:1687)
at android.app.ContextImpl.startService (ContextImpl.java:1632)
at android.content.ContextWrapper.startService (ContextWrapper.java:683)
at android.content.ContextWrapper.startService (ContextWrapper.java:683)
at crc640e87e93c5dbd1629.AlarmReceiver.n_onReceive (Native Method)
at crc640e87e93c5dbd1629.AlarmReceiver.onReceive (AlarmReceiver.java:29)
at android.app.ActivityThread.handleReceiver (ActivityThread.java:4116)
here is another log
java.lang.ClassNotFoundException
crc643622be0927bcf195.NotificationService.n_onStartCommand
java.lang.RuntimeException:
at android.app.ActivityThread.handleServiceArgs (ActivityThread.java:3755)
at android.app.ActivityThread.-wrap23 (ActivityThread.java)
at android.app.ActivityThread$H.handleMessage (ActivityThread.java:1744)
at android.os.Handler.dispatchMessage (Handler.java:102)
at android.os.Looper.loop (Looper.java:154)
at android.app.ActivityThread.main (ActivityThread.java:6780)
at java.lang.reflect.Method.invoke (Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:1500)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1390)
Caused by: java.lang.ClassNotFoundException:
at dalvik.system.BaseDexClassLoader.findClass (BaseDexClassLoader.java:56)
at java.lang.ClassLoader.loadClass (ClassLoader.java:380)
at java.lang.ClassLoader.loadClass (ClassLoader.java:312)
at crc643622be0927bcf195.NotificationService.n_onStartCommand (Native Method)
at crc643622be0927bcf195.NotificationService.onStartCommand (NotificationService.java:31)
at android.app.ActivityThread.handleServiceArgs (ActivityThread.java:3738)
Here is the NotificationService class :
[Service]
public class NotificationService : Service
{
private bool isStarted;
private int HIDDEN_NOTIFICATION_SERVICE_ID = 1;
private string HIDDEN_NOTIFICATION_CHANNEL_ID = "1";
private string HIDDEN_NOTIFICATION_NAME = "Hidden Notification Service";
[return: GeneratedEnum]
public override StartCommandResult OnStartCommand(Intent intent, [GeneratedEnum] StartCommandFlags flags, int startId)
{
if (!isStarted)
{
CreateHiddenNotificationChannel();
DispatchNotificationThatServiceIsRunning();
isStarted = true;
}
return StartCommandResult.NotSticky;
}
public override void OnDestroy()
{
// Remove the notification from the status bar.
var notificationManager = (NotificationManager)GetSystemService(NotificationService);
notificationManager.Cancel(HIDDEN_NOTIFICATION_SERVICE_ID);
isStarted = false;
base.OnDestroy();
}
void CreateHiddenNotificationChannel()
{
NotificationChannel hiddentNotificationChannel = new NotificationChannel(HIDDEN_NOTIFICATION_CHANNEL_ID, HIDDEN_NOTIFICATION_NAME, NotificationImportance.Low);
hiddentNotificationChannel.LockscreenVisibility = NotificationVisibility.Secret;
hiddentNotificationChannel.SetSound(null, null);
hiddentNotificationChannel.EnableVibration(false);
NotificationManager notificationManager = (NotificationManager)this.GetSystemService(Context.NotificationService);
notificationManager.CreateNotificationChannel(hiddentNotificationChannel);
}
//start a foreground notification to keep app alive
private void DispatchNotificationThatServiceIsRunning()
{
Intent intent = new Intent(this, typeof(BroadcastReceiver.CustomReceiver));
PendingIntent pendingIntent = PendingIntent.GetBroadcast(
this,
1,
intent,
PendingIntentFlags.UpdateCurrent
);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, HIDDEN_NOTIFICATION_CHANNEL_ID)
.SetDefaults((int)NotificationDefaults.All)
.SetSmallIcon(Resource.Drawable.icon)
.SetSound(null)
.SetContentIntent(pendingIntent)
.SetPriority(NotificationCompat.PriorityMin)
.SetAutoCancel(false)
.SetContentTitle(AppResources.MyApp)
.SetContentText(AppResources.ForegroundServiceNotificationMsg)
.SetStyle(new NotificationCompat.BigTextStyle().BigText(AppResources.ForegroundServiceNotificationMsg))
.SetOngoing(true);
NotificationManagerCompat notificationManager = NotificationManagerCompat.From(this);
StartForeground(HIDDEN_NOTIFICATION_SERVICE_ID, builder.Build());
}
public override IBinder OnBind(Intent intent)
{
return null;
}
}
Starting above service from MainActivity and from BroadcastReceiver class when user reboots the device
if (Android.OS.Build.VERSION.SdkInt >= BuildVersionCodes.Q)
Android.App.Application.Context.StartForegroundService(new Intent(Android.App.Application.Context, typeof(Services.NotificationService)));