Search code examples
c#androidxamarin.androidbroadcastreceiver

Running an android Worker when phone boots doesn't work


I have a worker which functions perfectly. I want to launch it when the phone is booted. I use a broadcast receiver which is supposed to listen to the system booted_completed event, but this broadcast receiver is never called.

In my manifest, I added this permission: <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

Here is my broadcast receiver:

[BroadcastReceiver(Enabled = true)]
[IntentFilter(new[] { Android.Content.Intent.ActionBootCompleted })]
public class BootBroadcastReceiver : BroadcastReceiver
{
    public override void OnReceive(Context context, Intent intent)
    {
        //Notify that the broadcast receiver is launched
        await AndroidNotificationService.NotifyUser("Device boot", "The device is booting", 11, context);
        OneTimeWorkRequest notifWork = new OneTimeWorkRequest.Builder(typeof(Services.Background.NotificationsBackgroundWorker))
            .Build();
        WorkManager.Instance.Enqueue(notifWork);
    }
}

But this dosn't help. the receiver never starts when I reboot my device. I'm testing this on android 9.


Solution

  • Turns out that as from API 26 Android restricts access to broadcast receivers. The way I overcame this was that I created a foreground service inside my broadcast receiver which did the work I wanted in background or which launched my WorkManager.

     [BroadcastReceiver]
    [IntentFilter(new [] { Intent.ActionBootCompleted }, Priority = (int)IntentFilterPriority.HighPriority)]
    public class BootBroadcastReceiver : BroadcastReceiver
    {
        public async override void OnReceive(Context context, Intent intent)
        {
            context.StartForegroundServiceCompat<AfterBootSyncService>();
        }
    }
    

    Here is the implementation of the extension method StartForegroundServiceCompat:

        public static void StartForegroundServiceCompat<T>(this Context context, Bundle args = null) where T : Service
        {
            var intent = new Intent(context, typeof(T));
            if (args != null)
            {
                intent.PutExtras(args);
            }
    
            if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.O)
            {
                context.StartForegroundService(intent);
            }
            else
            {
                context.StartService(intent);
            }
        }
    

    When I do this, code in my broadcast reveicer is called normally.