1cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le/* 2cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le * Copyright (C) 2013 DroidDriver committers 3cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le * 4cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le * Licensed under the Apache License, Version 2.0 (the "License"); 5cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le * you may not use this file except in compliance with the License. 6cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le * You may obtain a copy of the License at 7cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le * 8cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le * http://www.apache.org/licenses/LICENSE-2.0 9cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le * 10cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le * Unless required by applicable law or agreed to in writing, software 11cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le * distributed under the License is distributed on an "AS IS" BASIS, 12cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le * See the License for the specific language governing permissions and 14cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le * limitations under the License. 15cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le */ 16cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le 174b31201b5a2dbf8036da5a8d089a68a39cc1dc44Kevin Jinpackage io.appium.droiddriver.actions; 18cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le 19082c7925e5109092ff31d7021f1f9bb6daabee12Kevin Jinimport android.annotation.SuppressLint; 20082c7925e5109092ff31d7021f1f9bb6daabee12Kevin Jinimport android.annotation.TargetApi; 218d19bb634c670a49f7a58636a2a535c86b57d538Kevin Jinimport android.os.Build; 22cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Leimport android.view.KeyEvent; 23cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le 244b31201b5a2dbf8036da5a8d089a68a39cc1dc44Kevin Jinimport io.appium.droiddriver.UiElement; 254b31201b5a2dbf8036da5a8d089a68a39cc1dc44Kevin Jinimport io.appium.droiddriver.util.Events; 264b31201b5a2dbf8036da5a8d089a68a39cc1dc44Kevin Jinimport io.appium.droiddriver.util.Strings; 274b31201b5a2dbf8036da5a8d089a68a39cc1dc44Kevin Jinimport io.appium.droiddriver.util.Strings.ToStringHelper; 28cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le 29cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le/** 30082c7925e5109092ff31d7021f1f9bb6daabee12Kevin Jin * An action to press a single key. While it is convenient for navigating the UI, do not overuse it 31082c7925e5109092ff31d7021f1f9bb6daabee12Kevin Jin * - the application may interpret key codes in a custom way and, more importantly, application 32082c7925e5109092ff31d7021f1f9bb6daabee12Kevin Jin * users may not have access to it because the device (physical or virtual keyboard) may not support 33082c7925e5109092ff31d7021f1f9bb6daabee12Kevin Jin * all key codes. 34cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le */ 3529d66eeee5d30f7db747cceeb84defec961b4125Kevin Jinpublic class SingleKeyAction extends KeyAction { 36082c7925e5109092ff31d7021f1f9bb6daabee12Kevin Jin // Common instances for convenience and memory preservation. 3729d66eeee5d30f7db747cceeb84defec961b4125Kevin Jin public static final SingleKeyAction MENU = new SingleKeyAction(KeyEvent.KEYCODE_MENU); 3829d66eeee5d30f7db747cceeb84defec961b4125Kevin Jin public static final SingleKeyAction SEARCH = new SingleKeyAction(KeyEvent.KEYCODE_SEARCH); 3929d66eeee5d30f7db747cceeb84defec961b4125Kevin Jin public static final SingleKeyAction BACK = new SingleKeyAction(KeyEvent.KEYCODE_BACK); 4029d66eeee5d30f7db747cceeb84defec961b4125Kevin Jin public static final SingleKeyAction DELETE = new SingleKeyAction(KeyEvent.KEYCODE_DEL); 41082c7925e5109092ff31d7021f1f9bb6daabee12Kevin Jin /** Requires SDK API 11 or higher */ 42082c7925e5109092ff31d7021f1f9bb6daabee12Kevin Jin @SuppressLint("InlinedApi") 43337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett public static final SingleKeyAction CTRL_MOVE_HOME = new SingleKeyAction( 44337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett KeyEvent.KEYCODE_MOVE_HOME, KeyEvent.META_CTRL_LEFT_ON); 45082c7925e5109092ff31d7021f1f9bb6daabee12Kevin Jin /** Requires SDK API 11 or higher */ 46082c7925e5109092ff31d7021f1f9bb6daabee12Kevin Jin @SuppressLint("InlinedApi") 47337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett public static final SingleKeyAction CTRL_MOVE_END = new SingleKeyAction( 48337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett KeyEvent.KEYCODE_MOVE_END, KeyEvent.META_CTRL_LEFT_ON); 4970e34108e0fc19277e642aef3b36b65b8e254899Kevin Jin 50cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le private final int keyCode; 51337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett private final int metaState; 52cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le 53082c7925e5109092ff31d7021f1f9bb6daabee12Kevin Jin /** Defaults metaState to 0 */ 5429d66eeee5d30f7db747cceeb84defec961b4125Kevin Jin public SingleKeyAction(int keyCode) { 55337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett this(keyCode, 0); 5621a0001e2426644dd68e6140b5873ebaeafcc3dcKevin Jin } 5721a0001e2426644dd68e6140b5873ebaeafcc3dcKevin Jin 58082c7925e5109092ff31d7021f1f9bb6daabee12Kevin Jin /** Defaults timeoutMillis to 100 and checkFocused to false */ 59337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett public SingleKeyAction(int keyCode, int metaState) { 60337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett this(keyCode, metaState, 100L, false); 61337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett } 62337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett 63337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett public SingleKeyAction(int keyCode, int metaState, long timeoutMillis, boolean checkFocused) { 6470e34108e0fc19277e642aef3b36b65b8e254899Kevin Jin super(timeoutMillis, checkFocused); 65cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le this.keyCode = keyCode; 66337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett this.metaState = metaState; 67cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le } 68cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le 69cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le @Override 70cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le public boolean perform(InputInjector injector, UiElement element) { 7170e34108e0fc19277e642aef3b36b65b8e254899Kevin Jin maybeCheckFocused(element); 7270e34108e0fc19277e642aef3b36b65b8e254899Kevin Jin 73337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett final long downTime = Events.keyDown(injector, keyCode, metaState); 74337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett Events.keyUp(injector, downTime, keyCode, metaState); 75cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le 76337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett return true; 77cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le } 7852b875da168081ca17d5532cebfbe78974ecce55Kevin Jin 79082c7925e5109092ff31d7021f1f9bb6daabee12Kevin Jin @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1) 8052b875da168081ca17d5532cebfbe78974ecce55Kevin Jin @Override 8152b875da168081ca17d5532cebfbe78974ecce55Kevin Jin public String toString() { 828d19bb634c670a49f7a58636a2a535c86b57d538Kevin Jin String keyCodeString = 838d19bb634c670a49f7a58636a2a535c86b57d538Kevin Jin Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB_MR1 ? String.valueOf(keyCode) 848d19bb634c670a49f7a58636a2a535c86b57d538Kevin Jin : KeyEvent.keyCodeToString(keyCode); 85337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett ToStringHelper toStringHelper = Strings.toStringHelper(this); 86337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett if (metaState != 0) { 87337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett toStringHelper.add("metaState", metaState); 88337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett } 89337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett return toStringHelper.addValue(keyCodeString).toString(); 9052b875da168081ca17d5532cebfbe78974ecce55Kevin Jin } 91cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le} 92