2013-04-09 8 views
5

हम एंड्रॉइड के लिए इंडी गेम विकसित कर रहे हैं और उपयोगकर्ता को अपना उपनाम चुनना चाहते हैं। हमने एनडीके द्वारा प्रदान की गई मूल गतिविधि का उपयोग करना चुना है क्योंकि यह जाने का सबसे आसान तरीका प्रतीत होता है।देशी गतिविधि का उपयोग करते समय मुलायम कीबोर्ड बंद करते समय क्रैश

पहली समस्या हम कीबोर्ड के साथ सामना किया है था कि समारोह ANativeActivity_showSoftInput() सब पर कुछ भी नहीं करना (के रूप में वर्णित जैसे here) लगता है, इसलिए हम JNI कार्य करने के लिए कहता है का उपयोग कर कीबोर्ड को सामने लाने:

static void showKeyboard(Activity activity) { 
    String s = Context.INPUT_METHOD_SERVICE; 
    InputMethodManager m = (InputMethodManager)activity.getSystemService(s); 
    View w = activity.getWindow().getDecorView(); 
    m.showSoftInput(w, 0); 
} 

यह कुंजीपटल लाने के लिए ठीक काम करता है, और कुछ उपकरणों पर एक साथ ठीक काम करता है। लेकिन अन्य उपकरणों (जैसे नेक्सस 7), जब उपयोगकर्ता "कीबोर्ड छिपाएं" को हिट करके कीबोर्ड को बंद करने की कोशिश करता पर बटन आवेदन इस डिबग आउटपुट के साथ जमा:

I/InputDispatcher( 453): Application is not responding: AppWindowToken{429b54a8 token=Token{42661288 ActivityRecord{41bb0b00 u0 com.example.project/android.app.NativeActivity}}} - Window{420d6138 u0 com.example.project/android.app.NativeActivity}. It has been 5006.7ms since event, 5005.6ms since wait started. Reason: Waiting because the focused window has not finished processing the input events that were previously delivered to it. 
I/WindowManager( 453): Input event dispatching timed out sending to com.example.project/android.app.NativeActivity 

और फिर उपयोगकर्ता एक संवाद के साथ प्रस्तुत किया है बॉक्स कह रहा है:

Project isn't responding. Do you want to close it? [Wait]/[OK] 

क्या कुछ ऐसा है जो हम स्पष्ट रूप से गलत कर रहे हैं? या यह एक बग हो सकता है? this one जैसे मुद्दे इंगित करते हैं कि मूलभूत गोंद में कीबोर्ड कार्यक्षमता को ठीक से लागू नहीं किया गया है।

एक तरफ ध्यान दें, हमने अभी तक कई उपकरणों पर परीक्षण किया है, लेकिन जहां यह क्रैश नहीं होता है वे पुराने एंड्रॉइड ओएस वाले हैं। साथ ही, जब यह कीबोर्ड दिखाई देता है, तो यह वापस बटन को बदलता है जो इस backward arrow shaped button जैसा दिखता है जो इस V shaped button जैसा दिखता है। शायद यह एक अलग इनपुट घटना से मेल खाती है जिसे तब पहली बार देशी गोंद विकसित करने के लिए जिम्मेदार नहीं माना गया था? मैं बस अनुमान लगा रहा हूँ।

वैसे भी, अगर कोई व्यक्ति मूल गतिविधि का उपयोग करते समय सॉफ्ट कीबोर्ड काम कर रहा है, तो कृपया हमें बताएं कि आपने यह कैसे किया है।

चीयर्स

अद्यतन

यह Android here में एक बग के रूप में सूचित किया गया है, हम अभी भी हालांकि समाधानों के बारे में सुनने के लिए खुशी होगी। यदि आप इससे भी प्रभावित होते हैं, तो आप उस मुद्दे पर वोट डालना चाहेंगे (स्टार दबाकर)।

उत्तर

3

पीटर का समाधान अच्छी तरह से काम करता है। हालांकि अगर आप original_app_glue फ़ाइल को संशोधित नहीं करना चाहते हैं: ध्यान दें कि process_input को फ़ंक्शन पॉइंटर के रूप में असाइन किया गया है।

static void process_input(struct android_app* app, struct android_poll_source* source) { 
    AInputEvent* event = NULL; 
    if (AInputQueue_getEvent(app->inputQueue, &event) >= 0) { 
     int type = AInputEvent_getType(event); 
     LOGV("New input event: type=%d\n", AInputEvent_getType(event)); 

     bool skip_predispatch 
       = AInputEvent_getType(event) == AINPUT_EVENT_TYPE_KEY 
       && AKeyEvent_getKeyCode(event) == AKEYCODE_BACK; 

     // skip predispatch (all it does is send to the IME) 
     if (!skip_predispatch && AInputQueue_preDispatchEvent(app->inputQueue, event)) { 
      return; 
     } 

     int32_t handled = 0; 
     if (app->onInputEvent != NULL) handled = app->onInputEvent(app, event); 
     AInputQueue_finishEvent(app->inputQueue, event, handled); 
    } else { 
     LOGE("Failure reading next input event: %s\n", strerror(errno)); 
    } 
} 

अपने android_main समारोह की शुरुआत में, process_inputको android_app-> inputPollSource.process के अपने संस्करण में निर्दिष्ट करें: अपने कार्यान्वयन फ़ाइल में, अपने स्वयं के process_input कार्यों के रूप में पीटर द्वारा वर्णित पैदा करते हैं।

अपने ईवेंट हैंडलर में सुनिश्चित करें कि आप बैक कुंजी (AKEYCODE_BACK) की जांच करें और दृश्यमान होने पर अपने कीबोर्ड को छुपाने के लिए इसे रोक दें।

ध्यान दें कि यह समस्या एंड्रॉइड 4.1 और 4.2 में मौजूद है - 4.3

+0

मैंने पूरी तरह से याद किया, सी-फाइल को पैच करने से काफी बेहतर, धन्यवाद। –

+0

मौके से, मुझे आज अपने नेक्सस के लिए अपग्रेड मिला और ऐसा लगता है कि समस्या एंड्रॉइड 4.3 में तय की गई है। आपका सुझाव केवल पैच किए गए process_input फ़ंक्शन को लागू करना आसान बनाता है जब एंड्रॉइड संस्करण 4.2 है। यदि आप चाहें, तो आप दूसरों के लिए एक अंतिम समाधान प्रदान करने के लिए अपने और मेरे उत्तरों को जोड़ सकते हैं। इसके बाद मैं इसे अंतिम जवाब के रूप में चिह्नित करूंगा। अन्यथा, अगर मुझे याद होगा, तो मैं इसे अगले सप्ताह कुछ समय करने की कोशिश करूंगा। चीयर्स। –

+0

निश्चित - अद्यतन। मैंने यह भी देखा कि समस्या 4.3 में तय की गई है! बहुत बुरा यह 4.1 और 4.2 फोन पर थोड़ी देर के लिए बाजार में बने रहेगा ... – krsteeve

2

ठीक है, जैसा कि मेरे मूल प्रश्न के अद्यतन में उल्लिखित है, यह एंड्रॉइड ओएस के अंदर कहीं भी एक बग है। हमें एक कामकाज मिला है, यह वास्तव में बदसूरत है लेकिन यह काम करता है ताकि किसी को यह उपयोगी लगे।

सबसे पहले आप इस तरह देखने के लिए समारोह process_input बदलकर फ़ाइल

<NDK>/sources/android/native_app_glue/android_native_app_glue.c 

को संशोधित करने की आवश्यकता होगी:

// When user closes the software keyboard, this function is normally not 
// called at all. On the buggy devices, it is called as if AKEYCODE_BACK 
// was pressed. This event then gets consumed by the 
// AInputQueue_preDispatchEvent. There should be some mechanism that then 
// calls the process_input again to finish processing the input. 
// But it never does and AInputQueue_finishEvent is never called, the OS 
// notices this and closes our app. 
static void process_input(struct android_app* app 
         , struct android_poll_source* source) { 
    AInputEvent* event = NULL; 
    if (AInputQueue_getEvent(app->inputQueue, &event) >= 0) { 
     int type = AInputEvent_getType(event); 
     LOGV("New input event: type=%d\n", AInputEvent_getType(event)); 

     int skip_predispatch 
       = AInputEvent_getType(event) == AINPUT_EVENT_TYPE_KEY 
       && AKeyEvent_getKeyCode(event) == AKEYCODE_BACK; 

     // TODO: Not sure if we should skip the predispatch all together 
     //  or run it but not return afterwards. The main thing 
     //  is that the code below this 'if' block will be called. 
     if (!skip_predispatch) { 
      if (AInputQueue_preDispatchEvent(app->inputQueue, event)) { 
       return; 
      } 
     } 

     int32_t handled = 0; 
     if (app->onInputEvent != NULL) handled = app->onInputEvent(app, event); 
     AInputQueue_finishEvent(app->inputQueue, event, handled); 
    } else { 
     LOGE("Failure reading next input event: %s\n", strerror(errno)); 
    } 
} 

तो फिर तुम एक कोड है कि कुछ इस तरह दिखता होना चाहिए अपने स्वयं के इनपुट इवेंट हैंडलर के अंदर:

static int32_t handle_input(android_app* app, AInputEvent* event) { 
    int32_t handled = 0; 

    struct engine* engine = (struct engine*) app->userData; 
    switch (AInputEvent_getType(event)) { 
    case AINPUT_EVENT_TYPE_KEY: 
     switch (AKeyEvent_getAction(event)) { 
     case AKEY_EVENT_ACTION_DOWN: 
      int key = AKeyEvent_getKeyCode(event); 
      if (os_version_major == 4 && os_version_minor == 2) { 
      if (m_keyboard_is_visible && key == AKEYCODE_BACK) { 
       // You should set this to true when showing the keyboard. 
       m_keyboard_is_visible = false; 
       hide_keyboard(); 
       handled = 1; 
       break; 
      } 
      } 
      ... // your own "key down" event handling code. 
      break; 
     } 
     break; 
    ... 
    } 
    return handled; 
} 

ओएस संस्करण संख्या प्राप्त करने के लिए हम android.os.Build.VERSION.RELEASEandroid.os.Build.VERSION.SDK_INT से प्राप्त करने के लिए एक और जेएनआई कॉल का उपयोग करते हैं।शो_कीबोर्ड और hide_keyboardthis पोस्ट में रत्मोविक्स उत्तर से जानकारी का उपयोग करने के लिए।

नोट android_native_app_glue.c स्वचालित रूप से संकलित करवाने के लिए और NDK पेड़ से सीधे परिवर्तन कर से बचने के लिए, आप अपने प्रोजेक्ट की JNI/निर्देशिका पर फ़ाइल की प्रतिलिपि और अपने Android से इन दो पंक्तियों खाई करने के लिए चाहते हो सकता है। एमके

LOCAL_STATIC_LIBRARIES := android_native_app_glue 
$(call import-module,android/native_app_glue) 
+0

में हल किया गया है मेरे पास एंड्रॉइड 4.2 के साथ नेक्सस 4 पर यह समस्या है। इस मुद्दे को दस्तावेज करने के लिए धन्यवाद [ए एलओटी]! – Gaetan

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