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

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

حول eUICC

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

هاتف Android مزود بتطبيق Carrier وOEM LPA

الشكل 1. هواتف Android المزودة بتطبيق الناقل وOEM LPA

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

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

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

باستخدام EuiccManager

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

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

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

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

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

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

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

الحصول على مثيل EuiccManager من خلال Context#getSystemService . للحصول على التفاصيل، راجع getSystemService .

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

تم تمكين التحقق (عام)

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

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

الحصول على رقم الهوية (عام)

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

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

الحصول على EuiccInfo (عام)

الحصول على معلومات حول eUICC. يحتوي هذا على إصدار نظام التشغيل. لمزيد من التفاصيل، راجع getEuiccInfo .

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

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

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

يجب أن يكون لدى المتصل إذن 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);

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

(متوفر من Android 13) يقوم بالتبديل إلى (تمكين) الاشتراك المحدد مع فهرس المنفذ المحدد. يجب أن يكون لدى المتصل إما 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 ، راجع الثوابت .