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 following channels:
- The Jetpack games library release in Google Maven
- Zip file releases on the AGDK download page
This guide covers the first usage case. To use the zip file releases, refer to the instructions shipped inside the package.
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
GameTextInput
library dependency to your game'sbuild.gradle
file. Note that if your applications are using GameActivity, they cannot use the standaloneGameTextInput
library.Make sure
gradle.properties
contains 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=true
Import the
game-text-input
package and add it to your target in your project'sCMakeLists.txt
file:find_package(game-text-input REQUIRED CONFIG) ... target_link_libraries(... game-text-input::game-text-input)
In one of the
.cpp
files in your game, add the following line to include theGameTextInput
implementation:#include <game-text-input/gametextinput.cpp>
In the source files that use the
GameTextInput
C 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.gradle
files are properly set up. If the#include
file is not found, verify yourCMakeLists.txt
configuration file.
Integrate your build
From your C thread that is already attached to the JVM, or the app main thread, call
GameTextInput_init
with aJNIEnv
pointer.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
InputEnabledTextView
Java 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
InputEnabledTextView
to UI layout. For example, the following code inactivity_main.xml
can 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
InputEnabledTextView
class 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
inputConnection
intoGameTextInput_setInputConnection
. Pass a callback inGameTextInput_setEventCallback
to 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.