واجهات برمجة تطبيقات eUICC

في Android 9، تتوفّر واجهات برمجة التطبيقات لإدارة الملفات الشخصية (العامة وSystemApi@) من خلال الفئة EuiccManager. تتوفّر واجهات برمجة التطبيقات الخاصة بالتواصل مع eUICC ‎(SystemApi@ فقط) من خلال الفئة EuiccCardManager.

لمحة عن eUICC

يمكن لمشغّلي شبكات الجوّال إنشاء تطبيقات مشغِّل شبكة الجوّال باستخدام EuiccManager لإدارة الملفات الشخصية، كما هو موضّح في الشكل 1. لا يشترط أن تكون تطبيقات مشغّلي شبكات الجوّال تطبيقات نظام، ولكن يجب أن تحصل على امتيازات مشغّل شبكة الجوّال التي تمنحها ملفات eUICC. يجب أن يكون تطبيق LPA (واجهة المستخدم المحلية وخدمة LPA الخلفية) تطبيق نظام (أي مضمّن في صورة النظام) لاستدعاء @SystemApi.

هاتف Android مزوّد بتطبيق مشغّل شبكة الجوّال وLPA من الشركة المصنّعة للجهاز الأصلي

الشكل 1. هواتف Android التي تتضمّن تطبيق مشغّل شبكة الجوّال وLPA من الشركة المصنّعة للجهاز الأصلي

بالإضافة إلى منطق الاتصال بـ EuiccCardManager والتحدّث إلى eUICC، يجب أن تنفّذ تطبيقات LPA ما يلي:

  • يتواصل عميل SM-DP+ مع خادم SM-DP+ للمصادقة وتنزيل الملفات الشخصية
  • [اختياري] SM-DS للحصول على المزيد من الملفات الشخصية المحتمل تنزيلها
  • التعامل مع الإشعارات لإرسالها إلى الخادم من أجل تعديل حالة الملف الشخصي
  • [اختياري] إدارة الشرائح، بما في ذلك التبديل بين منطق شريحة eSIM وشريحة SIM الفعلية هذا الخيار اختياري إذا كان الهاتف يحتوي على شريحة eSIM فقط.
  • تحديث eSIM عبر الأثير

على الرغم من إمكانية توفّر أكثر من تطبيق LPA على هاتف Android، يمكن اختيار تطبيق LPA واحد فقط ليكون تطبيق LPA الفعلي الذي يتم استخدامه استنادًا إلى الأولوية المحدّدة في ملف AndroidManifest.xml لكل تطبيق.

استخدام EuiccManager

تتوفّر واجهات برمجة التطبيقات LPA بشكل علني من خلال EuiccManager (ضمن الحزمة android.telephony.euicc). يمكن لتطبيق مشغّل شبكة الجوّال الحصول على مثيل EuiccManager، واستدعاء الطرق في EuiccManager للحصول على معلومات eUICC وإدارة الاشتراكات (المشار إليها باسم الملفات الشخصية في مستندات GSMA RSP) كأمثلة SubscriptionInfo.

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

لا تتعامل منصة Android مع قواعد سياسة الملف الشخصي. إذا تم تحديد قاعدة سياسة في البيانات الوصفية للملف الشخصي، يمكن لتطبيق LPA اختيار كيفية التعامل مع إجراء تنزيل الملف الشخصي وتثبيته. على سبيل المثال، يمكن أن يتعامل LPA تابع لجهة خارجية من مصنّع المعدات الأصلية مع قواعد السياسة باستخدام رمز خطأ خاص (يتم تمرير رمز الخطأ من LPA التابع لجهة خارجية من مصنّع المعدات الأصلية إلى النظام الأساسي، ثم يمرّر النظام الأساسي الرمز إلى واجهة المستخدم المحلية التابعة لمصنّع المعدات الأصلية).

للحصول على معلومات حول واجهات برمجة التطبيقات الخاصة بالملفات الشخصية المتعددة المفعَّلة، يُرجى الاطّلاع على الملفات الشخصية المتعددة المفعَّلة.

واجهات برمجة التطبيقات

يمكن العثور على واجهات برمجة التطبيقات التالية في EuiccManager المستندات المرجعية وEuiccManager.java.

الحصول على مثيل (عام)

تعرض هذه السمة مثيلاً من EuiccManager من خلال Context#getSystemService. للحصول على التفاصيل، يُرجى الاطّلاع على getSystemService.

EuiccManager mgr = (EuiccManager) context.getSystemService(Context.EUICC_SERVICE);

التحقّق من التفعيل (علني)

تتحقّق هذه السمة ممّا إذا كان الاشتراك المضمّن مفعّلاً. يجب التحقّق من ذلك قبل الوصول إلى واجهات برمجة التطبيقات الخاصة بـ LPA. للحصول على التفاصيل، يُرجى الاطّلاع على isEnabled.

boolean isEnabled = mgr.isEnabled();
if (!isEnabled) {
    return;
}

الحصول على معرّف شريحة SIM المضمّنة (عام)

تعرض هذه السمة رقم تعريف بطاقة eUICC. قد تكون هذه القيمة فارغة إذا لم تكن شريحة eUICC جاهزة. يجب أن يكون لدى المتصل امتياز مشغّل شبكة الجوّال أو إذن READ_PRIVILEGED_PHONE_STATE. للحصول على التفاصيل، يُرجى الاطّلاع على getEid.

String eid = mgr.getEid();
if (eid == null) {
  // Handle null case.
}

Get EuiccInfo (عام)

تعرض هذه الطريقة معلومات عن شريحة eUICC. يحتوي هذا الحقل على إصدار نظام التشغيل. للحصول على التفاصيل، يُرجى الاطّلاع على getEuiccInfo.

EuiccInfo info = mgr.getEuiccInfo();
String osVer = info.getOsVersion();

تنزيل الاشتراك (عام)

تنزيل الاشتراك المحدّد (يُشار إليه باسم "الملف الشخصي" في مستندات GSMA RSP) يمكن إنشاء الاشتراك من رمز تفعيل. على سبيل المثال، يمكن تحليل رمز التفعيل من رمز استجابة سريعة. تنزيل اشتراك هو عملية غير متزامنة.

يجب أن يكون لدى المتصل إذن WRITE_EMBEDDED_SUBSCRIPTIONS أو امتيازات مشغّل شبكة الجوّال للاشتراك المستهدف. للحصول على التفاصيل، يُرجى الاطّلاع على downloadSubscription.

// Register receiver.
String action = "download_subscription";
BroadcastReceiver receiver =
        new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                if (!action.equals(intent.getAction())) {
                    return;
                }
                resultCode = getResultCode();
                detailedCode = intent.getIntExtra(
                    EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE,
                    0 /* defaultValue*/);
                resultIntent = intent;
            }
        };
context.registerReceiver(
        receiver,
        new IntentFilter(action),
        "example.broadcast.permission" /* broadcastPermission*/, null /* handler */);

// Download subscription asynchronously.
DownloadableSubscription sub =
        DownloadableSubscription.forActivationCode(code /* encodedActivationCode*/);
Intent intent = new Intent(action);
PendingIntent callbackIntent = PendingIntent.getBroadcast(
        getContext(), 0 /* requestCode */, intent, PendingIntent.FLAG_UPDATE_CURRENT);
mgr.downloadSubscription(sub, true /* switchAfterDownload */, callbackIntent);

تبديل الاشتراك (علني)

يتم التبديل إلى الاشتراك المحدّد (تفعيله). يجب أن يكون لدى المتصل إما WRITE_EMBEDDED_SUBSCRIPTIONS أو امتيازات مشغّل شبكة الجوّال للاشتراك الحالي المفعّل والاشتراك المستهدف. للحصول على التفاصيل، يُرجى الاطّلاع على switchToSubscription.

// Register receiver.
String action = "switch_to_subscription";
BroadcastReceiver receiver =
        new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                if (!action.equals(intent.getAction())) {
                    return;
                }
                resultCode = getResultCode();
                detailedCode = intent.getIntExtra(
                    EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE, 0 /* defaultValue*/);
                resultIntent = intent;
            }
        };
context.registerReceiver(receiver, new IntentFilter(action),
        "example.broadcast.permission" /* broadcastPermission*/, null /* handler */);

// Switch to a subscription asynchronously.
Intent intent = new Intent(action);
PendingIntent callbackIntent = PendingIntent.getBroadcast(
        getContext(), 0 /* requestCode */, intent, PendingIntent.FLAG_UPDATE_CURRENT);
mgr.switchToSubscription(1 /* subscriptionId */, callbackIntent);

تبديل الاشتراك باستخدام المنفذ (عام)

(متاحة بدءًا من الإصدار 13 من نظام التشغيل Android) يتم التبديل إلى (تفعيل) الاشتراك المحدّد باستخدام فهرس المنفذ المحدّد. يجب أن يكون لدى المتصل إما WRITE_EMBEDDED_SUBSCRIPTIONS أو امتيازات مشغّل شبكة الجوّال للاشتراك المفعّل حاليًا والاشتراك المستهدف. للحصول على التفاصيل، يُرجى الاطّلاع على switchToSubscription.

// Register receiver.
String action = "switch_to_subscription";
BroadcastReceiver receiver =
        new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                if (!action.equals(intent.getAction())) {
                    return;
                }
                resultCode = getResultCode();
                detailedCode = intent.getIntExtra(
                    EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE, 0 /* defaultValue*/);
                resultIntent = intent;
            }
        };
context.registerReceiver(receiver, new IntentFilter(action),
        "example.broadcast.permission" /* broadcastPermission*/, null /* handler */);

// Switch to a subscription asynchronously.
Intent intent = new Intent(action);
PendingIntent callbackIntent = PendingIntent.getBroadcast(
        getContext(), 0 /* requestCode */, intent, PendingIntent.FLAG_UPDATE_CURRENT);
mgr.switchToSubscription(1 /* subscriptionId */, 0 /*portIndex*/, callbackIntent);

هل يمكن نقل شريحة SIM (عام)؟

public boolean isSimPortAvailable(int portIndex)

(متاحة من Android 13) تعرض هذه السمة ما إذا كان فهرس المنفذ الذي تم تمريره متاحًا. يكون المنفذ متاحًا إذا لم يكن أي اشتراك مفعَّلاً عليه أو إذا كان تطبيق الاتصال لديه امتيازات مشغّل شبكة الجوّال على الاشتراك المثبَّت على المنفذ المحدّد. للحصول على التفاصيل، يُرجى الاطّلاع على isSimPortAvailable.

حذف الاشتراك (متاح للجميع)

تحذف هذه الطريقة اشتراكًا باستخدام رقم تعريف الاشتراك. إذا كان الاشتراك نشطًا حاليًا، سيتم إيقافه أولاً. يجب أن يكون لدى المتصل إما WRITE_EMBEDDED_SUBSCRIPTIONS أو امتيازات مشغّل شبكة الجوّال للاشتراك المستهدف. للحصول على التفاصيل، يُرجى الاطّلاع على deleteSubscription.

// Register receiver.
String action = "delete_subscription";
BroadcastReceiver receiver =
        new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                if (!action.equals(intent.getAction())) {
                    return;
                }
                resultCode = getResultCode();
                detailedCode = intent.getIntExtra(
                    EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE,
                    0 /* defaultValue*/);
                resultIntent = intent;
            }
        };
context.registerReceiver(receiver, new IntentFilter(action),
        "example.broadcast.permission" /* broadcastPermission*/,
        null /* handler */);

// Delete a subscription asynchronously.
Intent intent = new Intent(action);
PendingIntent callbackIntent = PendingIntent.getBroadcast(
        getContext(), 0 /* requestCode */, intent, PendingIntent.FLAG_UPDATE_CURRENT);
mgr.deleteSubscription(1 /* subscriptionId */, callbackIntent);

محو جميع الاشتراكات (واجهة برمجة تطبيقات النظام)

يمحو هذا الإجراء جميع الاشتراكات على الجهاز. اعتبارًا من Android 11، عليك تقديم قيمة تعداد EuiccCardManager#ResetOption لتحديد ما إذا كنت تريد محو جميع أنواع الاشتراكات الاختبارية أو التشغيلية أو كليهما. يجب أن يكون لدى المتصل إذن WRITE_EMBEDDED_SUBSCRIPTIONS.

// Register receiver.
String action = "delete_subscription";
BroadcastReceiver receiver =
        new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                if (!action.equals(intent.getAction())) {
                    return;
                }
                resultCode = getResultCode();
                detailedCode = intent.getIntExtra(
                    EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE,
                    0 /* defaultValue*/);
                resultIntent = intent;
            }
        };
context.registerReceiver(receiver, new IntentFilter(action),
        "example.broadcast.permission" /* broadcastPermission*/,
        null /* handler */);

// Erase all operational subscriptions asynchronously.
Intent intent = new Intent(action);
PendingIntent callbackIntent = PendingIntent.getBroadcast(
        getContext(), 0 /* requestCode */, intent, PendingIntent.FLAG_UPDATE_CURRENT);
mgr.eraseSubscriptions(
        EuiccCardManager.RESET_OPTION_DELETE_OPERATIONAL_PROFILES, callbackIntent);

بدء نشاط حلّ المشكلة (عام)

يبدأ نشاطًا لحلّ خطأ يمكن للمستخدم حله. إذا عرضت عملية ما الرمز EuiccManager#EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR، يمكن استدعاء هذه الطريقة لتوجيه المستخدم لحل المشكلة. لا يمكن استدعاء هذه الطريقة إلا مرة واحدة لكل خطأ معيّن.

...
mgr.startResolutionActivity(getActivity(), 0 /* requestCode */, resultIntent, callbackIntent);

الثوابت

للاطّلاع على قائمة بثوابت public في EuiccManager، راجِع الثوابت.