How to send a char array from JNI to android

I want to send a block of data from JNI to android.

I have created a jchar* in JNI and filled it with my data, and returned it to android as jcharArray. But while displaying the data in android, it results in junk values.

This is my JNI code:

JNIEXPORT jcharArray JNICALL Java_com_android_test_dsp_Vread(
      JNIEnv *env,
      jobject thiz,  
      jint length)
{
   jchar* datatosend;
   jcharArray ret;
   ret= (*env)->NewCharArray(env, length);
   memset(datatosend,1,length);
   (*env)->SetCharArrayRegion(env, ret, 0, length, datatosend);
   return ret;
}

My Java code:

char[] rxvddata = new rxvddata[length];
rxvddata =Vread(length);
textview.setText("Data1:"+Integer.tostring(rxvddata[0]) + 
    "Data2:"+Integer.tostring(rxvddata[1]));

Can anyone point out the mistake? struggling for long time..

Answers


Following is some code that is similar to what you are working with. In this example, a jobjectArray is returned to Java where the objects in the Array are UTF Strings.

Native code: ExampleNativeJni.c

#include <jni.h>
#include <android/log.h>

#define LOG_TAG "AndroidJniExample"
#define LOG(...)  __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
#define AUDIO_TRACK_BUFFER_SIZE (48)

/*
*  Method used to get the audio track language codes from a video file
*/

JNIEXPORT jobjectArray JNICALL Java_com_example_nativeGetAudioTracks (JNIEnv * env, jobject obj, jstring filePath) {

    // Convert filePath from jstring to null terminated UTF8 string
    const char *path = (*env)->GetStringUTFChars(env, filePath, 0);
    if (!path ) {
            LOGE ("ERROR : pathToFile Conversion error in nativeGetAudioTracks");
            (*env)->ReleaseStringUTFChars(env, filePath, path);
            return NULL;
    }

    // Each track is 3 chars + a null terminator.
    // Allows for up to 12 languages.
    char langCodeHolder[AUDIO_TRACK_BUFFER_SIZE] = {0};
    int numTracks = 0;
    int fd = open(path, O_RDONLY);
    if (fd > 0) {
        // get audio track magic through custom FUSE IOCTL handler
        numTracks = ioctl(fd, GET_AUDIO_TRACKS, &(langCodeHolder[0]));
        close(fd);
    } else {
        LOGE ("ERROR: open(%s) failed in nativeGetAudioTracks", path);
        (*env)->ReleaseStringUTFChars(env, filePath, path);
        close(fd);
        return NULL;
    }

    if (numTracks < 0) {
        LOG("ERROR: Invalid value returned from GET_AUDIO_TRACKS");
        (*env)->ReleaseStringUTFChars(env, filePath, path);
        return NULL;
    }

    if (numTracks == 0) {
        LOG("ERROR: No audio tracks returned");
        (*env)->ReleaseStringUTFChars(env, filePath, path);
        return NULL;
    }

    // Instantiate array to hold language codes.
    jobjectArray langs;
    const jint langArraySize = numTracks;
    jclass stringObject = (*env)->FindClass(env, "java/lang/String");
    if (stringObject == NULL) {
        (*env)->ReleaseStringUTFChars(env, filePath, path);
        return NULL;
    }
    langs = (*env)->NewObjectArray(env, langArraySize, stringObject, (*env)->NewStringUTF(env, NULL));

    // Extract each 3-letter language code and stuff them into the array.
    jstring langCode;
    char* temp = &(langCodeHolder[0]);
    jint i;
    for (i = 0; i < langArraySize; i++) {
        langCode = temp;
        (*env)->SetObjectArrayElement(env, langs, i, (*env)->NewStringUTF(env, langCode));
        temp += 4;
    }

    (*env)->ReleaseStringUTFChars(env, filePath, path);
    return langs;
}

Android JNI code : ExampleAndroidJni.java

public class ExampleAndroidJni {

    private static ExampleAndroidJni sInstance;
    private static final String TAG = "ExampleAndroidJni";

    public static String[] getAudioTracks(final String filePath) {
        if (sInstance == null) {
            sInstance = new ExampleJniClient();
        }

        if (filePath == null) {
            Log.e(TAG, "file path is null");
            return null;
        }

        final String[] auduioTracks = sInstance.nativeGetAudioTracks(filePath);
        if (auduioTracks == null || auduioTracks.length == 0) {
            Log.i(TAG, "No audio tracks returned for : " + filePath);
        }

        return auduioTracks;
    }

    native String[] nativeGetAudioTracks(String filePath);

    static {
        System.loadLibrary("ExampleNativeJni");
    }
}

In case anyone stumbled upon this to figure out how to create a NewCharArray in JNI, you can't.. you have to use NewObject instead (as Akos said). Here's how to do it in C++:

Here, "SendClass" is my jclass, "sendMain" is my jmethod, "env" is my JNIEnv

jstring stringOne = env->NewStringUTF("test1");
jstring stringTwo = env->NewStringUTF("test2");
jobject jobjDet = env->NewObject(SendClass, sendMain, stringOne, stringTwo);
env->CallStaticIntMethod(SendClass, sendMain, jobjDet);
env->DeleteLocalRef(stringOne);
env->DeleteLocalRef(stringTwo);
//may need to release more resources

==============================

EDIT:

I don't think the previous code I wrote will send a String[] arg... I do believe this would work, though:

//array size of 3 means [0], [1], [2]
jobjectArray jobjDet;
//creates String[3] = ""
jobjDet = env->NewObjectArray(3, env->FindClass("java/lang/String", env->NewStringUTF(""));
env->SetObjectArrayElement(jobjDet, 0, env->NewStringUTF("test1"));
env->SetObjectArrayElement(jobjDet, 1, env->NewStringUTF("test2"));
env->SetObjectArrayElement(jobjDet, 2, env->NewStringUTF("test3"));

Need Your Help

Get Comments with PHP Simple HTML DOM Parser

php parsing dom html-parsing

I'm working with PHP Simple HTML DOM Parser.

Zoom-in and Zoom-out image when Mouse Scroll

javascript html ajax zooming mousewheel

I want to zoom-in and zoom-out image on mouse scroll in HTML. There are multiple img tag without ID. So how can I do it using JavaScript or Ajax?