NativeActivity'ten taşıma   Android Game Development Kit'in bir parçasıdır.

Bu sayfada, Android oyun projenizde NativeActivity'ten GameActivity'e nasıl geçiş yapılacağı açıklanmaktadır.

GameActivity, Android çerçevesindeki NativeActivity'ü temel alır ve geliştirmeler ile yeni özellikler içerir:

  • Jetpack'ten Fragment desteklenir.
  • Dokunmatik klavye entegrasyonunu kolaylaştırmak için TextInput desteği eklendi.
  • Dokunma ve tuş etkinliklerini NativeActivity onInputEvent arayüzü yerine GameActivity Java sınıfında işler.

Taşıma işlemini başlatmadan önce, GameActivity'yi nasıl ayarlayacağınızı ve projenize nasıl entegre edeceğinizi açıklayan başlangıç kılavuzunu okumanızı öneririz.

Java derleme komut dosyası güncellemeleri

GameActivity, Jetpack kitaplığı olarak dağıtılır. Başlangıç kılavuzunda açıklanan Gradle komut dosyası güncelleme adımlarını uyguladığınızdan emin olun:

  1. Projenizin gradle.properties dosyasında Jetpack kitaplığını etkinleştirin:

    android.useAndroidX=true
    
  2. İsteğe bağlı olarak, aynı gradle.properties dosyasında bir Prefab sürümü belirtebilirsiniz. Örneğin:

    android.prefabVersion=2.0.0
    
  3. Uygulamanızın build.gradle dosyasında Prefab özelliğini etkinleştirin:

    android {
        ... // other configurations
        buildFeatures.prefab true
    }
    
  4. GameActivity bağımlılığını uygulamanıza ekleyin:

    1. core ve games-activity kitaplıklarını ekleyin.
    2. Şu anda desteklenen minimum API düzeyiniz 16'dan azsa en az 16 olacak şekilde güncelleyin.
    3. Derlenmiş SDK sürümünü, games-activitykitaplığının gerektirdiği sürüme güncelleyin. Jetpack genellikle sürüm derleme zamanında en son SDK sürümünü gerektirir.

    Güncellenen build.gradle dosyanız şöyle görünebilir:

    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 veya Java kod güncellemeleri

NativeActivity, başlangıç etkinliği olarak kullanılabilir ve tam ekran bir uygulama oluşturur. GameActivity şu anda başlangıç etkinliği olarak kullanılamaz. Uygulamalar, GameActivity sınıfından bir sınıf türetmeli ve bunu başlangıç etkinliği olarak kullanmalıdır. Tam ekran uygulama oluşturmak için ek yapılandırma değişiklikleri de yapmanız gerekir.

Aşağıdaki adımlarda, uygulamanızın başlangıç etkinliği olarak NativeActivity kullanıldığı varsayılmaktadır. Aksi takdirde bunların çoğunu atlayabilirsiniz.

  1. Yeni başlangıç etkinliğini barındıracak bir Kotlin veya Java dosyası oluşturun. Örneğin, aşağıdaki kodda MainActivity başlatma etkinliği olarak oluşturulur ve uygulamanın ana yerel kitaplığı olan libAndroidGame.so yüklenir:

    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. res\values\themes.xml dosyasında tam ekran uygulama teması oluşturun:

    <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. Temayı AndroidManifest.xml dosyasındaki uygulamaya uygulayın:

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

    Tam ekran moduyla ilgili ayrıntılı talimatlar için sürükleyici kılavuza ve games-samples deposundaki örnek uygulamaya bakın.

Bu taşıma kılavuzu, yerel kitaplık adını değiştirmez. Değiştirirseniz yerel kitaplık adlarının aşağıdaki üç konumda tutarlı olduğundan emin olun:

  • Kotlin veya Java kodu:

    System.loadLibrary(AndroidGame)
    
  • AndroidManifest.xml:

    <meta-data android:name="android.app.lib_name"
            android:value="AndroidGame" />
    
  • C/C++ derleme komut dosyası dosyasında (ör. CMakeLists.txt) şunları yapın:

    add_library(AndroidGame ...)
    

C/C++ derleme komut dosyası güncellemeleri

Bu bölümdeki talimatlarda örnek olarak cmake kullanılmaktadır. Uygulamanız ndk-build kullanıyorsa bunları ndk-build doküman sayfasında açıklanan eşdeğer komutlarla eşlemeniz gerekir.

GameActivity'nin C/C++ uygulaması, kaynak kodu sürümü sağlamaktadır. 1.2.2 ve sonraki sürümler için statik kitaplık sürümü sağlanır. Önerilen sürüm türü statik kitaplıktır.

Sürüm, prefab aracıyla AAR'a paketlenir. Yerel kod, GameActivity'nin C/C++ kaynaklarını ve native_app_glue kodunu içerir. Bu kitaplıklar, uygulamanızın C/C++ koduyla birlikte derlenmelidir.

NativeActivity uygulamaları zaten NDK'da bulunan native_app_glue kodunu kullanıyor. Bunu GameActivity'nin native_app_glue sürümüyle değiştirmeniz gerekir. Bunun dışında, başlangıç kılavuzunda belirtilen tüm cmake adımları geçerlidir:

  • C/C++ statik kitaplığını veya C/C++ kaynak kodunu projenize aşağıdaki gibi aktarın.

    Statik kitaplık

    Projenizin CMakeLists.txt dosyasında, game-activity statik kitaplığını game-activity_static hazır modülüne aktarın:

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

    Kaynak kodu

    Projenizin CMakeLists.txt dosyasında game-activity paketini içe aktarın ve hedefinize ekleyin. game-activity paketi libandroid.so gerektirir. Bu nedenle, eksikse libandroid.so'u da içe aktarmanız gerekir.

    find_package(game-activity REQUIRED CONFIG)
    ...
    target_link_libraries(... android game-activity::game-activity)
    
  • NDK'nın native_app_glue koduna yapılan tüm referansları kaldırın. Örneğin:

    ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c
        ...
    set(CMAKE_SHARED_LINKER_FLAGS
        "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate")
    
  • Kaynak kod sürümünü kullanıyorsanız GameActivity kaynak dosyalarını ekleyin. Aksi takdirde bu adımı atlayın.

    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)
    

UnsatisfiedLinkError sorununu giderme

com.google.androidgamesdk.GameActivity.initializeNativeCode() işlevi için UnsatsifiedLinkError ile karşılaşırsanız CMakeLists.txt dosyanıza şu kodu ekleyin:

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

C/C++ kaynak kodu güncellemeleri

Uygulamanızdaki NativeActivity referanslarını GameActivity ile değiştirmek için aşağıdaki adımları uygulayın:

  • GameActivity ile birlikte yayınlanan native_app_glue sürümünü kullanın. Tüm android_native_app_glue.h kullanımlarını arayıp şuyla değiştirin:

    #include <game-activity/native_app_glue/android_native_app_glue.h>
    
  • Uygulamanızın tüm giriş cihazlarından giriş etkinliği alabilmesi için hem hareket etkinliği filtresini hem de önemli etkinlik filtresini NULL olarak ayarlayın. Bunu genellikle android_main() işlevinde yaparsınız:

    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 ile ilgili kodu kaldırın ve GameActivity'nin InputBuffer uygulamasını kullanarak değiştirin:

    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;
    }
    
  • NativeActivity'nin AInputEvent özelliğine eklenen mantığı inceleyip güncelleyin. Önceki adımda gösterildiği gibi, GameActivity'nin InputBufferişlemesi ALooper_pollOnce() döngüsünün dışındadır.

  • android_app::activity->clazz kullanımını android_app:: activity->javaGameActivity ile değiştirin. GameActivity, Java GameActivity örneğini yeniden adlandırır.

Ek adımlar

Önceki adımlar NativeActivity'nin işlevlerini kapsar ancak GameActivity'te kullanmak isteyebileceğiniz ek özellikler de vardır:

Bu özellikleri keşfetmenizi ve oyunlarınıza uygun şekilde kullanmanızı öneririz.

GameActivity veya diğer AGDK kitaplıkları hakkında sorularınız ya da önerileriniz varsa bize bildirmek için bir hata kaydı oluşturun.