التطبيق العكسي لنظام التشغيل Android

تُدرِج ميزة "ربط التطبيقات باستخدام الوجه" المستندة إلى بروتوكول OAuth تطبيق Android في خطوات ربط حساب Google يتطلب التدفق التقليدي لربط الحسابات إدخال بيانات اعتماد المستخدم في المتصفِّح يؤدي استخدام ميزة "قلب التطبيقات" إلى تأجيل المستخدِم سجّل الدخول إلى تطبيق Android، مما يتيح لك الاستفادة من التفويضات. إذا سجَّل المستخدم الدخول إلى تطبيقك، لن يكون بحاجة إلى إعادة إدخال بيانات الاعتماد لربط الحساب. استخدام أقل قدر ممكن من الرموز البرمجية يجب إجراء التغييرات لتنفيذ ميزة "قلب التطبيقات" على تطبيق Android.

ستتعرّف في هذا المستند على كيفية تعديل تطبيق Android قلب التطبيق

تجربة النموذج

نموذج التطبيق الذي يستخدم ميزة "قلب التطبيقات" توضيح تكامل ربط الحساب المتوافق مع ميزة App Flip على Android إِنْتَ يمكنه استخدام هذا التطبيق للتحقّق من طريقة الردّ على عملية قلب تطبيق واردة من خلال ميزة "قلب التطبيق". تطبيقات Google للأجهزة الجوّالة.

تم ضبط نموذج التطبيق مسبقًا للدمج مع أداة اختبار قلب التطبيق). Android، الذي يمكنك استخدامه للتحقّق من دمج تطبيق Android مع التطبيق يُرجى العودة قبل ضبط ربط الحساب بحساب Google. يحاكي هذا التطبيق نية الشراء التي تظهر من خلال تطبيقات Google المتوافقة مع الأجهزة الجوّالة عند تفعيل ميزة "قلب التطبيق".

آلية العمل

يجب اتّباع الخطوات التالية لتنفيذ عملية دمج ميزة "قلب التطبيقات":

  1. يتحقّق تطبيق Google مما إذا كان تطبيقك مثبَّتًا على الجهاز باستخدام اسم الحزمة.
  2. يستخدم تطبيق Google عملية فحص توقيع الحزمة للتحقّق من أنّ التطبيقات التي تم تثبيتها هو التطبيق الصحيح.
  3. يوفّر تطبيق Google نية بدء نشاط معيّن في تطبيقك. يتضمّن هذا الغرض بيانات إضافية مطلوبة للربط. يتحقق أيضًا من لمعرفة ما إذا كان تطبيقك يتوافق مع ميزة "قلب التطبيقات" من خلال حلّ هذا الغرض من خلال إطار عمل Android.
  4. يتحقّق تطبيقك من أنّ الطلب وارد من تطبيق Google. لإجراء ذلك، يتحقّق تطبيقك من توقيع الحزمة ومعرِّف العميل المقدَّم.
  5. يطلب تطبيقك رمز تفويض من خادم OAuth 2.0. في جلسة المعمل، نهاية هذا التدفق، فإنها تعرض إما رمز تفويض أو خطأ في تطبيق Google.
  6. يستردّ تطبيق Google النتيجة ويواصل ربط الحساب. في حال حذف تقديم رمز تفويض، فيتم تبادل الرمز المميّز من خادم إلى خادم، تمامًا كما يحدث في ربط OAuth المستند إلى المتصفح التدفق.

تعديل تطبيق Android لدعم ميزة "قلب التطبيقات"

لإتاحة ميزة "قلب التطبيقات"، عليك إجراء التغييرات التالية على الرمز البرمجي للتطبيق المتوافق مع Android:

  1. أضِف <intent-filter> إلى ملف AndroidManifest.xml مع تنفيذ إجراء. سلسلة تطابق القيمة التي أدخلتها في الحقل هدف قلب التطبيق

    <activity android:name="AuthActivity">
      <!-- Handle the app flip intent -->
      <intent-filter>
        <action android:name="INTENT_ACTION_FROM_CONSOLE"/>
        <category android:name="android.intent.category.DEFAULT"/>
      </intent-filter>
    </activity>
    
  2. تحقَّق من صحة توقيع تطبيق الاتصال.

    private fun verifyFingerprint(
            expectedPackage: String,
            expectedFingerprint: String,
            algorithm: String
    ): Boolean {
    
        callingActivity?.packageName?.let {
            if (expectedPackage == it) {
                val packageInfo =
                    packageManager.getPackageInfo(it, PackageManager.GET_SIGNATURES)
                val signatures = packageInfo.signatures
                val input = ByteArrayInputStream(signatures[0].toByteArray())
    
                val certificateFactory = CertificateFactory.getInstance("X509")
                val certificate =
                    certificateFactory.generateCertificate(input) as X509Certificate
                val md = MessageDigest.getInstance(algorithm)
                val publicKey = md.digest(certificate.encoded)
                val fingerprint = publicKey.joinToString(":") { "%02X".format(it) }
    
                return (expectedFingerprint == fingerprint)
            }
        }
        return false
    }
    
  3. استخرِج معرِّف العميل من مَعلمات intent وتحقَّق من أنّ العميل. يتطابق رقم التعريف مع القيمة المتوقّعة.

    private const val EXPECTED_CLIENT = "<client-id-from-actions-console>"
    private const val EXPECTED_PACKAGE = "<google-app-package-name>"
    private const val EXPECTED_FINGERPRINT = "<google-app-signature>"
    private const val ALGORITHM = "SHA-256"
    ...
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    
        val clientId = intent.getStringExtra("CLIENT_ID")
    
        if (clientId == EXPECTED_CLIENT &&
            verifyFingerprint(EXPECTED_PACKAGE, EXPECTED_FINGERPRINT, ALGORITHM)) {
    
            // ...authorize the user...
        }
    }
    
  4. بعد نجاح التفويض، يُرجى إعادة رمز التفويض الناتج. إلى Google.

    // Successful result
    val data = Intent().apply {
        putExtra("AUTHORIZATION_CODE", authCode)
    }
    setResult(Activity.RESULT_OK, data)
    finish()
    
  5. إذا حدث خطأ، يمكنك عرض نتيجة الخطأ بدلاً من ذلك.

    // Error result
    val error = Intent().apply {
        putExtra("ERROR_TYPE", 1)
        putExtra("ERROR_CODE", 1)
        putExtra("ERROR_DESCRIPTION", "Invalid Request")
    }
    setResult(-2, error)
    finish()
    

محتوى القصد من الإطلاق

يتضمن هدف Android الذي يشغِّل تطبيقك الحقول التالية:

  • CLIENT_ID (String): تم تسجيل "client_id" على Google ضمن تطبيقك.
  • SCOPE (String[]): قائمة بالنطاقات المطلوبة
  • REDIRECT_URI (String): عنوان URL لإعادة التوجيه

محتوى بيانات الرد

يتم ضبط البيانات التي يتم إرجاعها إلى تطبيق Google في تطبيقك من خلال الاتصال بالرقم setResult(). وتشمل هذه البيانات ما يلي:

  • AUTHORIZATION_CODE (String): قيمة رمز التفويض
  • resultCode (int): تبلغ عن نجاح العملية أو فشلها على إحدى القيم التالية:
    • Activity.RESULT_OK: يشير إلى النجاح. يتم إرجاع رمز تفويض.
    • Activity.RESULT_CANCELLED: إشارات إلى أنّ المستخدم ألغى الدفع. في هذه الحالة، سيحاول تطبيق Google ربط الحساب باستخدام عنوان URL للمصادقة.
    • -2: تشير إلى حدوث خطأ. أنواع مختلفة من الأخطاء الموضحة أدناه.
  • ERROR_TYPE (int): نوع الخطأ، والذي يتضمّن أيًا مما يلي: القيم التالية:
    • 1: خطأ يمكن استرداده: سيحاول تطبيق Google ربط الحساب باستخدام عنوان URL للمصادقة.
    • 2: خطأ غير قابل للإصلاح: سيلغي تطبيق Google ربط الحساب.
    • 3: معلَمات طلب غير صالحة أو مفقودة.
  • ERROR_CODE (int): عدد صحيح يمثّل طبيعة الخطأ للاطلاع على معنى كل رمز خطأ، فراجع جدول رموز الأخطاء.
  • ERROR_DESCRIPTION (String، اختياري): رسالة حالة يمكن لشخص عادي قراءتها وصف الخطأ.

ويُتوقَّع ظهور قيمة للسمة AUTHORIZATION_CODE عندما resultCode == Activity.RESULT_OK في جميع الحالات الأخرى، قيمة يجب أن يكون الحقل "AUTHORIZATION_CODE" فارغًا. إذا كانت resultCode == -2، تكون من المتوقّع تعبئة قيمة "ERROR_TYPE".

جدول رموز الأخطاء

يوضح الجدول أدناه رموز الأخطاء المختلفة وما إذا كان كل خطأ منها قابلاً للإصلاح أو غير قابل للإصلاح:

رمز الخطأ المعنى قابل للاسترداد غير قابل للاسترداد
1 INVALID_REQUEST
2 NO_INTERNET_CONNECTION
3 OFFLINE_MODE_ACTIVE
4 CONNECTION_TIMEOUT
5 INTERNAL_ERROR
6 AUTHENTICATION_SERVICE_UNAVAILABLE
8 CLIENT_VERIFICATION_FAILED
9 INVALID_CLIENT
10 INVALID_APP_ID
11 INVALID_REQUEST
12 AUTHENTICATION_SERVICE_UNKNOWN_ERROR
13 AUTHENTICATION_DENIED_BY_USER
14 CANCELLED_BY_USER
15 FAILURE_OTHER
16 USER_AUTHENTICATION_FAILED

بالنسبة إلى جميع رموز الأخطاء، يجب عرض نتيجة الخطأ عبر setResult إلى لضمان ترتيب الإجراء الاحتياطي المناسب.