Extend Ndk Native Activity API

275 views
Skip to first unread message

sbilkoloft

unread,
Dec 29, 2015, 1:33:57 PM12/29/15
to android-ndk
Hi,

I'm dealing with a crazy problem here.

Short version
How can I extend the API of native activity to send some data from java to my native rendering thread? The java side is trivial, I'm stuck on the C++ side.

Long version:
I'm developing a game which needs the phone's orientation. On the native side I've tried using gyro/accel which has too much error for what I need. I want access to the rotation vector available on the java side. I'm using native activity and native app glue. Getting the data on the java side is easy (inherit from native activity, implement sensor interface). I need to find a proper way to pump this data to my game thread on the native side.

I was thinking of passing the info though the pipes/looper. I've been trying to mimic what native activity (the c++ side) does. Unfortunately, it uses a locally defined struct NativeCode which I don't have access to. Which means when the java side calls into c++, I have the native code handle, but I don't know how big the struct is and what is looks like. I tried duplicating the struct in my code so I can get the proper offset of the pipe fds so I can write info to them to be processed on native game thread. Had to fake implement String8 and sp.

Is this a good idea? Is there a simpler way? I know this is not reliable as it could stop working in future releases of the ndk if the structs/classe sizes change.

An alternative would be to have the game thread read from java through jni. So the java side will store a local copy of the latest read orientation and the game thread would read it upon each render frame. I don't like this approach as 2 threads are reading/writing shared data with no proper synchronization.

Any thoughts would be appreciated. Thanks.

Feature request: in NativeActivity.java please make 'mNativeHandle' protected so classes inheriting from it can access it.

sbilkoloft

unread,
Dec 30, 2015, 8:40:28 AM12/30/15
to android-ndk
I managed to what I wanted. Here is the solution if anyone's interested:

1) In Java my activity inherits from NativeActivity. Aside from calling super stuff, it implements the interface for sensor required to get the rotation vector.
2) In onCreate of the activity, I get a hold of mNativeHandle. This is private on the parent so I get it through reflection.
3) The activity defines a native method to send the sensor data on each onSensorChange call. In order to get jni to work this activity has to load the native lib with System.load as well. The first argument of the new call should be the mNativeHandle. The rest are sensor data or any other data you may need.
4) In native app glue 'android_app_entry' a new pipe is created for sensor data. Tell the looper to poll for the pipe as well. The logic here is very similar to the msgread/msgwrite pipe.
5) Each time the new native method is invoked, cast mNativeActivity to ANativeActivity*. Write the sensor data to the pipe.
6) On the other thread, when there is data ready, read the sensor data. You now have the rotation vector in your C++ code.

Hope his helps.

Reply all
Reply to author
Forward
0 new messages