2013-02-14 64 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