Access to rest api functions from PCL inside Android project

mjdevelopermjdeveloper Member ✭✭✭

Hi guys.
I have a xamarin.forms application that it works with Restful API that implemented inside PCL.
I couldn't access to Firebase service or other PushNots services. Because of that, I developed my own messaging system.
Now I want to have the notification on Android and iOS projects (local notification Maybe). The background service must check every 30 seconds with call a Rest API function From PCL. when the user has a new message I must show a notification. (Even the app had closed)
Please help with background service and access to PCL classes inside the service and local notification (sorry it's a very big question).

thanks in advance.
(sorry for poor English)

Best Answer

  • mjdevelopermjdeveloper ✭✭✭
    edited October 13 Accepted Answer

    @LeonLu said:
    I am still recommand you to use Forground service to achieve that when you app is running state like my first reply.

    Hi
    Thanks for your help. Finally, I got it (I think). I used FirebaseJobDispatcher.
    This is my code:
    service:

    [Service(Name = "com.mysite.MessagingJob")]
        [IntentFilter(new[] { FirebaseJobServiceIntent.Action })]
        public class MessagingJob : Firebase.JobDispatcher.JobService
        {
            const string tag = "my_job_tag";
            public override bool OnStartJob(IJobParameters jobParameters)
            {
                Task.Run(() =>
                {
                    LocalNotificationsImplementation.NotificationIconId = Resource.Drawable.Icon;
                    CrossLocalNotifications.Current.Show("notify", "You have a message!" + (new Random()).Next().ToString());
                });
                JobFinished(jobParameters, false);
                return true;
            }
            public override bool OnStopJob(IJobParameters jobParameters)
            {
                return true;
            }
        }
    

    MainActivity.cs ---> startJob()

    private void startJob()
     {
                FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(new GooglePlayDriver(this));
                Job myJob = dispatcher.NewJobBuilder()
                      .SetService<MessagingJob>("my_job_tag")
                      .SetLifetime(Lifetime.Forever)
                      .SetRecurring(true)
                      .SetTrigger(Firebase.JobDispatcher.Trigger.ExecutionWindow(10, 60))
                      .SetRetryStrategy(RetryStrategy.DefaultExponential)
                      .SetReplaceCurrent(true)
                      .Build();
                dispatcher.MustSchedule(myJob);
    }
    

    this code runs every 1 minute. even the app is closed. (tested on Android 8.1)
    The JobScheduler is available on API 21 and higher.

Answers

  • AlessandroCaliaroAlessandroCaliaro ITMember ✭✭✭✭✭

    I think you can reach classes in PCL from Platform specific project

  • mjdevelopermjdeveloper Member ✭✭✭

    Thank Alessandro for your quick response.
    oh yes, I didn't test it!
    I can access to PCL. could I call PCL methods inside the service?
    or
    If I use MessagingCenter does the service work when the app closed?

  • mjdevelopermjdeveloper Member ✭✭✭

    what's your suggestion for this scenario?

  • AlessandroCaliaroAlessandroCaliaro ITMember ✭✭✭✭✭

    you could try to call PCL methods inside services… I have never tested it

  • NMackayNMackay GBInsider, University mod

    certainly you can grab a service implementation from an IoC container in your platform specific projects and call the Restful call in the shared code, used that approach before and it works for all platform specific projects. I didn't call the implementation directly so couldn't comment if that works but the DI approach works.

  • LeonLuLeonLu Member, Xamarin Team Xamurai

    local notification Maybe,the background service must check every 30 seconds with call a Rest API function From PCL. when the user has a new message I must show a notification. (Even the app had closed)

    First of all, If you want to your service to check the every 30 seconds with call a Rest API function From PCL, due to the background execution limits In Oreo or after Oreo, we cannot make the background service awayls running, but we can use forground service to achieve that, and user cannot close this application – a foreground service is useful for when the app must perform some task in the background and the user may need to periodically interact with that task. If you want to know more details or achievement of code, you can refer to my reply in the SO

    https://stackoverflow.com/questions/55752147/how-to-create-service-doing-work-at-period-time-in-xamarin-forms/55757316#55757316

    If you app closed, your service(no matter of the background serivce or the forground service) will be killed by android OS.
    Here are several situations,even though an app is in the background, Android will wake up the app and relax these restrictions for a few minute
    https://docs.microsoft.com/en-us/xamarin/android/app-fundamentals/services/#background-execution-limits-in-android-80

  • mjdevelopermjdeveloper Member ✭✭✭

    I wrote a background service in Android studio with Java. it's always running (if the app had closed) and checks the user 's portal for a new message and shows a notification.
    I want to develop this solution in xamarin.forms.
    If I would have AlarmManager, does the background service fire periodically?

  • mjdevelopermjdeveloper Member ✭✭✭

    I'm in Iran and the US sanctions don't allow me to use Firebase and some same services to have notifications.
    Please help me to improve my app with some of your solutions.
    For the messaging system, the app must have a notification service.

  • LeonLuLeonLu Member, Xamarin Team Xamurai

    @mjdeveloper said:
    I wrote a background service in Android studio with Java. it's always running (if the app had closed) and checks the user 's portal for a new message and shows a notification.
    I want to develop this solution in xamarin.forms.
    If I would have AlarmManager, does the background service fire periodically?

    What is your android version? App closed not set the app to background.

    I did not use AlarmManager, you can make a test, here is a simple code.
    https://coderwall.com/p/qfoxfg/schedule-a-service-using-alarmmanager

  • mjdevelopermjdeveloper Member ✭✭✭

    Hi, guys again.
    this is my simple code for service and AlarmManager but when the app closed, AlarmManager and service do not fire.

        [Service(Label = "NotificationIntentService")]
            public class NotificationIntentService : IntentService
            {
                protected override void OnHandleIntent(Intent intent)
                {
                    LocalNotificationsImplementation.NotificationIconId = Resource.Drawable.Icon;
                    CrossLocalNotifications.Current.Show("my title", "You have new message!" + (new Random()).Next().ToString());
                    }
            }
    

    and MainActivity:

    int interval = 10 * 1000;
                var alarmTime = Calendar.Instance; // Alarm Start Time
                //alarmTime.Add(CalendarField.Second, 10);
                StartService(new Android.Content.Intent(this, typeof(NotificationIntentService)));
                using (var manager = (Android.App.AlarmManager)GetSystemService(AlarmService))
                {
                    var alarmIntent = new Intent(this, typeof(NotificationIntentService));
                    var pendingIntent = PendingIntent.GetService(this, 0, alarmIntent, PendingIntentFlags.CancelCurrent);
                    //manager.SetInexactRepeating(AlarmType.RtcWakeup, alarmTime.TimeInMillis, interval, pendingIntent);
                    manager.SetRepeating(AlarmType.RtcWakeup, alarmTime.TimeInMillis, interval, pendingIntent);
                }
    

    The second problem is that when the app is running service fires periodically but very erratically.
    Some times it fires after 10 seconds sometimes fires after 1 minute, sometimes after about 2 minutes and so on.
    The big problem is that when the app was closed, the service or AlarmManager doesn't work.

  • LeonLuLeonLu Member, Xamarin Team Xamurai

    The big problem is that when the app was closed, the service or AlarmManager doesn't work.

    I have told you, If your app was closed, your background sevice will be killed.

  • mjdevelopermjdeveloper Member ✭✭✭
    edited October 9

    oh boy, I'm tired. I think that I must use BroadcastReciever also.I'm still trying to do it.

    while a manifest-registered receiver can respond to broadcasts even though the app may not be running.

    https://docs.microsoft.com/en-us/xamarin/android/app-fundamentals/broadcast-receivers

  • LeonLuLeonLu Member, Xamarin Team Xamurai

    I am still recommand you to use Forground service to achieve that when you app is running state like my first reply.

  • mjdevelopermjdeveloper Member ✭✭✭
    edited October 12

    Hi guys.
    I decided to use the JobScheduler. I'll put the code here if everything was ok.

  • mjdevelopermjdeveloper Member ✭✭✭
    edited October 13 Accepted Answer

    @LeonLu said:
    I am still recommand you to use Forground service to achieve that when you app is running state like my first reply.

    Hi
    Thanks for your help. Finally, I got it (I think). I used FirebaseJobDispatcher.
    This is my code:
    service:

    [Service(Name = "com.mysite.MessagingJob")]
        [IntentFilter(new[] { FirebaseJobServiceIntent.Action })]
        public class MessagingJob : Firebase.JobDispatcher.JobService
        {
            const string tag = "my_job_tag";
            public override bool OnStartJob(IJobParameters jobParameters)
            {
                Task.Run(() =>
                {
                    LocalNotificationsImplementation.NotificationIconId = Resource.Drawable.Icon;
                    CrossLocalNotifications.Current.Show("notify", "You have a message!" + (new Random()).Next().ToString());
                });
                JobFinished(jobParameters, false);
                return true;
            }
            public override bool OnStopJob(IJobParameters jobParameters)
            {
                return true;
            }
        }
    

    MainActivity.cs ---> startJob()

    private void startJob()
     {
                FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(new GooglePlayDriver(this));
                Job myJob = dispatcher.NewJobBuilder()
                      .SetService<MessagingJob>("my_job_tag")
                      .SetLifetime(Lifetime.Forever)
                      .SetRecurring(true)
                      .SetTrigger(Firebase.JobDispatcher.Trigger.ExecutionWindow(10, 60))
                      .SetRetryStrategy(RetryStrategy.DefaultExponential)
                      .SetReplaceCurrent(true)
                      .Build();
                dispatcher.MustSchedule(myJob);
    }
    

    this code runs every 1 minute. even the app is closed. (tested on Android 8.1)
    The JobScheduler is available on API 21 and higher.

Sign In or Register to comment.