NativeActivity से माइग्रेट करना   Android Game Development Kit का हिस्सा है.

इस पेज पर, अपने Android गेम प्रोजेक्ट को NativeActivity से GameActivity पर माइग्रेट करने का तरीका बताया गया है.

GameActivity, Android फ़्रेमवर्क के NativeActivity पर आधारित है. इसमें कई सुधार और नई सुविधाएं हैं:

  • Jetpack के Fragment का इस्तेमाल किया जा सकता है.
  • सॉफ़्ट कीबोर्ड इंटिग्रेशन को आसान बनाने के लिए, TextInput की सुविधा जोड़ी गई है.
  • NativeActivity onInputEvent इंटरफ़ेस के बजाय, GameActivity Java क्लास में टच और मुख्य इवेंट को हैंडल करता है.

माइग्रेट करने से पहले, हमारा सुझाव है कि आप शुरू करने के लिए गाइड पढ़ें. इसमें, अपने प्रोजेक्ट में GameActivity को सेट अप और इंटिग्रेट करने का तरीका बताया गया है.

Java बिल्ड स्क्रिप्ट से जुड़े अपडेट

GameActivity को एक Jetpack लाइब्रेरी के तौर पर डिस्ट्रिब्यूट किया जाता है. शुरू करने के लिए गाइड में बताए गए, Gradle स्क्रिप्ट को अपडेट करने के तरीके को ज़रूर अपनाएं:

  1. अपने प्रोजेक्ट की gradle.properties फ़ाइल में Jetpack लाइब्रेरी चालू करने के लिए:

    android.useAndroidX=true
    
  2. इसके अलावा, उसी gradle.properties फ़ाइल में प्रीफ़ैब वर्शन भी दिया जा सकता है. उदाहरण के लिए:

    android.prefabVersion=2.0.0
    
  3. अपने ऐप्लिकेशन की build.gradle फ़ाइल में, प्रीफ़ैब सुविधा चालू करें:

    android {
        ... // other configurations
        buildFeatures.prefab true
    }
    
  4. अपने ऐप्लिकेशन में GameActivity डिपेंडेंसी जोड़ें:

    1. core और games-activity लाइब्रेरी जोड़ें.
    2. अगर आपके ऐप्लिकेशन के लिए काम करने वाला कम से कम एपीआई लेवल 16 से कम है, तो उसे कम से कम 16 पर अपडेट करें.
    3. कंपाइल किए गए SDK टूल के वर्शन को उस वर्शन पर अपडेट करें जिसकी games-activity लाइब्रेरी को ज़रूरत है. आम तौर पर, रिलीज़ के बिल्ड के समय, Jetpack को SDK टूल के नए वर्शन की ज़रूरत होती है.

    अपडेट की गई आपकी build.gradle फ़ाइल कुछ इस तरह दिख सकती है:

    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 या Java कोड के अपडेट

NativeActivity का इस्तेमाल स्टार्टअप गतिविधि के तौर पर किया जा सकता है. इससे फ़ुल स्क्रीन वाला ऐप्लिकेशन बनता है. फ़िलहाल, GameActivity का इस्तेमाल स्टार्टअप ऐक्टिविटी के तौर पर नहीं किया जा सकता. ऐप्लिकेशन को GameActivity से एक क्लास लेनी होगी और उसका इस्तेमाल स्टार्टअप गतिविधि के तौर पर करना होगा. फ़ुल स्क्रीन ऐप्लिकेशन बनाने के लिए, आपको कॉन्फ़िगरेशन में और भी बदलाव करने होंगे.

यहां दिए गए तरीके में यह माना गया है कि आपका ऐप्लिकेशन, स्टार्टअप ऐक्टिविटी के तौर पर NativeActivity का इस्तेमाल करता है. अगर ऐसा नहीं है, तो ज़्यादातर सवालों को छोड़ा जा सकता है.

  1. नई स्टार्टअप गतिविधि को होस्ट करने के लिए, Kotlin या Java फ़ाइल बनाएं. उदाहरण के लिए, यहां दिया गया कोड, MainActivity को स्टार्टअप गतिविधि के तौर पर बनाता है और ऐप्लिकेशन की मुख्य नेटिव लाइब्रेरी, 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. 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>
    
  3. AndroidManifest.xml फ़ाइल में, ऐप्लिकेशन पर थीम लागू करें:

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

    फ़ुल स्क्रीन मोड के बारे में ज़्यादा जानकारी के लिए, इमर्सिव गाइड देखें. साथ ही, games-samples repo में, इसे लागू करने का उदाहरण देखें.

माइग्रेशन की इस गाइड से, नेटिव लाइब्रेरी का नाम नहीं बदलता. अगर इसे बदला जाता है, तो पक्का करें कि नेटिव लाइब्रेरी के नाम इन तीन जगहों पर एक जैसे हों:

  • Kotlin या Java कोड:

    System.loadLibrary(AndroidGame)
    
  • AndroidManifest.xml:

    <meta-data android:name="android.app.lib_name"
            android:value="AndroidGame" />
    
  • C/C++ बिल्ड स्क्रिप्ट फ़ाइल में, जैसे कि CMakeLists.txt:

    add_library(AndroidGame ...)
    

C/C++ बिल्ड स्क्रिप्ट से जुड़े अपडेट

इस सेक्शन में दिए गए निर्देशों में, उदाहरण के तौर पर cmake का इस्तेमाल किया गया है. अगर आपका ऐप्लिकेशन ndk-build का इस्तेमाल करता है, तो आपको उन्हें ndk-build दस्तावेज़ पेज में बताए गए मिलते-जुलते निर्देशों पर मैप करना होगा.

GameActivity के C/C++ वर्शन को लागू करने से, सोर्स कोड रिलीज़ किया जा रहा है. 1.2.2 और उसके बाद के वर्शन के लिए, स्टैटिक लाइब्रेरी रिलीज़ उपलब्ध है. रिलीज़ के लिए स्टैटिक लाइब्रेरी का सुझाव दिया जाता है.

रिलीज़ को prefab उपयोगिता के साथ AAR में पैक किया जाता है. नेटिव कोड में, GameActivity के C/C++ सोर्स और native_app_glue कोड शामिल होते हैं. इन्हें आपके ऐप्लिकेशन के C/C++ कोड के साथ बनाया जाना चाहिए.

NativeActivity ऐप्लिकेशन, NDK में पहले से मौजूद native_app_glue कोड का इस्तेमाल करते हैं. आपको इसे GameActivity के native_app_glue वर्शन से बदलना होगा. इसके अलावा, शुरू करने के लिए दी गई गाइड में बताए गए cmake सभी चरण लागू होते हैं:

  • अपने प्रोजेक्ट में C/C++ स्टैटिक लाइब्रेरी या C/++ सोर्स कोड को इस तरह इंपोर्ट करें.

    स्टैटिक लाइब्रेरी

    अपने प्रोजेक्ट की CMakeLists.txt फ़ाइल में, game-activity स्टैटिक लाइब्रेरी को game-activity_static प्रीफ़ैब मॉड्यूल में इंपोर्ट करें:

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

    सोर्स कोड

    अपने प्रोजेक्ट की CMakeLists.txt फ़ाइल में, game-activity पैकेज इंपोर्ट करें और उसे अपने टारगेट में जोड़ें. game-activity पैकेज के लिए libandroid.so की ज़रूरत होती है. इसलिए, अगर यह मौजूद नहीं है, तो आपको इसे भी इंपोर्ट करना होगा.

    find_package(game-activity REQUIRED CONFIG)
    ...
    target_link_libraries(... android game-activity::game-activity)
    
  • NDK के native_app_glue कोड के सभी रेफ़रंस हटाएं. जैसे:

    ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c
        ...
    set(CMAKE_SHARED_LINKER_FLAGS
        "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate")
    
  • अगर सोर्स कोड रिलीज़ का इस्तेमाल किया जा रहा है, तो GameActivity सोर्स फ़ाइलें शामिल करें. अगर ऐसा नहीं है, तो इस चरण को छोड़ें.

    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 की समस्या को हल करना

अगर आपको com.google.androidgamesdk.GameActivity.initializeNativeCode() फ़ंक्शन के लिए UnsatsifiedLinkError मिलता है, तो अपनी CMakeLists.txt फ़ाइल में यह कोड जोड़ें:

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

C/C++ सोर्स कोड से जुड़े अपडेट

अपने ऐप्लिकेशन में NativeActivity रेफ़रंस को GameActivity से बदलने के लिए, यह तरीका अपनाएं:

  • GameActivity के साथ रिलीज़ किए गए native_app_glue का इस्तेमाल करें. android_native_app_glue.h के सभी इस्तेमाल को खोजें और इनके साथ बदलें:

    #include <game-activity/native_app_glue/android_native_app_glue.h>
    
  • मोशन इवेंट फ़िल्टर और मुख्य इवेंट फ़िल्टर, दोनों को NULL पर सेट करें, ताकि आपका ऐप्लिकेशन सभी इनपुट डिवाइसों से इनपुट इवेंट पा सके. आम तौर पर, ऐसा android_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.
    }
    
  • AInputEvent से जुड़ा कोड हटाएं और उसे GameActivity के InputBuffer लागू करने के तरीके से बदलें:

    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 के AInputEvent से जुड़े लॉजिक की समीक्षा करें और उसे अपडेट करें. पिछले चरण में दिखाया गया है कि GameActivity की InputBuffer प्रोसेसिंग, ALooper_pollOnce() लूप के बाहर होती है.

  • android_app::activity->clazz के इस्तेमाल को android_app:: activity->javaGameActivity से बदलें. GameActivity, Java GameActivity इंस्टेंस का नाम बदल देता है.

अन्य चरण

पिछले चरणों में, NativeActivity के फ़ंक्शन के बारे में बताया गया है. हालांकि, GameActivity में ऐसी अन्य सुविधाएं भी हैं जिनका इस्तेमाल किया जा सकता है:

हमारा सुझाव है कि इन सुविधाओं को एक्सप्लोर करें और अपने गेम के हिसाब से इन्हें अपनाएं.

अगर आपके पास GameActivity या AGDK की अन्य लाइब्रेरी के बारे में कोई सवाल या सुझाव है, तो हमें बताने के लिए गड़बड़ी की शिकायत करें.