مهاجرت از NativeActivity بخشی از کیت توسعه بازی اندروید .
این صفحه نحوهی مهاجرت از NativeActivity به GameActivity را در پروژهی بازی اندروید شما شرح میدهد.
GameActivity بر اساس NativeActivity از چارچوب اندروید ساخته شده است، با پیشرفتها و ویژگیهای جدید:
- از
Fragmentدر Jetpack پشتیبانی میکند. - پشتیبانی
TextInputرا برای تسهیل ادغام صفحهکلید نرمافزاری اضافه کرد. - رویدادهای لمس و کلید را در کلاس جاوا
GameActivityبه جای رابطNativeActivityonInputEventمدیریت میکند.
قبل از مهاجرت، توصیه میکنیم راهنمای شروع به کار را مطالعه کنید، که نحوه راهاندازی و ادغام GameActivity در پروژه شما را شرح میدهد.
بهروزرسانیهای اسکریپت ساخت جاوا
GameActivity به عنوان یک کتابخانه Jetpack توزیع شده است. حتماً مراحل بهروزرسانی اسکریپت Gradle که در راهنمای شروع به کار توضیح داده شده است را اعمال کنید:
کتابخانه Jetpack را در فایل
gradle.propertiesپروژه خود فعال کنید:android.useAndroidX=trueبه صورت اختیاری، یک نسخه Prefab را در همان فایل
gradle.propertiesمشخص کنید، برای مثال:android.prefabVersion=2.0.0ویژگی Prefab را در فایل
build.gradleبرنامه خود فعال کنید:android { ... // other configurations buildFeatures.prefab true }وابستگی
GameActivityرا به برنامه خود اضافه کنید:- کتابخانههای
coreوgames-activityرا اضافه کنید. - اگر حداقل سطح API پشتیبانیشده فعلی شما کمتر از ۱۶ است، آن را حداقل به ۱۶ بهروزرسانی کنید.
- نسخه SDK کامپایل شده را به نسخهای که کتابخانه
games-activityنیاز دارد، بهروزرسانی کنید. جتپک معمولاً در زمان ساخت نسخه آزمایشی به آخرین نسخه 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' }- کتابخانههای
بهروزرسانیهای کد کاتلین یا جاوا
NativeActivity میتواند به عنوان یک فعالیت راهاندازی استفاده شود و یک برنامه تمام صفحه ایجاد کند. در حال حاضر، GameActivity نمیتواند به عنوان فعالیت راهاندازی استفاده شود. برنامهها باید یک کلاس از GameActivity مشتق کنند و از آن به عنوان فعالیت راهاندازی استفاده کنند. همچنین برای ایجاد یک برنامه تمام صفحه باید تغییرات پیکربندی اضافی ایجاد کنید.
مراحل زیر فرض میکنند که برنامه شما NativeActivity به عنوان activity آغازین استفاده میکند. اگر اینطور نیست، میتوانید از اکثر آنها صرف نظر کنید.
یک فایل کاتلین یا جاوا برای میزبانی اکتیویتی راهاندازی جدید ایجاد کنید. برای مثال، کد زیر
MainActivityبه عنوان اکتیویتی راهاندازی ایجاد میکند و کتابخانه اصلی بومی برنامه،libAndroidGame.so، را بارگذاری میکند:کاتلین
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") } } }
جاوا
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"); } }
یک تم برنامه تمام صفحه در فایل
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>تم را در فایل
AndroidManifest.xmlبه برنامه اعمال کنید:<application android:theme=”@style/Application.Fullscreen”> <!-- other configurations not listed here. --> </application>برای دستورالعملهای دقیق برای حالت تمام صفحه، به راهنمای همهجانبه و پیادهسازی مثال در مخزن games-samples مراجعه کنید.
این راهنمای مهاجرت نام کتابخانه بومی را تغییر نمیدهد. اگر آن را تغییر میدهید، مطمئن شوید که نام کتابخانههای بومی در سه مکان زیر یکسان هستند:
کد کاتلین یا جاوا:
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 نگاشت کنید.
پیادهسازی C/C++ در GameActivity یک نسخه کد منبع ارائه داده است. برای نسخههای ۱.۲.۲ به بعد، یک نسخه کتابخانه استاتیک ارائه شده است. کتابخانه استاتیک نوع انتشار توصیه شده است.
این نسخه درون AAR به همراه ابزار prefab قرار دارد. کد native شامل منابع C/C++ مربوط به GameActivity و کد native_app_glue است. آنها باید همراه با کد C/C++ برنامه شما ساخته شوند.
برنامههای NativeActivity از قبل از کد native_app_glue که درون NDK قرار دارد استفاده میکنند. شما باید آن را با نسخه native_app_glue مربوط به GameActivity جایگزین کنید. به غیر از این، تمام مراحل cmake که در راهنمای شروع به کار مستند شدهاند، اعمال میشوند:
کتابخانه استاتیک C/C++ یا کد منبع C/++ را به صورت زیر به پروژه خود وارد کنید.
کتابخانه استاتیک
در فایل
CMakeLists.txtپروژه خود، کتابخانه استاتیکgame-activityرا به ماژول prefab مربوط به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را وارد کرده و آن را به پوشه target خود اضافه کنید. بستهgame-activityبهlibandroid.soنیاز دارد، بنابراین اگر آن را ندارید، باید آن را نیز وارد کنید.find_package(game-activity REQUIRED CONFIG) ... target_link_libraries(... android game-activity::game-activity)تمام ارجاعات به کد
native_app_glueاز NDK را حذف کنید ، مانند:${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
اگر با خطای UnsatsifiedLinkError برای تابع com.google.androidgamesdk.GameActivity.initializeNativeCode() مواجه شدید، این کد را به فایل CMakeLists.txt خود اضافه کنید:
set(CMAKE_SHARED_LINKER_FLAGS
"${CMAKE_SHARED_LINKER_FLAGS} -u \
Java_com_google_androidgamesdk_GameActivity_initializeNativeCode")
بهروزرسانیهای کد منبع C/C++
برای جایگزینی ارجاعات NativeActivity در برنامه خود با GameActivity ، این مراحل را دنبال کنید:
از
native_app_glueمنتشر شده باGameActivityاستفاده کنید. تمام موارد استفاده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را حذف کنید و آن را با پیادهسازیInputBufferاز 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; }منطق متصل به
AInputEventمربوط به NativeActivity را بررسی و بهروزرسانی کنید. همانطور که در مرحله قبل نشان داده شد، پردازشInputBufferمربوط به GameActivity خارج از حلقهALooper_pollOnce()است.android_app::activity->clazzرا باandroid_app:: activity->javaGameActivityجایگزین کنید. GameActivity نام نمونهی جاوایGameActivityرا تغییر میدهد.
مراحل اضافی
مراحل قبلی عملکرد NativeActivity را پوشش دادند، اما GameActivity ویژگیهای دیگری نیز دارد که ممکن است بخواهید از آنها استفاده کنید:
- ورودی متن .
- کنترل کننده بازی .
- تکه تکه شدن .
- دستورات InSets پنجره جدید در NativeAppGlueAppCmd تعریف شدهاند.
توصیه میکنیم این ویژگیها را بررسی کرده و آنها را متناسب با بازیهای خود به کار بگیرید.
اگر سؤالی یا پیشنهادی در مورد GameActivity یا سایر کتابخانههای AGDK دارید، لطفاً یک اشکال ایجاد کنید تا به ما اطلاع دهید.