Von NativeActivity migrieren Teil des Android Game Development Kit.

Auf dieser Seite wird beschrieben, wie Sie von NativeActivity bis GameActivity in deinem Android-Spielprojekt.

GameActivity basiert auf NativeActivity von Android mit Verbesserungen und neuen Funktionen:

  • Unterstützt Fragment von Jetpack.
  • Unterstützt TextInput für eine einfachere Integration über die Softtastatur.
  • Verarbeitet Tipp- und Schlüsselereignisse in der Java-Klasse GameActivity, statt NativeActivity onInputEvent-Schnittstelle.

Vor der Migration sollten Sie die Startleitfaden, in dem beschrieben wird, wie Sie um GameActivity einzurichten und in Ihr Projekt zu integrieren.

Aktualisierung des Java-Build-Skripts

GameActivity wird verteilt als Jetpack-Bibliothek. Wenden Sie die beschriebenen Schritte zur Aktualisierung des Gradle-Skripts an. im Startleitfaden:

  1. Aktivieren Sie die Jetpack-Bibliothek in der Datei gradle.properties Ihres Projekts:

    android.useAndroidX=true
    
  2. Optional können Sie in derselben gradle.properties-Datei eine Prefab-Version angeben. Beispiel:

    android.prefabVersion=2.0.0
    
  3. So aktivieren Sie die Prefab-Funktion in der build.gradle-Datei Ihrer App:

    android {
        ... // other configurations
        buildFeatures.prefab true
    }
    
  4. Fügen Sie Ihrer Anwendung die Abhängigkeit GameActivity hinzu:

    1. Fügen Sie die Bibliotheken core und games-activity hinzu.
    2. Wenn dein aktuell unterstütztes Mindest-API-Level weniger als 16 beträgt, aktualisiere es auf mindestens 16.
    3. Aktualisiere die kompilierte SDK-Version auf die Version, die der games-activity Bibliothek erforderlich ist. Jetpack erfordert normalerweise die neueste SDK-Version unter die Build-Erstellungszeit des Release.

    Die aktualisierte Datei build.gradle könnte in etwa so aussehen:

    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- oder Java-Codeaktualisierungen

NativeActivity kann als Startaktivität verwendet werden und erstellt einen Vollbildmodus . Derzeit kann GameActivity nicht als Startvorgang verwendet werden Aktivitäten. Apps müssen eine Klasse von GameActivity ableiten und diese als der Startaktivität. Sie müssen außerdem weitere Konfigurationsänderungen vornehmen, eine Vollbild-App zu erstellen.

Bei den folgenden Schritten wird davon ausgegangen, dass Ihre Anwendung NativeActivity als Startvorgang verwendet Aktivitäten. Ist dies nicht der Fall, können Sie die meisten dieser Vorschläge überspringen.

  1. Erstellen Sie eine Kotlin- oder Java-Datei, um die neue Startaktivität zu hosten. Beispiel: Mit dem folgenden Code werden die MainActivity als Startaktivität und lädt die native Hauptbibliothek der Anwendung, libAndroidGame.so:

    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

      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. Erstellen Sie in der Datei res\values\themes.xml ein Vollbild-App-Design:

    <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. Wenden Sie das Design auf die Anwendung in der Datei AndroidManifest.xml an:

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

    Eine ausführliche Anleitung für den Vollbildmodus finden Sie unter ausführlichen Leitfaden und eine Beispielimplementierung in Games-Beispiel-Repository.

Der Name der nativen Bibliothek wird in dieser Migrationsanleitung nicht geändert. Wenn Sie die Namen der nativen Bibliothek in den folgenden drei Standorte:

  • Kotlin- oder Java-Code:

    System.loadLibrary(AndroidGame)
    
  • AndroidManifest.xml:

    <meta-data android:name="android.app.lib_name"
            android:value="AndroidGame" />
    
  • Geben Sie in der C/C++-Build-Skriptdatei, z. B. CMakeLists.txt, Folgendes ein:

    add_library(AndroidGame ...)
    

Aktualisierungen des C/C++ Build-Scripts

In der Anleitung in diesem Abschnitt wird cmake als Beispiel verwendet. Wenn Ihre Anwendung ndk-build verwendet, müssen Sie sie den entsprechenden Befehlen zuordnen, die in Dokumentationsseite zu ndk-build.

Die C/C++-Implementierung von GameActivity lieferte einen Quellcode-Release. Für Version 1.2.2 oder höher wird ein statischer Bibliotheksrelease bereitgestellt. Die statische ist der empfohlene Veröffentlichungstyp.

Die Veröffentlichung ist im AAE enthalten prefab Dienstprogramm. Der native Code enthält die C/C++-Quellen von GameActivity und den native_app_glue-Code. Sie müssen gemeinsam mit Ihren C/C++ Code der Anwendung.

NativeActivity-Anwendungen verwenden bereits den native_app_glue Code innerhalb des NDK versendet. Du musst sie durch die Version von GameActivity ersetzen von native_app_glue. Davon abgesehen sind alle cmake darin dokumentierten Schritte finden Sie im Startleitfaden:

  • Importieren Sie entweder die statische C/C++-Bibliothek oder den C/++-Quellcode in Ihr wie im Folgenden beschrieben.

    Static-Bibliothek

    Importieren Sie das statische game-activity-Objekt in die Datei CMakeLists.txt Ihres Projekts. in das game-activity_static-Fertigmodul:

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

    Quellcode

    Importieren Sie den game-activity in die Datei CMakeLists.txt Ihres Projekts. Paket und fügen es Ihrem Ziel hinzu. Das game-activity-Paket benötigt libandroid.so. Fehlt sie, müssen Sie sie auch importieren.

    find_package(game-activity REQUIRED CONFIG)
    ...
    target_link_libraries(... android game-activity::game-activity)
    
  • Entfernen Sie alle Verweise auf den native_app_glue-Code von NDK, z. B.:

    ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c
        ...
    set(CMAKE_SHARED_LINKER_FLAGS
        "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate")
    
  • Wenn Sie den Quellcode-Release verwenden, geben Sie den GameActivity-Quellcode an Dateien. Andernfalls können Sie diesen Schritt überspringen.

    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)
    

Umgehen des Problems „UnexpectedLinkError“

Wenn ein UnsatsifiedLinkError für die com.google.androidgamesdk.GameActivity.initializeNativeCode()-Funktion, hinzufügen diesen Code in Ihre CMakeLists.txt-Datei ein:

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

Aktualisierungen des C/C++-Quellcodes

Mit den folgenden Schritten kannst du NativeActivity-Referenzen in deinem Anwendung mit GameActivity:

  • Verwende die native_app_glue, die mit GameActivity veröffentlicht wurde. Suchen und Ersetzen Sie die gesamte android_native_app_glue.h-Nutzung durch:

    #include <game-activity/native_app_glue/android_native_app_glue.h>
    
  • Setze sowohl den Bewegungsereignisfilter als auch den Schlüsselereignisfilter auf NULL, damit deine App Eingangsereignisse von allen Eingabegeräten empfangen. Das machst du normalerweise drinnen android_main()-Funktion:

    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.
    }
    
  • AInputEvent-bezogenen Code entfernen und durch GameActivity-Code ersetzen InputBuffer-Implementierung:

    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_pollAll(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;
    }
    
  • Logik für NativeActivity prüfen und aktualisieren AInputEvent Wie im vorherigen Schritt gezeigt, hat „InputBuffer“ von GameActivity die Verarbeitung außerhalb der ALooper_pollAll()-Schleife erfolgt.

  • Nutzung von android_app::activity->clazz ersetzen durch android_app:: activity->javaGameActivity. In „GameActivity“ wird die Java GameActivity-Instanz

Weitere Schritte

In den vorherigen Schritten wurde die Funktionalität von NativeActivity beschrieben. GameActivity hat jedoch weitere Funktionen, die Sie möglicherweise verwenden möchten:

Wir empfehlen Ihnen, diese Funktionen auszuprobieren und für Ihr Unternehmen Spiele.

Wenn du Fragen oder Empfehlungen zu GameActivity oder anderen AGDK hast erstellen Sie einen Fehler, um uns zu informieren.