Home » Android » android – Set/Get Java List<> from C code

android – Set/Get Java List<> from C code

Posted by: admin June 15, 2020 Leave a comment

Questions:

Java Code

In Java code I have class called IdentificationResult which has 3 members:

  1. enrollmentID
  2. enrollmentSettings
  3. identParams.

Here is the class:

package com.vito.android.framework.service;

class IdentificationResult
{
    class IdentParams {
        byte[] otp;
        String seedId;
    }

    String enrollmentID;
    String enrollmentSettings;
    List<IdentParams> identParams;
}

In the main class I have function IdentificationResult GetAuthenticationStatus( ), here is the main Class:

public class TokenManager 
{
    /* Some code goes here ... */

    public IdentificationResult GetAuthenticationStatus( )
    {
        /* Function do some actions here ... */
        return new IdentificationResult;
    }
}

C++ Code

I call Java method from my C++ code in this way

void GetAuthenticationStatus( )
{
    // Attach current thread.
    JNIEnv *env = NULL;
    m_javaVM->AttachCurrentThread( env, NULL );
    if( env == NULL ) {
        return -1;
    }

    jclass clazz = NULL;
    clazz = env->GetObjectClass( m_classObject );
    if( clazz == NULL ) {
        return -1;
    }

    // Get class method.
    jmethodID clazzMethod = NULL; 
    env->GetMethodID( clazz, "GetAuthenticationStatus", "(V;)Lcom/vito/android/framework/service/IdentificationResult;" );
    if( clazzMethod == NULL ) {
        return VCS_RESULT_ERROR;
    }

    // Call Java 'GetAuthenticationStatus' function.
    jobject methodReturnObj = env->CallObjectMethod( m_classObject, clazzMethod );

    // Get IdentificationResult Class from Object.
    jclass identifyResultClass = env->GetObjectClass( methodReturnObj );
    if( identifyResultClass == NULL ) 
    {
        return -1;
    }

    // Get identParams.
    jfieldID fieldID = env->GetFieldID( identifyResultClass , "identParams", "***1. Question***");
    if( fieldID == NULL ) {
        return -1;
    }
    else
    {
        *** 2. Question *** 
    }

}

Questions

  1. What I must write here to get List<IdentParams> field ID?

  2. How I can Get or Set field value?

How to&Answers:

Okay, I have solve the problem and want to share result with you, here is solution:

    fieldID = env->GetFieldID( identifyResultClass , "identParams", "Ljava/util/List;" );
    if( fieldID != NULL ) 
    {
        // Find "java/util/List" Class (Standard JAVA Class).
        jclass listClass = env->FindClass( "java/util/List" );
        if( listClass == NULL ) {
            DBG_WARNING(DBG_CTX, ("Can't Find Class \"java/util/List\".\n"));
            return -1;
        }

        // Get List object field.
        jobject listObject = env->GetObjectField( methodReturnObj, fieldID );
        if( listObject == NULL ) {
            DBG_WARNING(DBG_CTX, ("Can't get ObjectField for \"List\".\n"));
            return -1;
        }

        // Get "java.util.List.get(int location)" MethodID
        jmethodID getMethodID = env->GetMethodID( listClass, "get", "(I)Ljava/lang/Object;" );
        if( getMethodID == NULL ) {
            DBG_WARNING(DBG_CTX, ("Can't get MethodID for \"java.util.List.get(int location)\".\n"));
            return -1;
        }

        // Get "int java.util.List.size()" MethodID
        jmethodID sizeMethodID = env->GetMethodID( listClass, "size", "()I" );
        if( sizeMethodID == NULL ) {
            DBG_WARNING(DBG_CTX, ("Can't get MethodID for \"int java.util.List.size()\".\n"));
            return -1;
        }

        // Call "int java.util.List.size()" method and get count of items in the list.
        int listItemsCount = (int)env->CallIntMethod( listObject, sizeMethodID );
        DBG_DISPLAY(DBG_CTX,("List has %i items\n", listItemsCount));

        for( int i=0; i<listItemsCount; ++i )
        {
            // Call "java.util.List.get" method and get IdentParams object by index.
            jobject identParamsObject = env->CallObjectMethod( listObject, getMethodID, i - 1 );
            if( identParamsObject == NULL )
            {
                DBG_WARNING(DBG_CTX, ("Can't get Object from \"identParamsObject\" at index %i.\n", i - 1));
            }


        }

Thanks to @Joop Eggen he gives me great idea !!!

Answer:

Do not consider the following compilable, but you’ll get the idea:

jobject list = env->GetObjectField(methodReturnObj, "identParams"); // java.util.List
getMID = env->GetMethodID (listClass, "get","(I)Object");
jobject someIdentParam = env->CallMethod(getMid, new Object[] { list, 0 }); // java.lang.Object

Read the documentation first.