إتاحة التحديثات داخل التطبيق (Unreal Engine)

يوضّح هذا الدليل كيفية توفير التحديثات داخل التطبيق في تطبيقك باستخدام Unreal Engine. تتوفّر أدلة منفصلة للحالات التي يستخدم فيها التنفيذ لغة برمجة Kotlin أو لغة برمجة Java، والحالات التي يستخدم فيها التنفيذ رمزًا أصليًا (C/C++) أو Unity.

نظرة عامة على حزمة تطوير البرامج (SDK) لمحرك Unreal

واجهة برمجة التطبيقات Play In-App Updates API هي جزء من مجموعة حِزم تطوير البرامج (SDK) Play Core. توفّر واجهة برمجة التطبيقات لمحرك Unreal ‏Engine فئة UInAppUpdatesManager لمعالجة الاتصالات بين تطبيقك وواجهة برمجة التطبيقات Play API. بعد تقديم طلب، يمكن لتطبيقك التحقّق من حالة الطلب باستخدام EAppUpdateErrorCode.

إصدارات Unreal Engine المتوافقة

يتوافق المكوّن الإضافي مع Unreal Engine 5.0 وجميع الإصدارات اللاحقة.

إعداد بيئة التطوير

  1. نزِّل مكوّن Play Unreal Engine الإضافي من مستودع GitHub.

  2. انسخ مجلد GooglePlay داخل مجلد Plugins في مشروع Unreal Engine.

  3. افتح مشروع Unreal Engine وانقر على تعديل (Edit) → الإضافات (Plugins).

  4. ابحث عن Google Play وضَع علامة في مربّع الاختيار مفعَّل.

  5. أعِد تشغيل مشروع اللعبة وأطلِق عملية إنشاء.

  6. افتح ملف Build.cs في مشروعك وأضِف وحدة PlayInAppUpdates إلى PublicDependencyModuleNames:

    using UnrealBuildTool;
    
    public class MyGame : ModuleRules
    {
      public MyGame(ReadOnlyTargetRules Target) : base(Target)
      {
        // ...
    
        PublicDependencyModuleNames.Add("PlayInAppUpdates");
    
        // ...
      }
    }
    

التحقّق من توفّر تحديث

قبل طلب تحديث، تحقّق ممّا إذا كان هناك تحديث متوفّر لتطبيقك. يمكنك استخدام UInAppUpdatesManager::RequestInfo للبحث عن تحديث:

MyClass.h

void MyClass::OnRequestInfoOperationCompleted(
  EAppUpdateErrorCode ErrorCode,
  UAppUpdateInfo* UpdateInfo)
{
  // Check the resulting error code.
  if (ErrorCode == EAppUpdateErrorCode::AppUpdate_NO_ERROR)
  {
    // Check AppUpdateInfo's UpdateAvailability, UpdatePriority,
    // IsUpdateTypeAllowed(), ... and decide whether to ask the user
    // to start an in-app update.
  }
}

MyClass.cpp

void MyClass::CheckForUpdateAvailability()
{
  // Create a delegate to bind the callback function.
  FRequestInfoOperationCompletedDelegate Delegate;

  // Bind the completion handler (OnRequestInfoOperationCompleted) to the delegate.
  Delegate.BindDynamic(this, &MyClass::OnRequestInfoOperationCompleted);

  // Initiate the request info operation, passing the delegate to handle the result.
  GetGameInstance()
    ->GetSubsystem<UInAppUpdatesManager>()
    ->RequestInfo(Delegate);
}

يحتوي مثيل UAppUpdateInfo الذي تم إرجاعه على حالة توفّر التحديث. إذا كان التحديث داخل التطبيق قيد التقدّم، تُبلغ النسخة أيضًا عن حالة التحديث الجاري.

التحقّق من تقادم التحديث

بالإضافة إلى التحقّق مما إذا كان تحديث متاحًا، ننصحك أيضًا بالاطّلاع على المدّة التي انقضت منذ آخر إشعار تلقّاه المستخدم بشأن تحديث من خلال "متجر Play". يمكن أن يساعدك ذلك في تحديد ما إذا كان عليك بدء تعديل مرن أو تعديل فوري. على سبيل المثال، يمكنك الانتظار بضعة أيام قبل إشعار المستخدم بتحديث مرن، ثم الانتظار بضعة أيام بعد ذلك قبل طلب إجراء تحديث فوري.

استخدِم UAppUpdateInfo:GetClientVersionStalenessDays لمعرفة عدد الأيام منذ توفُّر التحديث من خلال "متجر Play":

int32 ClientVersionStalenessDays = UpdateInfo->GetClientVersionStalenessDays();

التحقّق من أولوية التحديث

تتيح لك Google Play Developer API ضبط أولوية كل تحديث. ويتيح ذلك لتطبيقك تحديد مدى قوة اقتراح التحديث على المستخدم. على سبيل المثال، يمكنك اتّباع الاستراتيجية التالية لتحديد أولوية التحديث:

  • تحسينات بسيطة في واجهة المستخدم: تحديث ذو أولوية منخفضة، لا تطلب تعديلاً مرنًا ولا تعديلاً فوريًا.
  • تحسينات الأداء: تحديث ذو أولوية متوسطة، يُرجى طلب تحديثٍ مرن.
  • تحديث أمان مهم: تحديث ذو أولوية عالية، يُرجى طلب التحديث فورًا.

لتحديد الأولوية، يستخدم Google Play قيمة عددية تتراوح بين 0 و5، وتكون القيمة 0 هي القيمة التلقائية والقيمة 5 هي أعلى قيمة. لتحديد الأولوية لأحد التحديثات، استخدِم الحقل inAppUpdatePriority ضمن Edits.tracks.releases في Google Play Developer API. تُعتبَر جميع الإصدارات المُضافة حديثًا في الإصدار ذات الأولوية نفسها التي يحظى بها الإصدار. لا يمكن ضبط الأولوية إلا عند طرح إصدار جديد، ولا يمكن تغييرها لاحقًا.

اضبط الأولوية باستخدام Google Play Developer API كما هو موضّح في مستندات Play Developer API. يجب تحديد أولوية التحديث داخل التطبيق في مصدر Edit.tracks الذي تم تمريره في طريقة Edit.tracks: update. يوضّح المثال التالي عملية طرح تطبيق برمز الإصدار 88 وinAppUpdatePriority 5:

{
  "releases": [{
      "versionCodes": ["88"],
      "inAppUpdatePriority": 5,
      "status": "completed"
  }]
}

في رمز تطبيقك، يمكنك التحقّق من مستوى الأولوية لتحديث معيّن باستخدام UAppUpdateInfo::UpdatePriority:

int32 Priority = UpdateInfo->GetPriority();

بدء تحديث

بعد تأكيد توفّر تحديث، يمكنك طلب تحديث باستخدام UInAppUpdatesManager::StartUpdate. قبل طلب إجراء تحديث، تأكَّد من توفُّر عنصر UAppUpdateInfo محدّث. يجب أيضًا إنشاء كائن UAppUpdateOptions لضبط عملية التحديث.

ينشئ المثال التالي عنصر UAppUpdateOptions لتدفّق تعديل فوري:

// Creates an UAppUpdateOptions defining an immediate in-app
// update flow and its parameters.
UAppUpdateOptions* Options = NewObject<UAppUpdateOptions>();
Options->CreateOptions(EAppUpdateType::AppUpdate_TYPE_IMMEDIATE);

ينشئ المثال التالي عنصر UAppUpdateOptions لتدفق تعديل مرن:

// Creates an UAppUpdateOptions defining a flexible in-app
// update flow and its parameters.
UAppUpdateOptions* Options = NewObject<UAppUpdateOptions>();
Options->CreateOptions(EAppUpdateType::AppUpdate_TYPE_FLEXIBLE);

يحتوي عنصر UAppUpdateOptions أيضًا على دالة IsAssetPackDeletionAllowed تُظهر ما إذا كان يُسمح للتحديث بمحو حِزم مواد العرض في حال كان مساحة التخزين في الجهاز محدودة. يتم ضبط هذا الحقل تلقائيًا على false، ولكن يمكنك ضبط الحقل باستخدام UAppUpdateOptions::SetAssetPackDeletionAllowed لضبطه على true بدلاً من ذلك:

// Sets the AssetPackDeletionAllowed field to true.
Options->SetAssetPackDeletionAllowed(true);

تعتمد الخطوات التالية على ما إذا كنت تطلب تعديلًا مرنًا أو تعديلًا فوريًا.

معالجة تعديل مرن

بعد الحصول على عنصر UAppUpdateInfo محدّث وعنصر UAppUpdateOptions تم ضبط إعداداته بشكل صحيح، يمكنك الاتصال بـ UInAppUpdatesManager::StartUpdate لطلب عملية تعديل.

MyClass.h

void MyClass::OnStartUpdateOperationCompleted(EAppUpdateErrorCode ErrorCode)
{
  // ...
}

MyClass.cpp

// .cpp
void MyClass::StartUpdate()
{
  // Create a delegate to bind the callback function.
  FUpdateOperationCompletedDelegate Delegate;

  // Bind the completion handler (OnStartUpdateOperationCompleted) to the delegate.
  Delegate.BindDynamic(this, &MyClass::OnStartUpdateOperationCompleted);

  // Initiate the start update operation, passing the delegate to handle the result.
  GetGameInstance()
    ->GetSubsystem<UInAppUpdatesManager>()
    ->StartUpdate(UpdateInfo, UpdateOptions, Delegate);
}

للحصول على عملية تحديث مرنة، عليك بدء تثبيت تحديث التطبيق بعد انتهاء عملية التنزيل بنجاح. لإجراء ذلك، اتصل بالرقم InAppUpdatesManager::CompleteUpdate، كما هو موضّح في المثال التالي:

MyClass.h

void MyClass::OnCompleteUpdateOperationCompleted(EAppUpdateErrorCode ErrorCode)
{
  // ...
}

MyClass.cpp

void MyClass::CompleteFlexibleUpdate()
{
  // Create a delegate to bind the callback function.
  FUpdateOperationCompletedDelegate Delegate;

  // Bind the completion handler (OnCompleteUpdateOperationCompleted) to the delegate.
  Delegate.BindDynamic(this, &MyClass::OnCompleteUpdateOperationCompleted);

  // Initiate the complete update operation, passing the delegate to handle the result.
  GetGameInstance()
    ->GetSubsystem<UInAppUpdatesManager>()
    ->CompleteUpdate(UpdateInfo, UpdateOptions, Delegate);
}

معالجة تحديث فوري

بعد الحصول على عنصر UAppUpdateInfo محدّث وعنصر UAppUpdateOptions تم ضبط إعداداته بشكل صحيح، يمكنك الاتصال بـ InAppUpdatesManager::StartUpdate لطلب عملية تعديل.

MyClass.h

void MyClass::OnStartUpdateOperationCompleted(EAppUpdateErrorCode ErrorCode)
{
  // ...
}

MyClass.cpp

void MyClass::StartUpdate()
{
  // Create a delegate to bind the callback function.
  FUpdateOperationCompletedDelegate Delegate;

  // Bind the completion handler (OnStartUpdateOperationCompleted) to the delegate.
  Delegate.BindDynamic(this, &MyClass::OnStartUpdateOperationCompleted);

  // Initiate the start update operation, passing the delegate to handle the result.
  GetGameInstance()
    ->GetSubsystem<UInAppUpdatesManager>()
    ->StartUpdate(UpdateInfo, UpdateOptions, Delegate);
}

لبدء عملية التحديث فورًا، يعرض Google Play مربّع حوار تأكيد للمستخدم. عندما يقبل المستخدم الطلب، ينزِّل Google Play التحديث تلقائيًا ويمثِّله، ثم يعيد تشغيل التطبيق بالإصدار المُحدَّث إذا كان التثبيت ناجحًا.

معالجة الأخطاء

يوضّح هذا القسم حلولاً للأخطاء الشائعة.

  • إذا كانت UInAppUpdatesManager::StartUpdate تعرِض خطأ AppUpdate_INVALID_REQUEST، يعني ذلك أنّ UAppUpdateInfo غير صالحة. تأكَّد من أنّ عنصر UAppUpdateInfo الذي تم إرجاعه من UInAppUpdatesManager::RequestInfo ليس فارغًا قبل بدء عملية تعديل.
  • إذا عرض العنصر UInAppUpdatesManager::StartUpdate خطأ AppUpdate_NOT_ALLOWED ، يعني ذلك أنّ العنصر UAppUpdateOptions يشير إلى نوع تحديث غير مسموح به للتحديث المتاح. تحقَّق مما إذا كان عنصر UAppUpdateInfo يشير إلى أنّ نوع التحديث المحدّد مسموح به قبل بدء عملية التحديث.

الخطوات التالية

اختبِر التحديثات داخل التطبيق للتأكّد من أنّ عملية الدمج تعمل بشكلٍ صحيح.