Menubutton больше не работает после обновления до кордовы 5 + cordova android 4.0.0

Недавно я обновился до кордовы 5 и удалил / воссоздал платформу Android в версии 4.0.0 и удалил / переустановил все плагины.

Мне также пришлось обновить android sdk до sdk 22 вместо 21.

Начиная с обновления, я больше не могу поймать событие menubutton, как описано в документации по cordova .

Поскольку он по-прежнему упоминается в пограничных документах, я предполагаю, что он все равно должен работать, и я ничего не видел об этом в примечаниях к выпуску.

Кнопка «Назад» все еще работает.

Я попытался установить target-sdk на 19, он ничего не решил о проблеме.

Редактировать: я выкопал исходный код кордовы и нашел в CordovaWebViewImpl.java. Я нашел подозрительный комментарий TODO:

public void setButtonPlumbedToJs(int keyCode, boolean override) { switch (keyCode) { case KeyEvent.KEYCODE_VOLUME_DOWN: case KeyEvent.KEYCODE_VOLUME_UP: case KeyEvent.KEYCODE_BACK: // TODO: Why are search and menu buttons handled separately? if (override) { boundKeyCodes.add(keyCode); } else { boundKeyCodes.remove(keyCode); } return; default: throw new IllegalArgumentException("Unsupported keycode: " + keyCode); } } 

Ну, мой ответ будет «НЕ ДОЛЖЕН !!!!»

Кордова делает список ключей для обработки, но не добавляет кнопку меню, а затем код ключа сравнивается с KeyEvent.KEYCODE_MENU только после того, как код ключа был пропущен, потому что его нет в списке.

Я попытался добавить кейс для кнопки меню, но, оказывается, функция вызывается только с кодом кнопки «Назад».

Итак, теперь я знаю, почему это не работает, но все же не так, как это исправить.

Редактировать 02/2016: В соответствии с последней версией Jira поддержка меню теперь фиксируется в java-части в Cordova Android 5.1.0, но все еще не инициализируется из javascript. На данный момент, как указал пользователь Jira Кит Вонг, вам нужно добавить вызов javascript, прежде чем добавлять слушателя событий:

 document.addEventListener("deviceready", function() { ... navigator.app.overrideButton("menubutton", true); // <-- Add this line document.addEventListener("menubutton", yourCallbackFunction, false); ... }, false); 

Solutions Collecting From Web of "Menubutton больше не работает после обновления до кордовы 5 + cordova android 4.0.0"

Ответ на ясность не сделал этого для меня, кнопка меню все еще не отвечала.

Я попробовал несколько патчей, еще одно предложение отключить проверку boundKeyCodes тоже не сделало этого, потому что тогда поведение подпирания было бы скомпрометировано.

Чистый способ вернуть прежнее поведение должен быть следующим. Проверка boundKeyCodes гарантирует, что пользовательское поведение выполняется только тогда, когда на самом деле есть специальный обработчик событий, связанный с событием. Но привязка обработчика событий к «menubutton» в JS-коде приложения больше не запускает код ключа меню, который должен быть добавлен в список boundKeyCodes. Это связано с тем, что метод setButtonPlumbedToJs никогда не выполняется для обработчика «menubutton» в первую очередь И даже если бы это было так, оператор switch в этом методе не обрабатывает KEYCODE_MENU.

Вы можете получить это поведение довольно легко, сначала вам придется применить изменения, предложенные ясными:

  1. Ручка KEYCODE_MENU

В CordovaLib / src / org / apache / cordova / CoreAndroid.java (около строки 357, setButtonPlumbedToJs) добавить запись case после записи KEYCODE_BACK следующим образом:

 public void setButtonPlumbedToJs(int keyCode, boolean override) { switch (keyCode) { case KeyEvent.KEYCODE_VOLUME_DOWN: case KeyEvent.KEYCODE_VOLUME_UP: case KeyEvent.KEYCODE_BACK: case KeyEvent.KEYCODE_MENU: // TODO: Why are search and menu buttons handled separately? if (override) { boundKeyCodes.add(keyCode); } else { boundKeyCodes.remove(keyCode); } return; default: throw new IllegalArgumentException("Unsupported keycode: " + keyCode); } } 

Затем убедитесь, что setButtonPlumbedToJs фактически выполняется. Для этого вам нужны еще два изменения.

  1. Добавить обработчик фреймов

В CordovaLib / src / org / apache / cordova / CoreAndroid.java (около строки 243, overrideButton) метод выглядит так (добавьте предложение else else if):

 public void overrideButton(String button, boolean override) { if (button.equals("volumeup")) { webView.setButtonPlumbedToJs(KeyEvent.KEYCODE_VOLUME_UP, override); } else if (button.equals("volumedown")) { webView.setButtonPlumbedToJs(KeyEvent.KEYCODE_VOLUME_DOWN, override); } else if (button.equals("menubutton")) { webView.setButtonPlumbedToJs(KeyEvent.KEYCODE_MENU, override); } } 
  1. Добавить вызов обработчика javascript

В platform_www / cordova.js (вокруг строки 1532, bootstrap) измените эту строку:

 cordova.addDocumentEventHandler('menubutton'); 

к этому:

 var menuButtonChannel = cordova.addDocumentEventHandler('menubutton'); menuButtonChannel.onHasSubscribersChange = function() { exec(null, null, APP_PLUGIN_NAME, "overrideButton", ['menubutton', this.numHandlers == 1]); }; 

Это вызовет метод overrideButton для каркаса, как только обработчик события будет добавлен в «menubutton».

Это должно сделать это. Я также добавил это решение в качестве комментария к https://issues.apache.org/jira/browse/CB-8921 и может вскоре подать запрос на перенос.

Просто добавьте в функцию setButtonPlumbedToJs одну строку: case KeyEvent.KEYCODE_MENU:

 public void setButtonPlumbedToJs(int keyCode, boolean override) { switch (keyCode) { case KeyEvent.KEYCODE_VOLUME_DOWN: case KeyEvent.KEYCODE_VOLUME_UP: case KeyEvent.KEYCODE_BACK: case KeyEvent.KEYCODE_MENU: 

Таким образом, в onDispatchKeyEvent переключатель будет работать:

  } else if (boundKeyCodes.contains(keyCode)) { String eventName = null; switch (keyCode) { case KeyEvent.KEYCODE_VOLUME_DOWN: eventName = "volumedownbutton"; break; case KeyEvent.KEYCODE_VOLUME_UP: eventName = "volumeupbutton"; break; case KeyEvent.KEYCODE_SEARCH: eventName = "searchbutton"; break; case KeyEvent.KEYCODE_MENU: eventName = "menubutton"; break; case KeyEvent.KEYCODE_BACK: eventName = "backbutton"; break; } 

Теперь с cordova-android 5.1, код изменился, и мой патч больше не работал (и, к сожалению, без патча кнопка меню все еще не работает в этой версии).

Поскольку я хотел иметь возможность обновлять платформу, не пересматривая код каждый раз, я искал новый способ вернуть кнопку меню снова.

В cordova android 5.1 выясняется, что все здесь находится в java-коде для работы кнопки, за исключением того, что клавиша кнопки меню никогда не добавляется в массив boundKeyCoded .

Оказывается, этот массив должен быть заполнен вызовом из javascript (который делается для кнопки «Назад» и «Громкость», но ни для кнопки поиска, ни для кнопки меню).

Недопустимый код:

 exec(null, null, APP_PLUGIN_NAME, 'overrideButton', ['menubutton' , true]); 

(Вызов js для функции java overrideButton из CoreAndroid.java, чтобы сказать, чтобы добавить кнопку кнопки меню в массив boundKeyCodes .

Я думаю, что этот вызов должен быть добавлен в platform.js , но так как platform.js используется для сборки cordova.js во время добавления платформы, я решил сделать hook_ after_platform_add, который исправляет файл cordova.js .

Преимущество этого крючка в том, что нет изменений в java, и он должен работать, даже если вы используете другой веб-просмотр, например, пешеходный переход.

Итак, во-первых, в config.xml , в разделе Android добавить hook:

 <platform name="android"> .... .... <hook type="after_platform_add" src="scripts/android/patch_menubutton.js" /> .... .... </platform> 

Затем в папке с скриптами добавьте файл hook patch_menubutton.js :

 #!/usr/bin/env node module.exports = function(ctx) { var fs = ctx.requireCordovaModule('fs'), path = ctx.requireCordovaModule('path'); var CordovaJSPath = path.join(ctx.opts.projectRoot, 'platforms/android/platform_www/cordova.js'); var data = fs.readFileSync(CordovaJSPath, 'utf8'); var result = data.replace(new RegExp("cordova\\.addDocumentEventHandler\\('menubutton'\\);", "g"), "cordova.addDocumentEventHandler('menubutton'); exec(null, null, APP_PLUGIN_NAME, 'overrideButton', ['menubutton' , true]);"); fs.writeFileSync(CordovaJSPath, result, 'utf8'); } 

(Он ищет инициализацию обработчика события для кнопки меню и добавляет вызов функции overrideButton , как описано в последней части ответа FewKinG)