Storing events to a database while app is running in background - android

I want my app to store events(fired by an SDK) to a database (using realm) even if the app is in background. My concept was to use a Service that makes some SDK initialization and listening on the events. By starting this Service within the onCreate() method of my custom Application class I wanted to assure that the Service is kept alive while the app is in background so that I don't miss any event to be stored into the database.
But now since Android 8 background services are no more allowed. But I don't want to use a Foreground Service because I would need to display a notification. And I don't want the user to know that events are stored in a database in background. I think that information is to technical for normal users.
I realized the problem when Application.onCreate() wanted to start the service but an exception was thrown:
Caused by: java.lang.IllegalStateException: Not allowed to start
service Intent {
cmp=my.package.name.debug/my.package.name.service.MyService }: app is
in background uid UidRecord{94b2e4a u0a204 SVC idle
change:idle|uncached procs:1 seq(0,0,0)}
Remarkably the exception is thrown if I kill the task of my app. So Application.onCreate() is called if I kill the app.
Finally I am not sure if a Service is the right thing to use for my use case.
I have two questions:
What kind of component to use if I want to store events in a database also if my app is in background?
Why does killing the app trigger Application's onCreate()?

You can use workmanager for your particular case.
It can fulfill all your requirements and it has guaranteed execution even if app is in background or device gets rebooted.
Check this (link to example code for WorkManager) out for more info on WorkManager Api.

I found an answer related to my 2nd question:
I start my Service using Service.START_STICKY. If the app is killed, the service is killed too. A sticky Service recreates itself if it is killed. And because the Application class starts the Service in my case, the Application is recreated, too. But still the app is in background and then I run into Application's onCreate() and the App crashes because Oreo doesn't allow any Service to be started while the app is in background.
Edit:
Answer to my first question: After reading more in Android's official documentation I come to the following conclusion: It really seems that a foreground service is the wrong choice here because the user does not need to know about events stored to the DB. A JobScheduler (or the newer Workmanager) is more for one-time or periodic jobs. So a mixed started/bound service seems to be the right choice here.

Related

Android 12 - Foreground service launch restrictions

I'm developing an SDK that needs to startForeground service from the background. Because it uses background location and Bluetooth-related works. If the application is killed, the monitoring is performing in the background. That's why I'm using the foreground service. There is a condition that starts the foreground service from the background.
Currently, my SDK using Service to handle this job. But Android 12 on-words it doesn't support to start service from the background.
I'm trying to start the service from the background the below exception throws.
ForegroundServiceStartNotAllowedException: Service.startForeground() not allowed due to mAllowStartForeground false
How can I use WorkManager to fix this issue, all my handling is done by the Service class and how can I pass the Service object to Worker class and start this job inside the Worker class.
Actually, my project is based on beacon technology.
and the beacon signals are used to show different recommendations to the user.
In my current implementation, if the application is killed by the user,
and also accepts the foreground service, the SDK will be run in the background.
and detect the beacon and provide appropriate actions.
My implementation is that, if the application initializes my SDK with the foreground service "OFF"
Then sometime later, when the application is in the background and trying to start the foreground service from the background this exception throws.
The foreground service-related decisions are held by the server-side API. I'm periodically checking whether the server-side value is changed or not, and if the value is changed the changed action is reflected in the SDK.
There is no one in the world that can give you an answer. The idea of all these restrictions is that we as developers need to optimize our applications. So if this is not possible for you it means most likely that you need to optimize the way you do your work. For this to happen you need to provide more info of what exactly events you are receiving, what is exactly your use case, etc.
https://developer.android.com/about/versions/12/foreground-services#cases-fgs-background-starts-allowed
As you can see there is info about exceptions for:
Your app receives a Bluetooth broadcast that requires the BLUETOOTH_CONNECT or BLUETOOTH_SCAN permissions.
But there is nothing in your question saying that your use case might relate to this.
Also, I don't understand how the app might be killed, but you keep working in the background.
Also if you want to constantly do something - why there is an event when you are in the background. Just when the user opens the app - start the service and keep it going.
You can also just "hack" it and ask the user to remove you from battery optimization.
https://developer.android.com/training/monitoring-device-state/doze-standby#support_for_other_use_cases
Earlier we were using Service to run background tasks. But, due to Android 12 - Foreground service launch restrictions, we will not be able to invoke Service for performing background tasks for Android 12+.
So from now on, from targetSdk 31, Service can be invoked only when the application is in the foreground. When the application is closed or when the application went to the background, invoking Service using startForegroundService will cause ForegroundServiceStartNotAllowedException.
So to perform background tasks, we need to use Worker instead of Service. Please refer to this answer to get an idea of how it is implemented. Hope it helps. Also, refer to the below links to get a high-level overview of what changes needs to be done.
Android 12 Behavior Changes
Work Requests
According to the official docs, if your app does one of the following, it should be able to start an FGS:
Your app receives a Bluetooth broadcast that requires the BLUETOOTH_CONNECT or BLUETOOTH_SCAN permissions.
or
Your app receives an event that's related to geofencing or activity recognition transition.
Those two seem like pretty good candidates for your use-case, at least how I understood it.

What exactly does change for my app in the background when it uses a service?

According to the Android developer website https://developer.android.com/guide/components/fundamentals.html
A service is a general-purpose entry point for keeping an app running in the background for all kinds of reasons.
And on several occasions, i read that a service is (also) used as a means to tell the system that the app requires doing some work in the background.
What is the difference in my Application object creating a sticky service and starting it and it creating a POJO that does the same work?
When the app enters the background (home button) how does the existence of the service change how the system treats my app? Will the service (which runs on the main thread) cause the system to schedule my main thread higher or not reduce it a priority while in the background ? Will it do so if there is no service but a POJO doing some work?
Neither will receive any notification of my app entering the background or coming back to front, neither will be connected to any activity (but could provide functionality for activities to connect to them).
So how exactly does the use of a service change how the system treats my app when it is in the background?
Somewhere it was mentioned that if there is a service running the app will be restarted should it be killed for any reason, however, the service will be killed along with its process (we are talking about a service running in the same process as the rest of the app) but this does not have anything to do with "running in the background" as the android guide mentions.
In addition, the Application object could bind to a service, holding it like a POJO. What would be the difference here, regarding how the system treats my app in the background?

Create a Long Running service

I need to create a service that runs alongside the android app,irrespective of which screen of the app the user is on.
The app is a chat application so when the device is offline the service should queue up all the messages that are being sent offline and when the device is connected it should sync all messages.
I have written code for the job scheduler to sync data automatically when the device is online but while the app is active i would like to handle this manually.
Creating a Long Running service.
Operating system still can terminate the service in low memory and possibly other situations. There are 2 ways to overcome this:
If you are implementing the service, override onStartCommand() and return START_STICKY as the result. It will tell the system that even if it will want to kill your service due to low memory, it should re-create it as soon as memory will be back to normal.
AlarmManager .A system service, which will execute actions periodically. That will ensure that if your service will be terminated, or even the whole process will die(for example with force close) - it will be 100% restarted by AlarmManager.
Thank you.
You can do this by simple following steps:
Create Simple Service and after first launch of app just start at splash screen.
In Service after getting one data you can call another request.
After that you can create one broadcast action globally which will always call every network changed.
At background you can sync again data and saved it to shared preferences or as per your your requirement.
For interval you can also using AlarManager.
A part from this you can simply create Service using JobSheduler in this you can assign job and time as well.
Refer link :
https://developer.android.com/reference/android/app/job/JobScheduler.html
Hopefully this logic will helps you.
You have to use a intent service with sticky instead of service for this which will be executed in a queue and do your work. And since it is a intent service it will be started automatically after sometime, when system kills the service process.

Android service that doesn't close with application

I have been searching the net for hours. I am trying to make an application that has a UI interface and a service running in the background for SIP phone communication, kind of like Skype.
The UI starts and stops the service based on UI events, and the service stays logged in with a internet server in the background. I have found many articles talking about running the service on a separate thread(done), using startService as opposed to binding the service(done) but whenever I use the task manager to kill the application as a user might, I get an error popup saying my application has crashed and the service no longer runs.
How do programs like Skype, Facebook, or email clients do this?
Do I have to run these as separate applications using implicit intents?
Is there some settings I have to set in the manifest file other than declaring the service and it's name?
Better yet, is there a link to some page or source example using this kind of service?
EDIT: Sorry, I guess I wasn't clear. The service is stopping, and I don't want it to. I am trying to keep the service running in the background even after a user kills the application with the application manager.
One of the more confusing things with Service is that it is not run in a separate thread by default. Calling startService() as opposed to bindService() makes no difference in this regard. However, the binder mechanism will cause the Service exposed methods to be called in arbitrary thread context. In both cases, your Service is part of your application's process. If you kill it via the task manager or it crashes then the Service dies as well.
When you kill the app via the task manager and it pops up the message about the app dying, you have something misbehaving. Check logcat and it will point you at exactly where the crash happened.
If you need to have your Service running regardless of the UI, then don't stop the Service when your UI exits. You will still call startService() when your UI starts to re-connect (and possibly re-start it), but don't stop it unless you really want it stopped. Starts do not "stack". If something calls start 5x it doesn't take 5 stops to terminate the Service, only 1.

Android: Creating a service that survives the application that started it

I'm developing an Android application that consists of:
a lightweight background service that logs events to a DB
a heavier GUI application that summarizes these events and displays graphs.
I'm having trouble creating the service part, though. The graphic application can use quite some RAM, and when it goes to the background, the OS closes it after some time of not being used.
The problem is, when the application gets shut down, so does the service. This is bad because this keeps me from recording further events. I don't care if the application gets terminated, but the service needs to keep on running.
I have tried numerous ways to keep the service alive, like having it use threads or a differently named process than the main app. Nothing has worked, and I have found no help on any of the android developer pages or forums.
Thank you for your advice!
Try to return START_STICKY in your service's onStartCommand(). Also how do you start your service? If you use bindService() with BIND_AUTO_CREATE flag it will be stopped automatically on unbindService(). You should explicitly start it with startService() and stop calling stopSelf(). Than OS keep your process running on the background after activity will be closed. Note: the activity and the service run in one process and it's imposible: "application gets terminated, but the service needs to keep on running". But it is possible to keep the process running without activities, with service running on the background.
Read the detailed info http://developer.android.com/reference/android/app/Service.html.
good luck!
You should use the AlarmManager to respawn your service. You just can't keep your service alive eternally.
Check about the lifecycle : http://developer.android.com/guide/topics/fundamentals.html

Categories

Resources