Usar JNI en Openframeworks Android (Parte III)

Usar JNI en Openframeworks Android (Parte III)

Como comentamos en las anteriores entradas, este post lo dedicaremos a comentar cómo llamar código Java Android desde métodos de Openframeworks.

En ocasiones, vamos a querer llamar alguna de las funciones nativas del SDK Android. Por ejemplo, si queremos acceder al teclado, mostrar un formulario o llamar a los métodos de “in-app billing”. Será cuando se dé alguna de estas circunstancias cuando llamaremos código Java desde nuestro contexto de OF.

Esta estrategia puede ser muy útil para generar aplicaciones con múltiples “activities”, que requieran interfaces gráficas sencillas o funcionalidades que solo se encuentran en el SDK Android. También puede ser útil para separar conceptualmente la parte gráficamente potente de OF de las funcionalidades ‘mas clásicas’ como logins, sign-ups, conexiones con google-play, google maps, database… En definitiva, funcionalidades muy útiles y fáciles de programar en Java Android.

En el ejemplo que mostramos a continuación, nos ayudaremos del addon ofxGui para crear un botón, donde llamaremos en su evento de click a un método Java que nos abrirá un nuevo “Activity” de Java Android con un pequeño formulario de login/email.

Empezaremos por lo tanto, editando la parte Java del fichero “OFActivity.java”, creando y añadiendo el código que ejecutaremos desde las llamadas en la parte C++.

	public void openActivity(){

		 Log.v("OFActiviy", "openActivity method in java native class access via OF");

		Intent nextScreen = new Intent(getApplicationContext(), SecondScreenActivity.class);

        //Sending data to another Activity
        nextScreen.putExtra("name", "Default Name");
        nextScreen.putExtra("email", "Default eMail");

        startActivity(nextScreen);

	}

Ampliar código

De esta manera, tenemos el método ‘openActivity’ preparado para llamarlo desde el botón creado en OF.

Para ello debemos crear, “setear” y posteriormente llamar a las siguientes instrucciones de OF. Empezando por el fichero “ofApp.h”, crearemos:

		ofxPanel gui;
		ofxButton changeActivity;
		void changeActivityPressed();

		// variable needed for import value from java
		jclass javaClass;
		jobject javaObject;

		void setupJNI();

Ampliar código

Aquí podemos ver como creamos los objetos necesarios para crear el botón y el método del botón con el addon ofxGUI. Por otro lado, creamos dos objetos “JNI”: jclass, donde guardaremos la clase java y jobject, que será un objeto Java de la clase en cuestión.

Por otro lado, en el “ofApp.cpp”, y a modo de encapsular código, creamos el método ‘setupJNI()’ donde haremos ‘setup’ de estos objetos ‘JNI’:

<pre>void ofApp::setupJNI(){

	JNIEnv *env = ofGetJNIEnv();

	//get OFActivity class from java
	jclass localClass = env->FindClass("cc/openframeworks/activitiesOF/OFActivity");
	javaClass = (jclass) env->NewGlobalRef(localClass);
	if (!javaClass) {
		ofLog() << "javaClass NOT found!" << endl;
	}else if(javaClass){
		ofLog() << "javaClass found!" << endl;
	}

	//get OFActiviy object from java
	javaObject = ofGetOFActivityObject();
	javaObject = (jobject) env->NewGlobalRef(javaObject);
	if (!javaObject) {
		ofLog() << "javaObject NOT found!" << endl;
	}else if(javaObject) {
		ofLog() << "javaObject found!" << endl;
	}
}

Ampliar código

En el fragmento anterior, deberemos especificar el “path” donde se encuentra nuestra clase Java (OFActivity) para, posteriormente, poder llamar al objeto de la misma y ejecutar su método.

A continuación, nos situamos en la parte del evento del botón creado en OF, donde añadiremos el siguiente código para llamar al método creado en la parte Java:

void ofApp::changeActivityPressed(){

	JNIEnv *env = ofGetJNIEnv();

	/**
	 * This calls the "openActivity" java-method, it's a "void" function without parameters.
	 *
	 */
	jmethodID javaReturnMethod = env->GetMethodID(javaClass,"openActivity","()V");
	if(!javaReturnMethod){
		ofLog() << "Method NOT found!" << endl;
	}else if(javaReturnMethod){
		ofLog() << "Method found!" << endl;
	}

	//This code execute Java method located in OFActivity.java
	env->CallVoidMethod(javaObject, javaReturnMethod);

	//Code that close actual OFActivity and give feedback to the activity change (coded in OFActivity.java)
	endApp();

}

Ampliar código

Tras introducir estas líneas, al apretar el botón el flujo de programa cerrará nuestro contexto Openframeworks, dejándolo listo para volverse a abrir. Mientras, por encima, se abrirá un “Activity” de Android donde se pedirá un usuario y email.

Hay que fijarse en el objeto ‘jmethodID‘, donde asignaremos el método de nombre ‘openActivity‘. Éste debe coincidir con el nombre del método en la parte Java Android. El tercer parámetro que recibe es sumamente importante, ya que indica el tipo de método a crear y los parámetros que se le envían ( debe coincidir!). Como en este caso se trata de un método ‘void’ sin parámetros, el tercer parámetro es ‘()V‘.

Para saber, conocer y manejar este tipo de codificación para las cabeceras de los métodos se puede consultar la documentación de JNI en el webpage de oracle.

http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/types.html

Adjuntamos un proyecto de ejemplo para poder testear y para que pueda servir de guía. El proyecto está funcionando en OF Android 0.8.3. para situar en la ruta, ../examples/Android/

Link al proyecto