Android Question Really confused about OnBoot Receiver

FrostCodes

Active Member
Licensed User
Hello everyone, my app has a service that is started at boot before without receivers and this was fine till the new requirements. I read this post and I can see I can still run my code at boot but the issue I have is I think its better to run my code from a service so at first, I was thinking better I create a receiver for the OnBoot and then call my service but then I read I can't do this as the app is in the background and then I thought maybe I should move my whole code to the receiver.

The problem now is that my code runs at certain times of the day and downloads a new update of some databases with or without the user opening the app as it's essential the user access the latest database data automatically. The update can take from 1 to 15 mins or even more depending on the user's internet connection speed which means before this was fine as I show a notification to keep the update running in a service till it's done.

In receivers, I can see that android expects what you do to be short and it kills the receiver so I am really confused about how to solve my issue.
Please any advice?
 

Computersmith64

Well-Known Member
Licensed User
Longtime User
[...] I was thinking better I create a receiver for the OnBoot and then call my service but then I read I can't do this as the app is in the background and then I thought maybe I should move my whole code to the receiver. [...]
That's exactly what I do in one of my apps. For devices running Android 8.0+ you have to start it as a foreground service.

- Colin.
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
Thank @Erel the update is a sqlite file with various data. The whole idea is everything is automatic and always up to date.
Why does it take 15 minutes?

If I start the service when the user is using the app only, can I still reschedule it or the rescheduling part is not possible with StartServieAt() or so.
No. There isn't a single case where StartServiceAt can be used.
 
Upvote 0

FrostCodes

Active Member
Licensed User
Why does it take 15 minutes?
The update sometimes can be a major one that is large (usually 1mb to 30 mb) but the main bottleneck is internet speed, those using the app are not where there is always high speed internet. Sometimes the internet can be as low as 1mbps.

The whole goal of the auto update feature was while they are on the road or anywhere, all devices gets the latest data without them having to do anything or remember to click some button to sync the data and when they need the app they simply open it and confirm the last update time and can start using the app data offline.
 
Upvote 0

Computersmith64

Well-Known Member
Licensed User
Longtime User
The update sometimes can be a major one that is large (usually 1mb to 30 mb) but the main bottleneck is internet speed, those using the app are not where there is always high speed internet. Sometimes the internet can be as low as 1mbps.

The whole goal of the auto update feature was while they are on the road or anywhere, all devices gets the latest data without them having to do anything or remember to click some button to sync the data and when they need the app they simply open it and confirm the last update time and can start using the app data offline.
You CAN start a foreground service that will continue to run indefinitely, although the use-case you describe isn't ideally suited for that. The other option is to use WorkManager, which seems to be more suited to what you're doing - however I'm not sure if it's implemented in B4X.
 
Upvote 0

FrostCodes

Active Member
Licensed User
You CAN start a foreground service that will continue to run indefinitely, although the use-case you describe isn't ideally suited for that. The other option is to use WorkManager, which seems to be more suited to what you're doing - however I'm not sure if it's implemented in B4X.
Thanks, I would look into it and try also if it's implemented.
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
You CAN start a foreground service that will continue to run indefinitely
This is also not true.
You can only start a foreground service while your app is in the foreground (visible).

WorkManager will behave similarly to StartReceiverAt. You will need to split the long task.
 
Upvote 0

Computersmith64

Well-Known Member
Licensed User
Longtime User
This is also not true.
You can only start a foreground service while your app is in the foreground (visible).
Well I don't know if that's true either Erel. I have an app that starts a foreground service from a BOOT_COMPLETED receiver. To do this I use context.startForegroundService(intent) & according to the Android Developer documentation:
Unlike the ordinary startService(android.content.Intent) , this method can be used at any time, regardless of whether the app hosting the service is in a foreground state.
Here's the Logcat from a reboot of a device running the app (note the 2 bold references to the foreground service being started from the background):
20:26:24.570 11203-11203 RECEIVED BROADCAST com.airlinemates.callsense D Intent { act=android.intent.action.BOOT_COMPLETED flg=0x89000010 cmp=com.airlinemates.callsense/.IncomingCallReceiver (has extras) }
2023-03-05 20:26:24.575 11203-11203 BOOT(Receiver) com.airlinemates.callsense D true
2023-03-05 20:26:24.582 1914-4037 ActivityManager system_server I Background started FGS: Allowed [callingPackage: com.airlinemates.callsense; callingUid: 10276; uidState: RCVR; intent: Intent { cmp=com.airlinemates.callsense/.PocketService }; code:SYSTEM_ALERT_WINDOW_PERMISSION; tempAllowListReason:<broadcast:1000:android.intent.action.BOOT_COMPLETED,reason:,reasonCode:BOOT_COMPLETED,duration:20000,callingUid:1000>; targetSdkVersion:33; callerTargetSdkVersion:33; startForegroundCount:0; bindFromPackage:null]
2023-03-05 20:26:24.611 11203-11203 POCKETSERVICE com.airlinemates.callsense I Service onStartCommand 1
2023-03-05 20:26:24.612 11203-11203 Compatibil...geReporter com.airlinemates.callsense D Compat change id reported: 160794467; UID 10276; state: ENABLED
2023-03-05 20:26:24.625 1914-4690 ActivityManager system_server W Foreground service started from background can not have location/camera/microphone access: service com.airlinemates.callsense/.PocketService


- Colin.
 
Upvote 0

FrostCodes

Active Member
Licensed User
Well I don't know if that's true either Erel. I have an app that starts a foreground service from a BOOT_COMPLETED receiver. To do this I use context.startForegroundService(intent) & according to the Android Developer documentation:

Here's the Logcat from a reboot of a device running the app (note the 2 bold references to the foreground service being started from the background):



- Colin.
Hi would be nice if you could upload a code sample
 
Upvote 0

Computersmith64

Well-Known Member
Licensed User
Longtime User
Hi would be nice if you could upload a code sample
I can, but it might not be much good to you as it's written in Kotlin (although in theory I guess you should be able to make it work in B4X using javaobject) although B4A has the same functionality implemented so you should be able to use that (Service.StartForeground). My point is that it seems Android does provide a way to start a foreground service from the background.

Java:
override fun onReceive(context: Context?, intent: Intent?) {
    Log.d("RECEIVED BROADCAST", intent.toString())
    if (Intent.ACTION_BOOT_COMPLETED == intent?.action || Intent.ACTION_MY_PACKAGE_REPLACED == intent?.action) {
        val doBoot = context?.getSharedPreferences("CallSensePrefs", Context.MODE_PRIVATE)?.getBoolean("boot", false)
        Log.d("BOOT(Receiver)", doBoot.toString())
        if (doBoot!!) {
            val i = Intent(context, PocketService::class.java)
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                context.startForegroundService(i)
            } else {
                context.startService(i)
            }
        }
    }
    [snip]
}

- Colin.
 
Last edited:
Upvote 0

Computersmith64

Well-Known Member
Licensed User
Longtime User
For some additional clarity on this, according to the Android Developer documentation there are some exemptions from the background start restrictions. In the case of my app, it's:
which is the use-case mentioned in the OP. The OP stated:
I was thinking better I create a receiver for the OnBoot and then call my service
& my first reply was that this is exactly what I do in one of my apps. According to the Android Developer documentation this is a use-case that is exempt from the background start restriction, so I would say go ahead & write your receiver & then when you receive a BOOT_COMPLETED action, start your foreground service.

- Colin.
 
Last edited:
Upvote 0

Computersmith64

Well-Known Member
Licensed User
Longtime User
Thanks, it's good it works for your app but since I have no idea how this part of android really functions, I guess it's a dead end for now. Hopefully, someone might have some solution using b4x.
It's pretty straightforward. Write your broadcast receiver to receive BOOT_COMPLETED (& whatever other startup actions you want) broadcasts & then when you receive a broadcast start your service by calling Service.StartForeground.

The Receivers & Services in 2023+ tutorial gives you an example that's pretty much exactly what you need for your use-case & then all you need to do is start your service from the Receiver_Receive sub.

- Colin.
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
You are correct @Computersmith64. I forgot that the on boot intent is in the exemptions list.
This means that the regular #StartAtBoot: True in a service will work.

I can say that from my experience there are many devices that do not honor this list. There are several discussions in the forum where users got the ForegroundServiceStartNotAllowedException although they were sending high priority messages which is an allowed use case. These reports were one of the main reasons that I've added receivers as a separate component.
 
Upvote 0
Top