/*
xbmc/android/Android_main.cpp
*/
extern void android_main(struct android_app* state)
{
{
app_dummy();
state->inputPollSource.process = process_input;
CEventLoop eventLoop(state);
CXBMCApp xbmcApp(state->activity);
if (xbmcApp.isValid())
{
IInputHandler inputHandler;
eventLoop.run(xbmcApp, inputHandler);
}
...
}
exit(0);
}
static void process_input(struct android_app* app, struct android_poll_source* source) {
AInputEvent* event = NULL;
int processed = 0;
while (AInputQueue_getEvent(app->inputQueue, &event) >= 0) {
if (AInputQueue_preDispatchEvent(app->inputQueue, event)) {
continue;
}
int32_t handled = 0;
if (app->onInputEvent != NULL) handled = app->onInputEvent(app, event);
AInputQueue_finishEvent(app->inputQueue, event, handled);
processed = 1;
}
...
}
//xbmc/android/activity/EventLoop.cpp
int32_t CEventLoop::inputCallback(android_app* application, AInputEvent* event)
{
if (application == NULL || application->userData == NULL || event == NULL)
return 0;
CEventLoop& eventLoop = *((CEventLoop*)application->userData);
return eventLoop.processInput(event);
}
int32_t CEventLoop::processInput(AInputEvent* event)
{
int32_t type = AInputEvent_getType(event);
int32_t source = AInputEvent_getSource(event);
switch(type)
{
case AINPUT_EVENT_TYPE_KEY:
if (source & AINPUT_SOURCE_GAMEPAD || source & AINPUT_SOURCE_JOYSTICK)
{
if (m_inputHandler->onJoyStickKeyEvent(event))
return true;
}
rtn = m_inputHandler->onKeyboardEvent(event);
break;
case...
}
return rtn;
}
//xbmc/android/activity/AndroidKey.cpp
typedef struct {
int32_t nativeKey;
int16_t xbmcKey;
} KeyMap;
static KeyMap keyMap[] = {
{ AKEYCODE_VOLUME_UP , XBMCK_PLUS },
};
bool CAndroidKey::onKeyboardEvent(AInputEvent *event)
{
int32_t flags = AKeyEvent_getFlags(event);
int32_t state = AKeyEvent_getMetaState(event);
int32_t action = AKeyEvent_getAction(event);
int32_t repeat = AKeyEvent_getRepeatCount(event);
int32_t keycode = AKeyEvent_getKeyCode(event);
int32_t deviceId = AInputEvent_getDeviceId(event);
CJNIKeyCharacterMap map = CJNIKeyCharacterMap::load(deviceId);
uint16_t unicode = map.get(keycode, state);
// Check if we got some special key
uint16_t sym = XBMCK_UNKNOWN;
for (unsigned int index = 0; index < sizeof(keyMap) / sizeof(KeyMap); index++)
{
if (keycode == keyMap[index].nativeKey)
{
sym = keyMap[index].xbmcKey;
break;
}
}
switch (action)
{
case AKEY_EVENT_ACTION_DOWN:
CXBMCApp::android_printf("CAndroidKey: key down (code: %d; repeat: %d; flags: 0x%0X; alt: %s; shift: %s; sym: %s)",
keycode, repeat, flags,
(state & AMETA_ALT_ON) ? "yes" : "no",
(state & AMETA_SHIFT_ON) ? "yes" : "no",
(state & AMETA_SYM_ON) ? "yes" : "no");
XBMC_Key((uint8_t)keycode, sym, modifiers, unicode, false);
return true;
...
}
}
我们得弄明白keyMap[index].nativeKey的值在哪儿定义的这句话
/*
tools/depends/target/android-sources-ics/android-source/frameworks/base/native/include/android/keycodes.h
*/
enum {
AKEYCODE_VOLUME_UP = 24,
...
}
接下来就是把android键盘打包为xbmc内部的XBMC_Event,扔到消息队列中
void CAndroidKey::XBMC_Key(uint8_t code, uint16_t key, uint16_t modifiers, uint16_t unicode, bool up)
{
XBMC_Event newEvent;
memset(&newEvent, 0, sizeof(newEvent));
unsigned char type = up ? XBMC_KEYUP : XBMC_KEYDOWN;
newEvent.type = type;
newEvent.key.type = type;
newEvent.key.keysym.scancode = code;
newEvent.key.keysym.sym = (XBMCKey)key;
newEvent.key.keysym.unicode = unicode;
newEvent.key.keysym.mod = (XBMCMod)modifiers;
//CXBMCApp::android_printf("XBMC_Key(%u, %u, 0x%04X, %d)", code, key, modifiers, up);
CWinEvents::MessagePush(&newEvent);
}