Home > Software engineering >  Execute function in mobile app every few minutes, regardless of foreground/background
Execute function in mobile app every few minutes, regardless of foreground/background

Time:12-16

I am trying to run a function with Xamarin Forms, specifically on Android, every few minutes. Sadly, the documentation surrounding this is nothing if not vague. Among other things, it referred me to the (deprecated) FireBase Job Dispatcher.

At the moment, I have tried this:

Android
MainActivity.cs

[Activity(Label = "SolutionName", Icon = "@mipmap/icon", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize )]
    public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
    {
        protected override void OnCreate(Bundle savedInstanceState)
        {
            TabLayoutResource = Resource.Layout.Tabbar;
            ToolbarResource = Resource.Layout.Toolbar;

            base.OnCreate(savedInstanceState);

            Xamarin.Essentials.Platform.Init(this, savedInstanceState);
            global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
            Xamarin.FormsMaps.Init(this, savedInstanceState);
            LoadApplication(new App());

            //StartService(new Intent(this, typeof(PeriodicService)));

            var alarmIntent = new Intent(this, typeof(BackgroundReceiver));

            var pending = PendingIntent.GetBroadcast(this, 0, alarmIntent, PendingIntentFlags.UpdateCurrent);

            var alarmManager = GetSystemService(AlarmService).JavaCast<AlarmManager>();
            alarmManager.Set(AlarmType.ElapsedRealtime, SystemClock.ElapsedRealtime()   3 * 1000, pending);
        }
    }
}

BroadcastReceiver.cs

[BroadcastReceiver]
    public class BackgroundReceiver : BroadcastReceiver
    {
        public override void OnReceive(Context context, Intent intent)
        {
            PowerManager pm = (PowerManager)context.GetSystemService(Context.PowerService);
            PowerManager.WakeLock wakeLock = pm.NewWakeLock(WakeLockFlags.Partial, "BackgroundReceiver");
            wakeLock.Acquire();

            MessagingCenter.Send<object, string>(this, "UpdateLabel", "Hello from Android");

            wakeLock.Release();
        }
    }

Main HomePage.xaml

<Label Text="Welcome to Xamarin Forms!" 
    x:Name="BackgroundServiceLabel"
    VerticalOptions="Center" 
    HorizontalOptions="Center" />

HomePage.xaml.cs

public HomePage()
    {
        InitializeComponent();
        InitializeGeofences();
        GetData();

        MessagingCenter.Subscribe<object, string>(this, "UpdateLabel", (s, e) =>
        {
            Device.BeginInvokeOnMainThread(() =>
        {
            BackgroundServiceLabel.Text = e;
        });
    });
}

This code doesn't run, and doesn't have any errors. Did I do something wrong? Are there any fixes? Are there alternate routes?

Thanks for taking the time to read this regardless.

CodePudding user response:

The short answer is "You can't do it." The long answer is: It's not a good design to force the system to execute something periodically new and new Android OS versions have more restrictions. It's better to design your app to execute some logic based on some system or user events.

you can schedule your tasks using WorkManager API to initiate some process you can use Push Notifications API

Sometimes we must force the system to execute some tasks for this, we can use ForegroundService BUT again it should be your "last resort".

  • Related