How to send a char array from JNI to android
android, android-ndk, arrays, java-native-interface
Solution
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");
}
}
Problem
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..