Effectuer une migration depuis NativeActivity composante de l'Android Game Development Kit
Cette page explique comment migrer de NativeActivity vers GameActivity dans votre projet de jeu Android.
GameActivity est basé sur NativeActivity, du framework Android, mais offre plusieurs améliorations et nouvelles fonctionnalités :
- Compatible avec l'élément
Fragment, de Jetpack. - Compatible avec
TextInputpour faciliter l'intégration des claviers virtuels. - Gère les événements associés aux gestes tactiles et aux touches dans la classe Java
GameActivityplutôt que dans l'interfaceonInputEventdeNativeActivity.
Avant de procéder à la migration, nous vous recommandons de lire le guide de démarrage, qui explique comment configurer et intégrer GameActivity à votre projet.
Mises à jour du script de compilation Java
GameActivity est distribué en tant que bibliothèque Jetpack. Veillez à appliquer la procédure de mise à jour du script Gradle décrite dans le guide de démarrage :
Activez la bibliothèque Jetpack dans le fichier
gradle.propertiesde votre projet :android.useAndroidX=trueVous pouvez également spécifier une version de Prefab dans le même fichier
gradle.properties, par exemple :android.prefabVersion=2.0.0Activez la fonctionnalité Prefab dans le fichier
build.gradlede votre application :android { ... // other configurations buildFeatures.prefab true }Ajoutez la dépendance
GameActivityà votre application :- Ajoutez les bibliothèques
coreetgames-activity. - Si votre niveau d'API minimal actuellement accepté est inférieur à 16, procédez à sa mise à jour vers cette version ou une version ultérieure.
- Mettez à jour la version du SDK compilée pour obtenir celle qui est requise par la bibliothèque
games-activity. Jetpack nécessite généralement la dernière version du SDK au moment de la compilation de la version.
Votre fichier
build.gradlemis à jour peut se présenter comme suit :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' }- Ajoutez les bibliothèques
Mises à jour du code Kotlin ou Java
L'élément NativeActivity peut être utilisé comme activité de démarrage et crée une application plein écran. Actuellement, il est impossible d'utiliser GameActivity comme activité de démarrage. Les applications doivent créer une classe dérivée de GameActivity et l'utiliser comme activité de démarrage. Vous devez également apporter des modifications de configuration supplémentaires pour créer une application plein écran.
Les étapes suivantes supposent que votre application utilise NativeActivity comme activité de démarrage. Si ce n'est pas le cas, vous pouvez en ignorer la majorité.
Créez un fichier Kotlin ou Java pour héberger la nouvelle activité de démarrage. Par exemple, le code suivant crée
MainActivityen tant qu'activité de démarrage et charge la principale bibliothèque native de l'application,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"); } }
Créez un thème d'application en plein écran dans le fichier
res\values\themes.xml:<resources xmlns:tools="http://schemas.android.com/t>ools&<quot; !-- Base application> them<e. -- style name="Application.Fullscreen" parent="Theme.App>Compat.Li<ght.NoActionBar" item n>ame=<">;android:<windowFullscreen"true/item >item <name=>"<androi>d<:windowCon>tentOverlay"@null/item" /style /resourcesAppliquez le thème à l'application dans le fichier
AndroidManifest.xml:<application android:theme=”@style/Application.Fullscreen”> <!-- other configurations not listed here. --> </application>Pour obtenir des instructions détaillées sur le mode plein écran, consultez le guide immersif et l'exemple d'implémentation qui figure dans le dépôt game-samples.
Ce guide de migration ne modifie pas le nom de la bibliothèque native. Si vous décidez de le modifier, assurez-vous que les noms des bibliothèques natives sont les mêmes aux trois emplacements suivants :
Code Kotlin ou Java :
System.loadLibrary(“AndroidGame”)AndroidManifest.xml:<meta-data android:name="android.app.lib_name" android:value=">;AndroidGame" /Dans le fichier de script de compilation C/C++, par exemple
CMakeLists.txt:add_library(AndroidGame ...)
Mises à jour de script de compilation C/C++
Les instructions de cette section utilisent cmake comme exemple. Si votre application utilise ndk-build, ajustez ces instructions avec commandes équivalentes décrites à la page de documentation de ndk-build.
L'implémentation C/C++ de GameActivity fournit une version de code source. À partir de la version 1.2.2, une version de bibliothèque statique est fournie. La bibliothèque statique est le type de version recommandé.
La version est intégrée à l'AAR avec l'utilitaire prefab. Le code natif inclut les sources C/C++ de GameActivity et le code native_app_glue. Ils doivent être compilés avec le code C/C++ de votre application.
Les applications NativeActivity utilisent déjà le code native_app_glue présent dans NDK. Vous devez le remplacer par la version de native_app_glue de GameActivity. En dehors de cela, toutes les opérations cmake décrites dans le guide de démarrage s'appliquent :
Importez la bibliothèque statique C/C++ ou le code source C/++ dans votre projet comme suit.
Bibliothèque statique
Dans le fichier
CMakeLists.txtde votre projet, importez la bibliothèque statiquegame-activitydans le module Prefabgame-activity_static:find_package(game-activity REQUIRED CONFIG) target_link_libraries(${PROJECT_NAME} PUBLIC log android game-activity::game-activity_static)Code source
Dans le fichier
CMakeLists.txtde votre projet, importez le packagegame-activityet ajoutez-le à votre cible. Le packagegame-activitynécessitelibandroid.so. S'il est absent, vous devez donc également l'importer.find_package(game-activity REQUIRED CONFIG) ... target_link_libraries(... android game-activity::game-activity)Supprimez toutes les références au code
native_app_gluede NDK, telles que :${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c ... set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate")Si vous utilisez la version du code source, incluez les fichiers sources
GameActivity. Sinon, ignorez cette étape.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)
Résoudre une erreur UnsatisfactionLinkError
Si vous rencontrez une UnsatsifiedLinkError pour la fonction com.google.androidgamesdk.GameActivity.initializeNativeCode(), ajoutez ce code à votre fichier CMakeLists.txt :
set(CMAKE_SHARED_LINKER_FLAGS
"${CMAKE_SHARED_LINKER_FLAGS} -u \
Java_com_google_androidgamesdk_GameActivity_initializeNativeCode")
Mises à jour du code source C/C++
Procédez comme suit pour remplacer les références NativeActivity dans votre application par GameActivity :
Utilisez l'élément
native_app_gluepublié avecGameActivity. Recherchez et remplacez toute utilisation deandroid_native_app_glue.hpar :#include <game-activity/native_app_glue/android_native_app_glue.h>Définissez le filtre d'événement de mouvement et le filtre d'événement de touche sur
NULLpour que votre application puisse recevoir les événements, quel que soit le périphérique d'entrée. Cette opération s'effectue généralement dans la fonctionandroid_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. }Supprimez le code associé
AInputEvent, puis remplacez-le par l'implémentationInputBufferde 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; }Examinez et mettez à jour la logique associée au
AInputEventd'activité native. Comme indiqué à l'étape précédente, le traitementInputBufferde GameActivity n'est pas exécuté dans la boucleALooper_pollOnce().Remplacez l'utilisation de
android_app::activity->clazzparandroid_app:: activity->javaGameActivity. GameActivity renomme l'instance JavaGameActivity.
Étapes supplémentaires :
Les opérations précédentes décrivent les fonctionnalités de NativeActivity, mais GameActivity propose des fonctionnalités supplémentaires qui peuvent vous être utiles :
- TextInput
- Manette de jeu
- Fragment
- Nouvelles commandes InSet de fenêtre définies dans NativeAppGlueAppCmd.
Nous vous recommandons d'essayer ces fonctionnalités et de les adopter si elles sont appropriées pour vos jeux.
Si vous avez des questions ou des recommandations concernant GameActivity ou d'autres bibliothèques AGDK, créez un rapport de bug pour nous en informer.