Von NativeActivity migrieren Teil des Android Game Development Kits.
Auf dieser Seite wird beschrieben, wie Sie in Ihrem Android-Spielprojekt von NativeActivity
zu GameActivity
migrieren.
GameActivity
basiert auf NativeActivity
aus dem Android-Framework mit Verbesserungen und neuen Funktionen:
- Unterstützt
Fragment
von Jetpack. - Unterstützung für
TextInput
hinzugefügt, um die Integration der Soft-Tastatur zu erleichtern. - Verarbeitet Touch- und Tastenereignisse in der
GameActivity
Java-Klasse und nicht über dieNativeActivity
onInputEvent
-Schnittstelle.
Bevor Sie mit der Migration beginnen, empfehlen wir Ihnen, den Einstiegsleitfaden zu lesen. Dort wird beschrieben, wie Sie GameActivity
in Ihrem Projekt einrichten und einbinden.
Aktualisierungen des Java-Build-Scripts
GameActivity
wird als Jetpack-Bibliothek verteilt. Führen Sie die Schritte zum Aktualisieren des Gradle-Scripts aus, die im Einstiegsleitfaden beschrieben sind:
Aktivieren Sie die Jetpack-Bibliothek in der Datei
gradle.properties
Ihres Projekts:android.useAndroidX=true
Optional können Sie in derselben
gradle.properties
-Datei eine Prefab-Version angeben, z. B.:android.prefabVersion=2.0.0
Aktivieren Sie die Prefab-Funktion in der Datei
build.gradle
Ihrer App:android { ... // other configurations buildFeatures.prefab true }
Fügen Sie Ihrer Anwendung die Abhängigkeit
GameActivity
hinzu:- Fügen Sie die Bibliotheken
core
undgames-activity
hinzu. - Wenn das derzeit unterstützte Mindest-API-Level unter 16 liegt, aktualisieren Sie es auf mindestens 16.
- Aktualisieren Sie die kompilierte SDK-Version auf die Version, die die
games-activity
-Bibliothek benötigt. Für Jetpack ist in der Regel die neueste SDK-Version erforderlich, die zum Zeitpunkt der Buildzeit der Veröffentlichung verfügbar ist.
Ihre aktualisierte
build.gradle
-Datei 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' }
- Fügen Sie die Bibliotheken
Aktualisierungen des Kotlin- oder Java-Codes
NativeActivity
kann als Startaktivität verwendet werden und erstellt eine Vollbildanwendung. Derzeit kann „GameActivity“ nicht als Startaktivität verwendet werden. Apps müssen eine Klasse von GameActivity
ableiten und diese als Startaktivität verwenden. Außerdem müssen Sie zusätzliche Konfigurationsänderungen vornehmen, um eine Vollbild-App zu erstellen.
Bei den folgenden Schritten wird davon ausgegangen, dass Ihre Anwendung NativeActivity
als Startaktivität verwendet. Andernfalls können Sie die meisten davon überspringen.
Erstellen Sie eine Kotlin- oder Java-Datei, um die neue Startaktivität zu hosten. Mit dem folgenden Code wird beispielsweise
MainActivity
als Startaktivität erstellt und die Haupt-native Bibliothek der Anwendung,libAndroidGame.so
, geladen: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"); } }
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>
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 im Leitfaden für immersive Inhalte und in der Beispielimplementierung im Repository „games-samples“.
In dieser Migrationsanleitung wird der Name der nativen Bibliothek nicht geändert. Wenn Sie ihn ändern, achten Sie darauf, dass die Namen der nativen Bibliotheken an den folgenden drei Stellen übereinstimmen:
Kotlin- oder Java-Code:
System.loadLibrary(“AndroidGame”)
AndroidManifest.xml
:<meta-data android:name="android.app.lib_name" android:value="AndroidGame" />
In der C/C++-Build-Scriptdatei, z. B.
CMakeLists.txt
: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 auf der Dokumentationsseite für ndk-build beschrieben sind.
Die C/C++-Implementierung von GameActivity wurde mit einem Quellcode veröffentlicht. Ab Version 1.2.2 wird ein Release als statische Bibliothek bereitgestellt. Die statische Bibliothek ist der empfohlene Release-Typ.
Die Version wird mit dem Dienstprogramm prefab
in das AAR verpackt. Der native Code umfasst die C/C++-Quellen von GameActivity und den native_app_glue
-Code. Sie müssen zusammen mit dem C/C++-Code Ihrer Anwendung erstellt werden.
NativeActivity
-Anwendungen verwenden bereits den native_app_glue
-Code, der im NDK enthalten ist. Sie müssen sie durch die Version von native_app_glue
für GameActivity ersetzen. Ansonsten gelten alle cmake
Schritte, die in der Anleitung für den Einstieg beschrieben sind:
Importieren Sie entweder die C/C++-Static-Library oder den C/C++-Quellcode in Ihr Projekt. Gehen Sie dazu so vor:
Statische Bibliothek
Importieren Sie in der Datei
CMakeLists.txt
Ihres Projekts die statische Bibliothekgame-activity
in das PreFab-Modulgame-activity_static
:find_package(game-activity REQUIRED CONFIG) target_link_libraries(${PROJECT_NAME} PUBLIC log android game-activity::game-activity_static)
Quellcode
Importieren Sie das
game-activity
-Paket in dieCMakeLists.txt
-Datei Ihres Projekts und fügen Sie es dem Ziel hinzu. Für dasgame-activity
-Paket istlibandroid.so
erforderlich. Wenn es fehlt, müssen Sie es 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 des 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 die Quellcodeversion verwenden, fügen Sie die
GameActivity
-Quelldateien hinzu. Andernfalls überspringen Sie diesen Schritt.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)
Problem „UnsatisfiedLinkError“ umgehen
Wenn Sie für die Funktion com.google.androidgamesdk.GameActivity.initializeNativeCode()
ein UnsatsifiedLinkError
sehen, fügen Sie der Datei CMakeLists.txt
diesen Code hinzu:
set(CMAKE_SHARED_LINKER_FLAGS
"${CMAKE_SHARED_LINKER_FLAGS} -u \
Java_com_google_androidgamesdk_GameActivity_initializeNativeCode")
Aktualisierungen des C/C++-Quellcodes
So ersetzen Sie Verweise auf NativeActivity
in Ihrer Bewerbung durch GameActivity
:
Verwenden Sie die
native_app_glue
, die mitGameActivity
veröffentlicht wurde. Suche nach allen Verwendungen vonandroid_native_app_glue.h
und ersetzte sie durch:#include <game-activity/native_app_glue/android_native_app_glue.h>
Legen Sie sowohl den Bewegungsereignisfilter als auch den Schlüsselereignisfilter auf
NULL
fest, damit Ihre App Eingabeereignisse von allen Eingabegeräten empfangen kann. Normalerweise geschieht dies in derandroid_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. }
Entfernen Sie den Code im Zusammenhang mit
AInputEvent
und ersetzen Sie ihn durch dieInputBuffer
-Implementierung von GameActivity: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; }
Prüfen und aktualisieren Sie die Logik, die mit der
AInputEvent
von NativeActivity verknüpft ist. Wie im vorherigen Schritt gezeigt, erfolgt dieInputBuffer
-Verarbeitung von GameActivity außerhalb derALooper_pollOnce()
-Schleife.Ersetzen Sie
android_app::activity->clazz
durchandroid_app:: activity->javaGameActivity
. GameActivity benennt die Java-GameActivity
-Instanz um.
Weitere Schritte
In den vorherigen Schritten wurden die Funktionen von NativeActivity beschrieben. GameActivity
bietet jedoch zusätzliche Funktionen, die Sie möglicherweise verwenden möchten:
- TextInput
- Controller
- Fragment
- InSets-Befehle für neue Fenster, die in NativeAppGlueAppCmd definiert sind.
Wir empfehlen Ihnen, diese Funktionen zu testen und sie nach Bedarf für Ihre Spiele zu verwenden.
Wenn Sie Fragen oder Empfehlungen zu GameActivity oder anderen AGDK-Bibliotheken haben, erstellen Sie einen Fehlerbericht.