Run native code as background service

3,896 views
Skip to first unread message

Stephan Menzel

unread,
Aug 6, 2019, 11:49:29 AM8/6/19
to android-ndk
Hello all,

I'm in the process of adapting a multi-component system to android based devices, namely SoC based VR headsets such as the Oculus Quest. I am an Android beginner but very solid with C++ on Linux and Windows. The system is C++ only, has a few dependencies such as boost and is built primarily via CMake.

During the last weeks I have thoroughly investigated into how to cross build it (it already was cross build capable for ARM) and I am now confident that I can create native libraries via NDK.

I also investigated into how to run such code and found that I'd have to bind it via JNI and then wrap it into a NativeActivity in Java. So far so good. Yet my next step is to run this component as a 'background process', like a daemon process, while another more user interface heavy process takes the front seat. This is what I'm struggling with.

The way I understand Activities, they are non-modal. Please correct me if I'm wrong but when one is open the others go to sleep. Looking around I found this: https://stackoverflow.com/questions/21406328/run-native-code-in-background which kind of confirms my fears.

So, my question is: Assuming I can cross build and wrap my native C++ component for Android, how can I have it run as a daemon like background process while another process if facing the user? The processes shall communicate via local TCP socket or (as they do now on Windows) via shared memory if that's an option but its not a must have.

Any hints are appreciated.

Best regards...

Stephan

Radovan Chytracek

unread,
Aug 7, 2019, 4:55:01 AM8/7/19
to andro...@googlegroups.com
Hi,

Shared memory is certainly an option.
Be also ready to use some JNI to talk to Android from C++ to manage the service life-time and system interactions.

Radovan


--
You received this message because you are subscribed to the Google Groups "android-ndk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to android-ndk...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/android-ndk/22d6cebb-38c2-46aa-9ce0-1fd607a9effc%40googlegroups.com.

AppCoder

unread,
Aug 7, 2019, 5:06:08 PM8/7/19
to android-ndk
I'd suggest SWIG for doing the JNI (just because that's what it does and lots of
folks have been using it for years.)


Once you have a class or interface for startReallyCoolVRStuffs, I'd put that
in a service and do the dance to make it a foreground service so Android doesn't
step on it (in app user land that's as close as you can get to a daemon, if you
are making your own firmware the rules are different.)


(I'd resist the temptation to make AndroidStudio generate the Swig code, as
even though there are nice swig plugins for standard gradle, AS has a bunch
of tasks that want to scan all the source files and no easy (that I've found)
hooks run it at the right time and have the swig foo.i file be treated as source
and the generated *.cpp/*.java be treated well for doing IDE things.)

Your other choice is to just have one super-activity and do all your modal stuff
inside that, but that's sort of ugly (but if you are porting some app that has a UI
written in OpenGL or something, you could pull the whole thing over and just
have the android Activity give an area to draw until exit.)

gjs

unread,
Aug 7, 2019, 5:06:08 PM8/7/19
to android-ndk
Hi,

Native code can be run from a background service ok, take a look at this code as an example https://github.com/pranjal23/android-jni-service/tree/master/NatSer/jni

Background services can also be run in seperate processes if necessary, this is specified via the service definition in the Android Manifest.

Regards

Alex Cohn

unread,
Aug 8, 2019, 2:50:52 AM8/8/19
to android-ndk
If you are building a native component for custom Android-based device, it can be a native Linux-style service. You can start it in init.rc, and eve choose to run it as root or system.

If the device is not under your control, you can still create a child native process from an app (see Java ProcessBuilder). Such process will run with the uid of your app, and may get killed by the system if the resources are required to run some other foreground app.

Such process can use sockets or shared memory for IPC, but Android way is to use Binder. Recently, NdkBinder has been added to make it possible to work with Binder from C++.

BR,
Alex

Stephan Menzel

unread,
Aug 8, 2019, 12:49:07 PM8/8/19
to android-ndk
Hello and thanks for your response!


Am Mittwoch, 7. August 2019 23:06:08 UTC+2 schrieb AppCoder:
I'd suggest SWIG for doing the JNI (just because that's what it does and lots of
folks have been using it for years.)


Well, we already got a shared mem interface in place as we are porting this from different platforms, so I'd rather just use and extend this. As long as I can have C++ code run and be able to use shared memory I should be good to go. 


Once you have a class or interface for startReallyCoolVRStuffs, I'd put that
in a service and do the dance to make it a foreground service so Android doesn't
step on it (in app user land that's as close as you can get to a daemon, if you
are making your own firmware the rules are different.)


From this page I understand a foreground service doesn't have as many restrictions as to what it can do compared to a background service. In that regards, our would be service does mostly network IO. It fetches and synchronizes data of all sorts and provides a networking back-end to thr running VR application. While being quite efficient, it does require a bit of CPU and quite a bit of network. So if a background service would imply that I'd have restrictions in that area, it would be ruled out.

Your other choice is to just have one super-activity and do all your modal stuff
inside that, but that's sort of ugly (but if you are porting some app that has a UI
written in OpenGL or something, you could pull the whole thing over and just
have the android Activity give an area to draw until exit.)

Well, the existing application is a Qt desktop app, fully native C++. We currently intend to strip the UI away and put the stuff that does the heavy lifting into this Android service. As it already has a shm interface we aim at having a native Android UI (presumably written in Java or being a game like C++ UI in VR). Either way, this shall only replace the UI and leave as much of the back-end libraries and functionalities intact as possible. 

I'll look into your suggestions, thanks!

Stephan

Stephan Menzel

unread,
Aug 8, 2019, 12:49:07 PM8/8/19
to android-ndk
Hello Alex,

thanks for your response!


Am Donnerstag, 8. August 2019 08:50:52 UTC+2 schrieb Alex Cohn:
If you are building a native component for custom Android-based device, it can be a native Linux-style service. You can start it in init.rc, and eve choose to run it as root or system.

I have seen this while doing my research and this certainly got my hopes up. But, just to clarify, this would mean I'm using Android for my own device, where I control the OS, right? Cause this is not the case. We aim at publically available SoC based VR devices and have no control over it. The user must be able to install our software regularily over the store.

If the device is not under your control, you can still create a child native process from an app (see Java ProcessBuilder). Such process will run with the uid of your app, and may get killed by the system if the resources are required to run some other foreground app.

OK, sadly, this we cannot tolerate. On the contrary. When a VR application gets started it will take considerable attention and resources from the device and my service must be able to run more or less unaffected in order to do its job.

Such process can use sockets or shared memory for IPC, but Android way is to use Binder. Recently, NdkBinder has been added to make it possible to work with Binder from C++.

Oh, I haven't seen this. Certainly looks interesting as well. Does Binder work when the service in question would run independently? Sorry if my questions seem silly and basic but I'm really just beginning to understand the Android ecosystem.

Thanks,
Stephan

AppCoder

unread,
Aug 9, 2019, 3:00:10 PM8/9/19
to android-ndk
Let me take a few steps back and push some architecture
stuff at you.

Apps are forked java processes with hooks to all the OS APIs.
The official support for C++ is an attempt to emulate the hooks
that the java stuff uses (nativeActivity) or JNI linked into the java
process.

While it's tempting to say "oh, it's just a linux and clang, I know
C++, I can make this go", there are all sorts of little traps for
not doing things "the right way".   Among those are:

1) the SE Android set up (that some OEMs tighten down
differently than others, nothing more annoying than having
your developer phone run fine and find that 70% of your
Samsung users are sad because of how Samsung set up
their Knox stuff.)
2) bionic (the libc on android) has various short cuts, and
restrictions compared to what you might be used to (like,
oh we don't fill out that struct, or that's not a supported
syscall)
3) the dynamic linker can get locked down differently in
new releases.
4) the process monitoring code in the OS for apps can
change the rules a few times a year (just look through
the history of API level for various alarm manager
functions.)

In the face of this, playing by the rules for a user app
means more time doing your app, less time figuring
out why this device/update borked your stuff.

In the face of all this, the most conservative/safe C++
interaction as an app is JNI talking to java that lives
for the lifetime of an activity.

The slightly more "chase the APIs and keep it working"
supported view is, make a foreground service in java,
and call that JNI and meet the requirements to keep
it alive.  (In theory using the binder to an active UI
component and doing the notification etc for a foreground
service provide similar benefits, assuming that you
can bind during activity transitions and not have a
gap where the Android takes down the service as
not in use.)

On Thursday, August 8, 2019 at 11:49:07 AM UTC-5, Stephan Menzel wrote:
Hello and thanks for your response!

Am Mittwoch, 7. August 2019 23:06:08 UTC+2 schrieb AppCoder:
I'd suggest SWIG for doing the JNI (just because that's what it does and lots of
folks have been using it for years.)


Well, we already got a shared mem interface in place as we are porting this from different platforms, so I'd rather just use and extend this. As long as I can have C++ code run and be able to use shared memory I should be good to go.

This was for a more supported way of having your process run vs. hoping Runtime.getRuntime().exec() works.
(Wrap "startMyC++ServiceThatDoesSharedMemory()" in JNI and start it in your foreground service or mega-activity.)
I like it because there are lots of little traps around JNI.
Assuming your UI will be Android java stuff, you still need a way to talk to the shared memory from java...
 

Once you have a class or interface for startReallyCoolVRStuffs, I'd put that
in a service and do the dance to make it a foreground service so Android doesn't
step on it (in app user land that's as close as you can get to a daemon, if you
are making your own firmware the rules are different.)


From this page I understand a foreground service doesn't have as many restrictions as to what it can do compared to a background service. In that regards, our would be service does mostly network IO. It fetches and synchronizes data of all sorts and provides a networking back-end to thr running VR application. While being quite efficient, it does require a bit of CPU and quite a bit of network. So if a background service would imply that I'd have restrictions in that area, it would be ruled out.


Mostly you will want it to keep the OS from deciding it can kill/restrict your service. 


Well, the existing application is a Qt desktop app, fully native C++. We currently intend to strip the UI away and put the stuff that does the heavy lifting into this Android service. As it already has a shm interface we aim at having a native Android UI (presumably written in Java or being a game like C++ UI in VR). Either way, this shall only replace the UI and leave as much of the back-end libraries and functionalities intact as possible.


A lot of the cross platform "make an app for iOS or Android" just makes
one single activity and implements all their own transitions.   This happens
because the Android activity life cycle is very much not under dev control.
So if I have 3 screens I want to show the user and they need some info
between them, I have to do android specific code since any one of the 2
not on the screen can get shut down.

The foreground service would be one way to let you have the UI stuff do
Android activities and not care about each UI screen android life cycle.

If you only had one big activity that just provided a canvas to your C++
stuff and just drew all the UI stuff per screen, the Activity life cycle would
not come into play (you'd always be the one true user interacting app in
the foreground) and you could probably bypass the service and do the
JNI call to start your C++ library when it launches.

Alex Cohn

unread,
Aug 11, 2019, 6:24:11 AM8/11/19
to android-ndk
I read from your recent replies that your native C++ component will be part of your app (another process facing the user), and not some universal service that supports a variety of other VR apps. If this is the case, you should be just fine without Services, Binder, and even without IPC. On Android, the (Java) app can run your C++ code on a background thread (naturally, not limited to single thread), and communication between Java and C++ can be handled by callbacks or sharing Java objects (via JNI). This is much easier to handle and debug than running C++ code in a separate process (which is possible, but probably not necessary in your scenario). As long as your VR app is on screen, the system will not kill the background threads, whether you wrap them in Android Services or not.

BR,
Alex

Luiz Valdetaro

unread,
Aug 11, 2019, 9:42:47 PM8/11/19
to andro...@googlegroups.com

You can load the library via jni into an android service. my recomendation to communice with the ui component is via tcp/ip. I reco,mwnd it due to the volatility kf the android apis.. once you get it working, you don't want to keep changing it every time a new android veraion ships..... tcp/ip is stable



On August 6, 2019, at 10:49, Stephan Menzel <stephan...@gmail.com> wrote:


Hello all,

I'm in the process of adapting a multi-component system to android based devices, namely SoC based VR headsets such as the Oculus Quest. I am an Android beginner but very solid with C++ on Linux and Windows. The system is C++ only, has a few dependencies such as boost and is built primarily via CMake.

During the last weeks I have thoroughly investigated into how to cross build it (it already was cross build capable for ARM) and I am now confident that I can create native libraries via NDK.

I also investigated into how to run such code and found that I'd have to bind it via JNI and then wrap it into a NativeActivity in Java. So far so good. Yet my next step is to run this component as a 'background process', like a daemon process, while another more user interface heavy process takes the front seat. This is what I'm struggling with.

The way I understand Activities, they are non-modal. Please correct me if I'm wrong but when one is open the others go to sleep. Looking around I found this: https://stackoverflow.com/questions/21406328/run-native-code-in-background which kind of confirms my fears.

So, my question is: Assuming I can cross build and wrap my native C++ component for Android, how can I have it run as a daemon like background process while another process if facing the user? The processes shall communicate via local TCP socket or (as they do now on Windows) via shared memory if that's an option but its not a must have.

Any hints are appreciated.

Best regards...

Stephan

--

Stephan Menzel

unread,
Aug 19, 2019, 10:26:31 AM8/19/19
to android-ndk
Thanks AppCoder,


Am Freitag, 9. August 2019 20:00:10 UTC+1 schrieb AppCoder:
Let me take a few steps back and push some architecture
stuff at you.

Yea, probably for the better...
 
Apps are forked java processes with hooks to all the OS APIs.
The official support for C++ is an attempt to emulate the hooks
that the java stuff uses (nativeActivity) or JNI linked into the java
process.

About that... I was trying to contain the JNI business to the absolute minimum. Probably personal history but I've been in the business for a long time and the last time I heard anything about JNI must have been in the late 90s or early 2000. I only recall the horror and what a terrible ugly thing that was and I was very glad never to hear from that again. I had no idea it still exists untill I started digging into Android and there it was! I couldn't believe at first the JNI was still a thing after all those years. I will deal with it as much as I have to in order to start or maintain my process but beyond that I have no intention of dragging this into my architecture.


While it's tempting to say "oh, it's just a linux and clang, I know
C++, I can make this go", there are all sorts of little traps for
not doing things "the right way".   Among those are:

1) the SE Android set up (that some OEMs tighten down
differently than others, nothing more annoying than having
your developer phone run fine and find that 70% of your
Samsung users are sad because of how Samsung set up
their Knox stuff.)
2) bionic (the libc on android) has various short cuts, and
restrictions compared to what you might be used to (like,
oh we don't fill out that struct, or that's not a supported
syscall)

Oh. That might turn out problematic. I am using things like Boost, Protobuf and other libraries extensively and I now I have to hope none of them go down on system calls that surprisingly don't work. 
 
In the face of this, playing by the rules for a user app
means more time doing your app, less time figuring
out why this device/update borked your stuff.

Yeah, in general I can see the value in this advice in general. I'm trying to find a way to follow that paradigm while still maintaining as much as possible of the existing code.
 
In the face of all this, the most conservative/safe C++
interaction as an app is JNI talking to java that lives
for the lifetime of an activity.

As I stated above, I am not prepared to have JNI in my arch to that extend. J&I will never be a team so to speak. ;-)
 
The slightly more "chase the APIs and keep it working"
supported view is, make a foreground service in java,
and call that JNI and meet the requirements to keep
it alive.  (In theory using the binder to an active UI
component and doing the notification etc for a foreground
service provide similar benefits, assuming that you
can bind during activity transitions and not have a
gap where the Android takes down the service as
not in use.)

This sounds like the way to go for me. I'll see where that takes me. Thanks for all the input!

Cheers,
Stephan

John Dallman

unread,
Aug 19, 2019, 1:06:59 PM8/19/19
to andro...@googlegroups.com
A question: are you delivering an app yourself, or are you just providing libraries for third-party use? 

I'm in the latter position, and found I could simplify my life considerably by building my existing command-line driven test hardness for the ADB shell environment, and doing all my testing there. However, if you have to deliver a finished app, this method is only a tempting distraction. 

John


--

Stephan Menzel

unread,
Aug 21, 2019, 12:57:45 PM8/21/19
to android-ndk
Hello John,


Am Montag, 19. August 2019 18:06:59 UTC+1 schrieb John Dallman:
A question: are you delivering an app yourself, or are you just providing libraries for third-party use? 

We are delivering the app ourselves, so deploying it via ADB is not in the cards.

Reply all
Reply to author
Forward
0 new messages