http://developer.android.com/guide/topics/text/creating-input-method.html#GeneralDesign
reads:
Because multiple IMEs may be installed on the device, provide a way for the user to switch to a different IME directly from the input method UI.
Let's assume I have the source of two input methods and can modify it.
I want to let the user switch between them quickly and am ready to reserve a button for that.
How do I "switch to a different IME directly from the input method UI"?
Switching to the previous input method from the current input method is:
//final String LATIN = "com.android.inputmethod.latin/.LatinIME";
// 'this' is an InputMethodService
try {
InputMethodManager imm = (InputMethodManager) this.getSystemService(Context.INPUT_METHOD_SERVICE);
final IBinder token = this.getWindow().getWindow().getAttributes().token;
//imm.setInputMethod(token, LATIN);
imm.switchToLastInputMethod(token);
} catch (Throwable t) { // java.lang.NoSuchMethodError if API_level<11
Log.e(TAG,"cannot set the previous input method:");
t.printStackTrace();
}
If you want to switch to a particular input method whose ID you know, you may do as the commented-out lines suggest.
EDIT #pRaNaY suggested a single .getWindow() in a silent edit (click "edited" below to see the history). I remember that it did not work for Android 2.3; if you consult the docs, you will see that the first call, InputMethodService.getWindow() returns a Dialog (which is not a subclass of Window), and the second call, Dialog.getWindow() returns a Window. There is no Dialog.getAttributes(), so with a single .getWindow() it will not even compile.
You cannot change the user's currently active IME through code for security reasons, sorry.
However, you can show a system provided dialog to allow the user to select one of the other enabled ones.
InputMethodManager imeManager = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
if (imeManager != null) {
imeManager.showInputMethodPicker();
} else {
Toast.makeText(context ,"Error", Toast.LENGTH_LONG).show();
}
If you have rooted device, you can use /system/bin/ime utility.
List all installed input methods: # ime list -a
Set google's keyboard as default:
ime set com.google.android.inputmethod.latin/com.android.inputmethod.latin.LatinIME
Related
I am trying to receive the scanned barcode result from a device paired via (Bluetooth/USB) to an android device.
so many topics said :
most plug-in barcode scanners (that I've seen) are made as HID profile devices so whatever they are plugged into should see them as a Keyboard basically.
source
So I am using this code to receive the result of the scan:
#Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (viewModel.onTriggerScan()) {
//1
char pressedKey = (char) event.getUnicodeChar();
viewModel.addCharToCode(pressedKey);
//2
String fullCode = event.getCharacters();
viewModel.fullCode(fullCode);
//check if the scan is done, received all the chars
if (event.getAction() == EditorInfo.IME_ACTION_DONE) {
//does this work ?
viewModel.gotAllChars();
//3
String fullCode2 = event.getCharacters();
viewModel.fullCode(fullCode2);
}
return true;
} else
return super.dispatchKeyEvent(event);
}
Note: I don't have a barcode scanner device for the test.
which code will receive the result ?? (1 or 2 or 3 ?)
You won't ever see an IME_ACTION_DONE, that's something that's Android only and an external keyboard would never generate.
After that, it's really up to how the scanner works. You may get a full key up and key down for each character. You may not, and may receive multiple characters per event. You may see it finish with a terminator (like \n) you may not- depends on how the scanner is configured. Unless you can configure it yourself or tell the user how to configure it, you need to be prepared for either (which means treating the data as done either after seeing the terminator, or after a second or two once new data stops coming in.
Really you need to buy a configurable scanner model and try it in multiple modes and make ever mode works. Expect it to take a few days in your schedule.
Workaround solution but it works 100%.
the solution is based on clone edittext (hidden from the UI), this edit text just receives the result on it, adds a listener, and when the result arrives gets it and clears the edittext field. An important step, when you try to receive the result(trigger scan) make sure that edittext has the focus otherwise you wil not get the result.
Quick steps:
1- create editText (any text field that receives inputs) in your layout
2- set its visibility to "gone" and clear it.
3- add onValueChangeListener to your edittext.
4- focus your edittext when you start trigger the scan
5- each time you the listener call, get the result and clear edittext
Note: never miss to focus your edittext whenever you start trigger scan.
Note: this method work(99%) for all external scan device and any barcode type.
I'm trying to get the available input devices on Android, in order to do that I'm using the InputMethodManager and using the API of getEnabledInputMethodList() as follows:
InputMethodManager inputMgr = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
List<InputMethodInfo> inputMethodList = inputMgr.getEnabledInputMethodList();
for (InputMethodInfo method : inputMethodList) {
List<InputMethodSubtype> subMethods = inputMgr.getEnabledInputMethodSubtypeList(method, true);
for (InputMethodSubtype submethod : subMethods) {
if (submethod.getMode().equals("keyboard")) { //Ignore voice input method
String localeString = submethod.getLocale();
Locale locale = new Locale(localeString);
String currentLanguage = locale.getLanguage();
//do something...
}
}
}
However, although I've got many more input languages available on my LG G3 and MEIZU M2, this API returns only 1 input language - English.
It seems that this API works as expected only on Google Nexus phones.
Has anyone tried to do the same and succeeded?
P.S
I've already read the solution on this thread but it doesn't help much:
how to get user keyboard language
There is no way to do this. A keyboard doesn't report to Android the list of languages it supports.
In fact, most keyboards keep the input language separate from the phone's locale, in order to switch without resetting the UI of the entire phone. So the OS has no idea what languages a keyboard can write in or is currently writing in.
We have a custom scanner to scan barcode using, which works with SOFT trigger (Using App Button) by using Motorola's emdk library.
barcodeManager = (BarcodeManager) this.emdkManager.getInstance(EMDKManager.FEATURE_TYPE.BARCODE);
scanner = barcodeManager.getDevice(BarcodeManager.DeviceIdentifier.DEFAULT);
scanner.addStatusListener(articleListener);
scanner.addDataListener(new Scanner.DataListener() {
#Override
public void onData(ScanDataCollection scanDataCollection) {
processData(scanDataCollection);
}
});
scanner.addDataListener(dataListener);
scanner.triggerType = Scanner.TriggerType.SOFT_ALWAYS;
scanner.enable();
How can i have both soft and Hard trigger to scan the data?
and with datalistener process the data received from both?
Zebra Technologies acquire Motorola Solution enterprise business in Oct. 2014, most of the updated documentation is now available under the Zebra Launchpad.
Scanner.TriggerType controls how you want to activate the barcode scanner on Zebra Android devices, usually you can set it up or Hard (scan is activated pressing the hardware trigger button) or Soft (scan is activated as soon as you call the Scanner.read() method).
To have an application that can use the Hardware trigger and having an on screen button to activate the scanner you can leave set the triggerType to Scanner.TriggerType.HARD and implement a login in the click event handler for the soft scan button so that you set the TriggerType to Scanner.TriggerType.SOFT_ONCE and then you call the Scanner.read() method. You can eventually check if there's another read active.
This is a sample implementation that you can test adding a button in the Barcode API sample included in the EMDK for Android (latest is v4.0):
private void softScan() {
if (scanner != null) {
try {
// Reset continuous flag
bContinuousMode = false;
if (scanner.isReadPending()) {
// Cancel the pending read.
scanner.cancelRead();
}
scanner.triggerType = TriggerType.SOFT_ONCE;
scanner.read();
new AsyncUiControlUpdate().execute(true);
} catch (ScannerException e) {
textViewStatus.setText("Status: " + e.getMessage());
}
}
}
So, usually you work with a TriggerType.HARD, but when you press the SCAN button you disable any pending read and you switch to TriggerType.SCAN_ONCE.
The implementation of the status listener needs to switch back the scanner to TriggerType.HARD and call the read() method.
You can find a complete sample at this github repository where I've added a Soft Scan button to the standard Zebra's EMDK Barcode API sample.
All the data are received by the same Data Listener.
I need to display an alert to the user if they haven't enabled Google voice typing from their settings(Language and input -> Google voice typing). Is there someway to detect that setting status?
So i found my answer. There is no official way of detecting wether voice typing is enabled or not. I have managed to get a list of enabled input methods ( keyboard, voice, etc).
String enabledMethods = Settings.Secure.getString(getActivity().getContentResolver(),Settings.Secure.ENABLED_INPUT_METHODS);
There we can see if Google voice typing is enabled or not and we can alert the user to turn it on, however this applies for the default keyboard. Some users use custom keyboards that have their own implementation of speech to text and it doesn't relly on the users settings for Google voice typing. So it will be a false positive for them.
Given that you know the package name of the IME, you can do something like this:
boolean isImeEnabled(String packageName) {
InputMethodManager imm =
(InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
for (InputMethodInfo imi : imm.getEnabledInputMethodList()) {
if (imi.getPackageName().equals(packageName)) {
return true;
}
}
return false;
}
How do I handle alerts in an Android web application using Appium server (1.0.1) and the Android SDK?
The below code is not working on android:
driver.switchTo().accept().alert();
Error message:
> -modal window does not get closed
You need to get the Alert before you try and accept it
This is code from some of the Appium Java Client Tests:
wait.until(ExpectedConditions.alertIsPresent());
Alert alert = driver.switchTo().alert();
alert.accept();
This should work most of the time.
If accept() isn't working, replace the driver.switchTo().alert(); and alert.accept(); with code to find the button and then click it.
If it's not finding the button wrap findElementBy(Method) code in a try/retry block, and then click on it.
The best way is to use the appium inspector. Click on the element and copy the resource-id from it. Use this resource id in findElement(By.id()) method.
For me resource-id: android:id/button1
((AndroidDriver) driver).findElement(By.id("android:id/button1")).click();
This is for Android. For regular use you can use
driver.findElement(By.id("android:id/button1")).click();
Some alerts may be native Android's alerts, not generated by a browser. In this case the following code:
Alert alert = driver.switchTo().alert(); alert.accept();
may throw:
WebDriverException: unknown error: unhandled inspector error: {"code":-32603,"message":"No JavaScript dialog to handle"}
To handle such alert, just switch to the native application context, make required actions, and then switch back to the browser:
AppiumDriver<WebElement> appiumDriver = (AppiumDriver<WebElement>) webDriver;
String currentContext = appiumDriver.getContext();
appiumDriver.context("NATIVE_APP");
// actions within the alert
appiumDriver.findElements(By.xpath(OK_BUTTON_LOCATOR)).click(); // put locator instead of OK_BUTTON_LOCATOR
appiumDriver.context(currentContext);
// continue working
WebElement btn = driver.findElement(By.xpath("//android.widget.Button[#content-desc='OK']"));
TouchAction act = new TouchAction(driver);
act.tap(241,320).perform();
(241,320) these are X & Y c ordinates of alert
This work perfectly for me
Appium comes with a default capability to accept, dismiss alerts
capabilities.SetCapability("autoAcceptAlerts", true);
capabilities.SetCapability("autoDismissAlerts", true);
If the alert display on Ui , taking more time to display when we need to wait ..we can use fluent wait instead of this..
So an updated answer on this is this: an AlertDialog is a system level element, so clicking on accept button you should use:
androidDriver.findElementById("android:id/button1").click()
else for cancel do this:
androidDriver.findElementById("android:id/button2").click()
// first check alert is present or not
public boolean isAlertPresent() {
try {
mobDriver.switchTo().alert();
log.info("ALERT IS PRESENT !! ");
return true;
} catch (Exception e) {
log.info("ALERT IS NOT PRESENT !! ");
return false;
}
}
public void mobileAlertHandle() {
if (isAlertPresent()) {
Alert alert = mobDriver.switchTo().alert();
alert.accept();
}
}
if this does not work then inspect your element and try with id or name
ex: mobDriver.findElementById("android:id/button2").click()
Please use the below code, Add some wait before clicking on OK Button.
After that pass the xpath of you OK Button.
synchronized (driver)
{
driver.wait(2000);
}
driver.context(NATIVE_APP);
driver.findElementByXPath{("//android.widget.Button[#resourceid=
‘android:id/button1’]").click();