Detecting soft keyboard being open / KeyEvent using a Service

I've read most of the posts here regarding detecting soft keyboards or detecting KeyEvent. I saw methods such as measuring the size of the view. However, the issue of my case is that I'd like to detect whether the soft keyboard is open or KeyEvent using a "service." Is it possible to do it via a service? Or, would it be possible to detect someone is typing in an activity? I'm working on a research and I need to log some activities on a phone, which include detecting typing in an activity. Thanks!


I found a tricky way to "kind of" solve this. However, this requires your user to do something for you if you have that power :) So obviously this will not solve all of your problems.

My tricky way is to use the AccessibilityEvent. You can specify which event you want to listen. One of the events that is related to window size is TYPE_WINDOW_CONTENT_CHANGED ( see below)

public static final int TYPE_WINDOW_CONTENT_CHANGED

Added in API level 14
Represents the event of changing the content of a window and more specifically the sub-tree rooted at the event's source.

Constant Value: 2048 (0x00000800)

As long as your accessibility service of your app is enabled, you will receive this event.

To listen to this event, you have to start your own AccessibilityService. Refer to this to learn how to build one. Then you can specify which accessibility event you want to receive. You can specify them either in an xml file:

<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
    android:packageNames="MypackageName"
    android:accessibilityEventTypes="typeWindowStateChanged"
    android:accessibilityFeedbackType="feedbackSpoken"
    android:notificationTimeout="100"
/>

or in the onServiceConnected method:

protected void onServiceConnected() {   
    AccessibilityServiceInfo info = new AccessibilityServiceInfo();    
    info.eventTypes = AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED;
}

Then you will receive the event in the method onAccessibilityEvent(event). However, this method has two drawbacks:

  1. whenever the window state changes, the event is fired.
  2. the user has to enable your accessibility service in [Setting] -> [Accessibility] -> [Services].

Again, this method only works for certain purposes. But it works for the case where you want to detect a soft keyboard "from a service" but not from your activity.


Use this:

boolean isKeyboardOpened() {
    List<AccessibilityWindowInfo> windowInfoList = getWindows();
    for(int k = 0; k < windowInfoList.size(); k++) {
        if(windowInfoList.get(k).getType() == AccessibilityWindowInfo.TYPE_INPUT_METHOD) {
            Log.i(TAG, "keyboard is opened!");
            return true;
        }
    }
    return false;
}

Also use

android:accessibilityFlags="flagRetrieveInteractiveWindows"