2012-04-20 16 views
5

में एक थ्रेड में जावावीएम * साझा करना मैं एक सीपीपी फ़ाइल से जावा क्लास विधियों को कॉल करना चाहता हूं जो किसी अन्य निष्पादन योग्य से कॉल बैक प्राप्त करता है।एंड्रॉइड एनडीके

इस लक्ष्य को हासिल करने के लिए, मैं एंड्रॉयड :: AndroidRuntime :: getJavaVM() .cpp फ़ाइल कि सीधे JNI विधि कॉल प्राप्त में विधि का उपयोग कर एक JavaVM सूचक लिया गया है। मैं अंतिम .cpp फ़ाइल के रूप में निम्नानुसार है जहाँ मैं जावा तरीकों की आवश्यकता कॉल करने के लिए निर्माता के माध्यम से इस JavaVM सूचक साझा कर रहा हूँ:

/* All the required objects(JNIEnv*,jclass,jmethodID,etc) are appropriately declared. */ 
**JNIEnv* env; 
jvm->AttachCurrentThread(&env, NULL); 
clazz = env->FindClass("com/skype/ref/NativeCodeCaller"); 
readFromAudioRecord = env->GetStaticMethodID(clazz, "readFromAudioRecord", "([B)I"); 
writeToAudioTrack = env->GetStaticMethodID(clazz, "writeToAudioTrack", "([B)I");** 

हालांकि, मैं एक SIGSEGV गलती इस कोड को चलाने के। http://java.sun.com/docs/books/jni/html/other.html#26206

इस संबंध में किसी भी मदद की सराहना की जाएगी:

JNI प्रलेखन के अनुसार इस आर्बिटरी संदर्भों में JNIEnv प्राप्त करने के लिए उचित तरीके से हो रहा है।

सादर, नीरज

+0

एंड्रॉइड :: AndroidRuntime :: getJavaVM क्या है? यह एनडीके सार्वजनिक एपीआई समारोह नहीं है। आप कुछ अनियंत्रित उपयोग कर रहे हैं। एनडीके में जावावीएम * प्राप्त करने के लिए आपको जेएनआई_ऑनलोड वैश्विक फ़ंक्शन को लागू करना होगा जिसे आपकी साझा लाइब्रेरी लोड होने पर स्वचालित रूप से कॉल किया जाता है। –

+0

आपकी प्रतिक्रिया के लिए धन्यवाद .. http://android.wooyd.org/JNIExample/#NWD1sCYeT-J - यह दस्तावेज़ JNI_OnLoad को बहुत अच्छा परिचय देता है, जहां एंड्रॉइड :: AndroidRuntime :: registerNativeMethods() का उपयोग किया जाता है। क्या आप निश्चित हैं एंड्रॉइड :: AndroidRuntime गैर दस्तावेज नहीं है? – Neeraj

+0

हां, यह सामान्य उपयोगकर्ता एनडीके कोड में अनियंत्रित सुविधा है। जेएनआई दस्तावेज (सूर्य से) पढ़ें और अन्य कानूनी और दस्तावेज एपीआई के लिए अपने एनडीके फ़ोल्डर में दस्तावेज़/STABLE-APIS.html फ़ाइल देखें। –

उत्तर

4

वैश्विक संदर्भ यदि आप संलग्न के बिना एक JNIEnv या JavaVM संदर्भ इस्तेमाल करने की कोशिश एक नया सूत्र में एक विभाजन गलती नहीं रोका जाएगा वीएम के लिए धागा। आप इसे पहली बार सही ढंग से कर रहे थे, मार्टिस्स मोझेइको यह कहने में गलत है कि आप जो कर रहे थे उसके साथ कुछ गड़बड़ थी।

इसे हटाएं, बस इसका उपयोग कैसे करें सीखें। वह लड़का नहीं जानता कि वह किस बारे में बात कर रहा है, अगर यह jni.h में है। आप सुनिश्चित हो सकते हैं कि यह कहीं भी नहीं जा रहा है। इसका कारण यह दस्तावेज नहीं है क्योंकि यह हास्यास्पद रूप से आत्म व्याख्यात्मक है। आपको ग्लोबल रेफरेंस ऑब्जेक्ट्स या कुछ भी बनाने की ज़रूरत नहीं है, बस कुछ ऐसा करें:

#include <jni.h> 
#include <string.h> 
#include <stdio.h> 
#include <android/log.h> 
#include <linux/threads.h> 
#include <pthread.h> 

#define LOG_TAG "[NDK]" 
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__) 
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN,LOG_TAG,__VA_ARGS__) 
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__) 

static pthread_mutex_t thread_mutex; 
static pthread_t thread; 
static JNIEnv* jniENV; 

void *threadLoop() 
{ 
    int exiting; 
    JavaVM* jvm; 
    int gotVM = (*jniENV)->GetJavaVM(jniENV,&jvm); 
    LOGI("Got JVM: %s", (gotVM ? "false" : "true")); 
    jclass javaClass; 
    jmethodID javaMethodId; 
    int attached = (*jvm)->AttachCurrentThread(jvm, &jniENV,NULL); 
    if(attached>0) 
    { 
     LOGE("Failed to attach thread to JavaVM"); 
     exiting = 1; 
    } 
    else{ 
     javaClass= (*jniENV)->FindClass(jniENV, "com/justinbuser/nativecore/NativeThread"); 
     javaMethodId= (*jniENV)->GetStaticMethodID(jniENV, javaClass, "javaMethodName", "()V"); 
    } 
    while(!exiting) 
    { 
     pthread_mutex_lock(&thread_mutex); 
     (*jniENV)->CallStaticVoidMethod(jniENV, javaClass, javaMethodId); 
     pthread_mutex_unlock(&thread_mutex); 
    } 
    LOGE("Thread Loop Exiting"); 
    void* retval; 
    pthread_exit(retval); 
    return retval; 
} 

void start_thread(){ 
    if(thread < 1) 
     { 
      if(pthread_mutex_init(&thread_mutex, NULL) != 0) 
      { 
       LOGE("Error initing mutex"); 
      } 
      if(pthread_create(&thread, NULL, threadLoop, NULL) == 0) 
      { 
       LOGI("Started thread#: %d", thread); 
       if(pthread_detach(thread)!=0) 
       { 
        LOGE("Error detaching thread"); 
       } 
      } 
      else 
      { 
       LOGE("Error starting thread"); 
      } 
     } 
} 

JNIEXPORT void JNICALL 
Java_com_justinbuser_nativecore_NativeMethods_startThread(JNIEnv * env, jobject this){ 
    jniENV = env; 
    start_thread(); 
} 
+0

मैंने कहां कहा कि jni.h से कुछ का उपयोग करना गलत है या अनुमति नहीं है? –

+1

"यह एनडीके सार्वजनिक एपीआई फ़ंक्शन नहीं है। आप कुछ अनियंत्रित उपयोग कर रहे हैं।एनडीके में जावावीएम * प्राप्त करने के लिए आपको जेएनआई_ऑनलोड वैश्विक फ़ंक्शन को लागू करना होगा जिसे आपकी साझा लाइब्रेरी लोड होने पर स्वचालित रूप से कॉल किया जाता है। "यह कहने के लिए खेद है कि पूरा कथन सिर्फ सादा गलत है। –

+0

और यह सच है - 'एंड्रॉइड :: एंड्रॉइड रनटाइम :: getJavaVM' jni.h में सार्वजनिक फ़ंक्शन या विधि नहीं है। मैंने कभी नहीं कहा कि jni.h (जैसे वैश्विक जेएनआई_ऑनलोड, या जावावीएम, या जेएनआईएनएनवी) से फ़ंक्शंस या विधियों का उपयोग करने की अनुमति नहीं है। लेकिन आपने निहित किया है कि मैंने कुछ कहा है वह jni.h से फ़ंक्शंस के साथ ठीक से इसका उपयोग नहीं कर रहा है। वह ** एंड्रॉइड :: एंड्रॉइड रनटाइम :: getJavaVM ** एंड्रॉइड इंटर्नल्स से फ़ंक्शन कैसे कर सकता है जो jni.h में नहीं है? –

0

समस्या हल। सेगमेंटेशन गलती इसलिए थी क्योंकि मैं साझा जेवीएम पॉइंटर से जेएनआईईएनवी ऑब्जेक्ट से पुनर्प्राप्त एक जेक्लास ऑब्जेक्ट को पुनर्प्राप्त नहीं कर सका।

मैंने जेवीएम के साथ एक वैश्विक संदर्भ jclass ऑब्जेक्ट का प्रचार किया और समस्या हल हो गई।

आपकी मदद Mārtiņš Možeiko! ..

सादर, नीरज के लिए धन्यवाद

संबंधित मुद्दे