问:
Need table of key codes for android and presenter
Can someone point me to the list of key codes that come from getKeyCode() in numeric form so that for example if I look up 72 I see "]" and if I look up 24 I see "vol up".

I have been looking for an hour and the answer is not an ASCII table.  That would be too easy...

I am getting key codes off my mouse-presenter and trying to intercept them.  There is one key that puts out 57 and 117 that I cannot intercept and I wanted to decode it before asking a question about it but can't find the reference.  I think 117 is shift but I don't know what 57 is.  That key on the presenter takes me out of my app even if I intercept it.

答:
#Complete list of key codes

Some of the other lists here are incomplete. The complete list can be found in the KeyEvent source code or documentation. The source code is ordered by integer value so I will use that here.

(Repetitive text removed to save space, all key codes are public static final int.)

```/** Unknown key code. */
KEYCODE_UNKNOWN = 0;
/** Soft Left key.
 * Usually situated below the display on phones and used as a multi-function
 * feature key for selecting a software defined function shown on the bottom left
 * of the display. */
KEYCODE_SOFT_LEFT = 1;
/** Soft Right key.
 * Usually situated below the display on phones and used as a multi-function
 * feature key for selecting a software defined function shown on the bottom right
 * of the display. */
KEYCODE_SOFT_RIGHT = 2;
/** Home key.
 * This key is handled by the framework and is never delivered to applications. */
KEYCODE_HOME = 3;
/** Back key. */
KEYCODE_BACK = 4;
/** Call key. */
KEYCODE_CALL = 5;
/** End Call key. */
KEYCODE_ENDCALL = 6;
/** '0' key. */
KEYCODE_0 = 7;
/** '1' key. */
KEYCODE_1 = 8;
/** '2' key. */
KEYCODE_2 = 9;
/** '3' key. */
KEYCODE_3 = 10;
/** '4' key. */
KEYCODE_4 = 11;
/** '5' key. */
KEYCODE_5 = 12;
/** '6' key. */
KEYCODE_6 = 13;
/** '7' key. */
KEYCODE_7 = 14;
/** '8' key. */
KEYCODE_8 = 15;
/** '9' key. */
KEYCODE_9 = 16;
/** '*' key. */
KEYCODE_STAR = 17;
/** '#' key. */
KEYCODE_POUND = 18;
/** Directional Pad Up key.
 * May also be synthesized from trackball motions. */
KEYCODE_DPAD_UP = 19;
/** Directional Pad Down key.
 * May also be synthesized from trackball motions. */
KEYCODE_DPAD_DOWN = 20;
/** Directional Pad Left key.
 * May also be synthesized from trackball motions. */
KEYCODE_DPAD_LEFT = 21;
/** Directional Pad Right key.
 * May also be synthesized from trackball motions. */
KEYCODE_DPAD_RIGHT = 22;
/** Directional Pad Center key.
 * May also be synthesized from trackball motions. */
KEYCODE_DPAD_CENTER = 23;
/** Volume Up key.
 * Adjusts the speaker volume up. */
KEYCODE_VOLUME_UP = 24;
/** Volume Down key.
 * Adjusts the speaker volume down. */
KEYCODE_VOLUME_DOWN = 25;
/** Power key. */
KEYCODE_POWER = 26;
/** Camera key.
 * Used to launch a camera application or take pictures. */
KEYCODE_CAMERA = 27;
/** Clear key. */
KEYCODE_CLEAR = 28;
/** 'A' key. */
KEYCODE_A = 29;
/** 'B' key. */
KEYCODE_B = 30;
/** 'C' key. */
KEYCODE_C = 31;
/** 'D' key. */
KEYCODE_D = 32;
/** 'E' key. */
KEYCODE_E = 33;
/** 'F' key. */
KEYCODE_F = 34;
/** 'G' key. */
KEYCODE_G = 35;
/** 'H' key. */
KEYCODE_H = 36;
/** 'I' key. */
KEYCODE_I = 37;
/** 'J' key. */
KEYCODE_J = 38;
/** 'K' key. */
KEYCODE_K = 39;
/** 'L' key. */
KEYCODE_L = 40;
/** 'M' key. */
KEYCODE_M = 41;
/** 'N' key. */
KEYCODE_N = 42;
/** 'O' key. */
KEYCODE_O = 43;
/** 'P' key. */
KEYCODE_P = 44;
/** 'Q' key. */
KEYCODE_Q = 45;
/** 'R' key. */
KEYCODE_R = 46;
/** 'S' key. */
KEYCODE_S = 47;
/** 'T' key. */
KEYCODE_T = 48;
/** 'U' key. */
KEYCODE_U = 49;
/** 'V' key. */
KEYCODE_V = 50;
/** 'W' key. */
KEYCODE_W = 51;
/** 'X' key. */
KEYCODE_X = 52;
/** 'Y' key. */
KEYCODE_Y = 53;
/** 'Z' key. */
KEYCODE_Z = 54;
/** ',' key. */
KEYCODE_COMMA = 55;
/** '.' key. */
KEYCODE_PERIOD = 56;
/** Left Alt modifier key. */
KEYCODE_ALT_LEFT = 57;
/** Right Alt modifier key. */
KEYCODE_ALT_RIGHT = 58;
/** Left Shift modifier key. */
KEYCODE_SHIFT_LEFT = 59;
/** Right Shift modifier key. */
KEYCODE_SHIFT_RIGHT = 60;
/** Tab key. */
KEYCODE_TAB = 61;
/** Space key. */
KEYCODE_SPACE = 62;
/** Symbol modifier key.
 * Used to enter alternate symbols. */
KEYCODE_SYM = 63;
/** Explorer special function key.
 * Used to launch a browser application. */
KEYCODE_EXPLORER = 64;
/** Envelope special function key.
 * Used to launch a mail application. */
KEYCODE_ENVELOPE = 65;
/** Enter key. */
KEYCODE_ENTER = 66;
/** Backspace key.
 * Deletes characters before the insertion point, unlike {@link #KEYCODE_FORWARD_DEL}. */
KEYCODE_DEL = 67;
/** '`' (backtick) key. */
KEYCODE_GRAVE = 68;
/** '-'. */
KEYCODE_MINUS = 69;
/** '=' key. */
KEYCODE_EQUALS = 70;
/** '[' key. */
KEYCODE_LEFT_BRACKET = 71;
/** ']' key. */
KEYCODE_RIGHT_BRACKET = 72;
/** '\' key. */
KEYCODE_BACKSLASH = 73;
/** ';' key. */
KEYCODE_SEMICOLON = 74;
/** ''' (apostrophe) key. */
KEYCODE_APOSTROPHE = 75;
/** '/' key. */
KEYCODE_SLASH = 76;
/** '@' key. */
KEYCODE_AT = 77;
/** Number modifier key.
 * Used to enter numeric symbols.
 * This key is not Num Lock; it is more like {@link #KEYCODE_ALT_LEFT} and is
 * interpreted as an ALT key by {@link android.text.method.MetaKeyKeyListener}. */
KEYCODE_NUM = 78;
/** Headset Hook key.
 * Used to hang up calls and stop media. */
KEYCODE_HEADSETHOOK = 79;
/** Camera Focus key.
 * Used to focus the camera. */
KEYCODE_FOCUS = 80; // *Camera* focus
/** '+' key. */
KEYCODE_PLUS = 81;
/** Menu key. */
KEYCODE_MENU = 82;
/** Notification key. */
KEYCODE_NOTIFICATION = 83;
/** Search key. */
KEYCODE_SEARCH = 84;
/** Play/Pause media key. */
KEYCODE_MEDIA_PLAY_PAUSE= 85;
/** Stop media key. */
KEYCODE_MEDIA_STOP = 86;
/** Play Next media key. */
KEYCODE_MEDIA_NEXT = 87;
/** Play Previous media key. */
KEYCODE_MEDIA_PREVIOUS = 88;
/** Rewind media key. */
KEYCODE_MEDIA_REWIND = 89;
/** Fast Forward media key. */
KEYCODE_MEDIA_FAST_FORWARD = 90;
/** Mute key.
 * Mutes the microphone, unlike {@link #KEYCODE_VOLUME_MUTE}. */
KEYCODE_MUTE = 91;
/** Page Up key. */
KEYCODE_PAGE_UP = 92;
/** Page Down key. */
KEYCODE_PAGE_DOWN = 93;
/** Picture Symbols modifier key.
 * Used to switch symbol sets (Emoji, Kao-moji). */
KEYCODE_PICTSYMBOLS = 94; // switch symbol-sets (Emoji,Kao-moji)
/** Switch Charset modifier key.
 * Used to switch character sets (Kanji, Katakana). */
KEYCODE_SWITCH_CHARSET = 95; // switch char-sets (Kanji,Katakana)
/** A Button key.
 * On a game controller, the A button should be either the button labeled A
 * or the first button on the bottom row of controller buttons. */
KEYCODE_BUTTON_A = 96;
/** B Button key.
 * On a game controller, the B button should be either the button labeled B
 * or the second button on the bottom row of controller buttons. */
KEYCODE_BUTTON_B = 97;
/** C Button key.
 * On a game controller, the C button should be either the button labeled C
 * or the third button on the bottom row of controller buttons. */
KEYCODE_BUTTON_C = 98;
/** X Button key.
 * On a game controller, the X button should be either the button labeled X
 * or the first button on the upper row of controller buttons. */
KEYCODE_BUTTON_X = 99;
/** Y Button key.
 * On a game controller, the Y button should be either the button labeled Y
 * or the second button on the upper row of controller buttons. */
KEYCODE_BUTTON_Y = 100;
/** Z Button key.
 * On a game controller, the Z button should be either the button labeled Z
 * or the third button on the upper row of controller buttons. */
KEYCODE_BUTTON_Z = 101;
/** L1 Button key.
 * On a game controller, the L1 button should be either the button labeled L1 (or L)
 * or the top left trigger button. */
KEYCODE_BUTTON_L1 = 102;
/** R1 Button key.
 * On a game controller, the R1 button should be either the button labeled R1 (or R)
 * or the top right trigger button. */
KEYCODE_BUTTON_R1 = 103;
/** L2 Button key.
 * On a game controller, the L2 button should be either the button labeled L2
 * or the bottom left trigger button. */
KEYCODE_BUTTON_L2 = 104;
/** R2 Button key.
 * On a game controller, the R2 button should be either the button labeled R2
 * or the bottom right trigger button. */
KEYCODE_BUTTON_R2 = 105;
/** Left Thumb Button key.
 * On a game controller, the left thumb button indicates that the left (or only)
 * joystick is pressed. */
KEYCODE_BUTTON_THUMBL = 106;
/** Right Thumb Button key.
 * On a game controller, the right thumb button indicates that the right
 * joystick is pressed. */
KEYCODE_BUTTON_THUMBR = 107;
/** Start Button key.
 * On a game controller, the button labeled Start. */
KEYCODE_BUTTON_START = 108;
/** Select Button key.
 * On a game controller, the button labeled Select. */
KEYCODE_BUTTON_SELECT = 109;
/** Mode Button key.
 * On a game controller, the button labeled Mode. */
KEYCODE_BUTTON_MODE = 110;
/** Escape key. */
KEYCODE_ESCAPE = 111;
/** Forward Delete key.
 * Deletes characters ahead of the insertion point, unlike {@link #KEYCODE_DEL}. */
KEYCODE_FORWARD_DEL = 112;
/** Left Control modifier key. */
KEYCODE_CTRL_LEFT = 113;
/** Right Control modifier key. */
KEYCODE_CTRL_RIGHT = 114;
/** Caps Lock key. */
KEYCODE_CAPS_LOCK = 115;
/** Scroll Lock key. */
KEYCODE_SCROLL_LOCK = 116;
/** Left Meta modifier key. */
KEYCODE_META_LEFT = 117;
/** Right Meta modifier key. */
KEYCODE_META_RIGHT = 118;
/** Function modifier key. */
KEYCODE_FUNCTION = 119;
/** System Request / Print Screen key. */
KEYCODE_SYSRQ = 120;
/** Break / Pause key. */
KEYCODE_BREAK = 121;
/** Home Movement key.
 * Used for scrolling or moving the cursor around to the start of a line
 * or to the top of a list. */
KEYCODE_MOVE_HOME = 122;
/** End Movement key.
 * Used for scrolling or moving the cursor around to the end of a line
 * or to the bottom of a list. */
KEYCODE_MOVE_END = 123;
/** Insert key.
 * Toggles insert / overwrite edit mode. */
KEYCODE_INSERT = 124;
/** Forward key.
 * Navigates forward in the history stack. Complement of {@link #KEYCODE_BACK}. */
KEYCODE_FORWARD = 125;
/** Play media key. */
KEYCODE_MEDIA_PLAY = 126;
/** Pause media key. */
KEYCODE_MEDIA_PAUSE = 127;
/** Close media key.
 * May be used to close a CD tray, for example. */
KEYCODE_MEDIA_CLOSE = 128;
/** Eject media key.
 * May be used to eject a CD tray, for example. */
KEYCODE_MEDIA_EJECT = 129;
/** Record media key. */
KEYCODE_MEDIA_RECORD = 130;
/** F1 key. */
KEYCODE_F1 = 131;
/** F2 key. */
KEYCODE_F2 = 132;
/** F3 key. */
KEYCODE_F3 = 133;
/** F4 key. */
KEYCODE_F4 = 134;
/** F5 key. */
KEYCODE_F5 = 135;
/** F6 key. */
KEYCODE_F6 = 136;
/** F7 key. */
KEYCODE_F7 = 137;
/** F8 key. */
KEYCODE_F8 = 138;
/** F9 key. */
KEYCODE_F9 = 139;
/** F10 key. */
KEYCODE_F10 = 140;
/** F11 key. */
KEYCODE_F11 = 141;
/** F12 key. */
KEYCODE_F12 = 142;
/** Num Lock key.
 * This is the Num Lock key; it is different from {@link #KEYCODE_NUM}.
 * This key alters the behavior of other keys on the numeric keypad. */
KEYCODE_NUM_LOCK = 143;
/** Numeric keypad '0' key. */
KEYCODE_NUMPAD_0 = 144;
/** Numeric keypad '1' key. */
KEYCODE_NUMPAD_1 = 145;
/** Numeric keypad '2' key. */
KEYCODE_NUMPAD_2 = 146;
/** Numeric keypad '3' key. */
KEYCODE_NUMPAD_3 = 147;
/** Numeric keypad '4' key. */
KEYCODE_NUMPAD_4 = 148;
/** Numeric keypad '5' key. */
KEYCODE_NUMPAD_5 = 149;
/** Numeric keypad '6' key. */
KEYCODE_NUMPAD_6 = 150;
/** Numeric keypad '7' key. */
KEYCODE_NUMPAD_7 = 151;
/** Numeric keypad '8' key. */
KEYCODE_NUMPAD_8 = 152;
/** Numeric keypad '9' key. */
KEYCODE_NUMPAD_9 = 153;
/** Numeric keypad '/' key (for division). */
KEYCODE_NUMPAD_DIVIDE = 154;
/** Numeric keypad '*' key (for multiplication). */
KEYCODE_NUMPAD_MULTIPLY = 155;
/** Numeric keypad '-' key (for subtraction). */
KEYCODE_NUMPAD_SUBTRACT = 156;
/** Numeric keypad '+' key (for addition). */
KEYCODE_NUMPAD_ADD = 157;
/** Numeric keypad '.' key (for decimals or digit grouping). */
KEYCODE_NUMPAD_DOT = 158;
/** Numeric keypad ',' key (for decimals or digit grouping). */
KEYCODE_NUMPAD_COMMA = 159;
/** Numeric keypad Enter key. */
KEYCODE_NUMPAD_ENTER = 160;
/** Numeric keypad '=' key. */
KEYCODE_NUMPAD_EQUALS = 161;
/** Numeric keypad '(' key. */
KEYCODE_NUMPAD_LEFT_PAREN = 162;
/** Numeric keypad ')' key. */
KEYCODE_NUMPAD_RIGHT_PAREN = 163;
/** Volume Mute key.
 * Mutes the speaker, unlike {@link #KEYCODE_MUTE}.
 * This key should normally be implemented as a toggle such that the first press
 * mutes the speaker and the second press restores the original volume. */
KEYCODE_VOLUME_MUTE = 164;
/** Info key.
 * Common on TV remotes to show additional information related to what is
 * currently being viewed. */
KEYCODE_INFO = 165;
/** Channel up key.
 * On TV remotes, increments the television channel. */
KEYCODE_CHANNEL_UP = 166;
/** Channel down key.
 * On TV remotes, decrements the television channel. */
KEYCODE_CHANNEL_DOWN = 167;
/** Zoom in key. */
KEYCODE_ZOOM_IN = 168;
/** Zoom out key. */
KEYCODE_ZOOM_OUT = 169;
/** TV key.
 * On TV remotes, switches to viewing live TV. */
KEYCODE_TV = 170;
/** Window key.
 * On TV remotes, toggles picture-in-picture mode or other windowing functions. */
KEYCODE_WINDOW = 171;
/** Guide key.
 * On TV remotes, shows a programming guide. */
KEYCODE_GUIDE = 172;
/** DVR key.
 * On some TV remotes, switches to a DVR mode for recorded shows. */
KEYCODE_DVR = 173;
/** Bookmark key.
 * On some TV remotes, bookmarks content or web pages. */
KEYCODE_BOOKMARK = 174;
/** Toggle captions key.
 * Switches the mode for closed-captioning text, for example during television shows. */
KEYCODE_CAPTIONS = 175;
/** Settings key.
 * Starts the system settings activity. */
KEYCODE_SETTINGS = 176;
/** TV power key.
 * On TV remotes, toggles the power on a television screen. */
KEYCODE_TV_POWER = 177;
/** TV input key.
 * On TV remotes, switches the input on a television screen. */
KEYCODE_TV_INPUT = 178;
/** Set-top-box power key.
 * On TV remotes, toggles the power on an external Set-top-box. */
KEYCODE_STB_POWER = 179;
/** Set-top-box input key.
 * On TV remotes, switches the input mode on an external Set-top-box. */
KEYCODE_STB_INPUT = 180;
/** A/V Receiver power key.
 * On TV remotes, toggles the power on an external A/V Receiver. */
KEYCODE_AVR_POWER = 181;
/** A/V Receiver input key.
 * On TV remotes, switches the input mode on an external A/V Receiver. */
KEYCODE_AVR_INPUT = 182;
/** Red "programmable" key.
 * On TV remotes, acts as a contextual/programmable key. */
KEYCODE_PROG_RED = 183;
/** Green "programmable" key.
 * On TV remotes, actsas a contextual/programmable key. */
KEYCODE_PROG_GREEN = 184;
/** Yellow "programmable" key.
 * On TV remotes, acts as a contextual/programmable key. */
KEYCODE_PROG_YELLOW = 185;
/** Blue "programmable" key.
 * On TV remotes, acts as a contextual/programmable key. */
KEYCODE_PROG_BLUE = 186;
/** App switch key.
 * Should bring up the application switcher dialog. */
KEYCODE_APP_SWITCH = 187;
/** Generic Game Pad Button #1.*/
KEYCODE_BUTTON_1 = 188;
/** Generic Game Pad Button #2.*/
KEYCODE_BUTTON_2 = 189;
/** Generic Game Pad Button #3.*/
KEYCODE_BUTTON_3 = 190;
/** Generic Game Pad Button #4.*/
KEYCODE_BUTTON_4 = 191;
/** Generic Game Pad Button #5.*/
KEYCODE_BUTTON_5 = 192;
/** Generic Game Pad Button #6.*/
KEYCODE_BUTTON_6 = 193;
/** Generic Game Pad Button #7.*/
KEYCODE_BUTTON_7 = 194;
/** Generic Game Pad Button #8.*/
KEYCODE_BUTTON_8 = 195;
/** Generic Game Pad Button #9.*/
KEYCODE_BUTTON_9 = 196;
/** Generic Game Pad Button #10.*/
KEYCODE_BUTTON_10 = 197;
/** Generic Game Pad Button #11.*/
KEYCODE_BUTTON_11 = 198;
/** Generic Game Pad Button #12.*/
KEYCODE_BUTTON_12 = 199;
/** Generic Game Pad Button #13.*/
KEYCODE_BUTTON_13 = 200;
/** Generic Game Pad Button #14.*/
KEYCODE_BUTTON_14 = 201;
/** Generic Game Pad Button #15.*/
KEYCODE_BUTTON_15 = 202;
/** Generic Game Pad Button #16.*/
KEYCODE_BUTTON_16 = 203;
/** Language Switch key.
 * Toggles the current input language such as switching between English and Japanese on
 * a QWERTY keyboard. On some devices, the same function may be performed by
 * pressing Shift+Spacebar. */
KEYCODE_LANGUAGE_SWITCH = 204;
/** Manner Mode key.
 * Toggles silent or vibrate mode on and off to make the device behave more politely
 * in certain settings such as on a crowded train. On some devices, the key may only
 * operate when long-pressed. */
KEYCODE_MANNER_MODE = 205;
/** 3D Mode key.
 * Toggles the display between 2D and 3D mode. */
KEYCODE_3D_MODE = 206;
/** Contacts special function key.
 * Used to launch an address book application. */
KEYCODE_CONTACTS = 207;
/** Calendar special function key.
 * Used to launch a calendar application. */
KEYCODE_CALENDAR = 208;
/** Music special function key.
 * Used to launch a music player application. */
KEYCODE_MUSIC = 209;
/** Calculator special function key.
 * Used to launch a calculator application. */
KEYCODE_CALCULATOR = 210;
/** Japanese full-width / half-width key. */
KEYCODE_ZENKAKU_HANKAKU = 211;
/** Japanese alphanumeric key. */
KEYCODE_EISU = 212;
/** Japanese non-conversion key. */
KEYCODE_MUHENKAN = 213;
/** Japanese conversion key. */
KEYCODE_HENKAN = 214;
/** Japanese katakana / hiragana key. */
KEYCODE_KATAKANA_HIRAGANA = 215;
/** Japanese Yen key. */
KEYCODE_YEN = 216;
/** Japanese Ro key. */
KEYCODE_RO = 217;
/** Japanese kana key. */
KEYCODE_KANA = 218;
/** Assist key.
 * Launches the global assist activity. Not delivered to applications. */
KEYCODE_ASSIST = 219;
/** Brightness Down key.
 * Adjusts the screen brightness down. */
KEYCODE_BRIGHTNESS_DOWN = 220;
/** Brightness Up key.
 * Adjusts the screen brightness up. */
KEYCODE_BRIGHTNESS_UP = 221;
/** Audio Track key.
 * Switches the audio tracks. */
KEYCODE_MEDIA_AUDIO_TRACK = 222;
/** Sleep key.
 * Puts the device to sleep. Behaves somewhat like {@link #KEYCODE_POWER} but it
 * has no effect if the device is already asleep. */
KEYCODE_SLEEP = 223;
/** Wakeup key.
 * Wakes up the device. Behaves somewhat like {@link #KEYCODE_POWER} but it
 * has no effect if the device is already awake. */
KEYCODE_WAKEUP = 224;
/** Pairing key.
 * Initiates peripheral pairing mode. Useful for pairing remote control
 * devices or game controllers, especially if no other input mode is
 * available. */
KEYCODE_PAIRING = 225;
/** Media Top Menu key.
 * Goes to the top of media menu. */
KEYCODE_MEDIA_TOP_MENU = 226;
/** '11' key. */
KEYCODE_11 = 227;
/** '12' key. */
KEYCODE_12 = 228;
/** Last Channel key.
 * Goes to the last viewed channel. */
KEYCODE_LAST_CHANNEL = 229;
/** TV data service key.
 * Displays data services like weather, sports. */
KEYCODE_TV_DATA_SERVICE = 230;
/** Voice Assist key.
 * Launches the global voice assist activity. Not delivered to applications. */
KEYCODE_VOICE_ASSIST = 231;
/** Radio key.
 * Toggles TV service / Radio service. */
KEYCODE_TV_RADIO_SERVICE = 232;
/** Teletext key.
 * Displays Teletext service. */
KEYCODE_TV_TELETEXT = 233;
/** Number entry key.
 * Initiates to enter multi-digit channel nubmber when each digit key is assigned
 * for selecting separate channel. Corresponds to Number Entry Mode (0x1D) of CEC
 * User Control Code. */
KEYCODE_TV_NUMBER_ENTRY = 234;
/** Analog Terrestrial key.
 * Switches to analog terrestrial broadcast service. */
KEYCODE_TV_TERRESTRIAL_ANALOG = 235;
/** Digital Terrestrial key.
 * Switches to digital terrestrial broadcast service. */
KEYCODE_TV_TERRESTRIAL_DIGITAL = 236;
/** Satellite key.
 * Switches to digital satellite broadcast service. */
KEYCODE_TV_SATELLITE = 237;
/** BS key.
 * Switches to BS digital satellite broadcasting service available in Japan. */
KEYCODE_TV_SATELLITE_BS = 238;
/** CS key.
 * Switches to CS digital satellite broadcasting service available in Japan. */
KEYCODE_TV_SATELLITE_CS = 239;
/** BS/CS key.
 * Toggles between BS and CS digital satellite services. */
KEYCODE_TV_SATELLITE_SERVICE = 240;
/** Toggle Network key.
 * Toggles selecting broacast services. */
KEYCODE_TV_NETWORK = 241;
/** Antenna/Cable key.
 * Toggles broadcast input source between antenna and cable. */
KEYCODE_TV_ANTENNA_CABLE = 242;
/** HDMI #1 key.
 * Switches to HDMI input #1. */
KEYCODE_TV_INPUT_HDMI_1 = 243;
/** HDMI #2 key.
 * Switches to HDMI input #2. */
KEYCODE_TV_INPUT_HDMI_2 = 244;
/** HDMI #3 key.
 * Switches to HDMI input #3. */
KEYCODE_TV_INPUT_HDMI_3 = 245;
/** HDMI #4 key.
 * Switches to HDMI input #4. */
KEYCODE_TV_INPUT_HDMI_4 = 246;
/** Composite #1 key.
 * Switches to composite video input #1. */
KEYCODE_TV_INPUT_COMPOSITE_1 = 247;
/** Composite #2 key.
 * Switches to composite video input #2. */
KEYCODE_TV_INPUT_COMPOSITE_2 = 248;
/** Component #1 key.
 * Switches to component video input #1. */
KEYCODE_TV_INPUT_COMPONENT_1 = 249;
/** Component #2 key.
 * Switches to component video input #2. */
KEYCODE_TV_INPUT_COMPONENT_2 = 250;
/** VGA #1 key.
 * Switches to VGA (analog RGB) input #1. */
KEYCODE_TV_INPUT_VGA_1 = 251;
/** Audio description key.
 * Toggles audio description off / on. */
KEYCODE_TV_AUDIO_DESCRIPTION = 252;
/** Audio description mixing volume up key.
 * Louden audio description volume as compared with normal audio volume. */
KEYCODE_TV_AUDIO_DESCRIPTION_MIX_UP = 253;
/** Audio description mixing volume down key.
 * Lessen audio description volume as compared with normal audio volume. */
KEYCODE_TV_AUDIO_DESCRIPTION_MIX_DOWN = 254;
/** Zoom mode key.
 * Changes Zoom mode (Normal, Full, Zoom, Wide-zoom, etc.) */
KEYCODE_TV_ZOOM_MODE = 255;
/** Contents menu key.
 * Goes to the title list. Corresponds to Contents Menu (0x0B) of CEC User Control
 * Code */
KEYCODE_TV_CONTENTS_MENU = 256;
/** Media context menu key.
 * Goes to the context menu of media contents. Corresponds to Media Context-sensitive
 * Menu (0x11) of CEC User Control Code. */
KEYCODE_TV_MEDIA_CONTEXT_MENU = 257;
/** Timer programming key.
 * Goes to the timer recording menu. Corresponds to Timer Programming (0x54) of
 * CEC User Control Code. */
KEYCODE_TV_TIMER_PROGRAMMING = 258;
/** Help key. */
KEYCODE_HELP = 259;
/** Navigate to previous key.
 * Goes backward by one item in an ordered collection of items. */
KEYCODE_NAVIGATE_PREVIOUS = 260;
/** Navigate to next key.
 * Advances to the next item in an ordered collection of items. */
KEYCODE_NAVIGATE_NEXT = 261;
/** Navigate in key.
 * Activates the item that currently has focus or expands to the next level of a navigation
 * hierarchy. */
KEYCODE_NAVIGATE_IN = 262;
/** Navigate out key.
 * Backs out one level of a navigation hierarchy or collapses the item that currently has
 * focus. */
KEYCODE_NAVIGATE_OUT = 263;
/** Primary stem key for Wear
 * Main power/reset button on watch. */
KEYCODE_STEM_PRIMARY = 264;
/** Generic stem key 1 for Wear */
KEYCODE_STEM_1 = 265;
/** Generic stem key 2 for Wear */
KEYCODE_STEM_2 = 266;
/** Generic stem key 3 for Wear */
KEYCODE_STEM_3 = 267;
/** Directional Pad Up-Left */
KEYCODE_DPAD_UP_LEFT = 268;
/** Directional Pad Down-Left */
KEYCODE_DPAD_DOWN_LEFT = 269;
/** Directional Pad Up-Right */
KEYCODE_DPAD_UP_RIGHT = 270;
/** Directional Pad Down-Right */
KEYCODE_DPAD_DOWN_RIGHT = 271;
/** Skip forward media key. */
KEYCODE_MEDIA_SKIP_FORWARD = 272;
/** Skip backward media key. */
KEYCODE_MEDIA_SKIP_BACKWARD = 273;
/** Step forward media key.
 * Steps media forward, one frame at a time. */
KEYCODE_MEDIA_STEP_FORWARD = 274;
/** Step backward media key.
 * Steps media backward, one frame at a time. */
KEYCODE_MEDIA_STEP_BACKWARD = 275;
/** put device to sleep unless a wakelock is held. */
KEYCODE_SOFT_SLEEP = 276;
/** Cut key. */
KEYCODE_CUT = 277;
/** Copy key. */
KEYCODE_COPY = 278;
/** Paste key. */
KEYCODE_PASTE = 279;
/** Consumed by the system for navigation up */
KEYCODE_SYSTEM_NAVIGATION_UP = 280;
/** Consumed by the system for navigation down */
KEYCODE_SYSTEM_NAVIGATION_DOWN = 281;
/** Consumed by the system for navigation left*/
KEYCODE_SYSTEM_NAVIGATION_LEFT = 282;
/** Consumed by the system for navigation right */
KEYCODE_SYSTEM_NAVIGATION_RIGHT = 283;

  /** Key code constant: Show all apps */
public static final int KEYCODE_ALL_APPS = 284;
/** Key code constant: Refresh key. */
public static final int KEYCODE_REFRESH = 285;
/** Key code constant: Thumbs up key. Apps can use this to let user upvote content. */
public static final int KEYCODE_THUMBS_UP = 286;
/** Key code constant: Thumbs down key. Apps can use this to let user downvote content. */
public static final int KEYCODE_THUMBS_DOWN = 287;
```
<p>###Notes</p>
<ul>
<li><p>Currently the last key code is <code>KEYCODE_SYSTEM_NAVIGATION_RIGHT</code>, which is 283 (but check the source code to make sure this is still true). So you could loop through them like this:</p>
```  for (int keyCode = 0; keyCode <= 287; keyCode++) {

  }
```

Most input to EditText (or a custom view that accepts keyboard input) from an Input Method Editor (IME) is done using an Input Connection, so many key codes are not sent at all in this case. See this answer.

Body:
#Complete list of key codes

Some of the other lists here are incomplete. The complete list can be found in the KeyEvent source code or documentation. The source code is ordered by integer value so I will use that here.

(Repetitive text removed to save space, all key codes are public static final int.)

/** Unknown key code. */
KEYCODE_UNKNOWN = 0;
/** Soft Left key.
 * Usually situated below the display on phones and used as a multi-function
 * feature key for selecting a software defined function shown on the bottom left
 * of the display. */
KEYCODE_SOFT_LEFT = 1;
/** Soft Right key.
 * Usually situated below the display on phones and used as a multi-function
 * feature key for selecting a software defined function shown on the bottom right
 * of the display. */
KEYCODE_SOFT_RIGHT = 2;
/** Home key.
 * This key is handled by the framework and is never delivered to applications. */
KEYCODE_HOME = 3;
/** Back key. */
KEYCODE_BACK = 4;
/** Call key. */
KEYCODE_CALL = 5;
/** End Call key. */
KEYCODE_ENDCALL = 6;
/** '0' key. */
KEYCODE_0 = 7;
/** '1' key. */
KEYCODE_1 = 8;
/** '2' key. */
KEYCODE_2 = 9;
/** '3' key. */
KEYCODE_3 = 10;
/** '4' key. */
KEYCODE_4 = 11;
/** '5' key. */
KEYCODE_5 = 12;
/** '6' key. */
KEYCODE_6 = 13;
/** '7' key. */
KEYCODE_7 = 14;
/** '8' key. */
KEYCODE_8 = 15;
/** '9' key. */
KEYCODE_9 = 16;
/** '*' key. */
KEYCODE_STAR = 17;
/** '#' key. */
KEYCODE_POUND = 18;
/** Directional Pad Up key.
 * May also be synthesized from trackball motions. */
KEYCODE_DPAD_UP = 19;
/** Directional Pad Down key.
 * May also be synthesized from trackball motions. */
KEYCODE_DPAD_DOWN = 20;
/** Directional Pad Left key.
 * May also be synthesized from trackball motions. */
KEYCODE_DPAD_LEFT = 21;
/** Directional Pad Right key.
 * May also be synthesized from trackball motions. */
KEYCODE_DPAD_RIGHT = 22;
/** Directional Pad Center key.
 * May also be synthesized from trackball motions. */
KEYCODE_DPAD_CENTER = 23;
/** Volume Up key.
 * Adjusts the speaker volume up. */
KEYCODE_VOLUME_UP = 24;
/** Volume Down key.
 * Adjusts the speaker volume down. */
KEYCODE_VOLUME_DOWN = 25;
/** Power key. */
KEYCODE_POWER = 26;
/** Camera key.
 * Used to launch a camera application or take pictures. */
KEYCODE_CAMERA = 27;
/** Clear key. */
KEYCODE_CLEAR = 28;
/** 'A' key. */
KEYCODE_A = 29;
/** 'B' key. */
KEYCODE_B = 30;
/** 'C' key. */
KEYCODE_C = 31;
/** 'D' key. */
KEYCODE_D = 32;
/** 'E' key. */
KEYCODE_E = 33;
/** 'F' key. */
KEYCODE_F = 34;
/** 'G' key. */
KEYCODE_G = 35;
/** 'H' key. */
KEYCODE_H = 36;
/** 'I' key. */
KEYCODE_I = 37;
/** 'J' key. */
KEYCODE_J = 38;
/** 'K' key. */
KEYCODE_K = 39;
/** 'L' key. */
KEYCODE_L = 40;
/** 'M' key. */
KEYCODE_M = 41;
/** 'N' key. */
KEYCODE_N = 42;
/** 'O' key. */
KEYCODE_O = 43;
/** 'P' key. */
KEYCODE_P = 44;
/** 'Q' key. */
KEYCODE_Q = 45;
/** 'R' key. */
KEYCODE_R = 46;
/** 'S' key. */
KEYCODE_S = 47;
/** 'T' key. */
KEYCODE_T = 48;
/** 'U' key. */
KEYCODE_U = 49;
/** 'V' key. */
KEYCODE_V = 50;
/** 'W' key. */
KEYCODE_W = 51;
/** 'X' key. */
KEYCODE_X = 52;
/** 'Y' key. */
KEYCODE_Y = 53;
/** 'Z' key. */
KEYCODE_Z = 54;
/** ',' key. */
KEYCODE_COMMA = 55;
/** '.' key. */
KEYCODE_PERIOD = 56;
/** Left Alt modifier key. */
KEYCODE_ALT_LEFT = 57;
/** Right Alt modifier key. */
KEYCODE_ALT_RIGHT = 58;
/** Left Shift modifier key. */
KEYCODE_SHIFT_LEFT = 59;
/** Right Shift modifier key. */
KEYCODE_SHIFT_RIGHT = 60;
/** Tab key. */
KEYCODE_TAB = 61;
/** Space key. */
KEYCODE_SPACE = 62;
/** Symbol modifier key.
 * Used to enter alternate symbols. */
KEYCODE_SYM = 63;
/** Explorer special function key.
 * Used to launch a browser application. */
KEYCODE_EXPLORER = 64;
/** Envelope special function key.
 * Used to launch a mail application. */
KEYCODE_ENVELOPE = 65;
/** Enter key. */
KEYCODE_ENTER = 66;
/** Backspace key.
 * Deletes characters before the insertion point, unlike {@link #KEYCODE_FORWARD_DEL}. */
KEYCODE_DEL = 67;
/** '`' (backtick) key. */
KEYCODE_GRAVE = 68;
/** '-'. */
KEYCODE_MINUS = 69;
/** '=' key. */
KEYCODE_EQUALS = 70;
/** '[' key. */
KEYCODE_LEFT_BRACKET = 71;
/** ']' key. */
KEYCODE_RIGHT_BRACKET = 72;
/** '\' key. */
KEYCODE_BACKSLASH = 73;
/** ';' key. */
KEYCODE_SEMICOLON = 74;
/** ''' (apostrophe) key. */
KEYCODE_APOSTROPHE = 75;
/** '/' key. */
KEYCODE_SLASH = 76;
/** '@' key. */
KEYCODE_AT = 77;
/** Number modifier key.
 * Used to enter numeric symbols.
 * This key is not Num Lock; it is more like {@link #KEYCODE_ALT_LEFT} and is
 * interpreted as an ALT key by {@link android.text.method.MetaKeyKeyListener}. */
KEYCODE_NUM = 78;
/** Headset Hook key.
 * Used to hang up calls and stop media. */
KEYCODE_HEADSETHOOK = 79;
/** Camera Focus key.
 * Used to focus the camera. */
KEYCODE_FOCUS = 80; // *Camera* focus
/** '+' key. */
KEYCODE_PLUS = 81;
/** Menu key. */
KEYCODE_MENU = 82;
/** Notification key. */
KEYCODE_NOTIFICATION = 83;
/** Search key. */
KEYCODE_SEARCH = 84;
/** Play/Pause media key. */
KEYCODE_MEDIA_PLAY_PAUSE= 85;
/** Stop media key. */
KEYCODE_MEDIA_STOP = 86;
/** Play Next media key. */
KEYCODE_MEDIA_NEXT = 87;
/** Play Previous media key. */
KEYCODE_MEDIA_PREVIOUS = 88;
/** Rewind media key. */
KEYCODE_MEDIA_REWIND = 89;
/** Fast Forward media key. */
KEYCODE_MEDIA_FAST_FORWARD = 90;
/** Mute key.
 * Mutes the microphone, unlike {@link #KEYCODE_VOLUME_MUTE}. */
KEYCODE_MUTE = 91;
/** Page Up key. */
KEYCODE_PAGE_UP = 92;
/** Page Down key. */
KEYCODE_PAGE_DOWN = 93;
/** Picture Symbols modifier key.
 * Used to switch symbol sets (Emoji, Kao-moji). */
KEYCODE_PICTSYMBOLS = 94; // switch symbol-sets (Emoji,Kao-moji)
/** Switch Charset modifier key.
 * Used to switch character sets (Kanji, Katakana). */
KEYCODE_SWITCH_CHARSET = 95; // switch char-sets (Kanji,Katakana)
/** A Button key.
 * On a game controller, the A button should be either the button labeled A
 * or the first button on the bottom row of controller buttons. */
KEYCODE_BUTTON_A = 96;
/** B Button key.
 * On a game controller, the B button should be either the button labeled B
 * or the second button on the bottom row of controller buttons. */
KEYCODE_BUTTON_B = 97;
/** C Button key.
 * On a game controller, the C button should be either the button labeled C
 * or the third button on the bottom row of controller buttons. */
KEYCODE_BUTTON_C = 98;
/** X Button key.
 * On a game controller, the X button should be either the button labeled X
 * or the first button on the upper row of controller buttons. */
KEYCODE_BUTTON_X = 99;
/** Y Button key.
 * On a game controller, the Y button should be either the button labeled Y
 * or the second button on the upper row of controller buttons. */
KEYCODE_BUTTON_Y = 100;
/** Z Button key.
 * On a game controller, the Z button should be either the button labeled Z
 * or the third button on the upper row of controller buttons. */
KEYCODE_BUTTON_Z = 101;
/** L1 Button key.
 * On a game controller, the L1 button should be either the button labeled L1 (or L)
 * or the top left trigger button. */
KEYCODE_BUTTON_L1 = 102;
/** R1 Button key.
 * On a game controller, the R1 button should be either the button labeled R1 (or R)
 * or the top right trigger button. */
KEYCODE_BUTTON_R1 = 103;
/** L2 Button key.
 * On a game controller, the L2 button should be either the button labeled L2
 * or the bottom left trigger button. */
KEYCODE_BUTTON_L2 = 104;
/** R2 Button key.
 * On a game controller, the R2 button should be either the button labeled R2
 * or the bottom right trigger button. */
KEYCODE_BUTTON_R2 = 105;
/** Left Thumb Button key.
 * On a game controller, the left thumb button indicates that the left (or only)
 * joystick is pressed. */
KEYCODE_BUTTON_THUMBL = 106;
/** Right Thumb Button key.
 * On a game controller, the right thumb button indicates that the right
 * joystick is pressed. */
KEYCODE_BUTTON_THUMBR = 107;
/** Start Button key.
 * On a game controller, the button labeled Start. */
KEYCODE_BUTTON_START = 108;
/** Select Button key.
 * On a game controller, the button labeled Select. */
KEYCODE_BUTTON_SELECT = 109;
/** Mode Button key.
 * On a game controller, the button labeled Mode. */
KEYCODE_BUTTON_MODE = 110;
/** Escape key. */
KEYCODE_ESCAPE = 111;
/** Forward Delete key.
 * Deletes characters ahead of the insertion point, unlike {@link #KEYCODE_DEL}. */
KEYCODE_FORWARD_DEL = 112;
/** Left Control modifier key. */
KEYCODE_CTRL_LEFT = 113;
/** Right Control modifier key. */
KEYCODE_CTRL_RIGHT = 114;
/** Caps Lock key. */
KEYCODE_CAPS_LOCK = 115;
/** Scroll Lock key. */
KEYCODE_SCROLL_LOCK = 116;
/** Left Meta modifier key. */
KEYCODE_META_LEFT = 117;
/** Right Meta modifier key. */
KEYCODE_META_RIGHT = 118;
/** Function modifier key. */
KEYCODE_FUNCTION = 119;
/** System Request / Print Screen key. */
KEYCODE_SYSRQ = 120;
/** Break / Pause key. */
KEYCODE_BREAK = 121;
/** Home Movement key.
 * Used for scrolling or moving the cursor around to the start of a line
 * or to the top of a list. */
KEYCODE_MOVE_HOME = 122;
/** End Movement key.
 * Used for scrolling or moving the cursor around to the end of a line
 * or to the bottom of a list. */
KEYCODE_MOVE_END = 123;
/** Insert key.
 * Toggles insert / overwrite edit mode. */
KEYCODE_INSERT = 124;
/** Forward key.
 * Navigates forward in the history stack. Complement of {@link #KEYCODE_BACK}. */
KEYCODE_FORWARD = 125;
/** Play media key. */
KEYCODE_MEDIA_PLAY = 126;
/** Pause media key. */
KEYCODE_MEDIA_PAUSE = 127;
/** Close media key.
 * May be used to close a CD tray, for example. */
KEYCODE_MEDIA_CLOSE = 128;
/** Eject media key.
 * May be used to eject a CD tray, for example. */
KEYCODE_MEDIA_EJECT = 129;
/** Record media key. */
KEYCODE_MEDIA_RECORD = 130;
/** F1 key. */
KEYCODE_F1 = 131;
/** F2 key. */
KEYCODE_F2 = 132;
/** F3 key. */
KEYCODE_F3 = 133;
/** F4 key. */
KEYCODE_F4 = 134;
/** F5 key. */
KEYCODE_F5 = 135;
/** F6 key. */
KEYCODE_F6 = 136;
/** F7 key. */
KEYCODE_F7 = 137;
/** F8 key. */
KEYCODE_F8 = 138;
/** F9 key. */
KEYCODE_F9 = 139;
/** F10 key. */
KEYCODE_F10 = 140;
/** F11 key. */
KEYCODE_F11 = 141;
/** F12 key. */
KEYCODE_F12 = 142;
/** Num Lock key.
 * This is the Num Lock key; it is different from {@link #KEYCODE_NUM}.
 * This key alters the behavior of other keys on the numeric keypad. */
KEYCODE_NUM_LOCK = 143;
/** Numeric keypad '0' key. */
KEYCODE_NUMPAD_0 = 144;
/** Numeric keypad '1' key. */
KEYCODE_NUMPAD_1 = 145;
/** Numeric keypad '2' key. */
KEYCODE_NUMPAD_2 = 146;
/** Numeric keypad '3' key. */
KEYCODE_NUMPAD_3 = 147;
/** Numeric keypad '4' key. */
KEYCODE_NUMPAD_4 = 148;
/** Numeric keypad '5' key. */
KEYCODE_NUMPAD_5 = 149;
/** Numeric keypad '6' key. */
KEYCODE_NUMPAD_6 = 150;
/** Numeric keypad '7' key. */
KEYCODE_NUMPAD_7 = 151;
/** Numeric keypad '8' key. */
KEYCODE_NUMPAD_8 = 152;
/** Numeric keypad '9' key. */
KEYCODE_NUMPAD_9 = 153;
/** Numeric keypad '/' key (for division). */
KEYCODE_NUMPAD_DIVIDE = 154;
/** Numeric keypad '*' key (for multiplication). */
KEYCODE_NUMPAD_MULTIPLY = 155;
/** Numeric keypad '-' key (for subtraction). */
KEYCODE_NUMPAD_SUBTRACT = 156;
/** Numeric keypad '+' key (for addition). */
KEYCODE_NUMPAD_ADD = 157;
/** Numeric keypad '.' key (for decimals or digit grouping). */
KEYCODE_NUMPAD_DOT = 158;
/** Numeric keypad ',' key (for decimals or digit grouping). */
KEYCODE_NUMPAD_COMMA = 159;
/** Numeric keypad Enter key. */
KEYCODE_NUMPAD_ENTER = 160;
/** Numeric keypad '=' key. */
KEYCODE_NUMPAD_EQUALS = 161;
/** Numeric keypad '(' key. */
KEYCODE_NUMPAD_LEFT_PAREN = 162;
/** Numeric keypad ')' key. */
KEYCODE_NUMPAD_RIGHT_PAREN = 163;
/** Volume Mute key.
 * Mutes the speaker, unlike {@link #KEYCODE_MUTE}.
 * This key should normally be implemented as a toggle such that the first press
 * mutes the speaker and the second press restores the original volume. */
KEYCODE_VOLUME_MUTE = 164;
/** Info key.
 * Common on TV remotes to show additional information related to what is
 * currently being viewed. */
KEYCODE_INFO = 165;
/** Channel up key.
 * On TV remotes, increments the television channel. */
KEYCODE_CHANNEL_UP = 166;
/** Channel down key.
 * On TV remotes, decrements the television channel. */
KEYCODE_CHANNEL_DOWN = 167;
/** Zoom in key. */
KEYCODE_ZOOM_IN = 168;
/** Zoom out key. */
KEYCODE_ZOOM_OUT = 169;
/** TV key.
 * On TV remotes, switches to viewing live TV. */
KEYCODE_TV = 170;
/** Window key.
 * On TV remotes, toggles picture-in-picture mode or other windowing functions. */
KEYCODE_WINDOW = 171;
/** Guide key.
 * On TV remotes, shows a programming guide. */
KEYCODE_GUIDE = 172;
/** DVR key.
 * On some TV remotes, switches to a DVR mode for recorded shows. */
KEYCODE_DVR = 173;
/** Bookmark key.
 * On some TV remotes, bookmarks content or web pages. */
KEYCODE_BOOKMARK = 174;
/** Toggle captions key.
 * Switches the mode for closed-captioning text, for example during television shows. */
KEYCODE_CAPTIONS = 175;
/** Settings key.
 * Starts the system settings activity. */
KEYCODE_SETTINGS = 176;
/** TV power key.
 * On TV remotes, toggles the power on a television screen. */
KEYCODE_TV_POWER = 177;
/** TV input key.
 * On TV remotes, switches the input on a television screen. */
KEYCODE_TV_INPUT = 178;
/** Set-top-box power key.
 * On TV remotes, toggles the power on an external Set-top-box. */
KEYCODE_STB_POWER = 179;
/** Set-top-box input key.
 * On TV remotes, switches the input mode on an external Set-top-box. */
KEYCODE_STB_INPUT = 180;
/** A/V Receiver power key.
 * On TV remotes, toggles the power on an external A/V Receiver. */
KEYCODE_AVR_POWER = 181;
/** A/V Receiver input key.
 * On TV remotes, switches the input mode on an external A/V Receiver. */
KEYCODE_AVR_INPUT = 182;
/** Red "programmable" key.
 * On TV remotes, acts as a contextual/programmable key. */
KEYCODE_PROG_RED = 183;
/** Green "programmable" key.
 * On TV remotes, actsas a contextual/programmable key. */
KEYCODE_PROG_GREEN = 184;
/** Yellow "programmable" key.
 * On TV remotes, acts as a contextual/programmable key. */
KEYCODE_PROG_YELLOW = 185;
/** Blue "programmable" key.
 * On TV remotes, acts as a contextual/programmable key. */
KEYCODE_PROG_BLUE = 186;
/** App switch key.
 * Should bring up the application switcher dialog. */
KEYCODE_APP_SWITCH = 187;
/** Generic Game Pad Button #1.*/
KEYCODE_BUTTON_1 = 188;
/** Generic Game Pad Button #2.*/
KEYCODE_BUTTON_2 = 189;
/** Generic Game Pad Button #3.*/
KEYCODE_BUTTON_3 = 190;
/** Generic Game Pad Button #4.*/
KEYCODE_BUTTON_4 = 191;
/** Generic Game Pad Button #5.*/
KEYCODE_BUTTON_5 = 192;
/** Generic Game Pad Button #6.*/
KEYCODE_BUTTON_6 = 193;
/** Generic Game Pad Button #7.*/
KEYCODE_BUTTON_7 = 194;
/** Generic Game Pad Button #8.*/
KEYCODE_BUTTON_8 = 195;
/** Generic Game Pad Button #9.*/
KEYCODE_BUTTON_9 = 196;
/** Generic Game Pad Button #10.*/
KEYCODE_BUTTON_10 = 197;
/** Generic Game Pad Button #11.*/
KEYCODE_BUTTON_11 = 198;
/** Generic Game Pad Button #12.*/
KEYCODE_BUTTON_12 = 199;
/** Generic Game Pad Button #13.*/
KEYCODE_BUTTON_13 = 200;
/** Generic Game Pad Button #14.*/
KEYCODE_BUTTON_14 = 201;
/** Generic Game Pad Button #15.*/
KEYCODE_BUTTON_15 = 202;
/** Generic Game Pad Button #16.*/
KEYCODE_BUTTON_16 = 203;
/** Language Switch key.
 * Toggles the current input language such as switching between English and Japanese on
 * a QWERTY keyboard. On some devices, the same function may be performed by
 * pressing Shift+Spacebar. */
KEYCODE_LANGUAGE_SWITCH = 204;
/** Manner Mode key.
 * Toggles silent or vibrate mode on and off to make the device behave more politely
 * in certain settings such as on a crowded train. On some devices, the key may only
 * operate when long-pressed. */
KEYCODE_MANNER_MODE = 205;
/** 3D Mode key.
 * Toggles the display between 2D and 3D mode. */
KEYCODE_3D_MODE = 206;
/** Contacts special function key.
 * Used to launch an address book application. */
KEYCODE_CONTACTS = 207;
/** Calendar special function key.
 * Used to launch a calendar application. */
KEYCODE_CALENDAR = 208;
/** Music special function key.
 * Used to launch a music player application. */
KEYCODE_MUSIC = 209;
/** Calculator special function key.
 * Used to launch a calculator application. */
KEYCODE_CALCULATOR = 210;
/** Japanese full-width / half-width key. */
KEYCODE_ZENKAKU_HANKAKU = 211;
/** Japanese alphanumeric key. */
KEYCODE_EISU = 212;
/** Japanese non-conversion key. */
KEYCODE_MUHENKAN = 213;
/** Japanese conversion key. */
KEYCODE_HENKAN = 214;
/** Japanese katakana / hiragana key. */
KEYCODE_KATAKANA_HIRAGANA = 215;
/** Japanese Yen key. */
KEYCODE_YEN = 216;
/** Japanese Ro key. */
KEYCODE_RO = 217;
/** Japanese kana key. */
KEYCODE_KANA = 218;
/** Assist key.
 * Launches the global assist activity. Not delivered to applications. */
KEYCODE_ASSIST = 219;
/** Brightness Down key.
 * Adjusts the screen brightness down. */
KEYCODE_BRIGHTNESS_DOWN = 220;
/** Brightness Up key.
 * Adjusts the screen brightness up. */
KEYCODE_BRIGHTNESS_UP = 221;
/** Audio Track key.
 * Switches the audio tracks. */
KEYCODE_MEDIA_AUDIO_TRACK = 222;
/** Sleep key.
 * Puts the device to sleep. Behaves somewhat like {@link #KEYCODE_POWER} but it
 * has no effect if the device is already asleep. */
KEYCODE_SLEEP = 223;
/** Wakeup key.
 * Wakes up the device. Behaves somewhat like {@link #KEYCODE_POWER} but it
 * has no effect if the device is already awake. */
KEYCODE_WAKEUP = 224;
/** Pairing key.
 * Initiates peripheral pairing mode. Useful for pairing remote control
 * devices or game controllers, especially if no other input mode is
 * available. */
KEYCODE_PAIRING = 225;
/** Media Top Menu key.
 * Goes to the top of media menu. */
KEYCODE_MEDIA_TOP_MENU = 226;
/** '11' key. */
KEYCODE_11 = 227;
/** '12' key. */
KEYCODE_12 = 228;
/** Last Channel key.
 * Goes to the last viewed channel. */
KEYCODE_LAST_CHANNEL = 229;
/** TV data service key.
 * Displays data services like weather, sports. */
KEYCODE_TV_DATA_SERVICE = 230;
/** Voice Assist key.
 * Launches the global voice assist activity. Not delivered to applications. */
KEYCODE_VOICE_ASSIST = 231;
/** Radio key.
 * Toggles TV service / Radio service. */
KEYCODE_TV_RADIO_SERVICE = 232;
/** Teletext key.
 * Displays Teletext service. */
KEYCODE_TV_TELETEXT = 233;
/** Number entry key.
 * Initiates to enter multi-digit channel nubmber when each digit key is assigned
 * for selecting separate channel. Corresponds to Number Entry Mode (0x1D) of CEC
 * User Control Code. */
KEYCODE_TV_NUMBER_ENTRY = 234;
/** Analog Terrestrial key.
 * Switches to analog terrestrial broadcast service. */
KEYCODE_TV_TERRESTRIAL_ANALOG = 235;
/** Digital Terrestrial key.
 * Switches to digital terrestrial broadcast service. */
KEYCODE_TV_TERRESTRIAL_DIGITAL = 236;
/** Satellite key.
 * Switches to digital satellite broadcast service. */
KEYCODE_TV_SATELLITE = 237;
/** BS key.
 * Switches to BS digital satellite broadcasting service available in Japan. */
KEYCODE_TV_SATELLITE_BS = 238;
/** CS key.
 * Switches to CS digital satellite broadcasting service available in Japan. */
KEYCODE_TV_SATELLITE_CS = 239;
/** BS/CS key.
 * Toggles between BS and CS digital satellite services. */
KEYCODE_TV_SATELLITE_SERVICE = 240;
/** Toggle Network key.
 * Toggles selecting broacast services. */
KEYCODE_TV_NETWORK = 241;
/** Antenna/Cable key.
 * Toggles broadcast input source between antenna and cable. */
KEYCODE_TV_ANTENNA_CABLE = 242;
/** HDMI #1 key.
 * Switches to HDMI input #1. */
KEYCODE_TV_INPUT_HDMI_1 = 243;
/** HDMI #2 key.
 * Switches to HDMI input #2. */
KEYCODE_TV_INPUT_HDMI_2 = 244;
/** HDMI #3 key.
 * Switches to HDMI input #3. */
KEYCODE_TV_INPUT_HDMI_3 = 245;
/** HDMI #4 key.
 * Switches to HDMI input #4. */
KEYCODE_TV_INPUT_HDMI_4 = 246;
/** Composite #1 key.
 * Switches to composite video input #1. */
KEYCODE_TV_INPUT_COMPOSITE_1 = 247;
/** Composite #2 key.
 * Switches to composite video input #2. */
KEYCODE_TV_INPUT_COMPOSITE_2 = 248;
/** Component #1 key.
 * Switches to component video input #1. */
KEYCODE_TV_INPUT_COMPONENT_1 = 249;
/** Component #2 key.
 * Switches to component video input #2. */
KEYCODE_TV_INPUT_COMPONENT_2 = 250;
/** VGA #1 key.
 * Switches to VGA (analog RGB) input #1. */
KEYCODE_TV_INPUT_VGA_1 = 251;
/** Audio description key.
 * Toggles audio description off / on. */
KEYCODE_TV_AUDIO_DESCRIPTION = 252;
/** Audio description mixing volume up key.
 * Louden audio description volume as compared with normal audio volume. */
KEYCODE_TV_AUDIO_DESCRIPTION_MIX_UP = 253;
/** Audio description mixing volume down key.
 * Lessen audio description volume as compared with normal audio volume. */
KEYCODE_TV_AUDIO_DESCRIPTION_MIX_DOWN = 254;
/** Zoom mode key.
 * Changes Zoom mode (Normal, Full, Zoom, Wide-zoom, etc.) */
KEYCODE_TV_ZOOM_MODE = 255;
/** Contents menu key.
 * Goes to the title list. Corresponds to Contents Menu (0x0B) of CEC User Control
 * Code */
KEYCODE_TV_CONTENTS_MENU = 256;
/** Media context menu key.
 * Goes to the context menu of media contents. Corresponds to Media Context-sensitive
 * Menu (0x11) of CEC User Control Code. */
KEYCODE_TV_MEDIA_CONTEXT_MENU = 257;
/** Timer programming key.
 * Goes to the timer recording menu. Corresponds to Timer Programming (0x54) of
 * CEC User Control Code. */
KEYCODE_TV_TIMER_PROGRAMMING = 258;
/** Help key. */
KEYCODE_HELP = 259;
/** Navigate to previous key.
 * Goes backward by one item in an ordered collection of items. */
KEYCODE_NAVIGATE_PREVIOUS = 260;
/** Navigate to next key.
 * Advances to the next item in an ordered collection of items. */
KEYCODE_NAVIGATE_NEXT = 261;
/** Navigate in key.
 * Activates the item that currently has focus or expands to the next level of a navigation
 * hierarchy. */
KEYCODE_NAVIGATE_IN = 262;
/** Navigate out key.
 * Backs out one level of a navigation hierarchy or collapses the item that currently has
 * focus. */
KEYCODE_NAVIGATE_OUT = 263;
/** Primary stem key for Wear
 * Main power/reset button on watch. */
KEYCODE_STEM_PRIMARY = 264;
/** Generic stem key 1 for Wear */
KEYCODE_STEM_1 = 265;
/** Generic stem key 2 for Wear */
KEYCODE_STEM_2 = 266;
/** Generic stem key 3 for Wear */
KEYCODE_STEM_3 = 267;
/** Directional Pad Up-Left */
KEYCODE_DPAD_UP_LEFT = 268;
/** Directional Pad Down-Left */
KEYCODE_DPAD_DOWN_LEFT = 269;
/** Directional Pad Up-Right */
KEYCODE_DPAD_UP_RIGHT = 270;
/** Directional Pad Down-Right */
KEYCODE_DPAD_DOWN_RIGHT = 271;
/** Skip forward media key. */
KEYCODE_MEDIA_SKIP_FORWARD = 272;
/** Skip backward media key. */
KEYCODE_MEDIA_SKIP_BACKWARD = 273;
/** Step forward media key.
 * Steps media forward, one frame at a time. */
KEYCODE_MEDIA_STEP_FORWARD = 274;
/** Step backward media key.
 * Steps media backward, one frame at a time. */
KEYCODE_MEDIA_STEP_BACKWARD = 275;
/** put device to sleep unless a wakelock is held. */
KEYCODE_SOFT_SLEEP = 276;
/** Cut key. */
KEYCODE_CUT = 277;
/** Copy key. */
KEYCODE_COPY = 278;
/** Paste key. */
KEYCODE_PASTE = 279;
/** Consumed by the system for navigation up */
KEYCODE_SYSTEM_NAVIGATION_UP = 280;
/** Consumed by the system for navigation down */
KEYCODE_SYSTEM_NAVIGATION_DOWN = 281;
/** Consumed by the system for navigation left*/
KEYCODE_SYSTEM_NAVIGATION_LEFT = 282;
/** Consumed by the system for navigation right */
KEYCODE_SYSTEM_NAVIGATION_RIGHT = 283;

  /** Key code constant: Show all apps */
public static final int KEYCODE_ALL_APPS = 284;
/** Key code constant: Refresh key. */
public static final int KEYCODE_REFRESH = 285;
/** Key code constant: Thumbs up key. Apps can use this to let user upvote content. */
public static final int KEYCODE_THUMBS_UP = 286;
/** Key code constant: Thumbs down key. Apps can use this to let user downvote content. */
public static final int KEYCODE_THUMBS_DOWN = 287;

###Notes

Currently the last key code is KEYCODE_SYSTEM_NAVIGATION_RIGHT, which is 283 (but check the source code to make sure this is still true). So you could loop through them like this:

  for (int keyCode = 0; keyCode <= 287; keyCode++) {

  }

Most input to EditText (or a custom view that accepts keyboard input) from an Input Method Editor (IME) is done using an Input Connection, so many key codes are not sent at all in this case. See this answer.


来源: stackexchange

问:
IOptionsSnapshot not refreshes after *.json file changed
I followed the hello world example form IOptionsSnapshot, but the content is not refreshed after file config.json is changed and saved.

My dev environment:

1.VS 2017

2 .csproj file below

```<code>  <PropertyGroup>
        <TargetFramework>netcoreapp1.1</TargetFramework>
        <PreserveCompilationContext>true</PreserveCompilationContext>
        <AssemblyName>UsingOptions</AssemblyName>
        <OutputType>Exe</OutputType>
        <PackageId>UsingOptions</PackageId>
        <RuntimeFrameworkVersion>1.0.4</RuntimeFrameworkVersion>
        <PackageTargetFallback>$(PackageTargetFallback);dotnet5.6;portable-net45+win8</PackageTargetFallback>
      </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore" Version="1.1.1" />
    <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="1.1.1" />
    <PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="1.1.1" />
    <PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="1.1.1" />
    <PackageReference Include="Microsoft.Extensions.Configuration" Version="1.1.1" />
    <PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="1.1.1" />
    <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="1.1.1" />
    <PackageReference Include="Microsoft.Extensions.Options" Version="1.1.1" />
    <PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="1.1.1" />
    <PackageReference Include="Microsoft.AspNetCore.Diagnostics" Version="1.1.1" />
    <PackageReference Include="Microsoft.Extensions.Logging" Version="1.1.1" />
    <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="1.1.1" />
  </ItemGroup>
</code>```

Below is the code from IOptionsSnapshot

```<code>config.json:
{
  "Time": {
    "Message": "Hello "
  }
}

public class TimeOptions
{
    // Records the time when the options are created.
    public DateTime CreationTime { get; set; } = DateTime.Now;

    // Bound to config. Changes to the value of "Message"
    // in config.json will be reflected in this property.
    public string Message { get; set; }
}

public class Controller
{
    public readonly TimeOptions _options;

    public Controller(IOptionsSnapshot<TimeOptions> options)
    {
        _options = options.Value;
    }

    public Task DisplayTimeAsync(HttpContext context)
    {
        return context.Response.WriteAsync(_options.Message + _options.CreationTime);
    }
}

public class Startup
{
    public Startup(IHostingEnvironment env)
    {
        var builder = new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            // reloadOnChange: true is required for config changes to be detected.
            .AddJsonFile("config.json", optional: false, reloadOnChange: true)
            .AddEnvironmentVariables();
        Configuration = builder.Build();
    }

    public IConfigurationRoot Configuration { get; set; }

    public void Configure(IApplicationBuilder app)
    {
        // Simple mockup of a simple per request controller that writes
        // the creation time and message of TimeOptions.
        app.Run(DisplayTimeAsync);
    }

    public void ConfigureServices(IServiceCollection services)
    {
        // Simple mockup of a simple per request controller.
        services.AddScoped<Controller>();

        // Binds config.json to the options and setups the change tracking.
        services.Configure<TimeOptions>(Configuration.GetSection("Time"));
    }

    public Task DisplayTimeAsync(HttpContext context)
    {
        context.Response.ContentType = "text/plain";
        return context.RequestServices.GetRequiredService<Controller>().DisplayTimeAsync(context);
    }

    public static void Main(string[] args)
    {
        var host = new WebHostBuilder()
            .UseKestrel()
            .UseIISIntegration()
            .UseStartup<Startup>()
            .Build();
        host.Run();
    }
}
</code>```

答:
The source code of IOptions and IOptionsSnapshot look the same. Those interfaces have common implementation in OptionsManager. So OptionsSnapshot does not reload options. Instead of IOptionsSnapshot, use IOptionsMonitor. You do not need to subscribe to OnChange event, just access to CurrentValue property.

UPD
Since Microsoft.Extensions.Options 2.x release IOptionsSnapshot has been removed.

ContentLicense: CC BY-SA 3.0

Body:
I followed the hello world example form IOptionsSnapshot, but the content is not refreshed after file config.json is changed and saved.

My dev environment:

1.VS 2017

2 .csproj file below

  <PropertyGroup>
        <TargetFramework>netcoreapp1.1</TargetFramework>
        <PreserveCompilationContext>true</PreserveCompilationContext>
        <AssemblyName>UsingOptions</AssemblyName>
        <OutputType>Exe</OutputType>
        <PackageId>UsingOptions</PackageId>
        <RuntimeFrameworkVersion>1.0.4</RuntimeFrameworkVersion>
        <PackageTargetFallback>$(PackageTargetFallback);dotnet5.6;portable-net45+win8</PackageTargetFallback>
      </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore" Version="1.1.1" />
    <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="1.1.1" />
    <PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="1.1.1" />
    <PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="1.1.1" />
    <PackageReference Include="Microsoft.Extensions.Configuration" Version="1.1.1" />
    <PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="1.1.1" />
    <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="1.1.1" />
    <PackageReference Include="Microsoft.Extensions.Options" Version="1.1.1" />
    <PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="1.1.1" />
    <PackageReference Include="Microsoft.AspNetCore.Diagnostics" Version="1.1.1" />
    <PackageReference Include="Microsoft.Extensions.Logging" Version="1.1.1" />
    <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="1.1.1" />
  </ItemGroup>

Below is the code from IOptionsSnapshot

config.json:
{
  "Time": {
    "Message": "Hello "
  }
}

public class TimeOptions
{
    // Records the time when the options are created.
    public DateTime CreationTime { get; set; } = DateTime.Now;

    // Bound to config. Changes to the value of "Message"
    // in config.json will be reflected in this property.
    public string Message { get; set; }
}

public class Controller
{
    public readonly TimeOptions _options;

    public Controller(IOptionsSnapshot<TimeOptions> options)
    {
        _options = options.Value;
    }

    public Task DisplayTimeAsync(HttpContext context)
    {
        return context.Response.WriteAsync(_options.Message + _options.CreationTime);
    }
}

public class Startup
{
    public Startup(IHostingEnvironment env)
    {
        var builder = new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            // reloadOnChange: true is required for config changes to be detected.
            .AddJsonFile("config.json", optional: false, reloadOnChange: true)
            .AddEnvironmentVariables();
        Configuration = builder.Build();
    }

    public IConfigurationRoot Configuration { get; set; }

    public void Configure(IApplicationBuilder app)
    {
        // Simple mockup of a simple per request controller that writes
        // the creation time and message of TimeOptions.
        app.Run(DisplayTimeAsync);
    }

    public void ConfigureServices(IServiceCollection services)
    {
        // Simple mockup of a simple per request controller.
        services.AddScoped<Controller>();

        // Binds config.json to the options and setups the change tracking.
        services.Configure<TimeOptions>(Configuration.GetSection("Time"));
    }

    public Task DisplayTimeAsync(HttpContext context)
    {
        context.Response.ContentType = "text/plain";
        return context.RequestServices.GetRequiredService<Controller>().DisplayTimeAsync(context);
    }

    public static void Main(string[] args)
    {
        var host = new WebHostBuilder()
            .UseKestrel()
            .UseIISIntegration()
            .UseStartup<Startup>()
            .Build();
        host.Run();
    }
}

ContentLicense: CC BY-SA 4.0


问:
PHP/AJAX checking users last online
I want to create a piece of code that checks if an individual user is online.

I have a nice style that can display a green online circle for if the user is online.

Picture of PHP example

I have the code to make this function for PHP but i want to make it available in real time (without the page refreshing, change the users icon to a grey circle for when they're offline or a green circle for when they're online) maybe using AJAX. Like I said, i have the classes to show the circles so I dont need any styling done. Just the AJAX to make it check if they're online without a refresh.

I also have a piece of code that checks how many clients are online without a refresh and is working but i'm not sure how to go about making that in to getting individual clients times. I will post both of my codes below.

My PHP working but without AJAX code (requires page load for user status to change) :

```<code><?php
    $user_grab = mysqli_query($con, "SELECT * FROM users");
    while($users_ = mysqli_fetch_array($user_grab)) {

        $last_online = strtotime($users_['lastonline']);

        if(time() - $last_online < user_session_timeout()) {
            echo '
                 <div class="chat-list-item -available" style="background: rgba(255,255,255,0.1);">
                    <img class="chat-list-avatar" src="'.$users_['profile_picture'].'"/><i class="fa fa-circle chat-list-status"> </i>
                    <div class="chat-list-user">'.$users_['username'].' (<font size="2">'.get_users_level_all($users_['userLevel']).'</font>)</div>
                    <div class="chat-list-excerpt">Online</div>
                 </div>
            ';
        } else {
            echo '
                 <div class="chat-list-item -offline" style="background: rgba(255,255,255,0.1); padding: 5px;">
                    <img class="chat-list-avatar" src="'.$users_['profile_picture'].'"/><i class="fa fa-circle chat-list-status"> </i>
                    <div class="chat-list-user">'.$users_['username'].' (<font size="2">'.get_users_level_all($users_['userLevel']).'</font>)</div>
                    <div class="chat-list-excerpt">Offline</div>
                 </div>
            ';
        }
    }
?>
</code>```

`

I have some PHP code which works (it gets the current online users) but i dont know how to make it check each users online status and display different classes if they're online or offline.

The code :

```<code>$session    = session_id();
$time       = time();
$time_check = $time - 300;     //We Have Set Time 5 Minutes

$sql    = "SELECT * FROM online_users WHERE session = '$session'";
$result = mysqli_query($con, $sql);
$count  = mysqli_num_rows($result);

//If count is 0 , then enter the values
if($count == "0") {
    $sql1    = "INSERT INTO online_users(session, time) VALUES ('$session', '$time')";
    $result1 = mysqli_query($con, $sql1);
}

 // else update the values
 else {
    $sql2    = "UPDATE online_users SET time = '$time' WHERE session = '$session'";
    $result2 = mysqli_query($con, $sql2);
}

 $sql3              = "SELECT * FROM online_users";
 $result3           = mysqli_query($con, $sql3);
 $count_user_online = mysqli_num_rows($result3);
 echo "<b>Users Online : </b> $count_user_online ";

 // after 5 minutes, session will be deleted
 $sql4    = "DELETE FROM online_users WHERE time < $time_check";
 $result4 = mysqli_query($con, $sql4);
</code>```

I only have AJAX for getting the online users for now.
I want a piece of AJAX code which will check each user's online status and display the different online / offline classes I use at the top section code of this question:

My AJAX for getting online clients :

```<code><script>
    function fetchOnline() {
        $.ajax({
            url: "includes/get_dash_settings.php",
            context: document.body,
            success: function(value){
                var data = value.split(",");
                $('#totalUsers').html(data[0]);
                $('#totalOnline').html(data[1]);
                $('#freeModeStatus').html(data[2]);
                $('#bypassesStatus').html(data[3]);
            },
            complete:function(){
               setTimeout(fetchOnline,5000);
            }
        })
    }

    $(document).ready(function() { setInterval(fetchOnline,5000); });
</script>
</code>```

答: I suggest that rather than return JSON with information about that user along with another JSON keypair about how many users are on line. Then, you can act on the JSON that is returned to update elements on your page based on the results.</p>

Title: PHP/AJAX checking users last online

Body:
I want to create a piece of code that checks if an individual user is online.

I have a nice style that can display a green online circle for if the user is online.

Picture of PHP example

I have the code to make this function for PHP but i want to make it available in real time (without the page refreshing, change the users icon to a grey circle for when they're offline or a green circle for when they're online) maybe using AJAX. Like I said, i have the classes to show the circles so I dont need any styling done. Just the AJAX to make it check if they're online without a refresh.

I also have a piece of code that checks how many clients are online without a refresh and is working but i'm not sure how to go about making that in to getting individual clients times. I will post both of my codes below.

My PHP working but without AJAX code (requires page load for user status to change) :

<?php
    $user_grab = mysqli_query($con, "SELECT * FROM users");
    while($users_ = mysqli_fetch_array($user_grab)) {

        $last_online = strtotime($users_['lastonline']);

        if(time() - $last_online < user_session_timeout()) {
            echo '

'.$users_['username'].' ('.get_users_level_all($users_['userLevel']).')

Online

            ';
        } else {
            echo '

'.$users_['username'].' ('.get_users_level_all($users_['userLevel']).')

Offline

            ';
        }
    }
?>

`

I have some PHP code which works (it gets the current online users) but i dont know how to make it check each users online status and display different classes if they're online or offline.

The code :

$session    = session_id();
$time       = time();
$time_check = $time - 300;     //We Have Set Time 5 Minutes

$sql    = "SELECT * FROM online_users WHERE session = '$session'";
$result = mysqli_query($con, $sql);
$count  = mysqli_num_rows($result);

//If count is 0 , then enter the values
if($count == "0") {
    $sql1    = "INSERT INTO online_users(session, time) VALUES ('$session', '$time')";
    $result1 = mysqli_query($con, $sql1);
}

 // else update the values
 else {
    $sql2    = "UPDATE online_users SET time = '$time' WHERE session = '$session'";
    $result2 = mysqli_query($con, $sql2);
}

 $sql3              = "SELECT * FROM online_users";
 $result3           = mysqli_query($con, $sql3);
 $count_user_online = mysqli_num_rows($result3);
 echo "Users Online :  $count_user_online ";

 // after 5 minutes, session will be deleted
 $sql4    = "DELETE FROM online_users WHERE time < $time_check";
 $result4 = mysqli_query($con, $sql4);

I only have AJAX for getting the online users for now.
I want a piece of AJAX code which will check each user's online status and display the different online / offline classes I use at the top section code of this question:

My AJAX for getting online clients :


问:
Usage of raw_input in python
I am having so much trouble with this python script:

```<code>import time
print "Loading Interface"
time.sleep(0.5)
print "Loaded Interface"
time.sleep(1)
question_one = raw_input = "Request: Enter your name: "
question_two = raw_input = "Request: Enter your password: "
time.sleep(1)
print "Searching for %s with the password %s in our database." % (question_one, question_two)
</code>```

Could anyone tell me what I am doing wrong?

答:
raw_input is a function, so you have to call it and not just assign some value to it.

Try this:

```<code>question_one = raw_input("Request: Enter your name: ")
</code>```

Title: Usage of raw_input in python

Body:
I am having so much trouble with this python script:

import time
print "Loading Interface"
time.sleep(0.5)
print "Loaded Interface"
time.sleep(1)
question_one = raw_input = "Request: Enter your name: "
question_two = raw_input = "Request: Enter your password: "
time.sleep(1)
print "Searching for %s with the password %s in our database." % (question_one, question_two)

Could anyone tell me what I am doing wrong?

Body:
raw_input is a function, so you have to call it and not just assign some value to it.

Try this:

question_one = raw_input("Request: Enter your name: ")


问:
Querying into a complex object with Dapper
I have a Customer class with the following properties:

```<code>public int Id { get; set; }
public string Name { get; set; }
public int AddressId { get; set; }
public Address Address { get; set; }
</code>```

My goal is to write a Dapper query that will use an Inner Join to populate the entire Address property within each Customer that is returned.

Here is what I have and it is working but I am wondering if this is the cleanest/simplest way to do it:

```<code>StringBuilder sql = new StringBuilder();
using (var conn = GetOpenConnection())
{
    sql.AppendLine("SELECT c.Id, c.Name, c.AddressId, a.Address1, a.Address2, a.City, a.State, a.ZipCode ");
    sql.AppendLine("FROM Customer c ");
    sql.AppendLine("INNER JOIN Address a ON c.AddressId = a.Id ");

    return conn.Query<Customer, Address, Customer>(
        sql.ToString(),
        (customer, address) => {
            customer.Address= address;
            return userRole;
        },
        splitOn: "AddressId"
    ).ToList();
}
</code>```

I have some concern about adding another property such as:

```<code>public Contact Contact { get; set; }
</code>```

I am not sure how I would switch the syntax above to populate both Address and Contact.

答:
I have coded using Dapper version 1.40 and I have written queries like the way below, I haven't got any issues to populate mote more than one object, but I have faced a limit of 8 different classes those I can map in a query. </p>

```<code>public class Customer {
    public int Id { get; set; }
    public string Name { get; set; }
    public int AddressId { get; set; }
    public int ContactId { get; set; }
    public Address Address { get; set; }
    public Contact Contact { get; set; }
}

public class Address {
    public int Id { get; set; }
    public string Address1 {get;set;}
    public string Address2 {get;set;}
    public string City {get;set;}
    public string State {get;set;}
    public int ZipCode {get;set;}
    public IEnumerable<Customer> Customer {get;set;}
}

public class Contact {
    public int Id { get; set; }
    public string Name { get; set; }
    public IEnumerable<Customer> Customer {get;set;}
}

using (var conn = GetOpenConnection())
{
    var query = _contextDapper
        .Query<Customer, Address, Contact, Customer>($@"
            SELECT c.Id, c.Name,
                c.AddressId, a.Id, a.Address1, a.Address2, a.City, a.State, a.ZipCode,
                c.ContactId, ct.Id, ct.Name
            FROM Customer c
            INNER JOIN Address a ON a.Id = c.AddressId
            INNER JOIN Contact ct ON ct.Id = c.ContactId",
            (c, a, ct) =>
            {
                c.LogType = a;
                c.Contact = ct;
                return c;
            }, splitOn: "AddressId, ContactId")
        .AsQueryable();

    return query.ToList();
}
</code>```

Body:
I have a Customer class with the following properties:

public int Id { get; set; }
public string Name { get; set; }
public int AddressId { get; set; }
public Address Address { get; set; }

My goal is to write a Dapper query that will use an Inner Join to populate the entire Address property within each Customer that is returned.

Here is what I have and it is working but I am wondering if this is the cleanest/simplest way to do it:

StringBuilder sql = new StringBuilder();
using (var conn = GetOpenConnection())
{
    sql.AppendLine("SELECT c.Id, c.Name, c.AddressId, a.Address1, a.Address2, a.City, a.State, a.ZipCode ");
    sql.AppendLine("FROM Customer c ");
    sql.AppendLine("INNER JOIN Address a ON c.AddressId = a.Id ");

    return conn.Query<Customer, Address, Customer>(
        sql.ToString(),
        (customer, address) => {
            customer.Address= address;
            return userRole;
        },
        splitOn: "AddressId"
    ).ToList();
}

I have some concern about adding another property such as:

public Contact Contact { get; set; }

I am not sure how I would switch the syntax above to populate both Address and Contact.

Body:
I have coded using Dapper version 1.40 and I have written queries like the way below, I haven't got any issues to populate mote more than one object, but I have faced a limit of 8 different classes those I can map in a query.

public class Customer {
    public int Id { get; set; }
    public string Name { get; set; }
    public int AddressId { get; set; }
    public int ContactId { get; set; }
    public Address Address { get; set; }
    public Contact Contact { get; set; }
}

public class Address {
    public int Id { get; set; }
    public string Address1 {get;set;}
    public string Address2 {get;set;}
    public string City {get;set;}
    public string State {get;set;}
    public int ZipCode {get;set;}
    public IEnumerable<Customer> Customer {get;set;}
}

public class Contact {
    public int Id { get; set; }
    public string Name { get; set; }
    public IEnumerable<Customer> Customer {get;set;}
}

using (var conn = GetOpenConnection())
{
    var query = _contextDapper
        .Query<Customer, Address, Contact, Customer>($@"
            SELECT c.Id, c.Name,
                c.AddressId, a.Id, a.Address1, a.Address2, a.City, a.State, a.ZipCode,
                c.ContactId, ct.Id, ct.Name
            FROM Customer c
            INNER JOIN Address a ON a.Id = c.AddressId
            INNER JOIN Contact ct ON ct.Id = c.ContactId",
            (c, a, ct) =>
            {
                c.LogType = a;
                c.Contact = ct;
                return c;
            }, splitOn: "AddressId, ContactId")
        .AsQueryable();

    return query.ToList();
}


问:
Joining two tables in rails
I am trying to link the location and the operating tables so that I can display some data in location table in the operatings views. However, I am stuck and don't know what to do. Any help would be appreciated.           </p>

```<code> #below are models#
 class Location < ApplicationRecord
    has_many :operatings
 end

 class Operating < ApplicationRecord
    belongs_to :location
 end

 ##below are my tables##

 enable_extension "plpgsql"

 create_table "locations", force: :cascade do |t|
    t.string   "country"
    t.string   "supra_region"
    t.string   "region"
    t.datetime "created_at",   null: false
    t.datetime "updated_at",   null: false
 end

 create_table "operatings", force: :cascade do |t|
  t.string   "operating_company_name"
  t.string   "address"
  t.date     "year_formed"
  t.string   "other_operational_countries"
  t.string   "about_company"
  t.string   "current_focus"
  t.string   "incumbent_irm_contractor"
  t.string   "irm_frame_agreements"
  t.text     "estimated_irm_budgets"
  t.integer  "location_id"
  t.datetime "created_at",                  null: false
  t.datetime "updated_at",                  null: false
  t.index ["location_id"], name: "index_operatings_on_location_id", using: :btree
 end

 add_foreign_key "operatings", "locations"

 ###below is my operating controller###

  def create
     @operating = Operating.new(op_company)
     if @operating.save
        flash[:success] = "A recorded has been successfully Saved"
        redirect_to operatings_path
     else
        render 'new'
     end
  end

 ####routes####
 resources :offshores,    :index, :show, :new, :create, :destroy
 resources :locations,    :index, :show, :new, :create, :destroy
</code>```

答:
Since your Location and Operating models are linked together using has_many and belongs_to, if you have an operating object in your template, you can easily access the attributes of its location:

```<code><% @operatings.each do |operating| %>
  <div>The name of its location: <%= operating.location.name %></div>
<% end %>
</code>```

You need to be careful with this though. If you only fetch the operatings from the database, accessing each operating's location attribute in that each loop will trigger a separate database query for every operating item. This is called an N+1 query, and it is very inefficient. To fix the problem, make sure to pre-fetch the associated location as well when loading operatings using includes:

```<code># in the controller
@operatings = Operating.all.includes(:location)
</code>```

This way the associated locations of every operating will be fetched using just a single query.

Title: Joining two tables in rails

Body:
I am trying to link the location and the operating tables so that I can display some data in location table in the operatings views. However, I am stuck and don't know what to do. Any help would be appreciated.

 #below are models#
 class Location < ApplicationRecord
    has_many :operatings
 end

 class Operating < ApplicationRecord
    belongs_to :location
 end

 ##below are my tables##

 enable_extension "plpgsql"

 create_table "locations", force: :cascade do |t|
    t.string   "country"
    t.string   "supra_region"
    t.string   "region"
    t.datetime "created_at",   null: false
    t.datetime "updated_at",   null: false
 end

 create_table "operatings", force: :cascade do |t|
  t.string   "operating_company_name"
  t.string   "address"
  t.date     "year_formed"
  t.string   "other_operational_countries"
  t.string   "about_company"
  t.string   "current_focus"
  t.string   "incumbent_irm_contractor"
  t.string   "irm_frame_agreements"
  t.text     "estimated_irm_budgets"
  t.integer  "location_id"
  t.datetime "created_at",                  null: false
  t.datetime "updated_at",                  null: false
  t.index ["location_id"], name: "index_operatings_on_location_id", using: :btree
 end

 add_foreign_key "operatings", "locations"

 ###below is my operating controller###

  def create
     @operating = Operating.new(op_company)
     if @operating.save
        flash[:success] = "A recorded has been successfully Saved"
        redirect_to operatings_path
     else
        render 'new'
     end
  end

 ####routes####
 resources :offshores,    :index, :show, :new, :create, :destroy
 resources :locations,    :index, :show, :new, :create, :destroy

Body:
Since your Location and Operating models are linked together using has_many and belongs_to, if you have an operating object in your template, you can easily access the attributes of its location:

<% @operatings.each do |operating| %>
  <div>The name of its location: <%= operating.location.name %></div>
<% end %>

You need to be careful with this though. If you only fetch the operatings from the database, accessing each operating's location attribute in that each loop will trigger a separate database query for every operating item. This is called an N+1 query, and it is very inefficient. To fix the problem, make sure to pre-fetch the associated location as well when loading operatings using includes:

# in the controller
@operatings = Operating.all.includes(:location)

This way the associated locations of every operating will be fetched using just a single query.


答:
I did not really understand from where those values <37, 38, 39, 40> came from in the lower 4 rows of the 1st column of the desired result that. I ignored those and assumed that those values were not supposed to be replaced.

The following my_cycle() function is not designed to be a general purposed for any iterable, it is here only to help us only with text1.txt. Though it can be modified for other purposes. I tried to have a modified version of itertools.cycle() to update a particular value after each cycle, in this case, the 3rd column from the right of test1.txt. To have a better understanding of itertools.cycle(), go through this post. And Python documentation is always helpful.

```<code>def update_targeted_column(element):
    list_elem = element.split()
    new_element = '    '.join(list_elem[:-3] + [str(int(list_elem[-3]) + 1)] + list_elem[-2:])
    return '\n    ' + new_element

def my_cycle(iterable):
    """After each iteration of all rows, my_cycle() should increment the 3rd right-most column by 1"""
    saved = []
    for element in iterable:
        yield element
        saved.append(update_targeted_column(element))
    while saved:
        for element in saved:
            yield element
            saved.append(update_targeted_column(element))

# Combining the two files into a third one
with open('f1.txt', 'r') as file_01:
    with open('f2.txt', 'r') as file_02:
        with open('f3.txt', 'a+') as file_03:
            cycled = my_cycle(file_01.readlines())
            for line_01, line_02 in zip(cycled, file_02.readlines()):
                last = '    '.join(line_01.split()[-4:])    # Separating the 4 right-most columns from lines of file_01
                first = '    '.join(line_02.split()[:5])    # Separating the 5 left-most columns from lines of file_02
                print(first + '    ' + last)                # Joining the separated columns to get expected result
                # file_03.write(first + '    ' + last + '\n')
</code>```

Output(in a 3rd file):

```<code>1    N1    31.2480    39.4030    91.8950    n3    1    UNL    -0.696600
2    N2    32.0980    38.3940    91.5460    n3    1    UNL    -0.278400
3    C1    33.0530    38.6590    90.7070    c3    1    UNL    0.169400
4    C2    33.9820    37.5500    90.1880    c3    1    UNL    0.671800
5    N1    55.1040    41.1430    27.6790    n3    2    UNL    -0.696600
6    N2    53.9860    41.7250    27.1570    n3    2    UNL    -0.278400
7    C1    53.7640    41.5940    25.8850    c3    2    UNL    0.169400
8    C2    52.5820    42.3090    25.2080    c3    2    UNL    0.671800
</code>```

Title: How to replace specific columns in a single file repeatedly into another file's columns?

Body:
I'm new to python coding, and I have this two text files that I need to manipulate. Does anyone know how to replace specific columns of one file into another files columns? So, for example,
I want to take  the last four columns of the 'test1.txt',

  1 N1          -3.8340    -1.0640     2.8770 n3         1 UNL      -0.696600
  2 N2          -2.7490    -1.5690     2.2220 n3         1 UNL      -0.278400
  3 C1          -2.3750    -0.9950     1.1200 c3         1 UNL       0.169400
  4 C2          -1.2280    -1.5720     0.2740 c3         1 UNL       0.671800

and replace only the last four columns of first text into 'test2.txt' --note that when it repeats it, the integer in the third to last column will increase.

  1 N1          31.2480    39.4030    91.8950 N.3        1 UNL       0.000000
  2 N2          32.0980    38.3940    91.5460 N.2        1 UNL       0.000000
  3 C1          33.0530    38.6590    90.7070 C.2        1 UNL       0.000000
  4 C2          33.9820    37.5500    90.1880 C.2        1 UNL       0.000000
  5 N1          55.1040    41.1430    27.6790 N.3        2 UNL       0.000000
  6 N2          53.9860    41.7250    27.1570 N.2        2 UNL       0.000000
  7 C1          53.7640    41.5940    25.8850 C.2        2 UNL       0.000000
  8 C2          52.5820    42.3090    25.2080 C.2        2 UNL       0.000000

so that the final result becomes

  1 N1          31.2480    39.4030    91.8950 n3         1 UNL      -0.696600
  2 N2          32.0980    38.3940    91.5460 n3         1 UNL      -0.278400
  3 C1          33.0530    38.6590    90.7070 c3         1 UNL       0.169400
  4 C2          33.9820    37.5500    90.1880 c3         1 UNL       0.671800
  5 N1          55.1040    41.1430    27.6790 n3         2 UNL      -0.696600
  6 N2          53.9860    41.7250    27.1570 n3         2 UNL      -0.278400
  7 C1          53.7640    41.5940    25.8850 c3         2 UNL       0.169400
  8 C2          52.5820    42.3090    25.2080 c3         2 UNL       0.671800

like this...
Is this even a possibility with python coding?
The two files are saved in two different filenames.

Body:
I did not really understand from where those values <37, 38, 39, 40> came from in the lower 4 rows of the 1st column of the desired result that. I ignored those and assumed that those values were not supposed to be replaced.

The following my_cycle() function is not designed to be a general purposed for any iterable, it is here only to help us only with text1.txt. Though it can be modified for other purposes. I tried to have a modified version of itertools.cycle() to update a particular value after each cycle, in this case, the 3rd column from the right of test1.txt. To have a better understanding of itertools.cycle(), go through this post. And Python documentation is always helpful.

def update_targeted_column(element):
    list_elem = element.split()
    new_element = '    '.join(list_elem[:-3] + [str(int(list_elem[-3]) + 1)] + list_elem[-2:])
    return '\n    ' + new_element

def my_cycle(iterable):
    """After each iteration of all rows, my_cycle() should increment the 3rd right-most column by 1"""
    saved = []
    for element in iterable:
        yield element
        saved.append(update_targeted_column(element))
    while saved:
        for element in saved:
            yield element
            saved.append(update_targeted_column(element))

# Combining the two files into a third one
with open('f1.txt', 'r') as file_01:
    with open('f2.txt', 'r') as file_02:
        with open('f3.txt', 'a+') as file_03:
            cycled = my_cycle(file_01.readlines())
            for line_01, line_02 in zip(cycled, file_02.readlines()):
                last = '    '.join(line_01.split()[-4:])    # Separating the 4 right-most columns from lines of file_01
                first = '    '.join(line_02.split()[:5])    # Separating the 5 left-most columns from lines of file_02
                print(first + '    ' + last)                # Joining the separated columns to get expected result
                # file_03.write(first + '    ' + last + '\n')

Output(in a 3rd file):

1    N1    31.2480    39.4030    91.8950    n3    1    UNL    -0.696600
2    N2    32.0980    38.3940    91.5460    n3    1    UNL    -0.278400
3    C1    33.0530    38.6590    90.7070    c3    1    UNL    0.169400
4    C2    33.9820    37.5500    90.1880    c3    1    UNL    0.671800
5    N1    55.1040    41.1430    27.6790    n3    2    UNL    -0.696600
6    N2    53.9860    41.7250    27.1570    n3    2    UNL    -0.278400
7    C1    53.7640    41.5940    25.8850    c3    2    UNL    0.169400
8    C2    52.5820    42.3090    25.2080    c3    2    UNL    0.671800


问:
Shrink double if statement in Python
I cannot use the following statement because x and y may be defined as None:

```<code>if x*y > 9:
    pass
</code>```

unsupported operand type(s) for *: 'NoneType' and 'NoneType'

So I should check first for the existence:

```<code>if x and y:
    if x*y > 9:
        pass
</code>```

It seems a bit redundant. Is there a better way to achieve this?

答:
While if x and y and x * y > 9: is the most straightforward way, an alternative I find satisfying in an hard to define way is to use defaults for x and y when they're falsy:

```<code>if (x or 0) * (y or 0) > 9:
</code>```

Since replacing either value with 0 makes the result 0, the test doesn't pass, as expected, when either value is None. This works because Python boolean and and or don't return True or False they return the last value evaluated (which will be truthy or falsy already). So if x is a non-zero number, you use x, otherwise you use 0, and same goes for y.

Title: Shrink double if statement in Python

Body:
I cannot use the following statement because x and y may be defined as None:

if x*y > 9:
    pass

unsupported operand type(s) for *: 'NoneType' and 'NoneType'

So I should check first for the existence:

if x and y:
    if x*y > 9:
        pass

It seems a bit redundant. Is there a better way to achieve this?

Body:
While if x and y and x * y > 9: is the most straightforward way, an alternative I find satisfying in an hard to define way is to use defaults for x and y when they're falsy:

if (x or 0) * (y or 0) > 9:

Since replacing either value with 0 makes the result 0, the test doesn't pass, as expected, when either value is None. This works because Python boolean and and or don't return True or False they return the last value evaluated (which will be truthy or falsy already). So if x is a non-zero number, you use x, otherwise you use 0, and same goes for y.


问:
Rails / Multi-Tenancy: Conditional default scope based on a different model's db value / global setting?
I've got a Rails application that is multi-tenant. Every model has an account_id, belongs to an account, and has a default scope to a current account id:

```<code>class Derp < ApplicationRecord
  default_scope { where(account_id: Account.current_id) }
  belongs_to :account
end
</code>```

This works well and I've used this pattern in production in other apps (I understand that default scopes are frowned upon, but this is an accepted pattern. See: https://leanpub.com/multi-tenancy-rails).

Now here's the kicker - I have one client (and potentially more down the line, who knows), who wants to run the software on their own server. To solve this, I simply made a Server model with a type attribute:

```<code>class Server < ApplicationRecord
  enum server_type: { multitenant: 0, standalone: 1 }
end
</code>```

Now on my multi-tenant server instance, I simply make one Server record and set the server_type to 0, and on my standalone instance I set it to 1. Then I've got some helper methods in my application controller to help with this, namely:

```<code>class ApplicationController < ActionController::Base
  around_action :scope_current_account

  ...

  def server
    @server ||= Server.first
  end

  def current_account
    if server.standalone?
      @current_account ||= Account.first
    elsif server.first.multitenant?
      @current_account ||= Account.find_by_subdomain(subdomain) if subdomain
    end
  end

  def scope_current_account
    Account.current_id = current_account.id
    yield
  rescue ActiveRecord::RecordNotFound
    redirect_to not_found_path
  ensure
    Account.current_id = nil
  end
end
</code>```

This works, but I've got large record sets that I'm querying on this particular standalone client (70,000 records). I've got an index on the account_id, but it took my main customers table from 100ms to 400ms on my development machine.

Then I realized: standalone servers really don't need to concern themselves with the account id at all, especially if it is going to affect performance.

So really all I've got to do is make this line conditional:

```<code>default_scope { where(account_id: Account.current_id) }
</code>```

I'd like to do something like this:

```<code>class Derp < ApplicationRecord
  if Server.first.multitenant?
    default_scope { where(account_id: Account.current_id) }
  end
end
</code>```

But obviously that syntax wrong. I've seen some other examples on Stack Overflow for conditional scopes, but none seem to work with a conditional statement based on a completely separate model. Is there a way to accomplish something like that in Ruby?

EDIT: Kicker here that I just realized is that this will only solve the speed issue for the one standalone server, and all the multi-tenant accounts will still have to deal with querying with the account_id. Maybe I should focus on that instead...

答:
I would avoid using default_scope as I've been bitten by it in the past. In particular, I've had places in an application where I want to definitely have it scoped, and other places where I don't. The places where I want the scoping typically end up being controllers / background jobs and the places where I don't want / need it end up being the tests.

So with that in mind, I would opt for an explicit method in the controller, rather than an implicit scoping in the model:

Whereas you have:

```<code>class Derp < ApplicationRecord
  if Server.first.multitenant?
    default_scope { where(account_id: Account.current_id) }
  end
end
</code>```

I would have a method in the controller called something like account_derps:

```<code>def account_derps
  Derp.for_account(current_account)
end
</code>```

Then wherever I wanted to load just the derps for the given account I would use account_derps. I would then be free to use Derp to do an unscoped find if I ever needed to do that.

Best part about this method is you could chuck your Server.first.multitenant? logic here too.

You mention another problem here:

This works, but I've got large record sets that I'm querying on this particular standalone client (70,000 records). I've got an index on the account_id, but it took my main customers table from 100ms to 400ms on my development machine.

I think this is most likely due to a missing index. But I don't see the table schema here or the query so I don't know for certain. It could be that you're doing a where query on account_id and some other field, but you've only added the index to the account_id. If you're using PostgreSQL, then an EXPLAIN ANALYZE before the query will point you in the right direction. If you're not sure how to decipher its results (and sometimes they can be tricky to) then I would recommend using the wonderful pev (Postgres EXPLAIN Visualizer) which will point you at the slowest parts of your query in a graphical format.

Lastly, thanks for taking the time to read my book and to ask such a detailed question about a related topic on SO :)

Body:
I've got a Rails application that is multi-tenant. Every model has an account_id, belongs to an account, and has a default scope to a current account id:

class Derp < ApplicationRecord
  default_scope { where(account_id: Account.current_id) }
  belongs_to :account
end

This works well and I've used this pattern in production in other apps (I understand that default scopes are frowned upon, but this is an accepted pattern. See: https://leanpub.com/multi-tenancy-rails).

Now here's the kicker - I have one client (and potentially more down the line, who knows), who wants to run the software on their own server. To solve this, I simply made a Server model with a type attribute:

class Server < ApplicationRecord
  enum server_type: { multitenant: 0, standalone: 1 }
end

Now on my multi-tenant server instance, I simply make one Server record and set the server_type to 0, and on my standalone instance I set it to 1. Then I've got some helper methods in my application controller to help with this, namely:

class ApplicationController < ActionController::Base
  around_action :scope_current_account

  ...

  def server
    @server ||= Server.first
  end

  def current_account
    if server.standalone?
      @current_account ||= Account.first
    elsif server.first.multitenant?
      @current_account ||= Account.find_by_subdomain(subdomain) if subdomain
    end
  end

  def scope_current_account
    Account.current_id = current_account.id
    yield
  rescue ActiveRecord::RecordNotFound
    redirect_to not_found_path
  ensure
    Account.current_id = nil
  end
end

This works, but I've got large record sets that I'm querying on this particular standalone client (70,000 records). I've got an index on the account_id, but it took my main customers table from 100ms to 400ms on my development machine.

Then I realized: standalone servers really don't need to concern themselves with the account id at all, especially if it is going to affect performance.

So really all I've got to do is make this line conditional:

default_scope { where(account_id: Account.current_id) }

I'd like to do something like this:

class Derp < ApplicationRecord
  if Server.first.multitenant?
    default_scope { where(account_id: Account.current_id) }
  end
end

But obviously that syntax wrong. I've seen some other examples on Stack Overflow for conditional scopes, but none seem to work with a conditional statement based on a completely separate model. Is there a way to accomplish something like that in Ruby?

EDIT: Kicker here that I just realized is that this will only solve the speed issue for the one standalone server, and all the multi-tenant accounts will still have to deal with querying with the account_id. Maybe I should focus on that instead...

Body:
I would avoid using default_scope as I've been bitten by it in the past. In particular, I've had places in an application where I want to definitely have it scoped, and other places where I don't. The places where I want the scoping typically end up being controllers / background jobs and the places where I don't want / need it end up being the tests.

So with that in mind, I would opt for an explicit method in the controller, rather than an implicit scoping in the model:

Whereas you have:

class Derp < ApplicationRecord
  if Server.first.multitenant?
    default_scope { where(account_id: Account.current_id) }
  end
end

I would have a method in the controller called something like account_derps:

def account_derps
  Derp.for_account(current_account)
end

Then wherever I wanted to load just the derps for the given account I would use account_derps. I would then be free to use Derp to do an unscoped find if I ever needed to do that.

Best part about this method is you could chuck your Server.first.multitenant? logic here too.

You mention another problem here:

This works, but I've got large record sets that I'm querying on this particular standalone client (70,000 records). I've got an index on the account_id, but it took my main customers table from 100ms to 400ms on my development machine.

I think this is most likely due to a missing index. But I don't see the table schema here or the query so I don't know for certain. It could be that you're doing a where query on account_id and some other field, but you've only added the index to the account_id. If you're using PostgreSQL, then an EXPLAIN ANALYZE before the query will point you in the right direction. If you're not sure how to decipher its results (and sometimes they can be tricky to) then I would recommend using the wonderful pev (Postgres EXPLAIN Visualizer) which will point you at the slowest parts of your query in a graphical format.

Lastly, thanks for taking the time to read my book and to ask such a detailed question about a related topic on SO :)