Migracja z NativeActivity Zawiera Android Game Development Kit.
Na tej stronie dowiesz się, jak przeprowadzić migrację z
NativeActivity
do
GameActivity
w projekcie gry na Androida.
Tabela GameActivity
jest oparta na modelu NativeActivity
z Androida
wraz z ulepszeniami i nowymi funkcjami:
- Obsługuje usługę
Fragment
firmy Jetpack. - Dodano obsługę
TextInput
, aby ułatwić integrację klawiatury programowej. - Obsługuje zdarzenia dotykowe i kluczowe zdarzenia w klasie Java
GameActivity
, a nie w interfejsieNativeActivity
onInputEvent
.
Przed migracją zapoznaj się z
przewodnika dla początkujących,
aby skonfigurować i zintegrować GameActivity
z projektem.
Aktualizacje skryptu kompilacji Java
Aplikacja GameActivity
jest rozpowszechniana jako
Biblioteka Jetpack. Pamiętaj, aby zastosować opisane kroki aktualizacji skryptu Gradle
w przewodniku dla początkujących:
Włącz bibliotekę Jetpack w pliku
gradle.properties
projektu:android.useAndroidX=true
Opcjonalnie określ wersję Prefab w tym samym pliku
gradle.properties
, np.:android.prefabVersion=2.0.0
Włącz funkcję Prefab w pliku
build.gradle
aplikacji:android { ... // other configurations buildFeatures.prefab true }
Dodaj zależność
GameActivity
do swojej aplikacji:- Dodaj biblioteki
core
igames-activity
. - Jeśli bieżący minimalny obsługiwany poziom interfejsu API jest niższy niż 16, zaktualizuj go co najmniej do 16.
- Zaktualizuj skompilowaną wersję pakietu SDK do tej, której używa
games-activity
wymaga biblioteki. Jetpack zwykle wymaga najnowszej wersji pakietu SDK dostępnej pod adresem czas kompilacji wydania.
Twój zaktualizowany plik
build.gradle
może wyglądać mniej więcej tak: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' }
- Dodaj biblioteki
Aktualizacje kodu w Kotlin lub Java
Aplikacja NativeActivity
może być używana jako aktywność podczas uruchamiania i tworzy pełny ekran
aplikacji. Obecnie nie można używać GameActivity jako startu
działania. Aplikacje muszą uzyskać klasę z metody GameActivity
i używać jej jako
podczas uruchamiania. Musisz też wprowadzić dodatkowe zmiany w konfiguracji
utwórz aplikację pełnoekranową.
W tych krokach aplikacja używa NativeActivity
jako uruchamiania
działania. Jeśli tak nie jest, możesz pominąć większość z nich.
Utwórz plik Kotlin lub Java, aby hostować nowe działanie startowe. Przykład: ten kod tworzy
MainActivity
jako działanie startowe oraz wczytuje główną bibliotekę natywną aplikacji (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"); } }
Utwórz motyw aplikacji pełnoekranowej w pliku
res\values\themes.xml
:<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>
Zastosuj motyw do aplikacji w pliku
AndroidManifest.xml
:<application android:theme=”@style/Application.Fullscreen”> <!-- other configurations not listed here. --> </application>
Szczegółowe instrukcje dotyczące trybu pełnoekranowego znajdziesz w wirtualny przewodnik i przykładowa implementacja repozytorium z przykładami gier.
Ten przewodnik po migracji nie zmienia nazwy biblioteki natywnej. Jeśli zmienisz należy się upewnić, że nazwy bibliotek natywnych są spójne w następujących 3 lokalizacje:
Kod Kotlin lub Java:
System.loadLibrary(“AndroidGame”)
AndroidManifest.xml
:<meta-data android:name="android.app.lib_name" android:value="AndroidGame" />
Wewnątrz pliku skryptu kompilacji C/C++, na przykład
CMakeLists.txt
:add_library(AndroidGame ...)
Aktualizacje skryptu kompilacji w C/C++
W instrukcjach w tej sekcji jako przykładu podano cmake
. Jeśli Twoja aplikacja
używa ndk-build
, musisz zmapować je na odpowiadające im polecenia opisane w
strona dokumentacji ndk-build.
Implementacja kodu w języku C/C++ w GameActivity udostępnia wersję kodu źródłowego. W przypadku wersji 1.2.2 i nowszych dostępna jest statyczna wersja biblioteki. Wartość statystyczna jest zalecanym typem wersji.
Wersja jest zapakowana w AAR wraz z
prefab
za media. Kod natywny zawiera źródła w C/C++ GameActivity oraz
Kod od native_app_glue
. Reklamy te muszą być tworzone razem
kodu C/C++ aplikacji.
NativeActivity
aplikacji już korzysta z: native_app_glue
wysłany wewnątrz NDK. Musisz zastąpić go wersją GameActivity
z native_app_glue
. Poza tym wszystkie cmake
kroki są udokumentowane w dokumentacji
znajdziesz w przewodniku dla początkujących:
Zaimportuj bibliotekę statyczną C/C++ lub kod źródłowy C/++ w następujący sposób.
Biblioteka statyczna
W pliku
CMakeLists.txt
projektu zaimportuj statyczny element typugame-activity
do modułu prefabgame-activity_static
:find_package(game-activity REQUIRED CONFIG) target_link_libraries(${PROJECT_NAME} PUBLIC log android game-activity::game-activity_static)
Kod źródłowy
Do pliku
CMakeLists.txt
projektu zaimportujgame-activity
i dodaj go do miejsca docelowego. Pakietgame-activity
wymagalibandroid.so
, więc jeśli go brakuje, musisz go też zaimportować.find_package(game-activity REQUIRED CONFIG) ... target_link_libraries(... android game-activity::game-activity)
Usuń wszelkie odwołania do kodu
native_app_glue
NDK, takie jak:${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c ... set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate")
Jeśli używasz wersji kodu źródłowego, umieść w niej kod źródłowy
GameActivity
. . W przeciwnym razie pomiń ten krok.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)
Rozwiązanie problemu „Niesatysfakcjonujący link”
Jeśli natrafisz na komunikat UnsatsifiedLinkError
dla
funkcji com.google.androidgamesdk.GameActivity.initializeNativeCode()
, dodaj
ten kod do pliku CMakeLists.txt
:
set(CMAKE_SHARED_LINKER_FLAGS
"${CMAKE_SHARED_LINKER_FLAGS} -u \
Java_com_google_androidgamesdk_GameActivity_initializeNativeCode")
Aktualizacje kodu źródłowego w C/C++
Wykonaj te czynności, aby zastąpić NativeActivity
odwołania w pliku
aplikacja z GameActivity
:
Użyj zasady
native_app_glue
udostępnionej wraz z aplikacjąGameActivity
. Wyszukiwanie i zastąp całe wykorzystanieandroid_native_app_glue.h
następującym fragmentem:#include <game-activity/native_app_glue/android_native_app_glue.h>
Ustaw filtr zdarzeń ruchu i filtr kluczowych zdarzeń na
NULL
, aby aplikacja mogła odbierania zdarzeń wejściowych ze wszystkich urządzeń wejściowych. Zazwyczaj robisz to wewnątrz Funkcjaandroid_main()
: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. }
Usuń powiązany kod
AInputEvent
i zastąp go kodem GameActivity ImplementacjaInputBuffer
: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; }
Sprawdź i zaktualizuj logikę powiązaną z parametrem NativeActivity
AInputEvent
Jak pokazano w poprzednim kroku, właściwośćInputBuffer
w GameActivity przetwarzanie odbywa się poza pętląALooper_pollAll()
.Zastąp użycie funkcji
android_app::activity->clazz
przezandroid_app:: activity->javaGameActivity
GameActivity zmienia nazwę Instancja JavaGameActivity
.
Dodatkowe czynności
Poprzednie kroki dotyczą funkcji NativeActivity, ale w GameActivity
dodatkowe funkcje, z których możesz skorzystać:
- TextInput.
- Kontroler gier.
- Fragment.
- Nowe okno zawiera polecenia InSets zdefiniowane w metodzie NativeAppGlueAppCmd.
Zalecamy zapoznanie się z tymi funkcjami i zastosowanie ich gry.
Jeśli masz pytania lub rekomendacje dotyczące GameActivity lub innych platform AGDK utwórz błąd, aby nas o tym poinformować.