Join FlipAndroid.COM Telegram Group: https://t.me/joinchat/F_aqThGkhwcLzmI49vKAiw


¿Cómo crear un objeto con JNI?

Necesito implementar algunas funciones en una aplicación de Android usando NDK y por lo tanto JNI.

Aquí está el código C, con mis preocupaciones, que escribí:

#include <jni.h> #include <stdio.h> jobject Java_com_example_ndktest_NDKTest_ImageRef(JNIEnv* env, jobject obj, jint width, jint height, jbyteArray myArray) { jint i; jobject object; jmethodID constructor; jobject cls; cls = (*env)->FindClass(env, "com/example/ndktest/NDKTest/Point"); //what should put as the second parameter? Is my try correct, according to what //you can find in .java file? I used this documentation: http://download.oracle.com/javase/6/docs/technotes/guides/jni/spec/functions.html#wp16027 constructor = (*env)->GetMethodID(env, cls, "<init>", "void(V)"); //http://download.oracle.com/javase/6/docs/technotes/guides/jni/spec/functions.html#wp16660 //Again, is the last parameter ok? object = (*env)->NewObject(env, cls, constructor, 5, 6); //I want to assign "5" and "6" to point.x and point.y respectively. return object; } 

Mis problemas se explican más o menos dentro del código. Tal vez también: es el tipo de retorno de la función (jobject) bien?

Ahora el NDKTest.java:

 package com.example.ndktest; import android.app.Activity; import android.widget.TextView; import android.os.Bundle; public class NDKTest extends Activity { /** Called when the activity is first created. */ public native Point ImageRef(int width, int height, byte[] myArray); public class Point { Point(int myx, int myy) { x = myx; y = myy; } int x; int y; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); TextView tv = new TextView(this); byte[] anArray = new byte[3]; for (byte i = 0; i < 3; i++) anArray[i] = i; Point point = ImageRef(2, 3, anArray); tv.setText(String.valueOf(point.x)); setContentView(tv); } static { System.loadLibrary("test"); } } 

Cuando intento ejecutar el código, no funciona.

  • ¿Qué causa exactamente un error de "spin on suspend" en Android?
  • ¿Cómo se aplica el permiso de Android?
  • Utilizar C ++ con Android ndk / jni
  • Comprimir vídeos utilizando FFMPEG y JNI
  • JNI operaciones de mapa de bits, para ayudar a evitar OOM cuando se utilizan imágenes grandes
  • Javah Error android.app.Activity not found
  • Android ffmpeg .so descargar
  • La llamada al método nativo dos veces de una biblioteca de terceros en una actividad hace que la aplicación de Android se cierre
  • 5 Solutions collect form web for “¿Cómo crear un objeto con JNI?”

    Puesto que el Point es una clase interna, la manera de conseguirla sería

     jclass cls = (*env)->FindClass(env, "com/example/ndktest/NDKTest$Point"); 

    La convención $ para las clases internas no está claramente documentada en las especificaciones autorizadas, pero está arraigada en tanto código de trabajo que es poco probable que cambie. Sin embargo, se sentiría algo más robusto si restringió su código JNI para trabajar con clases de nivel superior.

    Desea un constructor que toma dos argumentos como argumentos. La firma para eso es (II)V , así que:

     constructor = (*env)->GetMethodID(env, cls, "<init>", "(II)V"); 

    La próxima vez, incluya algunos errores de manejo en su código, de modo que usted tendrá una pista que parte de ella no funciona!

    La especificación es correcta, pero un poco engañoso en este caso. GetMethodID requiere un nombre de método y una firma de método. La especificación dice :

    Para obtener el ID de método de un constructor, suministre <init> como nombre del método y void (V) como el tipo de retorno.

    Tenga en cuenta que dice tipo de retorno , no la firma . Aunque void(V) parece superficialmente a una firma, la especificación le dice que la firma debe especificar un tipo de retorno void (es decir, V ).

    La firma correcta para un constructor sin argumentos es ()V Si el constructor tiene argumentos, deben ser descritos entre paréntesis, como han comentado otros comentaristas.

    Algunos problemas con su código.

    En primer lugar, ¿por qué está creando su propia clase Point en lugar de utilizar la biblioteca proporcionada por android.graphics.Point?

    En segundo lugar, la especificación de clase para las clases anidadas es diferente – sería "com / example / ndktest / NDKTest $ Point". El anidamiento de clases es diferente de los paquetes.

    En tercer lugar, no creo que JNI le permite crear instancias de clases anidadas no estáticas. Necesita pasar el objeto de clase de anidamiento ' this puntero en la creación del objeto – no hay tal argumento.

    Finalmente, mientras he visto la guía para usar "void (V)" como una firma de método constructor, pero esto está fuera de línea con el resto de firmas de método; Normalmente, un método con dos parámetros int y un tipo de retorno vacío sería "(II) V".

    Como una nota lateral, me pareció mucho más limpio para pasar tipos primitivos y matrices de primitivas mecanografiadas de NDK a Java. La creación / acceso a objetos es complicado y difícil de depurar.

    En JNI siempre se puede utilizar la herramienta javap para encontrar firmas de métodos. Simplemente ejecute javap -s com.example.ndktest.NDKTest y copie las firmas de método de la salida.

    Tres pasos deben crear el objeto Point con JNI:

     jobject Java_com_example_ndktest_NDKTest_ImageRef(JNIEnv* env, jobject obj, jint width, jint height, jbyteArray myArray) { ... jclass cls = (*env)->FindClass(env, "com/example/ndktest/NDKTest$Point"); jmethodID constructor = (*env)->GetMethodID(env, cls, "<init>", "void(V)"); jobject object = (*env)->NewObject(env, cls, constructor, obj, 5, 6); ... } 
    FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.