如何从JNI发送一个char数组到android

时间:2012-08-14 17:02:59

标签: android arrays android-ndk java-native-interface

我想从JNI向android发送一个数据块。

我在JNI中创建了一个jchar*并用我的数据填充它,并将其作为jcharArray返回到android。但是在android中显示数据时,会产生垃圾值。

这是我的JNI代码:

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;
}

我的Java代码:

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

有谁可以指出错误?挣扎了好久..

2 个答案:

答案 0 :(得分:4)

以下是一些类似于您正在使用的代码 在此示例中,jobjectArray返回到Java,其中Array中的对象是UTF字符串。

原生代码: 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代码: 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");
    }
}

答案 1 :(得分:0)

如果有人偶然发现了如何在JNI中创建NewCharArray,你就不能......你必须使用NewObject(正如Akos所说)。以下是如何在C ++中实现它:

这里,“SendClass”是我的jclass,“sendMain”是我的jmethod,“env”是我的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

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

编辑:

我不认为我之前编写的代码会发送一个String [] arg ...我相信这会起作用,但是:

//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"));