2013-02-14 32 views
0

我想从本机代码调用java方法。我遵循的步骤如下: Calling a java method from c++ in Android从本地代码调用java函数时出错

但是我的应用程序崩溃在调用java函数的地方。

我的Java代码是,如下所示:

02-14 15:37:06.814: D/MYAPP(11584): bArray successfully created... 

:打印日志消息后

#include <jni.h> 
#include "com_example_jnitry_MainActivity.h" 
#include <android/log.h> 
#include <stdio.h> 

JNIEXPORT void JNICALL Java_com_example_jnitry_MainActivity_mainfunc 
    (JNIEnv *env, jclass obj, jint n){ 

    __android_log_print(ANDROID_LOG_DEBUG,"MYAPP","mainfunction entered...",NULL); 
    int i; 
    unsigned char arr[10]; 
    jbyteArray bArray=(*env)->NewByteArray(env,n); 

    jclass cls = (*env)->FindClass(env, "com/example/jnitry/MainActivity"); 
     jmethodID mid = (*env)->GetMethodID(env, cls, "display", "([B)V"); 
     if (mid == 0){ 
      __android_log_print(ANDROID_LOG_DEBUG,"MYAPP","mid==0",NULL); 
      return; 
     } 
     if(bArray==NULL) 
      { __android_log_print(ANDROID_LOG_DEBUG,"MYAPP","bArray==NULL...",NULL); 
       return ; 
      } 
    for(i=0;i<n;i++){ 
     arr[i]=i; 
     __android_log_print(ANDROID_LOG_DEBUG,"MYAPP","Iteration number:%d",i); 
    } 

    (*env)->SetByteArrayRegion(env,bArray,0,n,arr); 
    __android_log_print(ANDROID_LOG_DEBUG,"MYAPP","bArray successfully created...",NULL); 
    (*env)->CallVoidMethod(env, obj, mid, bArray); 
    __android_log_print(ANDROID_LOG_DEBUG,"MYAPP","Returned from disp() java function.....",NULL); 

} 

我的应用崩溃:如下图所示

package com.example.jnitry; 

import android.os.Bundle; 
import android.app.Activity; 
import android.util.Log; 
import android.view.Menu; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.widget.Button; 

public class MainActivity extends Activity { 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     Log.d("MYAPP","Ocreate entered...."); 
     Button btn=(Button) findViewById(R.id.button1); 
     btn.setOnClickListener(new OnClickListener() { 

      @Override 
      public void onClick(View arg0) { 
       // TODO Auto-generated method stub 
       mainfunc(8); 
      } 
     }); 
    } 

    public void display(byte[] byt){ 
     Log.d("MYAPP", "display() is entered...."); 
     for(int i=0;i<byt.length;i++) 
      Log.d("MYAPP", "byt["+i+"]="+byt[i]); 
     Log.d("MYAPP", "display finished"); 
    } 

    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 
     // Inflate the menu; this adds items to the action bar if it is present. 
     getMenuInflater().inflate(R.menu.activity_main, menu); 
     return true; 
    } 
    public static native void mainfunc(int n); 

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

我的本机代码任何人都可以请告诉我原因。并为此提供解决方案。提前致谢。

注:我已经尝试CallVoidMedthodA()callByteMethod()CallObjectMethod()但结果是一样的。

回答

3

你的本地方法mainFunc是一个静态方法 - 它没有一个有效的this指针。同时,display是一个实例方法 - 它需要一个。

根据JNI规则,mainFunc的第二个参数实际上是MainActivity的类对象指针。在Java方面声明mainFunc是非静态的,这将起作用。

+0

非常感谢你...正如你所建议的,删除静态关键字工作.... – Zax 2013-02-15 05:07:44

0

AFAIK CallVoidMethod不采用env参数。至少在C++中。

+0

上面的代码是c。因此,在每个jni函数调用中将env作为第一个参数传递是强制性的。 – Zax 2013-02-14 10:23:13

1

我可以给你这个。有用。但它是C++。 (SO吃了标签 - 对不起)

// it returns NULL in the case of an exception 
// the returned memory is calloc()'d; it's the caller's responsibility to free() it. 
char* changeEncoding(const char*source, int len, int direction) 
{ 
    JNIEnv* env = threadUnsafeInfo.env; 
    jobject obj = threadUnsafeInfo.obj; 

    if (!source) { 
    JNU_ThrowByName(env, "java/lang/NullPointerException", 0); 
    return NULL; 
    } 
    jbyteArray srcArray = env->NewByteArray(len); 

    jclass cls = env->FindClass("com/xxx/Yyy"); 
    jmethodID mid = env->GetMethodID(cls, "convert", "([BI)[B"); 

    if (mid != NULL && srcArray != NULL) { 
    env->SetByteArrayRegion(srcArray, 0, len, (jbyte*)source); 
    env->ExceptionClear(); 

    jbyteArray resArray = (jbyteArray)env->CallObjectMethod(obj, mid, srcArray, direction); 
    if(env->ExceptionOccurred()) { 
     DLOG("exception in convert ([BI)[B"); 
     env->ExceptionDescribe(); 
     //env->ExceptionClear(); // ?? 
     return NULL; 
    } 

    int resultLen = env->GetArrayLength(resArray); 
    char* result = (char*)calloc(2 + resultLen,1); // why 2: a bit of healthy paranoia ain't gonna hurt anyone 
    if (result == 0) { 
     JNU_ThrowByName(env, "java/lang/OutOfMemoryError", 0); 
     return NULL; 
    } 
    env->GetByteArrayRegion(resArray, 0, resultLen, (jbyte *)result); 
    env->DeleteLocalRef(cls); 
    env->DeleteLocalRef(resArray); 
    env->DeleteLocalRef(srcArray); 
    return result; 
    } else { 
    JNU_ThrowByName(env, "java/lang/NullPointerException", 0); 
    myassert(("method id = 0",0)); 
    } 
    return NULL; 
} 
+0

+1。正如我所说我尝试使用CallObjectMethod也... – Zax 2013-02-14 10:44:49