GameTextInput Part of Android Game Development Kit.
Using the GameTextInput library is a
simpler alternative to writing a full-screen Android app that uses the soft
keyboard for text input.
GameTextInput provides a straightforward API to show or hide the soft
keyboard, set or get the currently-edited text, and receive notifications when
the text is changed. This is not meant for fully-fledged text editor apps, but
still provides selection and composing region support for typical uses cases in
games. Also, this library supports advanced input method editor
(IME) features such as spell-
checking, completions, and multi-key characters.
Internally, GameTextInput accumulates the input text (together with the
relevant states) to the internal buffer GameTextInput::currentState_ and notifies
the app of any changes in it. The app then performs text processing in its
registered callback function.
Availability
GameTextInput can be used in the following ways:
Together with GameActivity: GameActivity integrates GameTextInput. Applications that use GameActivity can only use the integrated GameTextInput. Usage instructions are fully documented on the GameActivity page . For a sample of GameActivity and GameTextInput integration, see the games-samples repository. This usage model is not within the scope of this guide.
As a standalone library: the rest of the guide describes the usage steps.
Note that the above two methods are mutually exclusive.
Formal GameTextInput releases are available in the Jetpack games library
release in Google Maven.
Set up your build
GameTextInput is distributed as an Android Archive (AAR). This AAR contains the Java classes and
the C source code, which implements the native features of GameTextInput. You
need to include these source files as part of your build process via
Prefab,
which exposes native libraries and source code to your CMake project or NDK build.
Follow the instructions on the Jetpack Android Games page to add the
GameTextInputlibrary dependency to your game'sbuild.gradlefile. Note that if your applications are using GameActivity, they cannot use the standaloneGameTextInputlibrary.Make sure
gradle.propertiescontains the following lines:# Tell Android Studio we are using AndroidX. android.useAndroidX=true # Use Prefab 1.1.2 or higher, which contains a fix for "header only" libs. android.prefabVersion=1.1.2 # Required only if you're using Android Studio 4.0 (4.1 is recommended). # android.enablePrefab=trueImport the
game-text-inputpackage and add it to your target in your project'sCMakeLists.txtfile:find_package(game-text-input REQUIRED CONFIG) ... target_link_libraries(... game-text-input::game-text-input)In one of the
.cppfiles in your game, add the following line to include theGameTextInputimplementation:#include <game-text-input/gametextinput.cpp>In the source files that use the
GameTextInputC API, include the header file:#include <game-text-input/gametextinput.h>Compile and run the app. If you have CMake errors, verify the AAR and the
build.gradlefiles are properly set up. If the#includefile is not found, verify yourCMakeLists.txtconfiguration file.
Integrate your build
From your C thread that is already attached to the JVM, or the app main thread, call
GameTextInput_initwith aJNIEnvpointer.static GameTextInput* gameTextInput = nullptr; extern "C" JNIEXPORT void JNICALL Java_com_gametextinput_testbed_MainActivity_onCreated(JNIEnv* env, jobject this) { { if(!gameTextInput) gameTextInput = GameTextInput_init(env); ... }Create a
InputEnabledTextViewJava class with access toInputConnection.public class InputEnabledTextView extends View implements Listener { public InputConnection mInputConnection; public InputEnabledTextView(Context context, AttributeSet attrs) { super(context, attrs); } public InputEnabledTextView(Context context) { super(context); } public void createInputConnection(int inputType) { EditorInfo editorInfo = new EditorInfo(); editorInfo.inputType = inputType; editorInfo.actionId = IME_ACTION_NONE; editorInfo.imeOptions = IME_FLAG_NO_FULLSCREEN; mInputConnection = new InputConnection(this.getContext(), this, new Settings(editorInfo, true) ).setListener(this); } @Override public InputConnection onCreateInputConnection(EditorInfo outAttrs) { if (outAttrs != null) { GameTextInput.copyEditorInfo(mInputConnection.getEditorInfo(), outAttrs); } return mInputConnection; } // Called when the IME input changes. @Override public void stateChanged(State newState, boolean dismissed) { onTextInputEventNative(newState); } @Override public void onImeInsetsChanged(Insets insets) { // handle Inset changes here } private native void onTextInputEventNative(State softKeyboardEvent); }Add the created
InputEnabledTextViewto UI layout. For example, the following code inactivity_main.xmlcan position it at the bottom of the screen:<com.android.example.gametextinputjava.InputEnabledTextView android:id="@+id/input_enabled_text_view" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" />Retrieve this new
InputEnabledTextViewclass to your Java activity. This is relative simple when you use View Binding:public class MainActivity extends AppCompatActivity { ... private ActivityMainBinding binding; private InputEnabledTextView inputEnabledTextView; private native void setInputConnectionNative(InputConnection c); @Override protected void onCreate(Bundle savedInstanceState) { ... binding = ActivityMainBinding.inflate(getLayoutInflater()); inputEnabledTextView = binding.inputEnabledTextView; inputEnabledTextView.createInputConnection(InputType.TYPE_CLASS_TEXT); setInputConnectionNative(inputEnabledTextView.mInputConnection); }In your C library, pass
inputConnectionintoGameTextInput_setInputConnection. Pass a callback inGameTextInput_setEventCallbackto be notified of events as C state structGameTextInputState.extern "C"JNIEXPORT void JNICALL Java_com_gametextinput_testbed_MainActivity_setInputConnectionNative( JNIEnv *env, jobject this, jobject inputConnection) { GameTextInput_setInputConnection(gameTextInput, inputConnection); GameTextInput_setEventCallback(gameTextInput,[](void *ctx, const GameTexgtInputState *state) { if (!env || !state) return; // process the newly arrived text input from user. __android_log_print(ANDROID_LOG_INFO, "TheGreateGameTextInput", state->text_UTF8); }, env); }In your C library, call
GameTextInput_processEvent, which internally calls your callback registered in the previous step, for your app to handle events when the state changes.extern "C" JNIEXPORT void JNICALL Java_com_gametextinput_testbed_InputEnabledTextView_onTextInputEventNative( JNIEnv* env, jobject this, jobject soft_keyboard_event) { GameTextInput_processEvent(gameTextInput, soft_keyboard_event); }
Utility functions
The GameTextInput library includes utility functions that lets you convert
between Java state objects and C state structs. Access functionality for showing
and hiding the IME through the GameTextInput_showIme
and GameTextInput_hideIme
functions.
References
Developers may find the following helpful when creating apps with
GameTextInput:
- GameTextInput test app
- Use GameTextInput with GameActivity
- GameTextInput Reference doc
- GameTextInput source code
Feedback
For any issues and questions for GameTextInput, create
a bug on the Google IssueTracker.