Edit build.gradle and modify cFlags to point to your NDK directory.
Use AndroidStudio (tested on 1.2) to build the solution.
This project has utilities to make working with JNI more affordable. While it has some specific code about Cocos Service Center, like a central Services registry, it contains utilities to:
- call arbitrary static methods on any class.
- call arbitrary methods from a Service
These calls automatically infer the method signature based on the calling parameters. This infernce happens at java side, where Boxed types are unboxed into primitives to figure out the best matching signature.
It also offers a convenient message based mechanism to invoke a native callback from Java. This of this as a java to native observer mechanism.
There are several methods available:
static jobject JavaDispatcher::callInService(
const char* serviceCanonicalJavaClass,
const char* methodName,
jobjectArray args );
This method will invoke a method on a previously registered Service. The invocation does not need
a method signature and will be automatically inferred.
The serviceCanonicalJavaClass must identify a fully qualified Service class. These
Service must have been reflectively instantiated before at ServicesRegistry creation time.
methodName is a method from the Service. In future implementations of CSC, the
implementation will prevent from calling methods belonging to the Service interface, which are
handled by the Application and ServiceRegistry lifecycle.
args if a jobjectArray. Arguments are passed in to Java in its most polymorphic form.
Primitive arguments will be boxed. It is important to note that the implementation expects
primitive types in the Java side function. The boxed parameters will be automatically unboxed before
trying to find the suitable Java method signature for the calling parameters.
static jobject JavaDispatcher::callStatic(
const char* className,
const char* methodName,
jobjectArray args );This method will invoke an arbitrary static method in any Class.
All the parameter definitions from the call method apply to this method as well.
In both cases, the result of the Java method invocation is returned. The return value will be a
jobject. In case the invoked method returned void or the method failed in any way
(from finding the class, to finding the method, to not finding a suitable method to invoke based
on the calling parameters).
static jobject JavaDispatcher::callInInstance(
jobject objRef,
const char* method,
jobjectArray params );If you have an object instance reference in Native, you can call any method of such instance with
this method. A Java instance can be obtained by using direct JNI calls, or by creating a
Proxy object.
This system is an observer pattern where native code registers interest in an Event (defined by a
String), and then Java can emit a notification back to any of the registered observers.
One remarkable feature of this approach is that you don't need to declare any native method in your Java classes. Everything is wrapped inside the NativeBridge class.
The process is therefore setup in two steps:
Native code registers interest in a Java event by calling:
NativeBridge::addEventListener( "GoogleAnalytics.Tick", functorCallback );This code registers interest in having the functorCallback invoked whenever Java emits
an event identified by the registered interest ( "GoogleAnalytics.Tick" in this case ).
The functorCallback currently must be defined by an Object and a pointer to member.
The following is an example for functorCallback
class GA {
public:
// functor parameters:
// @param event the registered event. i.e.: "GoogleAnalytics.Tick".
// @param params whatever object the java natvieEmit function call will pass in.
void A( std::string event, jobject params ) { ... }
};
SPCallback* functorCallback= new SPCallback( new JNIEventListener<GA>( new GA(), &GA::A ) );
JNIEventListener extends Functor.
SPCallback is a shared_ptr<Functor>
// the SPCallback receives a Functor by simple polymorphism.
Java invocation just has to do calls of the form
servicesRegistry.nativeEmit( "GoogleAnalytics.Tick", object_param );This call will invoke all native functors associated with this event.
To assist in building JNI types, there's the JNIUtils class. It has methods to assist in building
the necessary jobjectArray for the JavaDispatcher calls as well as
construction/destruction for common types.