-1

I am creating an application in Xamarin using visual studio,where that app services always should be running in background even if the app is closed and that service should send notification in a interval. If that app is closed by the system(in the condition when it is taking more memory space) then it should restart the services by showing the status as "0 process and 0 service Restarting.." under running services list in Settings.

Can anyone help me how to achieve that having some reference of sample project.

In BackgroundService.cs

[Service]
public class BackgroundService : Service
{
    const int SERVICE_RUNNING_NOTIFICATION_ID = 123;
    const string NOTIFICATION_CHANNEL_ID = "com.company.app.channel";
    public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
    {
        Log.Debug("service", "Service Started");
        // Check if device is running Android 8.0 or higher and call StartForeground() if so
        if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
        {
            var notification = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
                               .SetContentTitle(Resources.GetString(Resource.String.app_name))
                               .SetContentText(Resources.GetString(Resource.String.notification_text))
                               .SetSmallIcon(Resource.Drawable.notification_icon_background)
                               .SetOngoing(true)
                               .Build();

            var notificationManager =
                GetSystemService(NotificationService) as NotificationManager;

            var chan = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "On-going Notification", NotificationImportance.Min);

            notificationManager.CreateNotificationChannel(chan);

            StartForeground(SERVICE_RUNNING_NOTIFICATION_ID, notification);
        }
        return StartCommandResult.NotSticky;

    }

    public override IBinder OnBind(Intent intent)
    {
        return null;
    }

    public override void OnTaskRemoved(Intent rootIntent)
    {
        Intent restartServiceIntent = new Intent(this, this.Class);
        restartServiceIntent.SetPackage(this.PackageName);
        Log.Debug("service", "Service Restarted");

        PendingIntent restartServicePendingIntent = PendingIntent.GetService(this, 1, restartServiceIntent, PendingIntentFlags.OneShot);
        AlarmManager alarmService = (AlarmManager)this.GetSystemService(Context.AlarmService);
        alarmService.Set(
            AlarmType.ElapsedRealtime,
           SystemClock.ElapsedRealtime() + 1000,
            restartServicePendingIntent);
        base.OnTaskRemoved(rootIntent);
    }

}

Updtaed MainActivity.cs

public class MainActivity : AppCompatActivity
{
    String alarm = Android.Content.Context.AlarmService;
    const string NOTIFICATION_CHANNEL_ID = "com.companyname.ServiceSample3";
    protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);
        SetContentView(Resource.Layout.abc_activity_chooser_view);

        Android.Support.V7.Widget.Toolbar toolbar = FindViewById<Android.Support.V7.Widget.Toolbar>(Resource.Id.toolbar);
        SetSupportActionBar(toolbar);

        //var alarmIntent = new Intent(this, typeof(AlarmReceiver));
        //alarmIntent.PutExtra("title", "Hello");
        //alarmIntent.PutExtra("message", "World!");

        Intent intent = new Intent(NOTIFICATION_CHANNEL_ID);
        intent.SetClass(this, typeof(AlarmReceiver));

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

        var alarmManager = GetSystemService(AlarmService).JavaCast<AlarmManager>();
        alarmManager.SetRepeating(AlarmType.ElapsedRealtime, DateTime.Now.Millisecond, 5 * 100, pending);


    }
}

Thanks in advance.

shweta
  • 77
  • 6

1 Answers1

2

Please refer the below sample.You can use alarm manager for restarting the service.

Please follow the steps.

Step 1 : Create BroadcastReceiver

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;

namespace AlarmManagerApp
{
    [BroadcastReceiver(Enabled = true)]
    [IntentFilter(new[] { Android.Content.Intent.ActionBootCompleted })]
    class AlarmReceiver : BroadcastReceiver
    {
        Context context;
        public override void OnReceive(Context context, Intent intent)
        {
            this.context = context;
            Toast.MakeText(context,"Recieved",ToastLength.Long).Show();
            Intent background = new Intent(context, typeof(BackgroundService));
            context.StartService(background);

        }
    }
}

Step 2: Add AlarmManager in the MainActivity where you want to call the service

namespace AlarmManagerApp
{
    [Activity(Label = "@string/app_name", Theme = "@style/AppTheme.NoActionBar", MainLauncher = true)]
    public class MainActivity : AppCompatActivity
    {
        String alarm = Context.AlarmService;
        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);
            SetContentView(Resource.Layout.activity_main);

            Android.Support.V7.Widget.Toolbar toolbar = FindViewById<Android.Support.V7.Widget.Toolbar>(Resource.Id.toolbar);
            SetSupportActionBar(toolbar);

            var alarmIntent = new Intent(this, typeof(AlarmReceiver));
            alarmIntent.PutExtra("title", "Hello");
            alarmIntent.PutExtra("message", "World!");

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

            var alarmManager = GetSystemService(AlarmService).JavaCast<AlarmManager>();
            alarmManager.SetRepeating(AlarmType.ElapsedRealtime,DateTime.Now.Millisecond,  5 * 100, pending);


          }
   }

Step 3: Add you Service

namespace AlarmManagerApp
{
    [Service]
    public class BackgroundService : Service
    {
        public override void OnCreate()
        {
            base.OnCreate();

        }

        public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
        {
            Log.Debug("service","Service Started");
            //init the handler in oncreate
            System.Timers.Timer Timer1 = new System.Timers.Timer();
            Timer1.Start();
            Timer1.Interval = 3000;
            int a = 0;
            Timer1.Enabled = true;
            //Timer1.Elapsed += OnTimedEvent;
            Timer1.Elapsed += (object sender, System.Timers.ElapsedEventArgs e) =>
            {
                Timer1.Stop();
                Timer1.Start();
                a++;
               //Delete time since it will no longer be used.
                Timer1.Dispose();
            };
            Timer1.Start();

            return StartCommandResult.Sticky;
        }

        public override IBinder OnBind(Intent intent)
        {
            return null;
        }

        public override void OnTaskRemoved(Intent rootIntent)
        {
            Intent restartServiceIntent = new Intent(this, this.Class);
            restartServiceIntent.SetPackage(this.PackageName);
            Log.Debug("service", "Service Restarted");

            PendingIntent restartServicePendingIntent = PendingIntent.GetService(this, 1, restartServiceIntent, PendingIntentFlags.OneShot);
            AlarmManager alarmService = (AlarmManager)this.GetSystemService(Context.AlarmService);

            alarmService.SetRepeating(AlarmType.RtcWakeup, SystemClock.CurrentThreadTimeMillis(), 30 * 1000, restartServicePendingIntent);
            NotificationManager notificationManager =
                (NotificationManager)GetSystemService(NotificationService);

            Notification.Builder builder = new Notification.Builder(this);
            Intent notificationIntent = new Intent(this, typeof(MainActivity));
            PendingIntent contentIntent = PendingIntent.GetActivity(this, 0, notificationIntent, 0);

            //set
            builder.SetContentIntent(contentIntent);
            builder.SetSmallIcon(Resource.Mipmap.ic_launcher);
            builder.SetContentText("Contents");
            builder.SetContentTitle("title");
            builder.SetAutoCancel(true);
            builder.SetDefaults(NotificationDefaults.All);


            notificationManager.Notify(1, builder.Build());

            base.OnTaskRemoved(rootIntent);
        }
    }
}

This works also if app is closed and device restarted.

ramya br
  • 225
  • 2
  • 17
  • StartService(new Intent(this, typeof(BackgroundService))); I have to call this inside OnCreate Method??? – shweta Mar 19 '19 at 09:37
  • If you want to start the service in onCreate you can call that – ramya br Mar 19 '19 at 09:39
  • @shweta for notification also I have updated the code – ramya br Mar 19 '19 at 09:50
  • My service is running.But when i m clearing the cache of my mobile ,service is not running. – shweta Mar 19 '19 at 09:58
  • Above code is not working on Adndroid version 8.1.Can u please once look at it. I changed the StartService to StartForegroundService in OnRecieve Method(Restarter class) but then also it's not working. – shweta Mar 20 '19 at 12:54
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/190381/discussion-between-ramya-br-and-shweta). – ramya br Mar 20 '19 at 17:14
  • Can you go through once, what changes required to make the service run in background having android version 8.1 – shweta Mar 21 '19 at 05:00