XR_ANDROID_google_cloud_auth
Name String
XR_ANDROID_google_cloud_auth
نوع الإضافة
إضافة مثيل
رقم الإضافة المسجَّل
788
المراجعة
1
حالة التصديق
لم تتم المصادقة
الاعتماديات على الإضافات والإصدارات
XR_EXT_future
تاريخ آخر تعديل
2025-12-18
حالة عنوان IP
ما مِن مطالبات معروفة بشأن الملكية الفكرية.
المساهمون
"جون أولمان"، Google
"بن كينغ"، Google
"نيهاف جاين"، Google
"جاريد فايندر"، Google
نظرة عامة
تتيح هذه الإضافة استخدام إضافات مستندة إلى Google Cloud من خلال السماح للتطبيق بتقديم بيانات اعتماد المصادقة لواجهات Google Cloud APIs. على المطوّر استخدام Google Cloud Console ( https://console.cloud.google.com/ ) لإنشاء مشروع على السحابة الإلكترونية للتطبيق. تتطلّب هذه الإضافة الإضافة XR_EXT_future .
أثناء عملية التطوير، يمكن للتطبيق تصحيح الأخطاء في عملية إعداد Google Cloud باستخدام الإضافة XR_EXT_debug_utils . إذا كان التطبيق يتضمّن Debug Messenger، وحدث خطأ يمكن اتّخاذ إجراء بشأنه في وقت التشغيل عند إرسال طلب إلى Google Cloud نيابةً عن التطبيق، يستدعي وقت التشغيل معاودة الاتصال في Debug Messenger مع رسالة خطأ. في هذه الحالة، على المطوّر الاطّلاع على رسالة الخطأ وجميع المستندات المتاحة، ثم التأكّد من إعداد التطبيق ومشروع Google Cloud بشكلٍ صحيح لاستخدام Google Cloud APIs. يجب أن يستخدم وقت التشغيل نوع الرسالة XR_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT والخطورة XR_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT والمعرّف messageId "GoogleCloudError".
المصادقة
يتم تعريف بنية XrGoogleCloudAuthInfoBaseHeaderANDROID على النحو التالي:
typedef struct XrGoogleCloudAuthInfoBaseHeaderANDROID {
XrStructureType type;
const void* next;
} XrGoogleCloudAuthInfoBaseHeaderANDROID;
أوصاف الأعضاء
typeهو XrStructureType لهذه البنية.nextهوNULLأو مؤشر إلى البنية التالية في سلسلة البنية.
لا يتم استخدام هذه البنية مباشرةً في واجهة برمجة التطبيقات، ولكن يتم توسيعها من خلال بنى أخرى يمكن استخدامها مع xrSetGoogleCloudAuthAsyncANDROID لتوفير بيانات اعتماد المصادقة.
الاستخدام الصالح (الضمني)
- يجب تفعيل الإضافة
XR_ANDROID_google_cloud_authقبل استخدام XrGoogleCloudAuthInfoBaseHeaderANDROID - يجب أن تكون قيمة
typeإحدى قيم XrStructureType التالية:XR_TYPE_GOOGLE_CLOUD_AUTH_INFO_API_KEY_ANDROIDأوXR_TYPE_GOOGLE_CLOUD_AUTH_INFO_KEYLESS_ANDROIDأوXR_TYPE_GOOGLE_CLOUD_AUTH_INFO_TOKEN_ANDROID - يجب أن تكون قيمة
nextإماNULLأو مؤشرًا صالحًا إلى البنية التالية في سلسلة البِنى. راجِع أيضًا: XrGoogleCloudAuthErrorResultANDROID
يتم تعريف بنية XrGoogleCloudAuthInfoApiKeyANDROID على النحو التالي:
typedef struct XrGoogleCloudAuthInfoApiKeyANDROID {
XrStructureType type;
const void* next;
const char* apiKey;
} XrGoogleCloudAuthInfoApiKeyANDROID;
أوصاف الأعضاء
typeهو XrStructureType لهذه البنية.nextهوNULLأو مؤشر إلى البنية التالية في سلسلة البنية.-
apiKeyهو مؤشر إلى سلسلة تمثّل مفتاح واجهة برمجة التطبيقات.
عند تمرير هذه البنية إلى xrSetGoogleCloudAuthAsyncANDROID ، يجب أن يكون العنصر apiKey سلسلة ASCII غير فارغة بدون مسافات أو أحرف تحكّم، وإلا يجب أن يعرض وقت التشغيل XR_ERROR_VALIDATION_FAILURE .
apiKey يجب استيفاء الشروط التالية أيضًا:
- يجب أن يكون مفتاح واجهة برمجة تطبيقات صالحًا تم إنشاؤه لمشروعك على Google Cloud.
- يجب أن يفعّل مشروعك على السحابة الإلكترونية على Google واجهات Cloud APIs ذات الصلة (المحدّدة من خلال الإضافات التابعة).
- إذا كان مفتاح واجهة برمجة التطبيقات يتضمّن قيودًا، يجب أن تسمح القيود لواجهات Google Cloud APIs ذات الصلة وتطبيقك.
بخلاف ذلك، سينجح طلب xrSetGoogleCloudAuthAsyncANDROID، ولكن سيتم تنفيذ جميع طلبات الدوال التي تعتمد على إذن السحابة الإلكترونية كما هو موضّح في حالات تعذُّر الوصول إلى السحابة الإلكترونية في الإضافة التي تحدّد هذه الدوال. إذا كان بإمكان إحدى الدوال الإبلاغ عن حدوث خطأ، وكانت السلاسل التطبيقية XrGoogleCloudAuthErrorResultANDROID مرتبطة بمَعلمة الإخراج الخاصة بهذه الدالة، يجب أن يضبط وقت التشغيل error في XrGoogleCloudAuthErrorResultANDROID على XR_GOOGLE_CLOUD_AUTH_ERROR_ANDROID للإشارة إلى هذا الخطأ.
ستكتمل العملية غير المتزامنة مع XR_SUCCESS بعد التحقّق من صحة مفتاح واجهة برمجة التطبيقات من حيث التنسيق وتخزينه بواسطة وقت التشغيل.
الاستخدام الصالح (الضمني)
- يجب تفعيل الإضافة
XR_ANDROID_google_cloud_authقبل استخدام XrGoogleCloudAuthInfoApiKeyANDROID - يجب أن يكون
typeXR_TYPE_GOOGLE_CLOUD_AUTH_INFO_API_KEY_ANDROID - يجب أن تكون قيمة
nextهيNULLأو مؤشرًا صالحًا إلى البنية التالية في سلسلة البِنى - يجب أن يكون
apiKeyسلسلة UTF-8 تنتهي بقيمة فارغة
يتم تعريف بنية XrGoogleCloudAuthInfoTokenANDROID على النحو التالي:
typedef struct XrGoogleCloudAuthInfoTokenANDROID {
XrStructureType type;
const void* next;
const char* authToken;
} XrGoogleCloudAuthInfoTokenANDROID;
أوصاف الأعضاء
typeهو XrStructureType لهذه البنية.nextهوNULLأو مؤشر إلى البنية التالية في سلسلة البنية.-
authTokenهو مؤشر إلى سلسلة تمثّل رمز المصادقة.
عند تمرير هذه البنية إلى xrSetGoogleCloudAuthAsyncANDROID ، يجب أن يكون العنصر authToken سلسلة ASCII غير فارغة بدون مسافات أو أحرف تحكّم، وإلا يجب أن يعرض وقت التشغيل XR_ERROR_VALIDATION_FAILURE . authToken يجب استيفاء الشروط التالية أيضًا:
- يجب أن تكون بيانات اعتماد صالحة وغير منتهية الصلاحية تم إنشاؤها لمشروعك على Google Cloud.
- يجب أن يفعّل مشروعك على السحابة الإلكترونية على Google واجهات Cloud APIs ذات الصلة (المحدّدة من خلال الإضافات التابعة).
يجب أن تكون بيانات الاعتماد إحدى ما يلي:
- رمز مميز للوصول إلى OAuth2 يتضمّن النطاقات ذات الصلة، ويتم إنشاؤه من خلال تسجيل الدخول إلى حساب Google باستخدام تطبيقك، أو
- رمز JWT مميّز موقَّع يتضمّن المطالبات ذات الصلة، ويتم إنشاؤه بواسطة حساب خدمة من مشروعك على Google Cloud
يتم تحديد المتطلبات في كل حالة من خلال الإضافات التي تعتمد عليها. بخلاف ذلك، سينجح طلب xrSetGoogleCloudAuthAsyncANDROID، ولكن سيتم تنفيذ جميع طلبات الدوال التي تعتمد على إذن السحابة الإلكترونية كما هو موضّح في حالات تعذُّر الوصول إلى السحابة الإلكترونية في الإضافة التي تحدّد هذه الدوال. إذا كان بإمكان إحدى الدوال الإبلاغ عن حدوث خطأ، وكانت السلاسل التطبيقية XrGoogleCloudAuthErrorResultANDROID مرتبطة بمَعلمة الإخراج الخاصة بهذه الدالة، يجب أن يضبط وقت التشغيل error في XrGoogleCloudAuthErrorResultANDROID على XR_GOOGLE_CLOUD_AUTH_ERROR_ANDROID للإشارة إلى هذا الخطأ.
يجب أن يمرّر التطبيق بشكل استباقي رمزًا مميزًا جديدًا من خلال xrSetGoogleCloudAuthAsyncANDROID قبل انتهاء صلاحية الرمز المميز القديم. يجب أن يستخدم وقت التشغيل أحدث رمز مميّز يقدّمه التطبيق عند بدء طلب شبكة جديد.
ستكتمل العملية غير المتزامنة مع XR_SUCCESS بعد التحقّق من صحة الرمز المميز من حيث التنسيق وتخزينه بواسطة وقت التشغيل.
الاستخدام الصالح (الضمني)
- يجب تفعيل الإضافة
XR_ANDROID_google_cloud_authقبل استخدام XrGoogleCloudAuthInfoTokenANDROID - يجب أن يكون
typeXR_TYPE_GOOGLE_CLOUD_AUTH_INFO_TOKEN_ANDROID - يجب أن تكون قيمة
nextهيNULLأو مؤشرًا صالحًا إلى البنية التالية في سلسلة البِنى - يجب أن يكون
authTokenسلسلة UTF-8 تنتهي بقيمة فارغة
يتم تعريف بنية XrGoogleCloudAuthInfoKeylessANDROID على النحو التالي:
typedef struct XrGoogleCloudAuthInfoKeylessANDROID {
XrStructureType type;
const void* next;
} XrGoogleCloudAuthInfoKeylessANDROID;
أوصاف الأعضاء
typeهو XrStructureType لهذه البنية.nextهوNULLأو مؤشر إلى البنية التالية في سلسلة البنية.
عندما يتم تمرير هذه البنية إلى xrSetGoogleCloudAuthAsyncANDROID ، قد ينشئ وقت التشغيل بيانات الاعتماد ديناميكيًا (على سبيل المثال، على نظام التشغيل Android، يتواصل وقت التشغيل مع "خدمات Google Play" من عملية التطبيق). إذا لم يتم إعداد ميزة "المصادقة بدون مفتاح" بشكل صحيح، قد تعرض وقت التشغيل XR_ERROR_KEYLESS_AUTH_NOT_SETUP_ANDROID بشكل متزامن.
ستنفّذ العملية غير المتزامنة طلبات الشبكة اللازمة لجلب بيانات الاعتماد. سيتم عرض نتيجة هذه العملية في XrFutureCompletionEXT :: futureResult من xrSetGoogleCloudAuthCompleteANDROID . إذا كانت النتيجة المستقبلية هي XR_SUCCESS ، يعني ذلك أنّه تم تطبيق بيانات اعتماد ميزة "المصادقة بدون مفتاح" بنجاح. إذا كانت النتيجة المستقبلية هي XR_ERROR_KEYLESS_AUTH_FAILED_ANDROID ، قد يحاول التطبيق مرة أخرى لاحقًا.
الاستخدام الصالح (الضمني)
- يجب تفعيل الإضافة
XR_ANDROID_google_cloud_authقبل استخدام XrGoogleCloudAuthInfoKeylessANDROID - يجب أن يكون
typeXR_TYPE_GOOGLE_CLOUD_AUTH_INFO_KEYLESS_ANDROID - يجب أن تكون قيمة
nextهيNULLأو مؤشرًا صالحًا إلى البنية التالية في سلسلة البِنى
يتم تعريف الدالة xrSetGoogleCloudAuthAsyncANDROID على النحو التالي:
XrResult xrSetGoogleCloudAuthAsyncANDROID(
XrSession session,
const XrGoogleCloudAuthInfoBaseHeaderANDROID* authInfo,
XrFutureEXT* future);
أوصاف المَعلمات
-
sessionهو XrSession الذي سيستخدم بيانات الاعتماد. -
authInfoهو مؤشر إلى بنية تحدّد طريقة المصادقة والمَعلمات، ويشير الحقلtypeفي XrGoogleCloudAuthInfoBaseHeaderANDROID إلى البنية المحدّدة. futureهو مؤشر إلى مقبضXrFutureEXTيتم فيه عرض المستقبل الذي تم إنشاؤه، أو XR_NULL_HANDLE إذا لم تعرض الدالةXR_SUCCESS.
اضبط بيانات الاعتماد المستخدَمة للمصادقة باستخدام Google Cloud. هذه العملية غير متزامنة. استدعِ الدالة xrPollFutureEXT للتحقّق من حالة الاستعداد في المستقبل. بعد أن تصبح القيمة المستقبلية في حالة الجاهزية، يمكنك استدعاء الدالة xrSetGoogleCloudAuthCompleteANDROID لاسترداد النتيجة.
يجب أن تكون المَعلمة authInfo مؤشرًا إلى بنية يحدّد العضو type فيها طريقة المصادقة التي سيتم استخدامها، والتي توسّع XrGoogleCloudAuthInfoBaseHeaderANDROID (مثل XrGoogleCloudAuthInfoBaseHeaderANDROID).
يتم توضيح المتطلبات والسلوكيات وشروط الخطأ المحددة (المتزامنة وغير المتزامنة) لكل طريقة مصادقة في المستندات الخاصة ببُنى البيانات المعنية.
الاستخدام الصالح (الضمني)
- يجب تفعيل الإضافة
XR_ANDROID_google_cloud_authقبل استدعاء xrSetGoogleCloudAuthAsyncANDROID - يجب أن يكون
sessionمعرّفًا صالحًا لـ XrSession - يجب أن يكون
authInfoمؤشرًا إلى بنية صالحة مستندة إلى XrGoogleCloudAuthInfoBaseHeaderANDROID. راجِع أيضًا: XrGoogleCloudAuthInfoApiKeyANDROID وXrGoogleCloudAuthInfoKeylessANDROID وXrGoogleCloudAuthInfoTokenANDROID - يجب أن يكون
futureمؤشرًا إلى قيمةXrFutureEXT
رموز الإرجاع
XR_SUCCESSXR_SESSION_LOSS_PENDING
XR_ERROR_FUNCTION_UNSUPPORTEDXR_ERROR_HANDLE_INVALIDXR_ERROR_INSTANCE_LOSTXR_ERROR_KEYLESS_AUTH_NOT_SETUP_ANDROIDXR_ERROR_RUNTIME_FAILUREXR_ERROR_SESSION_LOSTXR_ERROR_VALIDATION_FAILURE
يتم تعريف الدالة xrSetGoogleCloudAuthCompleteANDROID على النحو التالي:
XrResult xrSetGoogleCloudAuthCompleteANDROID(
XrSession session,
XrFutureEXT future,
XrFutureCompletionEXT* completion);
أوصاف المَعلمات
-
sessionهو XrSession المستخدَم لبدء العملية. futureهوXrFutureEXTالمطلوب إكماله.-
completionهو مؤشر إلى XrFutureCompletionEXT يملأه وقت التشغيل.
رموز العودة المستقبلية
XrFutureCompletionEXT :: قيم futureResult:
-
XR_SUCCESS: تم تطبيق بيانات الاعتماد بنجاح.
-
XR_ERROR_KEYLESS_AUTH_FAILED_ANDROID: تعذّر إجراء المصادقة بدون مفتاح. يمكن للتطبيق إعادة المحاولة لاحقًا. قد يتحقّق التطبيق أو المطوّر أيضًا من بعض الشروط المسبقة لتحقيق النجاح (على سبيل المثال، على أجهزة Android، يجب أن يكون الجهاز مثبّتًا عليه أحدث إصدار من "خدمات Google Play" ويجب أن تعمل هذه الخدمات بشكل صحيح).
الاستخدام الصالح (الضمني)
- يجب تفعيل الإضافة
XR_ANDROID_google_cloud_authقبل استدعاء xrSetGoogleCloudAuthCompleteANDROID - يجب أن يكون
sessionمعرّفًا صالحًا لـ XrSession - يجب أن يكون
completionمؤشرًا إلى بنية XrFutureCompletionEXT
رموز الإرجاع
XR_SUCCESSXR_SESSION_LOSS_PENDING
XR_ERROR_FUNCTION_UNSUPPORTEDXR_ERROR_FUTURE_INVALID_EXTXR_ERROR_FUTURE_PENDING_EXTXR_ERROR_HANDLE_INVALIDXR_ERROR_INSTANCE_LOSTXR_ERROR_RUNTIME_FAILUREXR_ERROR_SESSION_LOSTXR_ERROR_VALIDATION_FAILURE
أخطاء مصادقة Google Cloud
يتم تعريف التعداد XrGoogleCloudAuthErrorANDROID على النحو التالي:
typedef enum XrGoogleCloudAuthErrorANDROID {
XR_GOOGLE_CLOUD_AUTH_ERROR_NONE_ANDROID = 0,
XR_GOOGLE_CLOUD_AUTH_ERROR_QUOTA_EXCEEDED_ANDROID = -1,
XR_GOOGLE_CLOUD_AUTH_ERROR_UNREACHABLE_ANDROID = -2,
XR_GOOGLE_CLOUD_AUTH_ERROR_ANDROID = -3,
XR_GOOGLE_CLOUD_AUTH_ERROR_MAX_ENUM_ANDROID = 0x7FFFFFFF
} XrGoogleCloudAuthErrorANDROID;
تحتوي القيم المُعدَّدة على القيم التالية:
وصف التعداد
XR_GOOGLE_CLOUD_AUTH_ERROR_NONE_ANDROID
لم يحدث أي خطأ عند استدعاء إحدى واجهات برمجة التطبيقات في Google Cloud.
XR_GOOGLE_CLOUD_AUTH_ERROR_QUOTA_EXCEEDED_ANDROID
تم تجاوز الحصة المحدّدة عند استدعاء إحدى واجهات Google Cloud API.
XR_GOOGLE_CLOUD_AUTH_ERROR_UNREACHABLE_ANDROID
تعذّر الوصول إلى إحدى واجهات برمجة التطبيقات في Google Cloud، ربما بسبب مشاكل في الاتصال بالشبكة أو توفّر الخادم.
XR_GOOGLE_CLOUD_AUTH_ERROR_ANDROID
حدث خطأ في المصادقة عند استدعاء إحدى واجهات Google Cloud API.
يتم تعريف بنية XrGoogleCloudAuthErrorResultANDROID على النحو التالي:
typedef struct XrGoogleCloudAuthErrorResultANDROID {
XrStructureType type;
void* next;
XrGoogleCloudAuthErrorANDROID error;
} XrGoogleCloudAuthErrorResultANDROID;
أوصاف الأعضاء
typeهو XrStructureType لهذه البنية.nextهوNULLأو مؤشر إلى البنية التالية في سلسلة البنية.-
errorهو XrGoogleCloudAuthErrorANDROID الذي يوضّح سبب حدوث خطأ في عملية الوصول إلى Google Cloud.
إذا تعذّرت عملية بسبب Google Cloud Authentication، يمكن ربط هذه البنية بنية نتيجة العملية لتوفير المزيد من المعلومات حول الخطأ.
الاستخدام الصالح (الضمني)
- يجب تفعيل إضافة
XR_ANDROID_google_cloud_authقبل استخدام XrGoogleCloudAuthErrorResultANDROID - يجب أن يكون
typeXR_TYPE_GOOGLE_CLOUD_AUTH_ERROR_RESULT_ANDROID - يجب أن تكون قيمة
nextهيNULLأو مؤشرًا صالحًا إلى البنية التالية في سلسلة البِنى - يجب أن تكون قيمة
errorقيمة صالحة XrGoogleCloudAuthErrorANDROID
مثال على الرمز
XrSession session; // previously initialized
XrInstance instance; // previously initialized
XrFutureEXT future = XR_NULL_HANDLE;
// The function pointers are previously initialized using
// xrGetInstanceProcAddr.
PFN_xrPollFutureEXT xrPollFutureEXT; // previously initialized
PFN_xrSetGoogleCloudAuthAsyncANDROID xrSetGoogleCloudAuthAsyncANDROID; // previously initialized
PFN_xrSetGoogleCloudAuthCompleteANDROID xrSetGoogleCloudAuthCompleteANDROID; // previously initialized
auto waitUntilReady = [&](XrFutureEXT future) {
XrFuturePollInfoEXT pollInfo{XR_TYPE_FUTURE_POLL_INFO_EXT};
XrFuturePollResultEXT pollResult{XR_TYPE_FUTURE_POLL_RESULT_EXT};
pollInfo.future = future;
do {
// sleep(1);
xrPollFutureEXT(instance, &pollInfo, &pollResult);
} while (pollResult.state != XR_FUTURE_STATE_READY_EXT);
};
// Set Google Cloud auth via API key.
XrGoogleCloudAuthInfoApiKeyANDROID authApiKey{XR_TYPE_GOOGLE_CLOUD_AUTH_INFO_API_KEY_ANDROID};
authApiKey.apiKey = "MYAPIKEY";
XrResult result = xrSetGoogleCloudAuthAsyncANDROID(
session, reinterpret_cast<XrGoogleCloudAuthInfoBaseHeaderANDROID*>(&authApiKey), &future);
// Or, set Google Cloud auth via auth token:
XrGoogleCloudAuthInfoTokenANDROID authToken{XR_TYPE_GOOGLE_CLOUD_AUTH_INFO_TOKEN_ANDROID};
authToken.authToken = "MYAUTHTOKEN";
result = xrSetGoogleCloudAuthAsyncANDROID(
session, reinterpret_cast<XrGoogleCloudAuthInfoBaseHeaderANDROID*>(&authToken), &future);
// Or, set Google Cloud auth via keyless auth:
XrGoogleCloudAuthInfoKeylessANDROID authKeyless{XR_TYPE_GOOGLE_CLOUD_AUTH_INFO_KEYLESS_ANDROID};
result = xrSetGoogleCloudAuthAsyncANDROID(
session, reinterpret_cast<XrGoogleCloudAuthInfoBaseHeaderANDROID*>(&authKeyless),
&future);
// Check the result of the auth setup.
if (result == XR_ERROR_VALIDATION_FAILURE) {
// The credentials were invalid.
} else if (result == XR_ERROR_KEYLESS_AUTH_NOT_SETUP_ANDROID) {
// Keyless auth was not properly setup.
} else if (result == XR_SUCCESS) {
waitUntilReady(future);
XrFutureCompletionEXT completion{XR_TYPE_FUTURE_COMPLETION_EXT};
xrSetGoogleCloudAuthCompleteANDROID(session, future, &completion);
if (completion.futureResult == XR_SUCCESS) {
// Credentials were successfully applied.
} else if (completion.futureResult == XR_ERROR_KEYLESS_AUTH_FAILED_ANDROID) {
// An error occurred when setting keyless auth credentials. This error may be retried.
}
}
الأوامر الجديدة
المنشآت الجديدة
- XrGoogleCloudAuthInfoApiKeyANDROID
- XrGoogleCloudAuthInfoBaseHeaderANDROID
- XrGoogleCloudAuthInfoKeylessANDROID
- XrGoogleCloudAuthInfoTokenANDROID
عمليات التعداد الجديدة
ثوابت التعداد الجديدة
XR_ANDROID_GOOGLE_CLOUD_AUTH_EXTENSION_NAMEXR_ANDROID_google_cloud_auth_SPEC_VERSIONتمديد XrResult :
XR_ERROR_KEYLESS_AUTH_FAILED_ANDROIDXR_ERROR_KEYLESS_AUTH_NOT_SETUP_ANDROID
توسيع XrStructureType :
XR_TYPE_GOOGLE_CLOUD_AUTH_ERROR_RESULT_ANDROIDXR_TYPE_GOOGLE_CLOUD_AUTH_INFO_API_KEY_ANDROIDXR_TYPE_GOOGLE_CLOUD_AUTH_INFO_KEYLESS_ANDROIDXR_TYPE_GOOGLE_CLOUD_AUTH_INFO_TOKEN_ANDROID
المشاكل
المراجعة 1، 18-12-2025 (Ben King)
- الوصف الأوّلي للإضافة