# Migrate from NativeActivityPart of[Android Game Development Kit](https://developer.android.com/games/agdk/overview).

This page describes how to migrate from[`NativeActivity`](https://developer.android.com/reference/android/app/NativeActivity)to[`GameActivity`](https://developer.android.com/games/agdk/game-activity)in your Android game project.

`GameActivity`is based on`NativeActivity`from the Android framework, with enhancements and new features:

- Supports`Fragment`from Jetpack.
- Adds`TextInput`support to facilitate soft keyboard integration.
- Handles touch and key events in the`GameActivity`Java class rather than the`NativeActivity``onInputEvent`interface.

Before migrating, we recommend reading the[get started guide](https://developer.android.com/games/agdk/game-activity/get-started), which describes how to set up and integrate`GameActivity`in your project.

## Java build script updates

`GameActivity`is[distributed](https://developer.android.com/games/agdk/game-activity#releases)as a Jetpack library. Make sure to apply the Gradle script updating steps described in the[get started guide](https://developer.android.com/games/agdk/game-activity/get-started):

1. Enable Jetpack library in your project's`gradle.properties`file:

       android.useAndroidX=true

2. Optionally, specify a Prefab version, in the same`gradle.properties`file, for example:

       android.prefabVersion=2.0.0

3. Enable Prefab feature in your app's`build.gradle`file:

       android {
           ... // other configurations
           buildFeatures.prefab true
       }

4. Add the`GameActivity`dependency to your application:

   1. Add the`core`and`games-activity`libraries.
   2. If your current minimum supported API level is less than 16, update it to at least 16.
   3. Update the compiled SDK version to the one that the`games-activity`library requires. Jetpack typically requires the latest SDK version at the release build time.

   Your updated`build.gradle`file might look something like this:  

       android {
           compiledSdkVersion 33
           ... // other configurations.
           defaultConfig {
               minSdkVersion 16
           }
           ... // other configurations.

           buildFeatures.prefab true
       }
       dependencies {
           implementation 'androidx.core:core:1.9.0'
           implementation 'androidx.games:games-activity:1.2.2'
       }

## Kotlin or Java code updates

`NativeActivity`can be used as a startup activity and creates a full screen application. At present, GameActivity*cannot* be used as the startup activity. Apps must derive a class from`GameActivity`and use that as the startup activity. You must also make additional configuration changes to create a full screen app.

The following steps assume your application uses`NativeActivity`as the startup activity. If that is not the case, you can skip most of them.

1. Create a Kotlin or Java file to host the new startup activity. For example, the following code creates the`MainActivity`as the startup activity and loads the application's main native library,`libAndroidGame.so`:

   ### Kotlin

   ```kotlin
   class MainActivity : GameActivity() {
      override fun onResume() {
          super.onResume()
          // Use the function recommended from the following page:
          // https://d.android.com/training/system-ui/immersive
          hideSystemBars()
      }
      companion object {
          init {
              System.loadLibrary("AndroidGame")
          }
      }
   }
   ```

   ### Java

   ```java
     public class MainActivity extends GameActivity {
         protected void onResume() {
             super.onResume();
             // Use the function recommended from
             // https://d.android.com/training/system-ui/immersive
             hideSystemBars();
         }
         static {
             System.loadLibrary("AndroidGame");
         }
     }
   ```
2. Create a full screen app theme in the`res\values\themes.xml`file:

       <resources xmlns:tools="http://schemas.android.com/tools">
           <!-- Base application theme. -->
           <style name="Application.Fullscreen" parent="Theme.AppCompat.Light.NoActionBar">
               <item name="android:windowFullscreen">true</item>
               <item name="android:windowContentOverlay">@null</item>"
           </style>
       </resources>

3. Apply the theme to the application in the`AndroidManifest.xml`file:

       <application  android:theme="@style/Application.Fullscreen">
            <!-- other configurations not listed here. -->
       </application>

   For detailed instructions for full screen mode, see to[the immersive guide](https://developer.android.com/training/system-ui/immersive)and example implementation in[the games-samples repo](https://github.com/android/games-samples/blob/main/agdk/agdktunnel/app/src/main/java/com/google/sample/agdktunnel/AGDKTunnelActivity.java).

This migration guide does not change the native library name. If you do change it, ensure the native library names are consistent in the following three locations:

- Kotlin or Java code:

      System.loadLibrary("AndroidGame")

- `AndroidManifest.xml`:

      <meta-data android:name="android.app.lib_name"
              android:value="AndroidGame" />

- Inside the C/C++ build script file, for example`CMakeLists.txt`:

      add_library(AndroidGame ...)

## C/C++ build script updates

The instructions in this section use`cmake`as the example. If your application uses`ndk-build`, you need to map them to the equivalent commands described in[ndk-build documentation page](https://developer.android.com/ndk/guides/ndk-build).

GameActivity's C/C++ implementation has been providing a source code release. For version 1.2.2 a later, a static library release is provided. The static library is the recommended release type.

The release is packed inside the AAR with the[`prefab`](https://developer.android.com/studio/build/dependencies#using-native-dependencies)utility. The native code includes GameActivity's C/C++ sources and the`native_app_glue`code. They need to be built together with your application's C/C++ code.

`NativeActivity`applications already use the`native_app_glue`code shipped inside NDK. You must replace it with GameActivity's version of`native_app_glue`. Other than that, all`cmake`steps documented inside the getting started guide apply:

- Import either the C/C++ static library or the C/++ source code into your project as follows.

  ### Static library

  In your project's`CMakeLists.txt`file, import the`game-activity`static library into the`game-activity_static`prefab module:  

      find_package(game-activity REQUIRED CONFIG)
      target_link_libraries(${PROJECT_NAME} PUBLIC log android
      game-activity::game-activity_static)

  ### Source code

  In your project's`CMakeLists.txt`file, import the`game-activity`package and add it to your target. The`game-activity`package requires`libandroid.so`, so if it's missing, you must also import it.  

      find_package(game-activity REQUIRED CONFIG)
      ...
      target_link_libraries(... android game-activity::game-activity)

- *Remove* all references to NDK's`native_app_glue`code, such as:

      ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c
          ...
      set(CMAKE_SHARED_LINKER_FLAGS
          "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate")

- If you are using the source code release, include the`GameActivity`source files. Otherwise, skip this step.

      get_target_property(game-activity-include
                          game-activity::game-activity
                          INTERFACE_INCLUDE_DIRECTORIES)
      add_library(${PROJECT_NAME} SHARED
          main.cpp
          ${game-activity-include}/game-activity/native_app_glue/android_native_app_glue.c
          ${game-activity-include}/game-activity/GameActivity.cpp
          ${game-activity-include}/game-text-input/gametextinput.cpp)

### Work around the UnsatisfiedLinkError issue

If you encounter an`UnsatsifiedLinkError`for the`com.google.androidgamesdk.GameActivity.initializeNativeCode()`function, add this code to your`CMakeLists.txt`file:  

    set(CMAKE_SHARED_LINKER_FLAGS
        "${CMAKE_SHARED_LINKER_FLAGS} -u \
        Java_com_google_androidgamesdk_GameActivity_initializeNativeCode")

## C/C++ source code updates

Follow these steps to replace`NativeActivity`references in your application with`GameActivity`:

- Use the`native_app_glue`released with`GameActivity`. Search and replace all`android_native_app_glue.h`usage with:

      #include <game-activity/native_app_glue/android_native_app_glue.h>

- Set both motion event filter and key event filter to`NULL`so your app can receive input events from all input devices. You typically do this inside`android_main()`function:

      void android_main(android_app* app) {
          ... // other init code.

          android_app_set_key_event_filter(app, NULL);
          android_app_set_motion_event_filter(app, NULL);

          ... // additional init code, and game loop code.
      }

- Remove`AInputEvent`related code, and replace it with GameActivity's`InputBuffer`implementation:

      while (true) {
          // Read all pending events.
          int events;
          struct android_poll_source* source;

          // If not animating, block forever waiting for events.
          // If animating, loop until all events are read, then continue
          // to draw the next frame of animation.
          while ((ALooper_pollOnce(engine.animating ? 0 : -1, nullptr, &events,
                                  (void**)&source)) >= 0) {
             // Process this app cycle or inset change event.
             if (source) {
                 source->process(source->app, source);
             }

                ... // Other processing.

             // Check if app is exiting.
             if (state->destroyRequested) {
                 engine_term_display(&engine);
                 return;
             }
          }
          // Process input events if there are any.
          engine_handle_input(state);

         if (engine.animating) {
             // Draw a game frame.
         }
      }

      // Implement input event handling function.
      static int32_t engine_handle_input(struct android_app* app) {
         auto* engine = (struct engine*)app->userData;
         auto ib = android_app_swap_input_buffers(app);
         if (ib && ib->motionEventsCount) {
             for (int i = 0; i < ib->motionEventsCount; i++) {
                 auto *event = &ib->motionEvents[i];
                 int32_t ptrIdx = 0;
                 switch (event->action & AMOTION_EVENT_ACTION_MASK) {
                     case AMOTION_EVENT_ACTION_POINTER_DOWN:
                     case AMOTION_EVENT_ACTION_POINTER_UP:
                         // Retrieve the index for the starting and the ending of any secondary pointers
                         ptrIdx = (event->action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >>
                                  AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
                     case AMOTION_EVENT_ACTION_DOWN:
                     case AMOTION_EVENT_ACTION_UP:
                         engine->state.x = GameActivityPointerAxes_getAxisValue(
                             &event->pointers[ptrIdx], AMOTION_EVENT_AXIS_X);
                         engine->state.y = GameActivityPointerAxes_getAxisValue(
                             &event->pointers[ptrIdx], AMOTION_EVENT_AXIS_Y);
                         break;
                      case AMOTION_EVENT_ACTION_MOVE:
                      // Process the move action: the new coordinates for all active touch pointers
                      // are inside the event->pointers[]. Compare with our internally saved
                      // coordinates to find out which pointers are actually moved. Note that there is
                      // no index embedded inside event->action for AMOTION_EVENT_ACTION_MOVE (there
                      // might be multiple pointers moved at the same time).
                          ...
                         break;
                 }
             }
             android_app_clear_motion_events(ib);
         }

         // Process the KeyEvent in a similar way.
             ...

         return 0;
      }

- Review and update logic that attached to NativeActivity's`AInputEvent`. As shown in the previous step, GameActivity's`InputBuffer`processing is outside the`ALooper_pollOnce()`loop.

- Replace`android_app::activity->clazz`usage with`android_app:: activity->javaGameActivity`. GameActivity renames the Java`GameActivity`instance.

## Additional steps

The previous steps cover NativeActivity's functionality, but`GameActivity`has additional features that you might want to use:

- [TextInput](https://developer.android.com/games/agdk/add-support-for-text-input).
- [Game Controller](https://developer.android.com/games/sdk/game-controller).
- [Fragment](https://developer.android.com/guide/fragments).
- New window InSets commands defined in[NativeAppGlueAppCmd](https://android.googlesource.com/platform/frameworks/opt/gamesdk/+/refs/heads/master/game-activity/prefab-src/modules/game-activity/include/game-activity/native_app_glue/android_native_app_glue.h#302).

We recommend exploring these features and adopting them as appropriate for your games.

If you have any questions or recommendations for GameActivity or other AGDK libraries, create[a bug](https://issuetracker.google.com/issues/new?component=897320&pli=1&template=1456805)to let us know.