2015-04-24 3 views
16

दबाया जाता है मैं सिर्फ हाल में जारी v22.1.0 AppCompat उपयोग करने के लिए मेरे एप्लिकेशन अपग्रेड कर दिया है और अब onKeyDown और onKeyUp ट्रिगर नहीं होते मेनू कुंजी है जब दब गया। अन्य चाबियाँ onKeyDown और onKeyUp सही ढंग से ट्रिगर करती हैं, लेकिन जब मैं मेनू कुंजी दबाता हूं तो कुछ भी नहीं होता है। अगर मैं v22.0.0 पर डाउनग्रेड करता हूं तो सब कुछ ठीक से काम करने के लिए लौटता है।AppCompat v22.1.0 में अपग्रेड किया गया है और अब OnKeyDown और onkeyup ट्रिगर नहीं कर रहे हैं जब मेनू कुंजी

मैं इसे कैसे ठीक करूं?

+1

अपने खुद के प्रश्न का उत्तर दें? एक ही पल में? – Niels

+2

हां, मैंने स्टैक ओवरफ़्लो –

+0

के सहायता केंद्र में इस [आलेख] (http://stackoverflow.com/help/self-answer) की सलाह का पालन किया है। ऐसा लगता है कि केडडाउन और ऑनकेप ईवेंट अब AppCompat पर मेनू कुंजी के लिए सही ढंग से ट्रिगर किए गए हैं v22.2.0। – NullNoname

उत्तर

31

अपडेट 23 अगस्त

यह appcompat-v7 समर्थन पुस्तकालय की v23.0.0 में फिर से has been fixed। इस फिक्स्ड को देखने के लिए अंतिम संस्करण में अपडेट करें।


अपडेट 19 जुलाई

दुर्भाग्य AppCompat v22.2.1 onKeyDown और onKeyUp घटनाओं again तोड़ दिया। मैं सिर्फ AppCompatActivityMenuKeyInterceptor अद्यतन v22.1.x और भी v22.2.1


अपडेट 29 मई

appcompat-v7 समर्थन पुस्तकालय की v22.2.0 में यह has been fixed समर्थन करने के लिए। इस फिक्स्ड को देखने के लिए अंतिम संस्करण में अपडेट करें।


दुर्भाग्य AppCompat v22.1.0 onKeyDown और onKeyUp घटनाओं को बीच में रोक और उन्हें प्रचार नहीं करता है जब मेनू कुंजी दबाया जाता है। एकमात्र संभावित समाधान में AppCompat करता है इससे पहले onKeyDown और onKeyUp ईवेंट को रोकने के लिए प्रतिबिंब का उपयोग करना शामिल है। आप ProGuard का उपयोग करें या DexGuard आपके विन्यास के लिए इन नियमों जोड़ देते हैं तो

public class MainActivity extends AppCompatActivity { 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     //Initialize the interceptor 
     AppCompatActivityMenuKeyInterceptor.intercept(this); 
    } 

    @Override 
    public boolean onKeyDown(int keyCode, KeyEvent event) { 
     // Now onKeyDown is called also for KEYCODE_MENU 
     if (keyCode == KeyEvent.KEYCODE_MENU) { 
      //do your stuff 

      //return false if you want to propagate the 
      //KeyEvent to AppCompat, return true otherwise 
      return false; 
     } 

     return super.onKeyDown(keyCode, event); 
    } 

    @Override 
    public boolean onKeyUp(int keyCode, KeyEvent event) { 
     // Now onKeyUp is called also for KEYCODE_MENU 
     if (keyCode == KeyEvent.KEYCODE_MENU) { 
      //do your stuff 

      //return false if you want to propagate the 
      //KeyEvent to AppCompat, return true otherwise 
      return false; 
     } 

     return super.onKeyUp(keyCode, event); 
    } 
} 

:

अपनी गतिविधि का onCreate में

public class AppCompatActivityMenuKeyInterceptor { 

    private static final String FIELD_NAME_DELEGATE = "mDelegate"; 
    private static final String FIELD_NAME_WINDOW = "mWindow"; 

    public static void intercept(AppCompatActivity appCompatActivity) { 
     new AppCompatActivityMenuKeyInterceptor(appCompatActivity); 
    } 

    private AppCompatActivityMenuKeyInterceptor(AppCompatActivity activity) { 
     try { 
      Field mDelegateField = AppCompatActivity.class.getDeclaredField(FIELD_NAME_DELEGATE); 
      mDelegateField.setAccessible(true); 
      Object mDelegate = mDelegateField.get(activity); 

      Class mDelegateClass = mDelegate.getClass().getSuperclass(); 
      Field mWindowField = null; 

      while (mDelegateClass != null) { 
       try { 
        mWindowField = mDelegateClass.getDeclaredField(FIELD_NAME_WINDOW); 
        break; 
       } catch (NoSuchFieldException ignored) { 
       } 

       mDelegateClass = mDelegateClass.getSuperclass(); 
      } 

      if (mWindowField == null) 
       throw new NoSuchFieldException(FIELD_NAME_WINDOW); 

      mWindowField.setAccessible(true); 
      Window mWindow = (Window) mWindowField.get(mDelegate); 

      Window.Callback mOriginalWindowCallback = mWindow.getCallback(); 
      mWindow.setCallback(new AppCompatWindowCallbackCustom(mOriginalWindowCallback, activity)); 
     } catch (NoSuchFieldException e) { 
      e.printStackTrace(); 
     } catch (IllegalAccessException e) { 
      e.printStackTrace(); 
     } 
    } 

    private class AppCompatWindowCallbackCustom extends WindowCallbackWrapper { 

     private WeakReference<AppCompatActivity> mActivityWeak; 

     public AppCompatWindowCallbackCustom(Window.Callback wrapped, AppCompatActivity appCompatActivity) { 
      super(wrapped); 

      mActivityWeak = new WeakReference<AppCompatActivity>(appCompatActivity); 
     } 

     @Override 
     public boolean dispatchKeyEvent(KeyEvent event) { 
      final int keyCode = event.getKeyCode(); 

      AppCompatActivity appCompatActivity = mActivityWeak.get(); 

      if (appCompatActivity != null && keyCode == KeyEvent.KEYCODE_MENU) { 
       if (appCompatActivity.dispatchKeyEvent(event)) 
        return true; 
      } 

      return super.dispatchKeyEvent(event); 
     } 
    } 
} 

कॉल AppCompatActivityMenuKeyInterceptor.intercept(this):

इस वर्ग अपनी परियोजना में जोड़े

-keepclassmembers class android.support.v7.app.AppCompatActivity { 
    private android.support.v7.app.AppCompatDelegate mDelegate; 
} 

-keepclassmembers class android.support.v7.app.AppCompatDelegateImplBase { 
    final android.view.Window mWindow; 
} 

अब आपकी गतिविधिप्राप्त कर सकती है मेनू कुंजी के लिएऔर onKeyUp ईवेंट भी।

+0

मैं अपने कोड को obfuscating के बाद इस के साथ एक समस्या में भाग गया। समर्थन पुस्तकालय को रखने में मदद की लग रही थी। अगर यह गलत लगता है, तो कृपया इस पर टिप्पणी करें, लेकिन मैंने अपने प्रोग्रार्ड- रुल्स.pro '-keep class android.support.v7 में जोड़ा। ** {*; } - इंटरफ़ेस android.support.v7- ** {*; } ' –

+1

@DaiwikDarun हाँ आपके नियम सही हैं, लेकिन आप सभी समर्थन पुस्तकालयों को रखते हैं। यदि आप एक विशिष्ट नियम चाहते हैं तो आप अद्यतन उत्तर देख सकते हैं। यह इंगित करने के लिए धन्यवाद कि –

+1

धन्यवाद, आपने अपना दिन – Dima

0

onKeyUp() या onKeyDown() के बजाय, कोई भी dispatchKeyEvent() का उपयोग कर सकता है। android-developers.blogspot.com से निम्नलिखित कोड देखें।

@Override 
public boolean dispatchKeyEvent(KeyEvent event) { 
    if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) { 
     if (event.getAction() == KeyEvent.ACTION_DOWN 
       && event.getRepeatCount() == 0) { 

      // Tell the framework to start tracking this event. 
      getKeyDispatcherState().startTracking(event, this); 
      return true; 

     } else if (event.getAction() == KeyEvent.ACTION_UP) { 
      getKeyDispatcherState().handleUpEvent(event); 
      if (event.isTracking() && !event.isCanceled()) { 
       // DO BACK ACTION HERE 
       return true; 
      } 
     } 
     return super.dispatchKeyEvent(event); 
    } else { 
     return super.dispatchKeyEvent(event); 
    } 
} 
+0

दुर्भाग्य से आपका समाधान काम नहीं करता है। V7 समर्थन लाइब्रेरी v22.1.0, v22.1.1 और v22.2.1 का उपयोग करते समय मेनू कुंजी दबाए जाने पर 'प्रेषणकेइवेन्ट' प्रचारित नहीं किया जाता है। यह एक ज्ञात बग है और यह v7 समर्थन पुस्तकालय के नवीनतम संस्करणों में तय किया गया था। –

+0

इसका मतलब है कि हार्डवेयर मेनू कुंजी प्रेस 22.0.1 –

+0

पर भी काम नहीं करता है जैसा कि आप शीर्षक में देख सकते हैं यह प्रश्न विशेष रूप से v22.1.0 और उच्चतर (v22.1.0, v22.1.1 और v22.2.1) के लिए है। –

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

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