Android Question B4XPages & Scheduled service

luke2012

Well-Known Member
Licensed User
Longtime User
Hi all,
It's the first time that I'm facing a B4XPages (https://www.b4x.com/android/forum/t...k-for-managing-multiple-pages.118901/#content) mobile app development.

Within this app my target is to implement a service that notify the user when a specific condition is true (check implemented within the service).

Note: For notifications (within the service) I'm using "NB6 notifications builder class (2018)" from @Erel
B4X:
Sub Simple_Notification
   Dim n As NB6
   n.Initialize("default", Application.LabelName, "DEFAULT").AutoCancel(True).SmallIcon(smiley)
   n.Build("Title", "Content", "tag1", Me).Notify(4) 'It will be Main (or any other activity) instead of Me if called from a service.
End Sub

I recap the prerequisites of the service that I have to develop:

1) It starts at device boot (Android & iOS)
2) It runs (self) sheduled every x hours
3) it runs also when the app isn't started by the user
4) It runs in background (no visible within the foreground)
5) It's able show a system notification (only when a condition is true) for both platform (Android & iOS)

Is there any sample / tutorial to do this for B4A & B4i ?
Thanks in advance for you help :)
Luca.
 

DonManfred

Expert
Licensed User
Longtime User
1) It starts at device boot (Android & iOS)
there is no such feature in iOS
it runs also when the app isn't started by the user
There is no such thing in Android. It is mandatory that the user start the app once so that the app can set up the services used.
 
Last edited:
Upvote 0

luke2012

Well-Known Member
Licensed User
Longtime User
there is no such feature in iOS

There is no such thing in Android. It is mandatory that the user start the app once so that the app can set up the services used.

Thank you for your replies.
About point 3: for example, a reminder app that show notifications to the user, if user don't start the app how it can works ?

I mean, that the target of this service is to notify the user that is some news within the app so the user tap on the notification to open the app.
 
Last edited:
Upvote 0

luke2012

Well-Known Member
Licensed User
Longtime User
I think that you are talking about different things.

You can use StartServiceAt to start a service at a scheduled time.
It is true that the app needs to run once for this to work. You can add #StartAtBoot: true to start the app after boot and reschedule the service.

Thank you @Erel. I implemented it (B4A 10, Android 10)
I'm testing it (within a B4XPages App) and I got this:

1) SERVICE SETTINGS (StartAtBoot with schedule)
B4X:
#Region  Service Attributes
    #StartAtBoot: true
#End Region

Sub Service_Start (StartingIntent As Intent)
    '>>>> TEST ONLY
    Log("SERVICE_START - CheckNews service is started!")
    Private smiley As Bitmap = LoadBitmapResize(File.DirAssets, "smiley.png", 24dip, 24dip, False)
    Private mp As B4XMainPage = B4XPages.MainPage
    mp.Simple_Notification ("APP NEWS", "There are news articles...", "new_art", smiley)
    '>>>> TEST ONLY
 
    'Schedule service
    Private NumOfSeconds As Int = 60  '1 hour = 3600 secs
    StartServiceAt(Me, DateTime.Now + NumOfSeconds * DateTime.TicksPerSecond, True)
End Sub
- EXPECTED RESULT: After device reboot I have to see the "smiley" notification, the log ("SERVICE_START...) and the schedule (service should run every 60 secs)
- RESULT: no "smiley" notification, no log and no schedule (also if #StartAtBoot: true it doesn't start after device boot)
Note: Before reboot the device I run one the app.

2) SERVICE SETTINGS (StartAtBoot, StartService with schedule)
B4X:
Private Sub B4XPage_Created (Root1 As B4XView)
    Root = Root1
    Root.LoadLayout("splash")
    toast.Initialize(Root)

    StartService (srvCheckNews)
End Sub

'<<< SERVICE "srvCheckNews" >>>
#Region  Service Attributes
    #StartAtBoot: true
#End Region
Sub Service_Start (StartingIntent As Intent)
    '>>>> TEST ONLY
    Log("SERVICE_START - CheckNews service is started!")
    Private smiley As Bitmap = LoadBitmapResize(File.DirAssets, "smiley.png", 24dip, 24dip, False)
    Private mp As B4XMainPage = B4XPages.MainPage

    mp.Simple_Notification ("APP NEWS", "There are news articles...", "new_art", smiley)
    '>>>> TEST ONLY
 
    'Schedule service
    Private NumOfSeconds As Int = 60  '1 hour = 3600 secs
    StartServiceAt(Me, DateTime.Now + NumOfSeconds * DateTime.TicksPerSecond, True)
End Sub
'<<< SERVICE "srvCheckNews" >>>
- EXPECTED RESULT: On app run (and after device boot) I have to see the "smiley" notification, the log ("SERVICE_START...) and the schedule (service should run every 60 secs)
- RESULT:
On first app run --> Log OK, Notification OK, Schedule OK
On device boot (after first app run) --> no "smiley" notification, no log and no schedule (also if #StartAtBoot: true it doesn't start after device boot)

AIM OF THE SERVICE
this type of service that I am implementing makes sense if the notification appears when the app is not open and in use by the user because the notification has the purpose of opening the app (by tapping the notification) when there is a new one content (of which the user is not yet aware) for the user.

So far with these settings I can start the service and schedule it but not reach the purpose of making it start scheduled after the device is booted (which is the most important thing)
 
Last edited:
Upvote 0

DonManfred

Expert
Licensed User
Longtime User
'Schedule service Private NumOfSeconds As Int = 60 '1 hour = 3600 secs
Android will not allow you to restart a service every 10 seconds. use at least 1800 seconds (30 Minutes)

Alternatively you can use a foregroundservice

See LocationTracking Example
 
Upvote 0

luke2012

Well-Known Member
Licensed User
Longtime User
Android will not allow you to restart a service every 10 seconds. use at least 1800 seconds (30 Minutes)

Alternatively you can use a foregroundservice

See LocationTracking Example

Hi @DonManfred ,
It is not scheduled every 10 seconds but every 60 seconds (see the code " NumOfSeconds As Int = 60")

So your hypothesis is that the schedule time is too short and Android doesn't start it ?
But if this is true, why the 60" scheduling works fine (see 2° test above) ?

Now I'm testing the 1800 seconds option as you seggested me.
So in this case "#StartAtBoot: true" should work?
 
Last edited:
Upvote 0

luke2012

Well-Known Member
Licensed User
Longtime User
Even 60 Seconds is too fast.

start at boot should work. Note that it can not work with the starter service.

@DonManfred I tested with 1800 seconds (see my post #6 point n.1) but "#StartAtBoot: true" seem that doen't work (no notification and no log, at boot and after 30 mins).

At this point I don't understand why #StartAtBoot doen't work (service isn't the starter service but it is my custom service; see my reply #6 1° point)
I'm wrong or #StartAtBoot doesn't work ?

P.S.
You said: "See LocationTracking Example by @Erel"
I already saw it but I haven't considered it because I don't need the notification to remain permanently visible but only when needed. When the user clicks on it the app should open and the notification should disappear.
 
Upvote 0

luke2012

Well-Known Member
Licensed User
Longtime User
The question is not related to B4XPages and you shouldn't access B4XPages from the service. B4XPages will only be available after the main activity has started.

Make sure to run your app in release mode and make sure to check the logs.

Hi @Erel
first of all, happy Sunday.
Sorry for make this post a little long but this feature is important about the project that I'm developing for my customer.
I tested this service code with Android 7, Android 8, Android 9 and Android 10 (AVD devices):

B4X:
#Region  Service Attributes 
    #StartAtBoot: true
#End Region

Sub Process_Globals

End Sub

Sub Service_Create
    
End Sub

Sub Service_Start (StartingIntent As Intent)
    'Service schedule
    Private NumOfSeconds As Int = 30  '1 hour = 3600 secs
    StartServiceAt(Me, DateTime.Now + NumOfSeconds * DateTime.TicksPerSecond, True)
    Private smiley As Bitmap = LoadBitmapResize(File.DirAssets, "smiley.png", 24dip, 24dip, False)
    Simple_Notification ("BotegApp NEWS", "Ci sono delle novità per te! Scopri quali...", "new_art", smiley)
End Sub

Sub Simple_Notification (aTitle As String, aContent As String, aTag As String, aSmallIcon As Bitmap)
    Dim n As NB6
    n.Initialize("default", Application.LabelName, "HIGH").AutoCancel(True).SmallIcon(aSmallIcon)
    n.Build(aTitle, aContent, aTag, Main).Notify(4) 'It will be Main (or any other activity) instead of Me if called from a service.
End Sub

Sub Service_Destroy

End Sub

I tested it in this way :
Note: all test are done in release mode.
1) I installed the app on all 4 AVD devices and run one
2) I shutted down all the AVD devices
3) I power on al the 4 AVD devices

RESULT
- The service is started at boot on all 4 devices (Android 7, 8, 9 and 10).
- The service is still running scheduled each 30" showing the notification on all Android versions (from 7 to 10).
So this is a success (so in this case I can say: "all work fine on all the tested Android versions), but ... this is true only within virtual devices with "pure" Android (not customized android).

THE PROBLEM
If I install the same app within my real device, a "Xiaomi Redmi Note 8 Pro" (with Android 10) and I did the same test (as above), the service doesn't start.

For me this is a insidious problem because people use real devices (not virtual google devices) and I have to "certify" this feature as "working feature" in front of my customer (the company that commissioned me the app).

So my questions are:
1) How to solve / handle this (I need to tell to my customer on which Android versions is tested and "certify" the app) ?
2) How can I known if only on this (real) Android 10 device the #StartAtBoot doesn't work ?

Thanks in advance for your precious help.
Luca.
 
Upvote 0

luke2012

Well-Known Member
Licensed User
Longtime User
There is no simple solution. Many devices don't allow apps to start in the background.
Push notifications work better.
On some devices there is a setting that allows the user to whitelist your app.

"Push notifications work better." ---> I known. But the notification should appear when a new CMS (Drupal in this case) content is putted within his database: I'm checking it using Drupal API and OKHttpUtils2, so how to implement a push notification in this case?

I understand it. I checked within my "Redmi Note 8 Pro" and Xiaomi installed by default a custom app called "Security" where by default set autostart as "off" for all the new installed apps. So this is the problem with this device.
 
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
I recap the prerequisites of the service that I have to develop:

1) It starts at device boot (Android & iOS)
Reading this thread, I asked myself if B4I had service modules.
I think I found the answer here (with a lot of effort; I thought there were still specific PDFs for each environment 🤔):
https://www.b4x.com/guides/B4XIDE/?page=12
1598245866246.png


So it seems to me that service modules don't exist in B4i-iOS; how did you solve it, Luca?
 
Upvote 0

luke2012

Well-Known Member
Licensed User
Longtime User
Reading this thread, I asked myself if B4I had service modules.
I think I found the answer here (with a lot of effort; I thought there were still specific PDFs for each environment 🤔):
https://www.b4x.com/guides/B4XIDE/?page=12
View attachment 98998

So it seems to me that service modules don't exist in B4i-iOS; how did you solve it, Luca?

Hi @LucaMs
probably in this case the solutions are:

1) This feature is only supported with the Android version of the app :)
2) Implement a push server (but in my case the server is a Drupal and my purpose is to notify the user when a new article is available)
3) Try to understand if there are some option within iOS in order to start a module on device boot that implement the notification.
 
Upvote 0
Top