2014-06-30 44 views
0

我是Java編程新手。我試圖使用JNI從Native C++代碼調用Java API。我收到以下錯誤 「未能獲得類參考」 下面的代碼片段 Java方面:無法從調用Java代碼的本地代碼獲取類引用

package com.example.playaudio; 

import android.app.Activity; 
import android.media.AudioManager; 
import android.media.MediaPlayer; 
import android.os.Bundle; 
import android.view.Menu; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.widget.Button; 

public class MainActivity extends Activity implements OnClickListener{ 
     private MediaPlayer mp; 
     @Override 
     protected void onCreate(Bundle savedInstanceState) { 
       super.onCreate(savedInstanceState); 
       setContentView(R.layout.activity_main); 
       setVolumeControlStream(AudioManager.STREAM_MUSIC); 
       Button button1=(Button)findViewById(R.id.button_1); 
       Button button2=(Button)findViewById(R.id.button_2); 
       button1.setOnClickListener(this); 
       button2.setOnClickListener(this); 
     } 

     public void onClick(View v) { 
       int resId; 
       switch (v.getId()) { 
       case R.id.button_1: 
         resId = R.raw.a; 
         break; 
       case R.id.button_2: 
         resId = R.raw.b; 
         break; 
       default: 
         resId = R.raw.a; 
         break; 
       } 
       // Release any resources from previous MediaPlayer 
       if (mp != null) { 
         mp.release(); 
       } 
       // Create a new MediaPlayer to play this sound 
       mp = MediaPlayer.create(this, resId); 
       mp.start(); 
     } 
     public void onStart() { 
       int resId; 
       // Release any resources from previous MediaPlayer 
       if (mp != null) { 
         mp.release(); 
       } 
       resId = R.raw.b; 
       // Create a new MediaPlayer to play this sound 
       mp = MediaPlayer.create(this, resId); 
       mp.start(); 
     } 
} 

機端(C++用JNI):

JavaVM * create_vm() { 
    JavaVM *jvm; 
    JNIEnv *env; 

    JavaVMInitArgs vm_args; 
    JavaVMOption *options = new JavaVMOption[1]; 
    options[0].optionString = "-Djava.class.path=."; 

    vm_args.version = JNI_VERSION_1_6; 
    vm_args.nOptions = 1; 
    vm_args.options = options; 
    vm_args.ignoreUnrecognized = false; 

    // Load and Initailize JVM, returns an JNI Intterface 
    int ret = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args); 
    if (ret < 0) 
      printf("Unable to launch JVM \n"); 

    return jvm; 
} 

void PlayAudio() 
{ 
    int status; 
    bool isAttached = false; 
    JNIEnv *env; 


    printf("PlayAudio\n"); 
    status = gJavaVM->GetEnv((void **) &env, JNI_VERSION_1_6); 


    status = gJavaVM->AttachCurrentThread((void **)&env, NULL); 


    jclass interfaceClass = 
      env->FindClass("com/example/playaudio/MainActivity"); 
    if(!interfaceClass) { 
      printf("PlayAudio: Failed To Get Class Reference\n"); 
      return; 
    } 

    jmethodID altmethod = env->GetMethodID(interfaceClass, "<init>","()V"); 
    jobject obj = env->NewGlobalRef(env->NewObject(interfaceClass, altmethod)); 

    jmethodID method = env->GetMethodID(interfaceClass, "onStart", "(I)V"); 
    if(!method) 
    { 
      printf("PlayAudio: Failed To Get Object Method\n"); 
      return; 
    } 
    env->CallVoidMethod(obj, method, NULL); 
} 

請指正如果有什麼是錯誤的,我coding.Following是錯誤

PlayAudio

Exception in thread "main" java.lang.NoClassDefFoundError: com/example/playaudio/MainActivity 
Caused by: java.lang.ClassNotFoundException: com.example.playaudio.MainActivity 
    at java.net.URLClassLoader$1.run(URLClassLoader.java:202) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.net.URLClassLoader.findClass(URLClassLoader.java:190) 
    at java.lang.ClassLoader.loadClass(ClassLoader.java:306) 
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301) 
    at java.lang.ClassLoader.loadClass(ClassLoader.java:247) 
PlayAudio: Failed To Get Class Reference 

問候 庫馬爾

+2

請發佈完整的錯誤消息,而不是您的消息摘要。 – CoryKramer

+0

執行以下語句printf(「PlayAudio:無法獲取類參考\ n」) – kumar

+1

@kumar當您在JNI中或任何地方遇到錯誤情況時,應打印所有可用的信息,而不是僅僅製作自己的錯誤信息。所做的只是告訴你發生了一個錯誤。有幾個關於異常和堆棧跟蹤的JNI函數。使用它們。在此發佈結果。將它們編輯成你的問題。 – EJP

回答

0

把你發現的類代碼在JNI_OnLoad,看看它是否工作。如果是這樣,那麼你的java類加載器有問題。如果不是這樣,那麼在運行應用程序時就會破壞你的java類路徑。

jint JNI_OnLoad(JavaVM* vm, void* reserved) { 
    jclass interfaceClass = env->FindClass("com/example/playaudio/MainActivity"); 
    if(!interfaceClass) { 
    printf("PlayAudio: Failed To Get Class Reference\n"); 
    } 

如果你的問題是類裝載器,這可能是由於JNLP ...我還沒有研究到底爲什麼這個問題存在,但我懷疑它的相關的類加載器具有額外的安全性,這不是正在解決。這一切都是推測性的,所以請運行上面的測試,讓我們知道發生了什麼。

+0

嗨,亞歷克斯,感謝您的回覆。建議的解決方案不工作。我的類路徑是bin/classes/com/example/playaudio /。因此,我修改了代碼,仍然沒有成功。伊姆試圖調用與Android相關的jaava clesses。如果您有其他方法,請告訴我。 – kumar

0

你可以嘗試的第一步是給你的Java類的選項值的修復路徑: options [0] .optionString =「-Djava.class.path =。」; ==>設置Java庫的完整路徑代替 如果它不起作用,我對將Java方法公開給您的本機庫的步驟有疑問。請仔細檢查您是否將java類編譯到類文件中,以便本機庫可以引用它。