Search code examples
androidxamarinlocalnotification

Android Local Notification BootReceiver not working


I am working with an application that displays a notification to the user at a specific time. Unfortunately, the application does not display a notification after restarting the phone. This is what my code looks like:

My Manifest:

<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="mivs.notificationtest" android:installLocation="auto">
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-sdk android:minSdkVersion="25" android:targetSdkVersion="30" />
<application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme">
<service android:name="com.mivs.notificationtest.app.RebootService"/> <receiver android:name="com.mivs.notificationtest.app.RebootReceiver">
<intent-filter>
    <action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter> </receiver>
</application> </manifest>

RebootReceiver.cs:

[BroadcastReceiver(Enabled =true, Name ="com.mivs.notificationtest.RebootReceiver")]
    [IntentFilter(new[] { Intent.ActionBootCompleted })]
public class RebootReceiver : BroadcastReceiver
{
    public Class AlarmService { get; private set; }

    public override void OnReceive(Context context, Intent intent)
    {
        
        if (intent.Action.Equals(Intent.ActionBootCompleted))
        {
            Toast.MakeText(context, "Action Boot Completed!", ToastLength.Long).Show();
            Intent serviceIntent = new Intent(context, typeof(RebootService));
            context.StartService(serviceIntent);

            string title = "If you see this";
            string message = "Its work";

            Intent alarmIntent = new Intent(Application.Context, typeof(AlarmReceiver));
            alarmIntent.PutExtra("message", message);
            alarmIntent.PutExtra("title", title);

            var pendingIntent = PendingIntent.GetBroadcast(context, 0, alarmIntent, PendingIntentFlags.UpdateCurrent);
            var alarmManager = context.GetSystemService(AlarmService).JavaCast<AlarmManager>();

            DateTime nowDate = DateTime.Now;

            int month = 09;
            int day = 29;
            int hour = 15;
            int minute = 35;

            DateTime dt = new DateTime(nowDate.Year, month, day, hour, minute, 0);
            DateTimeOffset dateOffsetValue = DateTimeOffset.Parse(dt.ToString());
            var millisec = dateOffsetValue.ToUnixTimeMilliseconds();

            alarmManager.Set(AlarmType.Rtc, millisec, pendingIntent);
        }
    }
}

RebootService.cs:

[Service(Name = "com.mivs.notificationtest.RebootService")]
public class RebootService : Service
{       
    public override IBinder OnBind(Intent intent)
    {
        return null;
    }
    public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
    {
        Toast.MakeText(this, "Service STARTED!", ToastLength.Long).Show();
        return StartCommandResult.Sticky;
    }

    public override void OnDestroy()
    {
        base.OnDestroy();

        Toast.MakeText(this, "Service STOPED", ToastLength.Long).Show();
    }
}

I have already tried everything I could find on the internet about it. The applications are tested on the LG G6 Android 9.0 device. Please help.

I also used this material from this post: “Rebooting receiver” not working android [Xamarin.Android]


Solution

  • I've just tested on my device. This works for me:

    Adding this permission to the manifest:

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

    Then creating this boot receiver:

    [BroadcastReceiver(
        Enabled = true,
        Permission = "android.permission.RECEIVE_BOOT_COMPLETED",
        Exported = true)]
    [IntentFilter(new []
    {
        "android.intent.action.BOOT_COMPLETED", 
        "android.intent.action.QUICKBOOT_POWERON", 
        "com.htc.intent.action.QUICKBOOT_POWERON"
    }, Categories = new []{ "android.intent.category.DEFAULT" })]
    public class MyRebootReceiver : BroadcastReceiver
    {
        private const string NotificationChannelId = "boot_notifications";
        private const int NotificationId = 1000;
        
        public override void OnReceive(Context? context, Intent? intent)
        {
            Log.Info("MyRebootReceiver", "Got intent");
            
            var notificationManager = (NotificationManager) context?.GetSystemService(Context.NotificationService);
            SetupNotificationChannel(notificationManager);
            
            var resultIntent = new Intent(context, typeof(MainActivity));
            var stackBuilder = TaskStackBuilder.Create(context);
            stackBuilder.AddParentStack(Java.Lang.Class.FromType(typeof(MainActivity)));
            stackBuilder.AddNextIntent(resultIntent);
    
            // Create the PendingIntent with the back stack:
            var resultPendingIntent = stackBuilder.GetPendingIntent(0, (int) PendingIntentFlags.UpdateCurrent);
    
            var notification = new NotificationCompat.Builder(context, NotificationChannelId)
                .SetContentTitle("Device Rebooted")
                .SetContentText("Your device rebooted")
                .SetSmallIcon(Resource.Drawable.ic_stat_accessibility_new)
                .SetContentIntent(resultPendingIntent);
                
            notificationManager?.Notify(NotificationId, notification.Build());
        }
        
        private void SetupNotificationChannel(NotificationManager notificationManager)
        {
            if (Build.VERSION.SdkInt < BuildVersionCodes.O) return;
    
            var channel = new NotificationChannel(NotificationChannelId, "Boot Notifications",
                NotificationImportance.Default)
            {
                Description = "Channel for receiving boot notifications"
            };
                
            notificationManager.CreateNotificationChannel(channel);
        }
    }
    

    You just have to ensure the App was launched at least once.