2012-11-06 12 views
7

हम NativeActivity कक्षा का उपयोग कर एंड्रॉइड पर ओपनजीएल गेम विकसित कर रहे हैं। अब तक सबकुछ ठीक हो गया है, लेकिन अब हमें कुछ कार्यक्षमता तक पहुंचने की ज़रूरत है जो केवल जावा से उपलब्ध है।एंड्रॉइड: मूल सक्रियता से जेएनआई का उपयोग

और भी कुछ हैं, लेकिन पहला जो हमने सोचा था वह उपयोगी होगा डीपीआई का उपयोग करना। here वर्णित है जावा कोड इस तरह दिखता है:

DisplayMetrics metrics = new DisplayMetrics(); 
getWindowManager().getDefaultDisplay().getMetrics(metrics); 

और यहाँ दुर्भाग्यपूर्ण इसी सी ++ कोड है:

// My checking routine. 
#define JNI_ASSERT(jni, cond) { \ 
    if (!(cond)) {\ 
    std::stringstream ss; \ 
    ss << __FILE__ << ":" << __LINE__; \ 
    throw std::runtime_error(ss.str()); \ 
    } \ 
    if (jni->ExceptionCheck()) { \ 
    std::stringstream ss; \ 
    ss << __FILE__ << ":" << __LINE__; \ 
    throw std::runtime_error("Exception: " + ss.str()); \ 
    } \ 
} 

void print_dpi(android_app* app) { 
    JNIEnv* jni; 
    app->activity->vm->AttachCurrentThread(&jni, NULL); 

    jclass activityClass = jni->FindClass("android/app/NativeActivity"); 
    JNI_ASSERT(jni, activityClass); 

    jmethodID getWindowManager = jni->GetMethodID 
            (activityClass 
            , "getWindowManager" 
            , "()Landroid/view/WindowManager;"); 
    JNI_ASSERT(jni, getWindowManager); 

    jobject wm = jni->CallObjectMethod(app->activity->clazz, getWindowManager); 
    JNI_ASSERT(jni, wm); 

    jclass windowManagerClass = jni->FindClass("android/view/WindowManager"); 
    JNI_ASSERT(jni, windowManagerClass); 

    jmethodID getDefaultDisplay = jni->GetMethodID(windowManagerClass 
               , "getDefaultDisplay" 
               , "()Landroid/view/Display;"); 
    JNI_ASSERT(jni, getDefaultDisplay); 

    jobject display = jni->CallObjectMethod(wm, getDefaultDisplay); 
    JNI_ASSERT(jni, display); 

    jclass displayClass = jni->FindClass("android/view/Display"); 
    JNI_ASSERT(jni, displayClass); 

    // Check if everything is OK so far, it is, the values it prints 
    // are sensible. 
    { 
    jmethodID getWidth = jni->GetMethodID(displayClass, "getWidth", "()I"); 
    JNI_ASSERT(jni, getWidth); 

    jmethodID getHeight = jni->GetMethodID(displayClass, "getHeight", "()I"); 
    JNI_ASSERT(jni, getHeight); 

    int width = jni->CallIntMethod(display, getWidth); 
    JNI_ASSERT(jni, true); 
    log("Width: ", width); // Width: 320 

    int height = jni->CallIntMethod(display, getHeight); 
    JNI_ASSERT(jni, true); 
    log("Height: ", height); // Height: 480 
    } 

    jclass displayMetricsClass = jni->FindClass("android/util/DisplayMetrics"); 
    JNI_ASSERT(jni, displayMetricsClass); 

    jmethodID displayMetricsConstructor = jni->GetMethodID(displayMetricsClass 
                 , "<init>", "()V"); 
    JNI_ASSERT(jni, displayMetricsConstructor); 

    jobject displayMetrics = jni->NewObject(displayMetricsClass 
             , displayMetricsConstructor); 
    JNI_ASSERT(jni, displayMetrics); 

    jmethodID getMetrics = jni->GetMethodID(displayClass 
             , "getMetrics" 
             , "(Landroid/util/DisplayMetrics;)V"); 
    JNI_ASSERT(jni, getMetrics); 

    jni->CallVoidMethod(display, getMetrics, displayMetrics); 
    JNI_ASSERT(jni, true); 

    { 
    jfieldID xdpi_id = jni->GetFieldID(displayMetricsClass, "xdpi", "F"); 
    JNI_ASSERT(jni, xdpi_id); 

    float xdpi = jni->GetFloatField(displayMetricsClass, xdpi_id); 
    JNI_ASSERT(jni, true); 

    log("XDPI: ", xdpi); // XDPI: 0 
    } 

    { 
    jfieldID height_id = jni->GetFieldID(displayMetricsClass 
             , "heightPixels", "I"); 
    JNI_ASSERT(jni, height_id); 

    int height = jni->GetIntField(displayMetricsClass, height_id); 
    JNI_ASSERT(jni, true); 

    log("Height: ", height); // Height: 0 
    } 
    // TODO: Delete objects here. 
    app->activity->vm->DetachCurrentThread(); 
} 

कोड आउटपुट:

Width: 320 
Height: 480 
XDPI: 0 
Height: 0 

यह ऐसा है displayMetrics है ऑब्जेक्ट को कॉल में सेट नहीं किया गया

jni->CallVoidMethod(display, getMetrics, displayMetrics); 

क्या यह मामला है कि जेएनआई मुझे रिटर्न वैल्यू के रूप में तर्क का उपयोग करने की अनुमति नहीं देगा? यदि हां, तो हम इसके आसपास कैसे जा सकते हैं यह देखते हुए कि हम मूल सक्रियता गोंद का उपयोग कर रहे हैं।

उत्तर

5

ईएच, मैं कुछ घंटों के लिए कोड पर देख रहा हूं और इसे नहीं देखा। फिर, डेस्क छोड़ वापस आया और वहाँ यह था:

के बजाय इन दो पंक्तियों

float xdpi = jni->GetFloatField(displayMetricsClass, xdpi_id); 
int height = jni->GetIntField(displayMetricsClass, height_id); 

मैं का इस्तेमाल किया है चाहिए:

float xdpi = jni->GetFloatField(displayMetrics, xdpi_id); 
int height = jni->GetIntField(displayMetrics, height_id); 

रवींद्र :)

(कम से कम यह किसी उदाहरण के रूप में कार्य कर सकता है अगर कोई डीपीआई कठिन तरीके से प्राप्त करना चाहता है :))

+0

ईयू! यह थोड़ी देर हो गया है क्योंकि मैंने कोई कट्टर जेएनआई किया है लेकिन मुझे इसी तरह की गलतियों को याद है। यह हमेशा कॉफी पकड़ने और आंखों के एक नए सेट के साथ वापस आने में मदद करता है! – Cliff

1

सबसे पहले, मैं ध्यान दें चाहिए कि मैं JNI :)

साथ बहुत अच्छा कहा नहीं कर रहा हूँ, मुझे लगता है समस्या हो सकता है कि displayMetrics चर

displayMetrics = jni->NewGlobalRef(displayMetrics); 
के साथ एक वैश्विक संदर्भ में किया जाना चाहिए

या ऐसा कुछ। DeleteGlobalRef के साथ इसे अपरिचित करना याद रखें। LocalRef भी काम कर सकता है ...

लेकिन अगर मुझे इस समस्या को हल करने के बारे में जाना है, तो मैं पूरी चीज़ को जावा समारोह में लपेटूंगा और बस इसे देशी से बुलाऊंगा और जावा पक्ष को अधिकांश फ़ंक्शन कॉलिंग करने दें - इसमें जावा-देशी बाड़ शामिल भी कम है।

+0

धन्यवाद, सुझाव के लिए +1, यह नहीं था एच, मेरी शर्म की बात है, मैंने पाया कि मेरे पास कोड में एक टाइपो है। एक जवाब लिखेंगे। –

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