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

يعمل ربط App Flip المستند إلى OAuth (App Flip) على إدراج تطبيق Android في تدفق ربط حساب Google. يتطلب تدفق ربط الحساب التقليدي من المستخدم إدخال بيانات اعتماده في المتصفح. يؤدي استخدام App Flip إلى إرجاء تسجيل دخول المستخدم إلى تطبيق Android ، مما يسمح لك بالاستفادة من التراخيص الحالية. إذا قام المستخدم بتسجيل الدخول إلى تطبيقك ، فلن يحتاج إلى إعادة إدخال بيانات اعتماده لربط حسابه. يلزم إجراء قدر ضئيل من تغييرات الكود لتطبيق App Flip على تطبيق Android الخاص بك.

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

جرب العينة

فليب التطبيقات ربط التطبيق عينة يدل على المتوافقة مع فليب حساب التطبيقات ربط التكامل على الروبوت. يمكنك استخدام هذا التطبيق للتحقق من كيفية الرد على تطبيق Flip intent من تطبيقات Google للجوال.

وتكوينها التطبيق عينة على الاندماج مع الوجه أداة اختبار التطبيقات لالروبوت ، والتي يمكنك استخدامها للتحقق من تكامل تطبيق Android مع التطبيقات الوجه قبل حساب تكوين ربط مع جوجل. يحاكي هذا التطبيق الهدف الذي يتم تشغيله بواسطة تطبيقات Google للجوّال عند تمكين App Flip.

كيف تعمل

الخطوات التالية مطلوبة لتنفيذ تكامل App Flip:

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

قم بتعديل تطبيق Android الخاص بك لدعم App Flip

لدعم App Flip ، قم بإجراء التغييرات التالية على التعليمات البرمجية لتطبيق 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 مسجلة تحت التطبيق الخاص بك.
  • 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 : خطأ غير قابل للاسترداد: حساب إحباط التطبيق وجوجل ربط.
    • 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 لضمان trigerred وتراجع المناسب.