将字符串传递给android代码时出现JNI问题

时间:2016-11-01 06:11:25

标签: android c java-native-interface

我们在将字符串从JNI .c代码传递给android时遇到了问题。给出下面的代码

.c代码

char* getSignatureMd5(JNIEnv* env, jobject obj)

{`char * sign = loadSignature(env, obj);`




    MD5_CTX context = { 0 };
    MD5Init(&context);
    MD5Update(&context, (unsigned char*)sign, strlen(sign));
    unsigned char dest[16] = { 0 };
    MD5Final(dest, &context);

    int i;
    static char destination[32]={0};
    for (i = 0; i < 16; i++) {
            sprintf(destination, "%s%02x", destination, dest[i]);
    }

    return destination;
}

JNIEXPORT jstring JNICALL Java_com_sign_signaturecapturesbi_MainActivity_getToken(JNIEnv *env, jobject obj,
                                                                    jstring string) {
__android_log_print(ANDROID_LOG_VERBOSE, "MyApp", "inside getToken");
char *signValue = getSignatureMd5(env, obj);
__android_log_print(ANDROID_LOG_VERBOSE, "MyApp", "inside ExceptionCheck if %s", signValue);
 char* msg = signValue;


jstring result;

 puts(msg);


__android_log_print(ANDROID_LOG_VERBOSE, "MyApp", "msg %s", msg);


result = (*env)->NewStringUTF(env,msg);
 return result;
}

Android原生代码

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
   mJavaText = (TextView) findViewById(R.id.java_sign);
  mJniText = (TextView) findViewById(R.id.jni_sign);
   // mJavaText.setText("Get token from jni:" + getPackage());
    //mJniText.setText("Get token from jni:" + getToken());
    try {

        String tokenvalue =  getSignature();
        System.out.println("tokenpackage in android ffi "+ tokenvalue);
       mJniText.setText("Get token from jni:" + tokenvalue);
        // mJniText.setText("Get token from jni:" + getPackage);
    }catch (Exception e) {
        // This will catch any exception, because they are all descended from Exception
        System.out.println("Error in android ffi "+ e.getMessage());

    }

}



static {
    System.loadLibrary("check-sign");

}
public native String getToken(String str);
public native String getPackage();

public String getSignature(){         //mJavaText.setText("从jni获取令牌:“+ getPackage());

    String valuetoken =  getToken("hello");


System.out.println("valuepackage in android ffi "+ valuetoken);
    // mJniText.setText("Get token from jni:" + getToken());
    return valuetoken;

    }

    }

但是我在这里得到的错误

JNI在应用程序中检测到错误:JNI NewStringUTF调用未知抛出位置抛出的挂起异常'java.lang.NullPointerException

请帮助我解决这个问题

我尝试使用以下代码。我仍然得到Null指针异常

jstring Java_com_sign_signaturecapturesbi_MainActivity_getToken(JNIEnv *env, jobject obj)
{
__android_log_print(ANDROID_LOG_VERBOSE, "MyApp", "inside signature");
   char *signValue = (char*)malloc(50);
   strcpy(signValue, getSignatureMd5(env, obj));
   jstring result = (*env)->NewStringUTF(env, signValue);
   __android_log_print(ANDROID_LOG_VERBOSE, "MyApp", "result if %s", result);
   return result;
}

添加了loadSignature方法&amp; jstringTostring方法

char* loadSignature(JNIEnv* env, jobject obj)


{
 jclass cls = (*env)->FindClass(env, "android/content/ContextWrapper");
 //this.getPackageManager();
 jmethodID mid = (*env)->GetMethodID(env, cls, "getPackageManager",
         "()Landroid/content/pm/PackageManager;");
 if (mid == NULL) {
     return "";
 }
 jobject pm = (*env)->CallObjectMethod(env, obj, mid);
 if (pm == NULL) {
     return "";
 }

 //this.getPackageName();
 mid = (*env)->GetMethodID(env, cls, "getPackageName", "()Ljava/lang/String;");
 if (mid == NULL) {
     return "";
 }

 jstring packageName = (jstring)(*env)->CallObjectMethod(env, obj, mid);

 // packageManager->getPackageInfo(packageName, GET_SIGNATURES);
 cls = (*env)->GetObjectClass(env, pm);
 mid  = (*env)->GetMethodID(env, cls, "getPackageInfo", "(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;");

 jobject packageInfo = (*env)->CallObjectMethod(env, pm, mid, packageName, 0x40); //GET_SIGNATURES = 64;

 cls = (*env)->GetObjectClass(env, packageInfo);
 jfieldID fid = (*env)->GetFieldID(env, cls, "signatures", "[Landroid/content/pm/Signature;");
 jobjectArray signatures = (jobjectArray)(*env)->GetObjectField(env, packageInfo, fid);
 jobject sign = (*env)->GetObjectArrayElement(env, signatures, 0);

 cls = (*env)->GetObjectClass(env, sign);
 mid = (*env)->GetMethodID(env, cls, "toCharsString", "()Ljava/lang/String;");
 if(mid == NULL){
     return "";
 }

 jstring signString = (jstring)(*env)->CallObjectMethod(env, sign, mid);

 return jstringTostring(env, signString);
 }
char* jstringTostring(JNIEnv* env, jstring jstr)


{
 char* rtn = NULL;


jclass clsstring = (*env)->FindClass(env, "java/lang/String");
 jstring strencode = (*env)->NewStringUTF(env, "utf-8");
 jmethodID mid = (*env)->GetMethodID(env, clsstring, "getBytes", "(Ljava/lang/String;)[B");
 jbyteArray barr= (jbyteArray)(*env)->CallObjectMethod(env, jstr, mid, strencode);
 jsize alen = (*env)->GetArrayLength(env, barr);
 jbyte* ba = (*env)->GetByteArrayElements(env, barr, JNI_FALSE);
 if (alen > 0)
 {
     rtn = (char*)malloc(alen + 1);
     memcpy(rtn, ba, alen);
     rtn[alen] = 0;
 }
 (*env)->ReleaseByteArrayElements(env, barr, ba, 0);
 return rtn;


}

1 个答案:

答案 0 :(得分:-1)

在使用 NewStringUTF 之前尝试检查NULL。这是我的代码:

...
if (msg == NULL){
 return NULL;
}

result = (*env)->NewStringUTF(env,msg);
return result;