Forum Xamarin.Android
We are excited to announce that the Xamarin Forums are moving to the new Microsoft Q&A experience. Q&A is the home for technical questions and answers at across all products at Microsoft now including Xamarin!

We encourage you to head over to Microsoft Q&A for .NET for posting new questions and get involved today.

Android intent service running faster then expected on a timer.

Philip_orrillPhilip_orrill Member
edited June 25 in Xamarin.Android

HI
I mainly have a windows development background and am trying to get my head around android. I want to create a service that runs every x seconds/minutes.

I am aiming to run this on Android 8+ (I know from my reading this might make a difference, as there have been API changes according to the Android documentation).

I have been through a few tutorials and some documentation around Background Services, worker manager and schedulers plus a few other such as alarm managers.

I gather that android will only allow certain actions to happen within a certain time period. Such as a schedule can only run every 15 minutes. It won't let you set a schedule for every 30 seconds as an example.

I did some reading and it seems a way to get the kind of behaviour I am looking for is with an Intent.
Where after it runs I can set a new timer within itself, so it repeats.

I have created a small test app to do this with some logs.

It calls the logs and runs, however the timer seems to fire every 5 seconds-ish and ignores any time I put in. I have change the type of timer and the way I am inputting the next time a few times and can't seem to get the result I want.

I have tried:
DateTime.Now.Millisecond + timer
SystemClock.ElapsedRealtime() + timer
DateTime.UtcNow.Millisecond + timer

A timer can be set a minimum for 5 seconds in the future from what I saw. The fact it seems to be firing close to that makes me guess that maybe I am setting the timer in the past? I'm not sure what happens in that case. I am also not sure how in each case it would always be in the past to cause this.

Any help to point me in the right direction would be greatly appreciated. I have included the code below.

MainActivity.cs:

` public class MainActivity : Activity
{
TimerBroadcastReceiver receiver;

    protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);
        Xamarin.Essentials.Platform.Init(this, savedInstanceState);
        // Set our view from the "main" layout resource
        SetContentView(Resource.Layout.activity_main);
        receiver = new TimerBroadcastReceiver();


    }

    protected override void OnResume()
    {
        base.OnResume();
        Intent intent = new Intent(this, typeof(TimerBroadcastReceiver));
        intent.PutExtra("extraContent", "1234");

        RegisterReceiver(receiver, new IntentFilter("com.timerbroadcast.ACTION_START_SERVICE"));
        SendBroadcast(intent);
    }

    protected override void OnPause()
    {
        UnregisterReceiver(receiver);
        base.OnPause();
    }

    public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
    {
        Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);

        base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
    }`

TimerBroadcastReceiver.cs:

[BroadcastReceiver] [IntentFilter(new[] { "com.timerbroadcast.ACTION_START_SERVICE" }, Categories = new[] { "android.intent.category.DEFAULT" })] public class TimerBroadcastReceiver : BroadcastReceiver { public override void OnReceive(Context context, Intent intent) { Toast.MakeText(context, "Received intent!", ToastLength.Short).Show(); var startServiceIntent = new Intent(context, typeof(TimerIntentService)); context.StartService(startServiceIntent); } }

TimerIntentService.cs

`[Service(Exported = true)]
[IntentFilter(new[] { "com.timerbroadcast.ACTION_START_SERVICE" })]
public class TimerIntentService : IntentService
{
static readonly string TAG = typeof(TimerIntentService).FullName;
static readonly int Timer = 30000;

    public TimerIntentService() : base("TimerIntentService")
    {

    }

    public override StartCommandResult OnStartCommand(Intent intent, [GeneratedEnum] StartCommandFlags flags, int startId)
    {
        base.OnStartCommand(intent, flags, startId);
        Log.Debug(TAG, "Starting Service.");
        return StartCommandResult.Sticky;
    }

    public override void OnCreate()
    {
        base.OnCreate();
        Log.Debug(TAG, "On create Service");
    }

    public override void OnDestroy()
    {
        Log.Debug(TAG, "On destroy Service");
        base.OnDestroy();
    }

    private void ScheduleNextRun()
    {
        Log.Debug(TAG, "Setting timer");
        String alarm = Context.AlarmService;
        AlarmManager am = (AlarmManager)GetSystemService(alarm);

        Intent intent = new Intent("com.timerbroadcast.ACTION_START_SERVICE");
        PendingIntent pi = PendingIntent.GetBroadcast(this, 0, intent, PendingIntentFlags.UpdateCurrent);

        long triggerTime = DateTime.UtcNow.Millisecond + Timer;
        am.SetExact(AlarmType.RtcWakeup, triggerTime, pi);
    }

    protected override void OnHandleIntent(Intent intent)
    {
        Log.Debug(TAG, "This should run every 30 seconds");
        ScheduleNextRun();
    }`
Sign In or Register to comment.